1.1 --- a/imipweb/resource.py Fri Oct 23 00:08:38 2015 +0200
1.2 +++ b/imipweb/resource.py Fri Oct 23 00:26:46 2015 +0200
1.3 @@ -21,8 +21,8 @@
1.4
1.5 from datetime import datetime, timedelta
1.6 from imiptools.client import Client, ClientForObject
1.7 -from imiptools.data import get_address, get_uri, uri_item, uri_values
1.8 -from imiptools.dates import format_datetime, get_recurrence_start_point, to_date
1.9 +from imiptools.data import get_uri
1.10 +from imiptools.dates import format_datetime, to_date
1.11 from imiptools.period import remove_period, remove_affected_period
1.12 from imipweb.data import event_period_from_period, form_period_from_period, \
1.13 FormDate, PeriodError
1.14 @@ -221,176 +221,6 @@
1.15 user = self.env.get_user()
1.16 ClientForObject.__init__(self, None, user and get_uri(user) or None, messenger)
1.17
1.18 - # Communication methods.
1.19 -
1.20 - def send_message(self, parts, sender, obj, from_organiser, bcc_sender):
1.21 -
1.22 - """
1.23 - Send the given 'parts' to the appropriate recipients, also sending a
1.24 - copy to the 'sender'. The 'obj' together with the 'from_organiser' value
1.25 - (which indicates whether the organiser is sending this message) are used
1.26 - to determine the recipients of the message.
1.27 - """
1.28 -
1.29 - # As organiser, send an invitation to attendees, excluding oneself if
1.30 - # also attending. The updated event will be saved by the outgoing
1.31 - # handler.
1.32 -
1.33 - organiser = get_uri(obj.get_value("ORGANIZER"))
1.34 - attendees = uri_values(obj.get_values("ATTENDEE"))
1.35 -
1.36 - if from_organiser:
1.37 - recipients = [get_address(attendee) for attendee in attendees if attendee != self.user]
1.38 - else:
1.39 - recipients = [get_address(organiser)]
1.40 -
1.41 - # Since the outgoing handler updates this user's free/busy details,
1.42 - # the stored details will probably not have the updated details at
1.43 - # this point, so we update our copy for serialisation as the bundled
1.44 - # free/busy object.
1.45 -
1.46 - freebusy = self.store.get_freebusy(self.user)
1.47 - self.update_freebusy(freebusy, self.user, from_organiser)
1.48 -
1.49 - # Bundle free/busy information if appropriate.
1.50 -
1.51 - part = self.get_freebusy_part(freebusy)
1.52 - if part:
1.53 - parts.append(part)
1.54 -
1.55 - if recipients or bcc_sender:
1.56 - self._send_message(sender, recipients, parts, bcc_sender)
1.57 -
1.58 - def _send_message(self, sender, recipients, parts, bcc_sender):
1.59 -
1.60 - """
1.61 - Send a message, explicitly specifying the 'sender' as an outgoing BCC
1.62 - recipient since the generic calendar user will be the actual sender.
1.63 - """
1.64 -
1.65 - if not bcc_sender:
1.66 - message = self.messenger.make_outgoing_message(parts, recipients)
1.67 - self.messenger.sendmail(recipients, message.as_string())
1.68 - else:
1.69 - message = self.messenger.make_outgoing_message(parts, recipients, outgoing_bcc=sender)
1.70 - self.messenger.sendmail(recipients, message.as_string(), outgoing_bcc=sender)
1.71 -
1.72 - def send_message_to_self(self, parts):
1.73 -
1.74 - "Send a message composed of the given 'parts' to the given user."
1.75 -
1.76 - sender = get_address(self.user)
1.77 - message = self.messenger.make_outgoing_message(parts, [sender])
1.78 - self.messenger.sendmail([sender], message.as_string())
1.79 -
1.80 - # Action methods.
1.81 -
1.82 - def process_declined_counter(self, attendee):
1.83 -
1.84 - "Process a declined counter-proposal."
1.85 -
1.86 - # Obtain the counter-proposal for the attendee.
1.87 -
1.88 - obj = self.get_stored_object(self.uid, self.recurrenceid, "counters", attendee)
1.89 - if not obj:
1.90 - return False
1.91 -
1.92 - method = "DECLINECOUNTER"
1.93 - self.update_senders(obj=obj)
1.94 - obj.update_dtstamp()
1.95 - obj.update_sequence(False)
1.96 - self._send_message(get_address(self.user), [get_address(attendee)], [obj.to_part(method)], True)
1.97 - return True
1.98 -
1.99 - def process_received_request(self, changed=False):
1.100 -
1.101 - """
1.102 - Process the current request for the current user. Return whether any
1.103 - action was taken. If 'changed' is set to a true value, or if 'attendees'
1.104 - is specified and differs from the stored attendees, a counter-proposal
1.105 - will be sent instead of a reply.
1.106 - """
1.107 -
1.108 - # Reply only on behalf of this user.
1.109 -
1.110 - attendee_attr = self.update_participation()
1.111 -
1.112 - if not attendee_attr:
1.113 - return False
1.114 -
1.115 - if not changed:
1.116 - self.obj["ATTENDEE"] = [(self.user, attendee_attr)]
1.117 - else:
1.118 - self.update_senders()
1.119 -
1.120 - self.update_dtstamp()
1.121 - self.update_sequence(False)
1.122 - self.send_message([self.obj.to_part(changed and "COUNTER" or "REPLY")], get_address(self.user), self.obj, False, True)
1.123 - return True
1.124 -
1.125 - def process_created_request(self, method, to_cancel=None, to_unschedule=None):
1.126 -
1.127 - """
1.128 - Process the current request, sending a created request of the given
1.129 - 'method' to attendees. Return whether any action was taken.
1.130 -
1.131 - If 'to_cancel' is specified, a list of participants to be sent cancel
1.132 - messages is provided.
1.133 -
1.134 - If 'to_unschedule' is specified, a list of periods to be unscheduled is
1.135 - provided.
1.136 - """
1.137 -
1.138 - # Here, the organiser should be the current user.
1.139 -
1.140 - organiser, organiser_attr = uri_item(self.obj.get_item("ORGANIZER"))
1.141 -
1.142 - self.update_sender(organiser_attr)
1.143 - self.update_senders()
1.144 - self.update_dtstamp()
1.145 - self.update_sequence(True)
1.146 -
1.147 - if method == "REQUEST":
1.148 - methods, parts = self.get_message_parts(self.obj, "REQUEST")
1.149 -
1.150 - # Add message parts with cancelled occurrence information.
1.151 -
1.152 - unscheduled_parts = self.get_unscheduled_parts(to_unschedule)
1.153 -
1.154 - # Send the updated event, along with a cancellation for each of the
1.155 - # unscheduled occurrences.
1.156 -
1.157 - self.send_message(parts + unscheduled_parts, get_address(organiser), self.obj, True, False)
1.158 -
1.159 - # Since the organiser can update the SEQUENCE but this can leave any
1.160 - # mail/calendar client lagging, issue a PUBLISH message to the
1.161 - # user's address.
1.162 -
1.163 - methods, parts = self.get_message_parts(self.obj, "PUBLISH")
1.164 - self.send_message_to_self(parts + unscheduled_parts)
1.165 -
1.166 - # When cancelling, replace the attendees with those for whom the event
1.167 - # is now cancelled.
1.168 -
1.169 - if method == "CANCEL" or to_cancel:
1.170 - if to_cancel:
1.171 - obj = self.obj.copy()
1.172 - obj["ATTENDEE"] = to_cancel
1.173 - else:
1.174 - obj = self.obj
1.175 -
1.176 - # Send a cancellation to all uninvited attendees.
1.177 -
1.178 - parts = [obj.to_part("CANCEL")]
1.179 - self.send_message(parts, get_address(organiser), obj, True, False)
1.180 -
1.181 - # Issue a CANCEL message to the user's address.
1.182 -
1.183 - if method == "CANCEL":
1.184 - self.send_message_to_self(parts)
1.185 -
1.186 - return True
1.187 -
1.188 class FormUtilities:
1.189
1.190 "Utility methods resource mix-in."