1.1 --- a/imiptools/content.py Sun Oct 26 23:10:12 2014 +0100
1.2 +++ b/imiptools/content.py Sun Oct 26 23:39:11 2014 +0100
1.3 @@ -7,6 +7,7 @@
1.4
1.5 from datetime import date, datetime, timedelta
1.6 from email.mime.text import MIMEText
1.7 +from imiptools.period import have_conflict, insert_period, remove_period
1.8 from pytz import timezone, UnknownTimeZoneError
1.9 from vCalendar import parse, ParseError, to_dict
1.10 from vRecurrence import get_parameters, get_rule
1.11 @@ -155,6 +156,11 @@
1.12
1.13 def get_periods(obj, window_size=100):
1.14
1.15 + """
1.16 + Return periods for the given object 'obj', confining materialised periods
1.17 + to the given 'window_size' in days starting from the present moment.
1.18 + """
1.19 +
1.20 dtstart = get_utc_datetime(obj, "DTSTART")
1.21 dtend = get_utc_datetime(obj, "DTEND")
1.22
1.23 @@ -186,6 +192,35 @@
1.24
1.25 return periods
1.26
1.27 +def update_freebusy(attendee, periods, transp, uid, store):
1.28 +
1.29 + """
1.30 + For the given 'attendee', update the free/busy details with the given
1.31 + 'periods', 'transp' setting and 'uid' in the 'store'. Where no conflict
1.32 + occurs, return the updated free/busy details; otherwise return None.
1.33 + """
1.34 +
1.35 + conflict = False
1.36 + freebusy = store.get_freebusy(attendee) or []
1.37 +
1.38 + if freebusy:
1.39 + remove_period(freebusy, uid)
1.40 + conflict = have_conflict(freebusy, periods)
1.41 +
1.42 + # If the event can be scheduled, it is registered in the free/busy list.
1.43 +
1.44 + if not conflict:
1.45 +
1.46 + for start, end in periods:
1.47 + insert_period(freebusy, (start, end, uid))
1.48 +
1.49 + if transp in (None, "OPAQUE"):
1.50 + store.set_freebusy(attendee, freebusy)
1.51 +
1.52 + return freebusy
1.53 +
1.54 + return None
1.55 +
1.56 # Handler mechanism objects.
1.57
1.58 def handle_itip_part(part, recipients, handlers):
1.59 @@ -325,6 +360,9 @@
1.60 def get_periods(self):
1.61 return get_periods(self.details)
1.62
1.63 + def update_freebusy(self, attendee, periods):
1.64 + return update_freebusy(attendee, periods, self.get_value("TRANSP"), self.uid, self.store)
1.65 +
1.66 def filter_by_recipients(self, values):
1.67 return self.recipients.intersection(map(get_address, values))
1.68
2.1 --- a/imiptools/handlers/resource.py Sun Oct 26 23:10:12 2014 +0100
2.2 +++ b/imiptools/handlers/resource.py Sun Oct 26 23:39:11 2014 +0100
2.3 @@ -5,7 +5,6 @@
2.4 """
2.5
2.6 from imiptools.content import Handler, format_datetime, to_part
2.7 -from imiptools.period import have_conflict, insert_period, remove_period
2.8 from vCalendar import to_node
2.9
2.10 class Event(Handler):
2.11 @@ -75,44 +74,23 @@
2.12 # free/busy record and check for suitability.
2.13
2.14 periods = self.get_periods()
2.15 -
2.16 - conflict = False
2.17 - freebusy = self.store.get_freebusy(attendee) or []
2.18 + freebusy = self.update_freebusy(attendee, periods)
2.19 + scheduled = freebusy is not None
2.20
2.21 - if freebusy:
2.22 - remove_period(freebusy, self.uid)
2.23 - conflict = have_conflict(freebusy, periods)
2.24 + attendee_attr["PARTSTAT"] = scheduled and "ACCEPTED" or "DECLINED"
2.25
2.26 - # If the event can be scheduled, it is registered and a reply sent
2.27 - # accepting the event. (The attendee has PARTSTAT=ACCEPTED as an
2.28 - # attribute.)
2.29 + self.details["ATTENDEE"] = [(attendee, attendee_attr)]
2.30
2.31 - if not conflict:
2.32 - for start, end in periods:
2.33 - insert_period(freebusy, (start, end, self.uid))
2.34 + calendar.append(to_node(
2.35 + {"VEVENT" : [(self.details, {})]}
2.36 + ))
2.37
2.38 - if self.get_value("TRANSP") in (None, "OPAQUE"):
2.39 - self.store.set_freebusy(attendee, freebusy)
2.40 -
2.41 - if self.publisher:
2.42 - self.publisher.set_freebusy(attendee, freebusy)
2.43 -
2.44 + if scheduled:
2.45 self.store.set_event(attendee, self.uid, to_node(
2.46 {"VEVENT" : [(self.details, {})]}
2.47 ))
2.48 - attendee_attr["PARTSTAT"] = "ACCEPTED"
2.49 -
2.50 - # If the event cannot be scheduled, it is not registered and a reply
2.51 - # sent declining the event. (The attendee has PARTSTAT=DECLINED as an
2.52 - # attribute.)
2.53 -
2.54 - else:
2.55 - attendee_attr["PARTSTAT"] = "DECLINED"
2.56 -
2.57 - self.details["ATTENDEE"] = [(attendee, attendee_attr)]
2.58 - calendar.append(to_node(
2.59 - {"VEVENT" : [(self.details, {})]}
2.60 - ))
2.61 + if self.publisher:
2.62 + self.publisher.set_freebusy(attendee, freebusy)
2.63
2.64 return "REPLY", to_part("REPLY", calendar)
2.65