diff --git a/TODO b/TODO index 89926a93d5c2855d45991ab6a8e091ad1fc4319b..3274cb0cb1b695f40b04bbbea409d1dace6a3e73 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ DB: - Trigger na "last modified" u meetingů - indexy +- vazby: on delete cascade Hook: - Adjust number of workers diff --git a/hook/fetch-meetings.py b/hook/fetch-meetings.py index fbdf86d5c71ed33a14a73350ede4c444518641d7..f74ab7606d4e60a7d0fff38dcc70b881eb5d810b 100755 --- a/hook/fetch-meetings.py +++ b/hook/fetch-meetings.py @@ -9,9 +9,7 @@ import psycopg2.extras import time import dateutil.parser import sys - -verbose = True -very_verbose = True +import argparse config = configparser.ConfigParser() config.read('zoom.ini') @@ -26,28 +24,18 @@ def parse_time(iso_time): return dateutil.parser.isoparse(iso_time) -def add_recurring(mid, meet): - time.sleep(0.2) - resp = client.meeting.get(host_id = meet['host_id'], id = meet['id']) +def get_meeting(host_id, meeting_id): + resp = client.meeting.get(host_id=host_id, id=meeting_id) resp.raise_for_status() details = json.loads(resp.content) - if very_verbose: + if debug: pprint(details) + return details - for occ in details["occurrences"]: - db.execute(""" - INSERT INTO zoom_schedule - (mid, occurrence_id, start_time, duration) - VALUES (%s, %s, %s, %s) - """, ( - mid, - occ['occurrence_id'], - parse_time(occ['start_time']), - occ['duration'], - )) +def insert_meeting(uid, meet): + meeting_id = meet["id"] -def add_meeting(uid, meet): db.execute(""" INSERT INTO zoom_meetings (meeting_id, uuid, host_uid, topic, type) @@ -63,12 +51,26 @@ def add_meeting(uid, meet): meeting_row = db.fetchone() mid = meeting_row.mid - mtype = meet['type'] - if mtype == 8: - # Recurring meetings: need to ask for the list of occurrences - add_recurring(mid, meet) + print(f"Meeting {meeting_id}: Creating") + + if 'occurrences' in meet: + # Recurrent meetings have a list of occurrences + for occ in meet["occurrences"]: + occ_id = occ['occurrence_id'] + print(f"Meeting {meeting_id}.{occ_id}: Scheduling") + db.execute(""" + INSERT INTO zoom_schedule + (mid, occurrence_id, start_time, duration) + VALUES (%s, %s, %s, %s) + """, ( + mid, + occ_id, + parse_time(occ['start_time']), + occ['duration'], + )) elif 'start_time' in meet: # Other meetings usually have a starting time + print(f"Meeting {meeting_id}: Scheduling") db.execute(""" INSERT INTO zoom_schedule (mid, occurrence_id, start_time, duration) @@ -80,6 +82,18 @@ def add_meeting(uid, meet): meet['duration'], )) + return mid + + +def add_meeting(uid, meet): + mtype = meet['type'] + if mtype == 8: + # Recurring meetings: need to ask for the list of occurrences + time.sleep(0.2) + meet = get_meeting(meet['host_id'], meet['id']) + + insert_meeting(uid, meet) + def get_meetings(uid, user_id): page_id = 1 @@ -88,14 +102,13 @@ def get_meetings(uid, user_id): total_rec = 0 while page_id <= num_pages: - if verbose: - print(f"Fetching meetings for user {user_id}: page {page_id} of {num_pages}") + print(f"Fetching meetings for user {user_id}: page {page_id} of {num_pages}") resp = client.meeting.list(user_id = user_id, type = 'scheduled', page_number = page_id) resp.raise_for_status() meeting_list = json.loads(resp.content) - if very_verbose: + if debug: pprint(meeting_list) num_pages = meeting_list['page_count'] @@ -111,12 +124,56 @@ def get_meetings(uid, user_id): assert total_rec == expected_rec, "Unexpected number of records, probably because of race condition" -db.execute('DELETE FROM zoom_schedule') -db.execute('DELETE FROM zoom_meetings') +def fetch_all(): + db.execute('DELETE FROM zoom_schedule') + db.execute('DELETE FROM zoom_meetings') + + db.execute("SELECT * FROM zoom_users") + users = db.fetchall() + for u in users: + get_meetings(u.uid, u.user_id) -db.execute("SELECT * FROM zoom_users") -users = db.fetchall() -for u in users: - get_meetings(u.uid, u.user_id) + db_conn.commit() -db_conn.commit() + +def fetch_single(user_email, meeting_id): + db.execute("SELECT * FROM zoom_users WHERE email=%s", (user_email,)) + user_row = db.fetchone() + if user_row is None: + print(f"E-mail {user_email} not found", file=sys.stderr) + sys.exit(1) + uid = user_row.uid + + db.execute("SELECT * FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,)) + meeting_row = db.fetchone() + if meeting_row is not None: + assert meeting_row.host_uid == uid, "Mismatched user ID" + print(f"Deleting previous records on meeting {meeting_id}") + db.execute("DELETE FROM zoom_schedule WHERE mid=%s", (meeting_row.mid,)) + db.execute("DELETE FROM zoom_meetings WHERE mid=%s", (meeting_row.mid,)) + + meet = get_meeting(user_row.user_id, meeting_id) + insert_meeting(uid, meet) + + db_conn.commit() + + +argp = argparse.ArgumentParser(description="Fetch meeting data from Zoom API") +argp.add_argument('--all', action='store_const', const=True, default=False, help="re-fetch all meetings") +argp.add_argument('--user', metavar='EMAIL', help='fetch meetings hosted by a given user') +argp.add_argument('--meeting', type=int, metavar='ID', help='fetch a single meeting (requires --user)') +argp.add_argument('--debug', action='store_const', const=True, default=False, help="enable debugging dumps") + +args = argp.parse_args() +debug = args.debug + +if args.all: + fetch_all() +elif args.meeting is not None: + if args.user is None: + argp.error("--meeting requires --user") + fetch_single(args.user, args.meeting) +elif args.user is not None: + raise NotImplementedError +else: + print("Nothing to do.")