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