1 #!/usr/bin/env python 2 3 from imiptools.data import get_window_end, Object 4 from imiptools.dates import format_datetime, get_default_timezone 5 from imiptools.profile import Preferences 6 from imip_store import FileStore, FilePublisher 7 import sys 8 9 def get_periods(fb, obj, tzid, window_end, only_organiser): 10 11 # Update free/busy details with the actual periods associated with the event. 12 13 for start, end in obj.get_periods_for_freebusy(tzid, window_end): 14 fb.append((start, end, 15 obj.get_value("UID"), 16 only_organiser and "ORG" or obj.get_value("TRANSP") or "OPAQUE", 17 format_datetime(obj.get_utc_datetime("RECURRENCE-ID")) or "", 18 )) 19 20 # Main program. 21 22 try: 23 user = sys.argv[1] 24 store_and_publish = "-s" in sys.argv[2:] 25 except IndexError: 26 print >>sys.stderr, "Need a user, along with the -s option if updating the store." 27 sys.exit(1) 28 29 preferences = Preferences(user) 30 tzid = preferences.get("TZID") or get_default_timezone() 31 32 # Get the size of the free/busy window. 33 34 try: 35 window_size = int(preferences.get("window_size")) 36 except (TypeError, ValueError): 37 window_size = 100 38 window_end = get_window_end(tzid, window_size) 39 40 store = FileStore() 41 publisher = FilePublisher() 42 43 # Get all identifiers for events. 44 45 uids = store.get_events(user) 46 47 all_events = set() 48 for uid in uids: 49 all_events.add((uid, None)) 50 all_events.update([(uid, recurrenceid) for recurrenceid in store.get_recurrences(user, uid)]) 51 52 # Filter out cancelled events. 53 54 cancelled = store.get_cancellations(user) or [] 55 all_events.difference_update(cancelled) 56 57 # Obtain event objects. 58 59 objs = [] 60 for uid, recurrenceid in all_events: 61 print >>sys.stderr, uid, recurrenceid 62 event = store.get_event(user, uid, recurrenceid) 63 if event: 64 objs.append(Object(event)) 65 66 # Build a free/busy collection for the given user. 67 68 fb = [] 69 for obj in objs: 70 attendees = obj.get_value_map("ATTENDEE") 71 organiser = obj.get_value("ORGANIZER") 72 73 for attendee, attendee_attr in attendees.items(): 74 75 # Only consider events where this user actually attends. 76 77 if attendee == user: 78 if attendee_attr.get("PARTSTAT", "NEEDS-ACTION") not in ("DECLINED", "DELEGATED", "NEEDS-ACTION"): 79 get_periods(fb, obj, tzid, window_end, False) 80 break 81 82 # Where not attending, retain the affected periods and mark them as 83 # organising periods. 84 85 else: 86 if organiser == user: 87 get_periods(fb, obj, tzid, window_end, True) 88 89 fb.sort() 90 91 # Store and publish the free/busy collection. 92 93 if store_and_publish: 94 store.set_freebusy(user, fb) 95 publisher.set_freebusy(user, fb) 96 else: 97 for item in fb: 98 print "\t".join(item) 99 100 # vim: tabstop=4 expandtab shiftwidth=4