1.1 --- a/imiptools/client.py Sun Jul 26 01:48:20 2015 +0200
1.2 +++ b/imiptools/client.py Sun Jul 26 01:59:34 2015 +0200
1.3 @@ -20,11 +20,14 @@
1.4 """
1.5
1.6 from datetime import datetime
1.7 -from imiptools.data import get_address, get_uri, get_window_end, uri_dict, uri_items, uri_values
1.8 +from imiptools.data import get_address, get_uri, get_window_end, \
1.9 + make_freebusy, to_part, \
1.10 + uri_dict, uri_items, uri_values
1.11 +from imiptools.dates import format_datetime, get_default_timezone, \
1.12 + get_timestamp, to_timezone
1.13 from imiptools.period import update_freebusy
1.14 from imiptools.profile import Preferences
1.15 -from imiptools.dates import format_datetime, get_default_timezone, \
1.16 - to_timezone
1.17 +import imip_store
1.18
1.19 def update_attendees(obj, attendees, removed):
1.20
1.21 @@ -75,9 +78,16 @@
1.22
1.23 default_window_size = 100
1.24
1.25 - def __init__(self, user, messenger=None):
1.26 + def __init__(self, user, messenger=None, store=None, publisher=None):
1.27 self.user = user
1.28 self.messenger = messenger
1.29 + self.store = store or imip_store.FileStore()
1.30 +
1.31 + try:
1.32 + self.publisher = publisher or imip_store.FilePublisher()
1.33 + except OSError:
1.34 + self.publisher = None
1.35 +
1.36 self.preferences = None
1.37
1.38 def get_preferences(self):
1.39 @@ -113,6 +123,12 @@
1.40
1.41 # Common operations on calendar data.
1.42
1.43 + def is_participating(self, attr, as_organiser=False):
1.44 + return as_organiser or not attr or attr.get("PARTSTAT") != "DECLINED"
1.45 +
1.46 + def get_overriding_transparency(self, attr, as_organiser=False):
1.47 + return as_organiser and not (attr and attr.get("PARTSTAT")) and "ORG" or None
1.48 +
1.49 def update_participation(self, obj, partstat=None):
1.50
1.51 """
1.52 @@ -136,12 +152,35 @@
1.53 if self.messenger and self.messenger.sender != get_address(self.user):
1.54 attr["SENT-BY"] = get_uri(self.messenger.sender)
1.55
1.56 + # Free/busy operations.
1.57 +
1.58 + def get_freebusy_part(self):
1.59 +
1.60 + """
1.61 + Return a message part containing free/busy information for the user.
1.62 + """
1.63 +
1.64 + if self.is_sharing() and self.is_bundling():
1.65 +
1.66 + # Invent a unique identifier.
1.67 +
1.68 + utcnow = get_timestamp()
1.69 + uid = "imip-agent-%s-%s" % (utcnow, get_address(self.user))
1.70 +
1.71 + freebusy = self.store.get_freebusy(self.user)
1.72 +
1.73 + user_attr = {}
1.74 + self.update_sender(user_attr)
1.75 + return to_part("PUBLISH", [make_freebusy(freebusy, uid, self.user, user_attr)])
1.76 +
1.77 + return None
1.78 +
1.79 class ClientForObject(Client):
1.80
1.81 "A client maintaining a specific object."
1.82
1.83 - def __init__(self, obj, user, messenger=None):
1.84 - Client.__init__(self, user, messenger)
1.85 + def __init__(self, obj, user, messenger=None, store=None, publisher=None):
1.86 + Client.__init__(self, user, messenger, store, publisher)
1.87 self.set_object(obj)
1.88
1.89 def set_object(self, obj):
1.90 @@ -190,11 +229,7 @@
1.91 else:
1.92 self.remove_from_freebusy(freebusy)
1.93
1.94 - def is_participating(self, attr, as_organiser=False):
1.95 - return as_organiser or not attr or attr.get("PARTSTAT") != "DECLINED"
1.96 -
1.97 - def get_overriding_transparency(self, attr, as_organiser=False):
1.98 - return as_organiser and not (attr and attr.get("PARTSTAT")) and "ORG" or None
1.99 + # Object update methods.
1.100
1.101 def update_dtstamp(self):
1.102