diff --git a/hook.wsgi b/hook.wsgi index 320af2d18f0ca6e88f88b2202e8d39abd8653b1f..61a11404af8187c54356850a70c5ee8fb1920dcc 100644 --- a/hook.wsgi +++ b/hook.wsgi @@ -7,7 +7,6 @@ import psycopg2 import psycopg2.extras import traceback import dateutil.parser -# import dateutil.tz ### Configuration ### @@ -43,11 +42,8 @@ def db_query(query, args=()): # FIXME: Move to shared code? -def parse_time(iso_time, tz_name): - utc = dateutil.parser.isoparse(iso_time) - # tz = dateutil.tz.gettz(tz_name) - # return utc.astimezone(tz) - return utc +def parse_time(iso_time): + return dateutil.parser.isoparse(iso_time) ### Application ### @@ -80,12 +76,10 @@ class HookApp: uid, meeting['topic'], meeting['type'], - parse_time(meeting['start_time'], meeting['timezone']), + parse_time(meeting['start_time']), meeting['duration'], )) - db_connection.commit() - def create_recurring_meeting(self, uid, meeting): meeting_id = meeting["id"] @@ -105,12 +99,10 @@ class HookApp: uid, meeting['topic'], meeting['type'], - parse_time(occ['start_time'], meeting['timezone']), + parse_time(occ['start_time']), occ['duration'], )) - db_connection.commit() - def create_meeting(self, js): payload = js["payload"] @@ -145,8 +137,6 @@ class HookApp: meeting_id, )) - db_connection.commit() - def delete_recurring_meeting(self, meeting): meeting_id = meeting["id"] @@ -165,8 +155,6 @@ class HookApp: occ_id, )) - db_connection.commit() - def delete_meeting(self, js): payload = js["payload"] @@ -183,6 +171,138 @@ class HookApp: return + def update_common_attrs(self, meeting_id, occurrence_id, new): + if "topic" in new: + self.log(f"Meeting {meeting_id}.{occurrence_id}: Updating topic") + db_query("UPDATE zoom_meetings SET topic=%s WHERE meeting_id=%s AND (occurrence_id=%s OR %s = '0')", + (new["topic"], meeting_id, occurrence_id, occurrence_id)) + + for a in ['uuid', 'host_id']: + if a in new: + self.log(f"Meeting {meeting_id}.{occurrence_id}: Change of {a} not supported") + + + def update_schedule(self, meeting_id, occurrence_id, new): + if "start_time" in new: + self.log(f"Meeting {meeting_id}.{occurrence_id}: Updating start time") + db_query("UPDATE zoom_meetings SET start_time=%s WHERE meeting_id=%s AND (occurrence_id=%s OR %s = '0')", + (parse_time(new['start_time']), meeting_id, occurrence_id, occurrence_id)) + + if "duration" in new: + self.log(f"Meeting {meeting_id}.{occurrence_id}: Updating duration") + db_query("UPDATE zoom_meetings SET duration=%s WHERE meeting_id=%s AND (occurrence_id=%s OR %s = '0')", + (new['duration'], meeting_id, occurrence_id, occurrence_id)) + + + def update_regular_meeting(self, meeting_id, old, new): + self.log(f"Meeting {meeting_id}: Updating regular meeting") + self.update_common_attrs(meeting_id, 0, new) + self.update_schedule(meeting_id, 0, new) + + + def update_recurring_meeting_single(self, meeting_id, old, new): + self.log(f"Meeting {meeting_id}: Updating single occurrence") + for occ in new["occurrences"]: + self.update_common_attrs(meeting_id, occ["occurrence_id"], new) + self.update_schedule(meeting_id, occ["occurrence_id"], new) # e.g., duration can be set here + self.update_schedule(meeting_id, occ["occurrence_id"], occ) + + + def update_recurring_meeting_all(self, meeting_id, old, new): + meeting_id = new["id"] + self.log(f"Meeting {meeting_id}: Updating all occurrences") + + if "occurrences" not in new: + self.update_common_attrs(meeting_id, 0, new) + return + + db_query("SELECT * FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + orig = db.fetchone() + if orig is None: + self.log(f"Meeting {meeting_id}: Update did not find previous version") + return + + db_query("DELETE FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + + for occ in new["occurrences"]: + occurrence_id = occ["occurrence_id"] + self.log(f"Meeting {meeting_id}.{occurrence_id}: Re-creating") + + db_query(""" + INSERT INTO zoom_meetings + (meeting_id, uuid, occurrence_id, host_id, topic, type, start_time, duration) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s) + """, ( + meeting_id, + new.get('uuid', orig.uuid), + occurrence_id, + orig.host_id, + new.get('topic', orig.topic), + new.get('type', orig.type), + parse_time(occ['start_time']), + occ['duration'], + )) + + + def update_regular_to_recurring(self, meeting_id, old, new): + self.log(f"Meeting {meeting_id}: Type change to recurring") + self.update_recurring_meeting_all(meeting_id, old, new) + + + def update_recurring_to_regular(self, meeting_id, old, new): + self.log(f"Meeting {meeting_id}: Type change to regular") + + db_query("SELECT * FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + orig = db.fetchone() + if orig is None: + self.log(f"Meeting {meeting_id}: Update did not find previous version") + return + + db_query("DELETE FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + + db_query(""" + INSERT INTO zoom_meetings + (meeting_id, uuid, host_id, topic, type, start_time, duration) + VALUES (%s, %s, %s, %s, %s, %s, %s) + """, ( + meeting_id, + new.get('uuid', orig.uuid), + orig.host_id, + new.get('topic', orig.topic), + new['type'], + parse_time(new['start_time']), + new['duration'], + )) + + + def update_meeting(self, js): + payload = js["payload"] + new = payload["object"] + old = payload["old_object"] + meeting_id = new["id"] + + new_type = new.get("type", -1) + old_type = old.get("type", -1) + if old_type != new_type: + if old_type == 2 and new_type == 8: + self.update_regular_to_recurring(meeting_id, old, new) + elif old_type == 8 and new_type == 2: + self.update_recurring_to_regular(meeting_id, old, new) + else: + self.log(f"Meeting {meeting_id}: Unsupported type change from {old_type} to {new_type}") + return + + scope = payload.get("scope", "") + if scope == "": + self.update_regular_meeting(meeting_id, old, new) + elif scope == "all": + self.update_recurring_meeting_all(meeting_id, old, new) + elif scope == "single": + self.update_recurring_meeting_single(meeting_id, old, new) + else: + self.log(f"Meeting {meeting_id}: Unsupported update scope {scope}") + + def run(self): method = self.env['REQUEST_METHOD'] if method != 'POST': @@ -201,12 +321,17 @@ class HookApp: self.create_meeting(js) elif event == "meeting.deleted": self.delete_meeting(js) + elif event == "meeting.updated": + self.update_meeting(js) else: self.log(f"Unknown event: {event}") + db_connection.commit() + self.wsgi_start("204 No Content", []) return b"" + def application(env, start_response): app = HookApp(env, start_response) try: