From c47a2d1cdb14ec83a29530fd41d85cd7913ec78f Mon Sep 17 00:00:00 2001 From: Martin Mares <mj@ucw.cz> Date: Mon, 23 Mar 2020 22:57:53 +0100 Subject: [PATCH] Hooks: New data model should make everything simpler And as a side effect, correct :) --- hook.wsgi | 273 ++++++++++++++++++++---------------------------------- 1 file changed, 102 insertions(+), 171 deletions(-) diff --git a/hook.wsgi b/hook.wsgi index 6b7d1c7..4c66f0a 100644 --- a/hook.wsgi +++ b/hook.wsgi @@ -40,8 +40,6 @@ def db_query(query, args=()): ### Utilities ### -# FIXME: Move to shared code? - def parse_time(iso_time): return dateutil.parser.isoparse(iso_time) @@ -53,57 +51,32 @@ class HookApp: self.env = env self.wsgi_start = start_response + def log(self, msg): print(msg, file=self.env['wsgi.errors'], flush=True) + def http_error(self, code, msg, extra_headers=[]): self.wsgi_start("{} {}".format(code, msg), extra_headers + [ ('Content-Type', 'text/plain') ]) return ["{} {}".format(code, msg)] - def create_regular_meeting(self, uid, meeting): - meeting_id = meeting["id"] - self.log(f"Meeting {meeting_id}: Planning") + def create_schedule(self, mid, meeting_id, occurrence_id, occ): + self.log("Meeting {meeting_id}.{occurrence_id}: Scheduling") db_query(""" - INSERT INTO zoom_meetings - (meeting_id, uuid, host_id, topic, type, start_time, duration) - VALUES (%s, %s, %s, %s, %s, %s, %s) + INSERT INTO zoom_schedule + (mid, occurrence_id, start_time, duration) + VALUES (%s, %s, %s, %s) """, ( - meeting_id, - meeting['uuid'], - uid, - meeting['topic'], - meeting['type'], - parse_time(meeting['start_time']), - meeting['duration'], + mid, + occurrence_id,, + parse_time(occ['start_time']), + occ['duration'], )) - def create_recurring_meeting(self, uid, meeting): - meeting_id = meeting["id"] - - for occ in meeting["occurrences"]: - occ_id = occ["occurrence_id"] - self.log(f"Meeting {meeting_id}: Planning occurrence {occ_id}") - - 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, - meeting['uuid'], - occ_id, - uid, - meeting['topic'], - meeting['type'], - parse_time(occ['start_time']), - occ['duration'], - )) - - def create_meeting(self, js): payload = js["payload"] meeting = payload["object"] @@ -116,42 +89,39 @@ class HookApp: self.log(f"Meeting {meeting_id}: Host {host_user_id} not found in zoom_users") return - type = meeting["type"] - if type == 2: - self.create_regular_meeting(user.id, meeting) - elif type == 8: - self.create_recurring_meeting(user.id, meeting) - else: - self.log(f"Meeting {meeting_id}: Unknown type {type}") - return - - - def delete_regular_meeting(self, meeting): - meeting_id = meeting["id"] - - self.log(f"Meeting {meeting_id}: Deleting") db_query(""" - DELETE FROM zoom_meetings - WHERE meeting_id=%s + INSERT INTO zoom_meetings + (meeting_id, uuid, host_uid, topic, type) + VALUES (%s, %s, %s, %s, %s) + RETURNING mid """, ( meeting_id, + meeting['uuid'], + user.uid, + meeting['topic'], + meeting['type'], )) + meeting_row = db.fetchone() + mid = meeting_row.mid + mtype = meeting["type"] + self.log(f"Meeting {meeting_id}: Creating with mid={mid}, type={mtype}") + if mtype == 8: + for occ in meeting["occurrences"]: + self.create_schedule(mid, meeting_id, occ["occurrence_id"], meeting) + elif 'start_time' in meeting: + self.create_schedule(mid, meeting_id, 0, meeting) - def delete_recurring_meeting(self, meeting): - meeting_id = meeting["id"] - - if "occurrences" not in meeting: - return self.delete_regular_meeting(meeting) + def delete_recurring_schedule(self, mid, meeting_id, meeting): for occ in meeting["occurrences"]: occ_id = occ["occurrence_id"] - self.log(f"Meeting {meeting_id}: Deleting occurrence {occ_id}") + self.log(f"Meeting {meeting_id}.{occ_id}: Descheduling") db_query(""" - DELETE FROM zoom_meetings - WHERE meeting_id=%s AND occurrence_id=%s + DELETE FROM zoom_schedule + WHERE mid=%s AND occurrence_id=%s """, ( - meeting_id, + mid, occ_id, )) @@ -161,32 +131,27 @@ class HookApp: meeting = payload["object"] meeting_id = meeting["id"] - type = meeting["type"] - if type == 2: - self.delete_regular_meeting(meeting) - elif type == 8: - self.delete_recurring_meeting(meeting) - else: - self.log(f"Meeting {meeting_id}: Unknown type {type}") + db_query("SELECT * FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + meeting_row = db.fetchone() + if meeting_row is None: + self.log(f"Meeting {meeting_id}: Unknown on delete") return + mid = meeting_row.mid + mtype = meeting_row.type - - 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") + if mtype == 8 and "occurrences" in meeting: + delete_recurring_schedule(mid, meeting_id, meeting) + else: + self.log(f"Meeting {meeting_id}: Deleting") + db_query("DELETE FROM zoom_schedule WHERE mid=%s", (mid,)) + db_query("DELETE FROM zoom_meetings WHERE mid=%s", (mid,)) - def update_schedule(self, meeting_id, occurrence_id, new): + def update_schedule(self, mid, 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)) + db_query("UPDATE zoom_schedule SET start_time=%s WHERE mid=%s AND occurrence_id=%s", + (parse_time(new['start_time']), mid, occurrence_id)) if "duration" in new: self.log(f"Meeting {meeting_id}.{occurrence_id}: Updating duration") @@ -194,85 +159,43 @@ class HookApp: (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") + def update_meeting_single(self, mid, meeting_id, old, new): + self.log(f"Meeting {meeting_id}: Updating single occurrences") 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) + self.update_schedule(mid, meeting_id, occ["occurrence_id"], new) # e.g., duration can be set here + self.update_schedule(mid, meeting_id, occ["occurrence_id"], occ) - def update_recurring_meeting_all(self, meeting_id, old, new): - meeting_id = new["id"] + def update_meeting_all(self, mid, meeting_id, old, new): 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,)) + if "occurrences" in new: + # So this will be a recurrent meeting, replace all occurrences + db_query("DELETE FROM zoom_schedule WHERE mid=%s", (mid,)) + for occ in meeting["occurrences"]: + self.create_schedule(mid, meeting_id, occ["occurrence_id"], new) + + elif "start_time" in new: + if new["start_time"] == "": + # Descheduling (this can happen in type 3 meetings) + self.log(f"Meeting {meeting_id}: Descheduling") + db_query("DELETE FROM zoom_schedule WHERE mid=%s", (mid,)) + elif "duration" in new: + # Both start time and duration are set => can safely replacing schedule + self.log(f"Meeting {meeting_id}.0: Replacing schedule") + db_query("DELETE FROM zoom_schedule WHERE mid=%s", (mid,)) + self.create_schedule(mid, meeting_id, 0, new) + else: + # This is just a schedule change + self.log(f"Meeting {meeting_id}.0: Rescheduling with new start_time") + db_query("UPDATE zoom_schedule SET start_time=%s WHERE mid=%s", + (parse_time(new["start_time"]), mid)) - 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'], - )) + elif "duration" in new: + # This is just a schedule change + self.log(f"Meeting {meeting_id}.0: Rescheduling with new duration") + db_query("UPDATE zoom_schedule SET duration=%s WHERE mid=%s", + (new["duration"], mid)) def update_meeting(self, js): @@ -281,24 +204,32 @@ class HookApp: old = payload["old_object"] meeting_id = new["id"] + db_query("SELECT * FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + meeting_row = db.fetchone() + if meeting_row is None: + self.log(f"Meeting {meeting_id}: Unknown on update") + return + mid = meeting_row.mid + + old_type = meeting_row.type 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 + self.log(f"Meeting {meeting_id}: Transmuting from from type {old_type} to {new_type}") + db_query("UPDATE zoom_meetings SET type=%s WHERE mid=%s", (new_type, mid)) + + if "topic" in new: + self.log(f"Meeting {meeting_id}: Updating topic") + db_query("UPDATE zoom_meetings SET topic=%s WHERE mid=%s", (new['topic'], mid)) + + for a in ['uuid', 'host_id']: + if a in new: + self.log(f"Meeting {meeting_id}: Change of {a} not supported") - 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) + scope = payload.get("scope", "all") + if scope == "single": + self.update_meeting_single(mid, meeting_id, old, new) + elif scope == all": + self.update_meeting_all(mid, meeting_id, old, new) else: self.log(f"Meeting {meeting_id}: Unsupported update scope {scope}") -- GitLab