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