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