chiark / gitweb /
Handle modified / deleted recurrences
[gooswapper] / gooswapper.py
index e18da2f470c0d569ee7426aa6f1fc077c8b82746..f54038cc1e2efa526a7ac31ff134738e4c781456 100644 (file)
@@ -74,6 +74,17 @@ def get_ex_event_by_id_and_changekey(acct,itemid,changekey):
     l=list(acct.fetch([(itemid,changekey)]))
     return list(acct.fetch([(itemid,changekey)]))[0]
 
+def get_gcal_recur_instance(gcal_acct,gcal_master,start,gcal_id="primary"):
+    ans = gcal_acct.events().instances(calendarId=gcal_id,
+                                       eventId=gcal_master,
+                                       originalStart=start.isoformat(),
+                                       showDeleted=True).execute()
+    if len(ans['items']) != 1:
+        logger.error("Searching for recurrance instance returned %d events" % \
+                     len(ans['items']))
+        return None
+    return ans['items'][0]
+
 def get_ex_cred(username="SANGER\mv3",password=None):
     if password is None:
         password = getpass.getpass(prompt="Password for user %s: " % username)
@@ -172,6 +183,41 @@ def rrule_from_ex(event,gcal_tz):
         logger.warning("Modified/Deleted recurrences not supported")
     return [rr]
 
+def modify_recurring(ex_acct,gcal_acct,gcal_tz,
+                     events,master,gcal_id="primary"):
+    if master.modified_occurrences is not None:
+        for mod in master.modified_occurrences:
+            instance = get_gcal_recur_instance(gcal_acct,master.gcal_link,
+                                               mod.original_start,gcal_id)
+            if instance is None: #give up after first failure
+                return events
+            mod_event = get_ex_event_by_itemid(ex_acct.calendar,mod.item_id)
+            gevent = build_gcal_event_from_ex(mod_event,gcal_tz)
+            gevent = gcal_acct.events().update(calendarId=gcal_id,
+                                               eventId=instance.get('id'),
+                                               body=gevent,
+                                               sendUpdates="none").execute()
+            mod_event.gcal_link = gevent.get("id")
+            mod_event.save(update_fields=["gcal_link"])
+            if mod_event.item_id in events:
+                events[mod_event.item_id] = events[mod_event.item_id]._replace(changekey=mod_event.changekey,gcal_link=mod_event.gcal_link)
+            else:
+                events[mod_event.item_id] = CachedExEvent(mod_event.changekey,
+                                                      mod_event.gcal_link)
+    if master.deleted_occurrences is not None:
+        for d in master.deleted_occurrences:
+            instance = get_gcal_recur_instance(gcal_acct,master.gcal_link,
+                                               d.start,gcal_id)
+            if instance is None: #give up after any failure
+                return events
+            if instance["status"] != "cancelled":
+                instance["status"]="cancelled"
+                gcal_acct.events().update(calendarId=gcal_id,
+                                          eventId=instance.get('id'),
+                                          body=instance,
+                                          sendUpdates="none").execute()
+    return events
+
 def build_gcal_event_from_ex(event,gcal_tz):
     gevent={}
     gevent["summary"]=event.subject
@@ -210,7 +256,11 @@ def add_ex_to_gcal(ex_acct,
         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):
+            events = modify_recurring(ex_acct,gcal_acct,gcal_tz,
+                                      events,event,gcal_id)
+        
 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: