imip-agent

imiptools/handlers/person.py

67:1dbe146491d3
2014-10-25 Paul Boddie Introduced an abstract handler to ensure the availability of a common method.
     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 PersonHandler(Handler):    12     13     "Handling mechanisms specific to people."    14     15     def _record_and_deliver(self, queue=False):    16     17         oa = self.require_organiser_and_attendees()    18         if not oa:    19             return False    20     21         (organiser, organiser_attr), attendees = oa    22     23         # Process each attendee separately.    24     25         for attendee, attendee_attr in attendees.items():    26     27             if not self.have_new_object(attendee, "VEVENT"):    28                 continue    29     30             # Store the event and queue any request.    31     32             self.store.set_event(attendee, self.uid, to_node(    33                 {"VEVENT" : [(self.details, {})]}    34                 ))    35     36             if queue:    37                 self.store.queue_request(attendee, self.uid)    38     39         return True    40     41 class Event(PersonHandler):    42     43     "An event handler."    44     45     def add(self):    46     47         # NOTE: Queue a suggested modification to any active event.    48     49         # The message is now wrapped and passed on to the recipient.    50     51         return "ADD", MIMEText("An addition to an event has been received.")    52     53     def cancel(self):    54     55         # NOTE: Queue a suggested modification to any active event.    56     57         # The message is now wrapped and passed on to the recipient.    58     59         return "CANCEL", MIMEText("A cancellation has been received.")    60     61     def counter(self):    62     63         # NOTE: Queue a suggested modification to any active event.    64     65         # The message is now wrapped and passed on to the recipient.    66     67         return "COUNTER", MIMEText("A counter proposal has been received.")    68     69     def declinecounter(self):    70     71         # NOTE: Queue a suggested modification to any active event.    72     73         # The message is now wrapped and passed on to the recipient.    74     75         return "DECLINECOUNTER", MIMEText("A declining counter proposal has been received.")    76     77     def publish(self):    78     79         # NOTE: Register details of any relevant event.    80     81         # The message is now wrapped and passed on to the recipient.    82     83         return "PUBLISH", MIMEText("Details of an event have been received.")    84     85     def refresh(self):    86     87         # NOTE: Update details of any active event.    88     89         # The message is now wrapped and passed on to the recipient.    90     91         return "REFRESH", MIMEText("An event update has been received.")    92     93     def reply(self):    94     95         "Record replies and notify the recipient."    96     97         self._record_and_deliver(False)    98     99         # The message is now wrapped and passed on to the recipient.   100    101         return "REPLY", MIMEText("A reply has been received.")   102    103     def request(self):   104    105         "Hold requests and notify the recipient."   106    107         self._record_and_deliver(True)   108    109         # The message is now wrapped and passed on to the recipient.   110    111         return "REQUEST", MIMEText("A request has been queued.")   112    113 class Freebusy(PersonHandler):   114    115     "A free/busy handler."   116    117     def publish(self):   118    119         # NOTE: Register free/busy information.   120    121         # The message is now wrapped and passed on to the recipient.   122    123         return "PUBLISH", MIMEText("Details of a contact's availability have been received.")   124    125     def reply(self):   126    127         "Record replies and notify the recipient."   128    129         self._record_and_deliver(False)   130    131         # The message is now wrapped and passed on to the recipient.   132    133         return "REPLY", MIMEText("A reply has been received.")   134    135     def request(self):   136    137         """   138         Respond to a request by preparing a reply containing free/busy   139         information for each indicated attendee.   140         """   141    142         # NOTE: This is currently the same as the resource handler but should be   143         # NOTE: subject to policy/preferences.   144    145         oa = self.require_organiser_and_attendees()   146         if not oa:   147             return None   148    149         (organiser, organiser_attr), attendees = oa   150    151         # Construct an appropriate fragment.   152    153         calendar = []   154         cwrite = calendar.append   155    156         # Get the details for each attendee.   157    158         for attendee, attendee_attr in attendees.items():   159             freebusy = self.store.get_freebusy(attendee)   160    161             record = []   162             rwrite = record.append   163    164             rwrite(("ORGANIZER", organiser_attr, organiser))   165             rwrite(("ATTENDEE", attendee_attr, attendee))   166             rwrite(("UID", {}, self.uid))   167    168             if freebusy:   169                 for start, end, uid in freebusy:   170                     rwrite(("FREEBUSY", {"FBTYPE" : "BUSY"}, [start, end]))   171    172             cwrite(("VFREEBUSY", {}, record))   173    174         # Return the reply.   175    176         return "REPLY", to_part("REPLY", calendar)   177    178 class Journal(PersonHandler):   179    180     "A journal entry handler."   181    182     def add(self):   183    184         # NOTE: Queue a suggested modification to any active entry.   185    186         # The message is now wrapped and passed on to the recipient.   187    188         return "ADD", MIMEText("An addition to a journal entry has been received.")   189    190     def cancel(self):   191    192         # NOTE: Queue a suggested modification to any active entry.   193    194         # The message is now wrapped and passed on to the recipient.   195    196         return "CANCEL", MIMEText("A cancellation has been received.")   197    198     def publish(self):   199    200         # NOTE: Register details of any relevant entry.   201    202         # The message is now wrapped and passed on to the recipient.   203    204         return "PUBLISH", MIMEText("Details of a journal entry have been received.")   205    206 class Todo(PersonHandler):   207    208     "A to-do item handler."   209    210     def add(self):   211    212         # NOTE: Queue a suggested modification to any active item.   213    214         # The message is now wrapped and passed on to the recipient.   215    216         return "ADD", MIMEText("An addition to an item has been received.")   217    218     def cancel(self):   219    220         # NOTE: Queue a suggested modification to any active item.   221    222         # The message is now wrapped and passed on to the recipient.   223    224         return "CANCEL", MIMEText("A cancellation has been received.")   225    226     def counter(self):   227    228         # NOTE: Queue a suggested modification to any active item.   229    230         # The message is now wrapped and passed on to the recipient.   231    232         return "COUNTER", MIMEText("A counter proposal has been received.")   233    234     def declinecounter(self):   235    236         # NOTE: Queue a suggested modification to any active item.   237    238         # The message is now wrapped and passed on to the recipient.   239    240         return "DECLINECOUNTER", MIMEText("A declining counter proposal has been received.")   241    242     def publish(self):   243    244         # NOTE: Register details of any relevant item.   245    246         # The message is now wrapped and passed on to the recipient.   247    248         return "PUBLISH", MIMEText("Details of an item have been received.")   249    250     def refresh(self):   251    252         # NOTE: Update details of any active item.   253    254         # The message is now wrapped and passed on to the recipient.   255    256         return "REFRESH", MIMEText("An item update has been received.")   257    258     def reply(self):   259    260         "Record replies and notify the recipient."   261    262         self._record_and_deliver(False)   263    264         # The message is now wrapped and passed on to the recipient.   265    266         return "REPLY", MIMEText("A reply has been received.")   267    268     def request(self):   269    270         "Hold requests and notify the recipient."   271    272         self._record_and_deliver(True)   273    274         # The message is now wrapped and passed on to the recipient.   275    276         return "REQUEST", MIMEText("A request has been queued.")   277    278 # Handler registry.   279    280 handlers = [   281     ("VFREEBUSY",   Freebusy),   282     ("VEVENT",      Event),   283     ("VTODO",       Todo),   284     ("VJOURNAL",    Journal),   285     ]   286    287 # vim: tabstop=4 expandtab shiftwidth=4