1 #!/usr/bin/env python 2 3 """ 4 Handlers for a person for whom scheduling is performed. 5 """ 6 7 from email.mime.text import MIMEText 8 from imiptools.content import Handler, to_part 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 _record_and_deliver(self, queue=False): 43 44 oa = self.require_organiser_and_attendees() 45 if not oa: 46 return False 47 48 (organiser, organiser_attr), attendees = oa 49 50 # Process each attendee separately. 51 52 for attendee, attendee_attr in attendees.items(): 53 54 if not self.have_new_object(attendee, "VEVENT"): 55 continue 56 57 # Store the event and queue any request. 58 59 self.store.set_event(attendee, self.uid, to_node( 60 {"VEVENT" : [(self.details, {})]} 61 )) 62 63 if queue: 64 self.store.queue_request(attendee, self.uid) 65 66 return True 67 68 def reply(self): 69 70 "Record replies and notify the recipient." 71 72 self._record_and_deliver(False) 73 74 # The message is now wrapped and passed on to the recipient. 75 76 return "REPLY", MIMEText("A reply has been received.") 77 78 def request(self): 79 80 "Hold requests and notify the recipient." 81 82 self._record_and_deliver(True) 83 84 # The message is now wrapped and passed on to the recipient. 85 86 return "REQUEST", MIMEText("A request has been queued.") 87 88 class Freebusy(Handler): 89 90 "A free/busy handler." 91 92 def publish(self): 93 pass 94 95 def reply(self): 96 97 "Since this handler does not send requests, it will not handle replies." 98 99 pass 100 101 def request(self): 102 103 """ 104 Respond to a request by preparing a reply containing free/busy 105 information for each indicated attendee. 106 """ 107 108 # NOTE: This is currently the same as the resource handler but should be 109 # NOTE: subject to policy/preferences. 110 111 oa = self.require_organiser_and_attendees() 112 if not oa: 113 return None 114 115 (organiser, organiser_attr), attendees = oa 116 117 # Construct an appropriate fragment. 118 119 calendar = [] 120 cwrite = calendar.append 121 122 # Get the details for each attendee. 123 124 for attendee, attendee_attr in attendees.items(): 125 freebusy = self.store.get_freebusy(attendee) 126 127 record = [] 128 rwrite = record.append 129 130 rwrite(("ORGANIZER", organiser_attr, organiser)) 131 rwrite(("ATTENDEE", attendee_attr, attendee)) 132 rwrite(("UID", {}, self.uid)) 133 134 if freebusy: 135 for start, end, uid in freebusy: 136 rwrite(("FREEBUSY", {"FBTYPE" : "BUSY"}, [start, end])) 137 138 cwrite(("VFREEBUSY", {}, record)) 139 140 # Return the reply. 141 142 return "REPLY", to_part("REPLY", calendar) 143 144 class Journal(Handler): 145 146 "A journal entry handler." 147 148 def add(self): 149 pass 150 151 def cancel(self): 152 pass 153 154 def publish(self): 155 pass 156 157 class Todo(Handler): 158 159 "A to-do item handler." 160 161 def add(self): 162 pass 163 164 def cancel(self): 165 pass 166 167 def counter(self): 168 169 "Since this handler does not send requests, it will not handle replies." 170 171 pass 172 173 def declinecounter(self): 174 175 """ 176 Since this handler does not send counter proposals, it will not handle 177 replies to such proposals. 178 """ 179 180 pass 181 182 def publish(self): 183 pass 184 185 def refresh(self): 186 pass 187 188 def reply(self): 189 190 "Since this handler does not send requests, it will not handle replies." 191 192 pass 193 194 def request(self): 195 pass 196 197 # Handler registry. 198 199 handlers = [ 200 ("VFREEBUSY", Freebusy), 201 ("VEVENT", Event), 202 ("VTODO", Todo), 203 ("VJOURNAL", Journal), 204 ] 205 206 # vim: tabstop=4 expandtab shiftwidth=4