# HG changeset patch # User Paul Boddie # Date 1422667083 -3600 # Node ID df5306c66db5ddf375afe7d389fc19d275e8d843 # Parent 6b26599f8401610b45a55ba8ceffb051f9017769 Added initial support for sending invitations. diff -r 6b26599f8401 -r df5306c66db5 imip_manager.py --- a/imip_manager.py Sat Jan 31 02:17:37 2015 +0100 +++ b/imip_manager.py Sat Jan 31 02:18:03 2015 +0100 @@ -112,25 +112,32 @@ self.user = user self.messenger = messenger - self.organisers = map(get_address, self.get_values("ORGANIZER")) + self.organiser = self.get_value("ORGANIZER") + self.attendees = self.get_values("ATTENDEE") # Communication methods. - def send_message(self, sender): + def send_message(self, method, sender): """ - Create a full calendar object and send it to the organisers, sending a - copy to the 'sender'. + Create a full calendar object employing the given 'method', and send it + to the appropriate recipients, also sending a copy to the 'sender'. """ node = to_node(self.obj) - part = to_part("REPLY", [node]) - message = self.messenger.make_outgoing_message([part], self.organisers, outgoing_bcc=sender) - self.messenger.sendmail(self.organisers, message.as_string(), outgoing_bcc=sender) + part = to_part(method, [node]) + + if self.user == self.organiser: + recipients = map(get_address, self.attendees) + else: + recipients = [get_address(self.organiser)] + + message = self.messenger.make_outgoing_message([part], recipients, outgoing_bcc=sender) + self.messenger.sendmail(recipients, message.as_string(), outgoing_bcc=sender) # Action methods. - def process_request(self, accept, update=False): + def process_received_request(self, accept, update=False): """ Process the current request for the given 'user', accepting any request @@ -147,8 +154,6 @@ for attendee, attendee_attr in self.get_items("ATTENDEE"): if attendee == self.user: - freebusy = self.store.get_freebusy(attendee) - attendee_attr["PARTSTAT"] = accept and "ACCEPTED" or "DECLINED" if self.messenger and self.messenger.sender != get_address(attendee): attendee_attr["SENT-BY"] = get_uri(self.messenger.sender) @@ -158,12 +163,31 @@ self.details["SEQUENCE"] = [(str(int(sequence) + 1), {})] self.update_dtstamp() - self.send_message(get_address(attendee)) + self.send_message("REPLY", get_address(attendee)) return True return False + def process_created_request(self, update=False): + + """ + Process the current request for the given 'user', sending a created + request to attendees. Return whether any action was taken. + + If 'update' is given, the sequence number will be incremented in order + to override any previous message. + """ + + if update: + sequence = self.get_value("SEQUENCE") or "0" + self.details["SEQUENCE"] = [(str(int(sequence) + 1), {})] + self.update_dtstamp() + + self.send_message("REQUEST", get_address(self.organiser)) + + return True + class Manager: "A simple manager application." @@ -293,7 +317,10 @@ def handle_newevent(self): - "Handle any new event operation." + """ + Handle any new event operation, creating a new event and redirecting to + the event page for further activity. + """ # Handle a submitted form. @@ -330,8 +357,8 @@ rwrite(("UID", {}, uid)) rwrite(("SUMMARY", {}, "New event at %s" % utcnow)) rwrite(("DTSTAMP", {}, utcnow)) - rwrite(("DTSTART", {"VALUE" : "DATE-TIME"}, start)) - rwrite(("DTEND", {"VALUE" : "DATE-TIME"}, end or + rwrite(("DTSTART", {"VALUE" : "DATE-TIME", "TZID" : tzid}, start)) + rwrite(("DTEND", {"VALUE" : "DATE-TIME", "TZID" : tzid}, end or format_datetime(get_end_of_day(get_datetime(start, {"TZID" : tzid}))) )) rwrite(("ORGANIZER", {}, self.user)) @@ -367,19 +394,21 @@ accept = args.has_key("accept") decline = args.has_key("decline") + invite = args.has_key("invite") update = not queued and args.has_key("update") - if accept or decline: + if accept or decline or invite: handler = ManagerHandler(request, self.user, self.messenger) - if handler.process_request(accept, update): + # Process the request and remove it from the list. - # Remove the request from the list. + if (accept or decline) and handler.process_received_request(accept, update) or \ + invite and handler.process_created_request(update): self.remove_request(uid) - elif args.has_key("ignore"): + elif args.has_key("discard"): # Remove the request from the list. @@ -402,17 +431,20 @@ details = self._get_details(obj) - attendees = get_value_map(details, "ATTENDEE") - attendee_attr = attendees.get(self.user) + is_organiser = get_value(details, "ORGANIZER") == self.user + + if not is_organiser: + attendees = get_value_map(details, "ATTENDEE") + attendee_attr = attendees.get(self.user) - if attendee_attr: - partstat = attendee_attr.get("PARTSTAT") - if partstat == "ACCEPTED": - self.page.p("This request has been accepted.") - elif partstat == "DECLINED": - self.page.p("This request has been declined.") - else: - self.page.p("This request has been ignored.") + if attendee_attr: + partstat = attendee_attr.get("PARTSTAT") + if partstat == "ACCEPTED": + self.page.p("This request has been accepted.") + elif partstat == "DECLINED": + self.page.p("This request has been declined.") + else: + self.page.p("This request has not yet been dealt with.") if needs_action: self.page.p("An action is required for this request:") @@ -421,13 +453,24 @@ self.page.form(method="POST") self.page.p() - self.page.input(name="accept", type="submit", value="Accept") + + # Show appropriate options depending on the role of the user. + + if is_organiser: + self.page.input(name="invite", type="submit", value="Invite") + else: + self.page.input(name="accept", type="submit", value="Accept") + self.page.add(" ") + self.page.input(name="decline", type="submit", value="Decline") + self.page.add(" ") - self.page.input(name="decline", type="submit", value="Decline") - self.page.add(" ") - self.page.input(name="ignore", type="submit", value="Ignore") + self.page.input(name="discard", type="submit", value="Discard") + + # Updated objects need to have details updated upon sending. + if not needs_action: self.page.input(name="update", type="hidden", value="true") + self.page.p.close() self.page.form.close()