1 #!/usr/bin/env python 2 3 """ 4 Handlers for a resource. 5 """ 6 7 from imiptools.content import Handler, format_datetime, get_address, get_uri, to_part 8 from imiptools.handlers.common import CommonFreebusy 9 from vCalendar import to_node 10 11 class Event(Handler): 12 13 "An event handler." 14 15 def add(self): 16 pass 17 18 def cancel(self): 19 pass 20 21 def counter(self): 22 23 "Since this handler does not send requests, it will not handle replies." 24 25 pass 26 27 def declinecounter(self): 28 29 """ 30 Since this handler does not send counter proposals, it will not handle 31 replies to such proposals. 32 """ 33 34 pass 35 36 def publish(self): 37 pass 38 39 def refresh(self): 40 pass 41 42 def reply(self): 43 44 "Since this handler does not send requests, it will not handle replies." 45 46 pass 47 48 def request(self): 49 50 """ 51 Respond to a request by preparing a reply containing accept/decline 52 information for each indicated attendee. 53 54 No support for countering requests is implemented. 55 """ 56 57 oa = self.require_organiser_and_attendees() 58 if not oa: 59 return None 60 61 organiser_item, attendees = oa 62 63 # Validate the organiser, ignoring spoofed requests. 64 65 if not self.validate_identities([organiser_item]): 66 return None 67 68 # Process each attendee separately. 69 70 calendar = [] 71 72 for attendee, attendee_attr in attendees.items(): 73 74 # Check for event using UID. 75 76 if not self.have_new_object(attendee, "VEVENT"): 77 continue 78 79 # If newer than any old version, discard old details from the 80 # free/busy record and check for suitability. 81 82 periods = self.get_periods() 83 freebusy = self.store.get_freebusy(attendee) or [] 84 scheduled = self.can_schedule(freebusy, periods) 85 86 attendee_attr["PARTSTAT"] = scheduled and "ACCEPTED" or "DECLINED" 87 if self.messenger and self.messenger.sender != get_address(attendee): 88 attendee_attr["SENT-BY"] = get_uri(self.messenger.sender) 89 self.details["ATTENDEE"] = [(attendee, attendee_attr)] 90 91 event = to_node({"VEVENT" : [(self.details, {})]}) 92 calendar.append(event) 93 self.store.set_event(attendee, self.uid, event) 94 95 # Only update free/busy details if the event is scheduled. 96 97 if scheduled: 98 self.update_freebusy(freebusy, attendee, periods) 99 else: 100 self.remove_from_freebusy(freebusy, attendee) 101 102 if self.publisher: 103 self.publisher.set_freebusy(attendee, freebusy) 104 105 return "REPLY", to_part("REPLY", calendar) 106 107 class Freebusy(Handler, CommonFreebusy): 108 109 "A free/busy handler." 110 111 def publish(self): 112 pass 113 114 def reply(self): 115 116 "Since this handler does not send requests, it will not handle replies." 117 118 pass 119 120 # request provided by CommonFreeBusy.request 121 122 class Journal(Handler): 123 124 "A journal entry handler." 125 126 def add(self): 127 pass 128 129 def cancel(self): 130 pass 131 132 def publish(self): 133 pass 134 135 class Todo(Handler): 136 137 "A to-do item handler." 138 139 def add(self): 140 pass 141 142 def cancel(self): 143 pass 144 145 def counter(self): 146 147 "Since this handler does not send requests, it will not handle replies." 148 149 pass 150 151 def declinecounter(self): 152 153 """ 154 Since this handler does not send counter proposals, it will not handle 155 replies to such proposals. 156 """ 157 158 pass 159 160 def publish(self): 161 pass 162 163 def refresh(self): 164 pass 165 166 def reply(self): 167 168 "Since this handler does not send requests, it will not handle replies." 169 170 pass 171 172 def request(self): 173 pass 174 175 # Handler registry. 176 177 handlers = [ 178 ("VFREEBUSY", Freebusy), 179 ("VEVENT", Event), 180 ("VTODO", Todo), 181 ("VJOURNAL", Journal), 182 ] 183 184 # vim: tabstop=4 expandtab shiftwidth=4