1 #!/usr/bin/env python 2 3 """ 4 Handlers for a resource. 5 """ 6 7 from imiptools.content import Handler, format_datetime, 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 self.details["ATTENDEE"] = [(attendee, attendee_attr)] 82 83 event = to_node({"VEVENT" : [(self.details, {})]}) 84 calendar.append(event) 85 self.store.set_event(attendee, self.uid, event) 86 87 # Only update free/busy details if the event is scheduled. 88 89 if scheduled: 90 self.update_freebusy(freebusy, attendee, periods) 91 if self.publisher: 92 self.publisher.set_freebusy(attendee, freebusy) 93 94 return "REPLY", to_part("REPLY", calendar) 95 96 class Freebusy(Handler): 97 98 "A free/busy handler." 99 100 def publish(self): 101 pass 102 103 def reply(self): 104 105 "Since this handler does not send requests, it will not handle replies." 106 107 pass 108 109 def request(self): 110 111 """ 112 Respond to a request by preparing a reply containing free/busy 113 information for each indicated attendee. 114 """ 115 116 oa = self.require_organiser_and_attendees() 117 if not oa: 118 return None 119 120 (organiser, organiser_attr), attendees = oa 121 122 # Construct an appropriate fragment. 123 124 calendar = [] 125 cwrite = calendar.append 126 127 # Get the details for each attendee. 128 129 for attendee, attendee_attr in attendees.items(): 130 freebusy = self.store.get_freebusy(attendee) 131 132 record = [] 133 rwrite = record.append 134 135 rwrite(("ORGANIZER", organiser_attr, organiser)) 136 rwrite(("ATTENDEE", attendee_attr, attendee)) 137 rwrite(("UID", {}, self.uid)) 138 139 if freebusy: 140 for start, end, uid in freebusy: 141 rwrite(("FREEBUSY", {"FBTYPE" : "BUSY"}, [start, end])) 142 143 cwrite(("VFREEBUSY", {}, record)) 144 145 # Return the reply. 146 147 return "REPLY", to_part("REPLY", calendar) 148 149 class Journal(Handler): 150 151 "A journal entry handler." 152 153 def add(self): 154 pass 155 156 def cancel(self): 157 pass 158 159 def publish(self): 160 pass 161 162 class Todo(Handler): 163 164 "A to-do item handler." 165 166 def add(self): 167 pass 168 169 def cancel(self): 170 pass 171 172 def counter(self): 173 174 "Since this handler does not send requests, it will not handle replies." 175 176 pass 177 178 def declinecounter(self): 179 180 """ 181 Since this handler does not send counter proposals, it will not handle 182 replies to such proposals. 183 """ 184 185 pass 186 187 def publish(self): 188 pass 189 190 def refresh(self): 191 pass 192 193 def reply(self): 194 195 "Since this handler does not send requests, it will not handle replies." 196 197 pass 198 199 def request(self): 200 pass 201 202 # Handler registry. 203 204 handlers = [ 205 ("VFREEBUSY", Freebusy), 206 ("VEVENT", Event), 207 ("VTODO", Todo), 208 ("VJOURNAL", Journal), 209 ] 210 211 # vim: tabstop=4 expandtab shiftwidth=4