Skip to content

Instantly share code, notes, and snippets.

@mooware
Last active January 17, 2021 01:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mooware/4860529d59f296a62fb8fe882b943c29 to your computer and use it in GitHub Desktop.
Save mooware/4860529d59f296a62fb8fe882b943c29 to your computer and use it in GitHub Desktop.
Simple bottle.py application to open a multitwitch (or similar site) for an SRL race
from bottle import *
from urllib.request import urlopen
import json
import re
DEFAULT_HOSTS = ['multitwitch.tv', 'multistre.am', 'kadgar.net/live']
SRL_API = "https://api.speedrunslive.com/races/"
SANITY_RE = re.compile('[0-9a-z]+')
RACE_STATE_COMPLETE = 4 # from the SRL API
HTML_INDEX_TEMPLATE = """
<html>
<head>
<title>SRL Races</title>
</head>
<body>
% for race in races:
<div>
<a href="https://www.speedrunslive.com/race/?id={{race['id']}}">#srl-{{race['id']}} ({{race['statetext']}})</a>
<span>
{{race['game']['name']}}
{{' - ' + race['goal'] if race['goal'] else ''}}
</span>
</div>
<div>
% for i, entrant in enumerate(race['entrants'].values()):
<span>
{{'/' if i != 0 else ''}}
% if entrant['twitch']:
<a href="https://twitch.tv/{{entrant['twitch']}}">{{entrant['displayname']}}</a>
% else:
{{entrant['displayname']}}
% end
</span>
% end
</div>
% for j, host in enumerate(hosts):
{{'/' if j != 0 else ''}}
<a href="{{host}}/{{race['id']}}">{{host}}</a>
% end
<br/><br/>
% end
</body>
</html>
"""
def get_json(url):
req = urlopen(url)
reqdata = req.read().decode()
return json.loads(reqdata)
@route('/srlmulti')
@route('/')
def redirect_to_index():
# we need trailing slash for relative urls
return redirect('/srlmulti/')
@route('/srlmulti/')
def index():
data = get_json(SRL_API)
races = (r for r in data['races'] if r['state'] < RACE_STATE_COMPLETE)
return template(HTML_INDEX_TEMPLATE, races=races, hosts=DEFAULT_HOSTS)
@route('/srlmulti/<race_id>')
def showmulti(race_id):
return showmulti_with_host(DEFAULT_HOSTS[0], race_id)
@route('/srlmulti/<host:path>/<race_id>')
def showmulti_with_host(host, race_id):
race_id = race_id.strip()
if race_id.startswith('srl-'):
race_id = race_id[4:]
if not SANITY_RE.fullmatch(race_id):
abort(400, 'invalid format for race id')
# request might fail with exception, let it go through
data = get_json(SRL_API + race_id)
# srl api returns empty json object for invalid race id
if not data:
abort(404, "race id '" + race_id + "' not found")
streams = (v['twitch'] for v in data['entrants'].values() if v['twitch'])
return redirect('https://' + host + '/' + '/'.join(streams))
if __name__ == '__main__':
run(host='localhost', port=8080)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment