Skip to content
Merged
Show file tree
Hide file tree
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 Sep 30, 2020
c11f047
Update schedule_zoom_talks.yml
everthemore Sep 30, 2020
d260eca
Create zoom_scheduling_bot_requirements.txt
everthemore Sep 30, 2020
22eef8a
Create schedulezoomtalks.py
everthemore Sep 30, 2020
ae82381
WIP
everthemore Sep 30, 2020
2d33d76
Merge branch 'master' into schedule-zoom-talks-bot
everthemore Oct 7, 2020
2dea154
WIP
everthemore Oct 8, 2020
22625c6
Implement round of comments; password action missing
everthemore Oct 8, 2020
b826336
Update req's, rename function for clarity, attempt to add registratio…
everthemore Oct 8, 2020
86ff429
Remove incorrect '-'
everthemore Oct 8, 2020
b5b7504
More suggestions implemented
everthemore Oct 8, 2020
cfd0443
Fix link
everthemore Oct 9, 2020
2434663
Use PATCH for questions
everthemore Oct 9, 2020
1a2683e
Update requirements.txt
everthemore Oct 9, 2020
827364a
Delete redundant requirements.txt
everthemore Oct 9, 2020
b4255a7
Switch to test branch
everthemore Oct 9, 2020
f84c120
Speaker registration
everthemore Oct 9, 2020
313dfb6
Remove live link
everthemore Oct 9, 2020
0723abd
Issue response
everthemore Oct 10, 2020
e39fc28
Tweaks
everthemore Oct 10, 2020
ee6c61d
Email WIP
everthemore Oct 10, 2020
ee9e924
Email v1
everthemore Oct 10, 2020
1ae7003
Add date and time to email
everthemore Oct 10, 2020
de39fb8
Add zoom link
everthemore Oct 11, 2020
49129d6
Add mailgun key
everthemore Oct 11, 2020
0d7ac9f
bugfixes
akhmerov Oct 11, 2020
fec3226
Turn off submission to researchseminars.org
everthemore Oct 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/schedule_zoom_talks.yml
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 }}
1 change: 1 addition & 0 deletions .github/workflows/zoom_scheduling_bot_requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

103 changes: 103 additions & 0 deletions researchseminarsdotorg.py
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",
"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
99 changes: 99 additions & 0 deletions schedulezoomtalks.py
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 *

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
"timezone": "UTC",
"duration": 60, # 90 minutes
"schedule_for": "vsf@virtualscienceforum.org", # Zoom user ID or Zoom email address
"agenda":talk.get("title"),
"password": "",

# Meeting settings
"settings": {
"host_video": True,
"participant_video": True,
"cn_meeting": False, # Host the meeting in China?
"in_meeting": False, # Host the meeting in India?
"join_before_host": False,
"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": "",
"registrants_email_notification": True,
"contact_email": "vsf@virtualscienceforum.org",
}
}

response = zoom_request(
requests.post,
f"{ZOOM_API}users/{user_id}/meetings",
params={"body":request_body}
)

return response.id

def parse_talks(talks) -> int:
num_updated = 0
for talk in talks:
if( talk.get('zoom_link', "") == "" && talk.get('event_type') == "speakers_corner" ):
# 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:
# ... 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:
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'
)