l=list(acct.fetch([(itemid,changekey)]))
return list(acct.fetch([(itemid,changekey)]))[0]
+def get_gcal_event_by_eventid(gcal_acct,eventId,gcal_id="primary"):
+ return gcal_acct.events().get(calendarId=gcal_id,eventId=eventId).execute()
+
def get_gcal_recur_instance(gcal_acct,gcal_master,start,gcal_id="primary"):
ans = gcal_acct.events().instances(calendarId=gcal_id,
eventId=gcal_master,
def rr_daystr_from_int(i):
return exchangelib.recurrence._weekday_to_str(i).upper()[:2]
+#for monthly patterns, we want the week (or -1 for last) combined with each
+#day specified
+def rr_daystr_monthly(p):
+ if p.week_number == 5:
+ wn = "-1"
+ else:
+ wn = str(p.week_number)
+ return ",".join([wn + rr_daystr_from_int(x) for x in p.weekdays])
+
def rrule_from_ex(event,gcal_tz):
if event.type != "RecurringMaster":
logger.error("Cannot make recurrence from not-recurring event")
(event.recurrence.pattern.interval,
",".join([rr_daystr_from_int(x) for x in event.recurrence.pattern.weekdays]),
rr_daystr_from_int(event.recurrence.pattern.first_day_of_week) )
+ elif isinstance(event.recurrence.pattern,
+ exchangelib.recurrence.RelativeMonthlyPattern):
+ rr = "RRULE:FREQ=MONTHLY;INTERVAL=%d;BYDAY=%s" % \
+ (event.recurrence.pattern.interval,
+ rr_daystr_monthly(event.recurrence.pattern))
+ elif isinstance(event.recurrence.pattern,
+ exchangelib.recurrence.AbsoluteMonthlyPattern):
+ rr = "RRULE:FREQ=MONTHLY;INTERVAL=%d;BYMONTHDAY=%d" % \
+ (event.recurrence.pattern.interval,
+ event.recurrence.pattern.day_of_month)
+ elif isinstance(event.recurrence.pattern,
+ exchangelib.recurrence.AbsoluteYearlyPattern):
+ rr = "RRULE:FREQ=YEARLY;BYMONTH=%d;BYMONTHDAY=%d" % \
+ (event.recurrence.pattern.month,
+ event.recurrence.pattern.day_of_month)
+ elif isinstance(event.recurrence.pattern,
+ exchangelib.recurrence.RelativeYearlyPattern):
+ rr = "RRULE:FREQ=YEARLY;BYMONTH=%d;BYDAY=%s" % \
+ (event.recurrence.pattern.month,
+ rr_daystr_monthly(event.recurrence.pattern))
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)
+ elif isinstance(event.recurrence.boundary,
+ exchangelib.recurrence.NoEndPattern):
+ pass #no end date to set
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 modify_recurring(ex_acct,gcal_acct,gcal_tz,
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)
if event.type=="RecurringMaster" and (event.deleted_occurrences or \
event.modified_occurrences):
modify_recurring(ex_acct,gcal_acct,gcal_tz,
events,event,gcal_id)
+ #changekey is updated by the above
+ event.refresh()
+ 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:
if events[ev_id].gcal_link is not None:
- gcal_acct.events().delete(calendarId=gcal_id,
- eventId=events[ev_id].gcal_link,
- sendUpdates="none").execute()
+ gevent = get_gcal_event_by_eventid(gcal_acct,
+ events[ev_id].gcal_link,
+ gcal_id)
+ if gevent["status"] != "cancelled":
+ gcal_acct.events().delete(calendarId=gcal_id,
+ eventId=events[ev_id].gcal_link,
+ sendUpdates="none").execute()
def update_ex_to_gcal(ex_acct,
gcal_acct,gcal_tz,
gcal_id="primary"):
for ev_id in changed:
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().update(calendarId=gcal_id,
+ 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
+ if event.deleted_occurrences or \
+ event.modified_occurrences:
+ modify_recurring(ex_acct,gcal_acct,gcal_tz,
+ events,event,gcal_id)
+ event.refresh() #changekey is updated by the above
+ events[event.item_id] = events[event.item_id]._replace(changekey=event.changekey,gcal_link=event.gcal_link)
+ else:
+ logger.warning("Unable to set recurrence for %s" % event.item_id)
+ continue #don't make the gcal event
+ gevent = gcal_acct.events().update(calendarId=gcal_id,
eventId=event.gcal_link,
body=gevent,
sendUpdates="none").execute()
- else:
- logger.warning("recurring events not yet supported")
def match_ex_to_gcal(ex_acct,gcal_acct,gcal_tz,events,gcal_id="primary"):
recur = 0