-
Notifications
You must be signed in to change notification settings - Fork 1
Automatically scheduling zoom talks and sending keys #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
59db27a
New workflow triggered using repository_dispatch
everthemore c11f047
Update schedule_zoom_talks.yml
everthemore d260eca
Create zoom_scheduling_bot_requirements.txt
everthemore 22eef8a
Create schedulezoomtalks.py
everthemore ae82381
WIP
everthemore 2d33d76
Merge branch 'master' into schedule-zoom-talks-bot
everthemore 2dea154
WIP
everthemore 22625c6
Implement round of comments; password action missing
everthemore b826336
Update req's, rename function for clarity, attempt to add registratio…
everthemore 86ff429
Remove incorrect '-'
everthemore b5b7504
More suggestions implemented
everthemore cfd0443
Fix link
everthemore 2434663
Use PATCH for questions
everthemore 1a2683e
Update requirements.txt
everthemore 827364a
Delete redundant requirements.txt
everthemore b4255a7
Switch to test branch
everthemore f84c120
Speaker registration
everthemore 313dfb6
Remove live link
everthemore 0723abd
Issue response
everthemore e39fc28
Tweaks
everthemore ee6c61d
Email WIP
everthemore ee9e924
Email v1
everthemore 1ae7003
Add date and time to email
everthemore de39fb8
Add zoom link
everthemore 49129d6
Add mailgun key
everthemore 0d7ac9f
bugfixes
akhmerov fec3226
Turn off submission to researchseminars.org
everthemore File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| name: Schedule Zoom Talks | ||
| on: | ||
| repository_dispatch: | ||
| types: [schedule-zoom-talk] | ||
|
|
||
| jobs: | ||
| scheduleTalks: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout code | ||
| - uses: actions/checkout@v2 | ||
|
|
||
| - name: Set up Python 3.8 | ||
| uses: actions/setup-python@v2 | ||
| with: | ||
| python-version: 3.8 | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| if [ -f bots/zoom_scheduling_bot_requirements.txt ]; then pip install -r bots/zoom_scheduling_bot_requirements.txt; fi | ||
|
|
||
| - name: Schedule talks | ||
| working-directory: ./bots | ||
| run: python3 schedulezoomtalks.py | ||
| env: | ||
| VSF_BOT_TOKEN: ${{ secrets.VSF_BOT_TOKEN }} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| import os | ||
| from requests import get, post | ||
|
|
||
| SPEAKERS_CORNER_SEMINAR_SERIES = {"series_id": "speakerscorner", | ||
| "name": "Speakers\' Corner", | ||
| "is_conference": False, | ||
| "topics": [""], # TODO: Get a list of topics | ||
| "language": "en", | ||
| "institutions": ["Global"], | ||
| "timezone": "America/New_York", | ||
| "homepage": "https://virtualscienceforum.org/speakerscorner.md", | ||
| "visibility": 1, # 0=private, 1=unlisted, 2=public | ||
| "access_control": 0, # 0=open, see schema for more | ||
| "slots": [""], | ||
| "organizers": [{"name": "Virtual Science Forum", | ||
everthemore marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "email": "vsf@virtualscienceforum.org", | ||
| "homepage": "https://virtualscienceforum.org", | ||
| "organizer": True, | ||
| "order": 0, | ||
| "display": True}]} | ||
|
|
||
| def find_seminar_series(series_id): | ||
| url = "https://researchseminars.org/api/0/search/series?series_id=%s"%series_id | ||
| r = get(url) | ||
| if r.status_code == 200: | ||
| J = r.json() | ||
| results = J["properties"]["results"] | ||
| return (len(results) != 0) | ||
|
|
||
| def create_seminar_series(payload, authorization): | ||
| url = "https://researchseminars.org/api/0/save/series/" | ||
| r = post(url, json=payload, headers={"authorization":authorization}) | ||
| J = r.json() | ||
| code = J.get("code") | ||
|
|
||
| if r.status_code == 200: | ||
| if code == "warning": | ||
| return True, J["warnings"] | ||
| else: | ||
| return True, "" | ||
| else: | ||
| return False, "" | ||
|
|
||
| def edit_seminar_series(name, payload, authorization): | ||
| url = "https://researchseminars.org/api/0/save/series/" | ||
| r = post(url, json=payload, headers={"authorization":authorization}) | ||
| J = r.json() | ||
| code = J.get("code") | ||
|
|
||
| if r.status_code == 200: | ||
| if code == "warning": | ||
| return True, J["warnings"] | ||
| else: | ||
| return True, "" | ||
| else: | ||
| return False, "" | ||
|
|
||
| def add_talk_to_series(series_id, payload, authorization): | ||
| url = "https://researchseminars.org/api/0/save/talk/" | ||
| r = post(url, json=payload, headers={"authorization":authorization}) | ||
| J = r.json() | ||
| code = J.get("code") | ||
| if r.status_code == 200: | ||
| if code == "warning": | ||
| return J["series_ctr"], J["warnings"] | ||
| else: | ||
| return J["series_ctr"] | ||
| else: | ||
| return "", r.status_code | ||
|
|
||
| def add_talk_to_speakerscorner(talk): | ||
| # talk should be provided in yaml format | ||
| api_token = os.getenv("RESEARCHSEMINARS_API_TOKEN") | ||
| authorization = "vsf@virtualscienceforum.org %s" % api_token | ||
|
|
||
| # Find speakers' corner series, and create it if it doesn't exist | ||
| if( !find_seminar_series("speakerscorner") ): | ||
| create_seminar_series(SPEAKERS_CORNER_SEMINAR_SERIES) | ||
|
|
||
| # TODO: Figure out if we need to edit the series; | ||
| # Would be annoying since edits have to be approved | ||
|
|
||
| # Set up payload for talk creation | ||
| talk_payload = {"title":talk.get('title'), | ||
| "speaker":talk.get('author'), # TODO: will be 'speakerS' | ||
| "live_link":"zoom.us/%s"%talk.get('zoom_meeting_id'), | ||
| "online":1, | ||
| "start_time":talk.get("time"), | ||
| "timezone":"UTC" # TODO | ||
| } | ||
|
|
||
| # Make request to remote API | ||
| series_ctr, warnings = add_talk_to_series("speakerscorner", talk_payload, authorization) | ||
|
|
||
| if series_ctr != "": | ||
| print("Talk with id {0} successfully added".format(series_ctr)) | ||
| if warnings != "": | ||
| print("Warnings: {0}".format(warnings)) | ||
| return True | ||
| else: | ||
| print("-- ERROR -- ") | ||
| print("Could not add talk to series, status code {0}".format(warnings)) | ||
| return False | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| import os | ||
| import github | ||
| import requests | ||
| from researchseminarsdotorg import * | ||
| from requests import get, post, put | ||
| from io import StringIO | ||
| from ruamel.yaml import YAML | ||
| from common import * | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| TALKS_FILE = "speakers_corner_talks.yml" | ||
|
|
||
| def schedule_zoom_talk(talk) -> string: | ||
|
|
||
| # Form the talk registration body | ||
| request_body = | ||
| { | ||
| "topic": "Speakers\' corner talk by %s"%(talk.get("name")), | ||
| "type": 2, # Scheduled meeting | ||
| "start_time": talk.get("time"), #2020-03-31T17:00:00 | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "timezone": "UTC", | ||
| "duration": 60, # 90 minutes | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "schedule_for": "vsf@virtualscienceforum.org", # Zoom user ID or Zoom email address | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "agenda":talk.get("title"), | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "password": "", | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # Meeting settings | ||
| "settings": { | ||
| "host_video": True, | ||
| "participant_video": True, | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "cn_meeting": False, # Host the meeting in China? | ||
| "in_meeting": False, # Host the meeting in India? | ||
| "join_before_host": False, | ||
everthemore marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "mute_upon_entry": True, | ||
| "watermark": False, # Add a watermark when screensharing? | ||
| "use_pmi": False, # Don't use the Personal Meeting ID, but generate one | ||
| "approval_type": 0, # Automatically approve | ||
| "audio": "both", | ||
| "auto_recording": "cloud", | ||
| "enforce_login": False, | ||
| "alternative_hosts": "", | ||
everthemore marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "registrants_email_notification": True, | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "contact_email": "vsf@virtualscienceforum.org", | ||
| } | ||
akhmerov marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| response = zoom_request( | ||
| requests.post, | ||
| f"{ZOOM_API}users/{user_id}/meetings", | ||
| params={"body":request_body} | ||
| ) | ||
|
|
||
| return response.id | ||
|
|
||
| def parse_talks(talks) -> int: | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| num_updated = 0 | ||
| for talk in talks: | ||
| if( talk.get('zoom_link', "") == "" && talk.get('event_type') == "speakers_corner" ): | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # Schedule the talk | ||
| meeting_id = schedule_zoom_talk(talk) | ||
| # Update the talk | ||
| talk.get("zoom_meeting_id") = meeting_id | ||
| num_updated += 1 | ||
|
|
||
| # Add this talk to researchseminars.org | ||
| add_talk_to_speakerscorner(talk) | ||
|
|
||
| return num_updated | ||
|
|
||
| if __name__ == "__main__": | ||
| # Get a handle on the repository | ||
| gh = github.Github(os.getenv("VSF_BOT_TOKEN")) | ||
| repo = gh.get_repo("virtualscienceforum/virtualscienceforum") | ||
|
|
||
| # Read the talks file | ||
| yaml = YAML() | ||
| try: | ||
| talks_data = repo.get_contents(TALKS_FILE, ref="master") | ||
| talks = yaml.load(StringIO(talks_data.decoded_content.decode())) | ||
| except github.UnknownObjectException: | ||
| talks_data = None | ||
| talks = [] | ||
|
|
||
| # If there are talks to be parsed... | ||
| if len(talks) != 0: | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # ... parse them and keep track of how many we updated | ||
| num_updated = parse_talks(talks) | ||
|
|
||
| # If we added Zoom links, we should update the file in the repo | ||
| if num_updated != 0: | ||
everthemore marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| serialized = StringIO() | ||
| yaml.dump(talks, serialized) | ||
|
|
||
| repo.update_file( | ||
| TALKS_FILE, f"Added Zoom link{1} for {0} scheduled speakers\'"\ | ||
| "corner talk{1}".format(num_updated,'' if num_updated == 1 else 's'), | ||
| serialized.getvalue(), | ||
| sha=talks_data.sha, | ||
| branch='master' | ||
| ) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.