X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~matthewv/git?a=blobdiff_plain;f=gooswapper.py;h=75edd3febb2c54bcd77979cfadd513b4268f169e;hb=3ab26f0d9fff9530325a1c227f4f2e8da81b6f58;hp=6e1598bbe43dd159b63c79ef52645a5480fc17a4;hpb=e3511d9d24ca9adabf88d0afeccc642df9d67988;p=gooswapper diff --git a/gooswapper.py b/gooswapper.py index 6e1598b..75edd3f 100644 --- a/gooswapper.py +++ b/gooswapper.py @@ -54,7 +54,18 @@ class ex_gcal_link(exchangelib.ExtendedProperty): property_name = "google calendar event id" property_type = 'String' -exchangelib.CalendarItem.register('gcal_link',ex_gcal_link) +try: + exchangelib.CalendarItem.get_field_by_fieldname('gcal_link') +except ValueError: + exchangelib.CalendarItem.register('gcal_link',ex_gcal_link) + +#useful if you want to replay an event +def drop_from_ex_cache(itemid): + with open(cachepath,"rb") as f: + cache = pickle.load(f) + cache.pop(itemid) + with open(cachepath,"wb") as f: + pickle.dump(cache,f) def get_ex_event_by_itemid(calendar,itemid): return calendar.get(item_id=itemid) @@ -125,6 +136,30 @@ def ex_event_changes(old,new): len(deleted))) return added, deleted, changed +def rrule_from_ex(event,gcal_tz): + if event.type != "RecurringMaster": + logger.error("Cannot make recurrence from not-recurring event") + return None + if event.recurrence is None: + logger.error("Empty recurrence structure") + return None + if isinstance(event.recurrence.pattern, + exchangelib.recurrence.DailyPattern): + rr = "RRULE:FREQ=DAILY;INTERVAL=%d" % event.recurrence.pattern.interval + else: + logger.error("Recurrence %s not supported" % event.recurrence) + return None + if isinstance(event.recurrence.boundary, + exchangelib.recurrence.EndDatePattern): + rr += ";UNTIL={0:%Y}{0:%m}{0:%d}".format(event.recurrence.boundary.end) + else: + logger.error("Recurrence %s not supported" % event.recurrence) + return None + if event.modified_occurrences is not None or \ + event.deleted_occurrences is not None: + logger.warning("Modified/Deleted recurrences not supported") + return [rr] + def build_gcal_event_from_ex(event,gcal_tz): gevent={} gevent["summary"]=event.subject @@ -132,10 +167,10 @@ def build_gcal_event_from_ex(event,gcal_tz): gevent["end"]={"date": str(event.end.astimezone(gcal_tz).date())} gevent["start"]={"date": str(event.start.astimezone(gcal_tz).date())} else: - gevent["end"]={"dateTime": event.end.isoformat(), - "timeZone": event.end.tzname()} - gevent["start"]={"dateTime": event.start.isoformat(), - "timeZone": event.start.tzname()} + gevent["end"]={"dateTime": event.end.astimezone(gcal_tz).isoformat(), + "timeZone": str(gcal_tz)} + gevent["start"]={"dateTime": event.start.astimezone(gcal_tz).isoformat(), + "timeZone": str(gcal_tz)} if event.text_body is not None and event.text_body.strip() != '': gevent["description"] = event.text_body if event.location is not None: @@ -149,15 +184,20 @@ def add_ex_to_gcal(ex_acct, gcal_id="primary"): for ev_id in added: event = get_ex_event_by_itemid(ex_acct.calendar,ev_id) - if not event.is_recurring: - gevent = build_gcal_event_from_ex(event,gcal_tz) - gevent = gcal_acct.events().insert(calendarId=gcal_id, - body=gevent).execute() - event.gcal_link = gevent.get("id") - event.save(update_fields=["gcal_link"]) - events[event.item_id] = events[event.item_id]._replace(changekey=event.changekey,gcal_link=event.gcal_link) - else: - logger.warning("recurring events not yet supported") + gevent = build_gcal_event_from_ex(event,gcal_tz) + if event.type=="RecurringMaster": + rr = rrule_from_ex(event,gcal_tz) + if rr is not None: + gevent["recurrence"] = rr + print(gevent) + else: + logger.warning("Unable to set recurrence for %s" % event.item_id) + continue #don't make the gcal event + gevent = gcal_acct.events().insert(calendarId=gcal_id, + body=gevent).execute() + event.gcal_link = gevent.get("id") + event.save(update_fields=["gcal_link"]) + events[event.item_id] = events[event.item_id]._replace(changekey=event.changekey,gcal_link=event.gcal_link) def del_ex_to_gcal(ex_acct, gcal_acct, events, deleted, gcal_id="primary"): for ev_id in deleted: