#! /Users/arianagiroux/Documents/Coding/owncast-obs-streamer/venv/bin/python3 """ A simple flask app to provide a streamer UI for obs and owncast. Usage: $ ./app.py > * Serving Flask app 'app' (lazy loading) > * Environment: production > WARNING: This is a development server. Do not use it in a production deployment. > Use a production WSGI server instead. > * Debug mode: off > * Running on http://127.0.0.1:5000 (Press CTRL+C to quit) > Open 127.0.0.1:5000 in your local browser Note: If port 5000 is already bound, use the following command to start the flask app: $ flask run -p INTEGER The app will automatically fail if there is not file containing valid JSON data located at ./resources/data.json. This json file should have the following data structure: { "stream_url":"https://yourstream.url", "user_name":"admin", "stream_key":"your_stream_key" } """ import chevron import requests import json from os import path from pprint import pprint from flask import Flask, request, Response # load json data, or raise exception. if path.exists('resources/data.json'): try: stream_data = json.load(open('resources/data.json', 'r')) except json.JSONDecodeError as e: raise RuntimeError('JSON data did not pass validation.') else: raise RuntimeError('Could not find ./resources/data.json, required for ' 'runtime!') # initialize requests session session = requests.Session() session.auth = ('admin', stream_data['stream_key']) # initialize flask app app = Flask(__name__) def render(data={}): """ Template rendering function using mustache (via the pypi chevron implementation. :returns: A full HTML template with relevant data from the server. """ return chevron.render(template=open('index.mustache', 'r'), data=data) @app.route("/api/serverstatus", methods=['GET']) def getServerStatus(): """ Obtains useful information from the server from either /api/yp or /api/status. :returns: the collected data as a JSON formatted dict. """ response = session.get(stream_data['stream_url'] + '/api/yp') response_data = response.json() data = { 'name': response_data['name'], 'online': response_data['online'], 'overallMaxViewerCount': response_data['overallMaxViewerCount'], 'sessionMaxViewerCount': response_data['sessionMaxViewerCount'], 'viewerCount': response_data['viewerCount'], 'description': response_data['description'], 'tags': response_data['tags'], 'nsfw': response_data['nsfw'], } response = session.get(stream_data['stream_url'] + '/api/status') response_data = response.json() data['streamTitle'] = response_data['streamTitle'] return json.dumps(data) @app.route("/api/update/streamtitle", methods=['POST']) def updateStreamTitle(): """ An endpoint to allow the user to update the stream title. :returns: the status code of the post request made to the server. """ response = session.post( stream_data['stream_url'] + '/api/admin/config/streamtitle', data=json.dumps({'value': request.get_json(force=True)}) ) return Response(status=response.status_code) @app.route('/api/update/servertags', methods=['POST']) def updateServerTags(): """ An endpoint to allow the user to update the stream title. :returns: the status code of the post request made to the server. """ values = [i.strip() for i in request.get_json(force=True).split(',')] response = session.post( stream_data['stream_url'] + '/api/admin/config/tags', data=json.dumps({ 'value': values }) ) return Response(status=response.status_code) @app.route("/") def index(): """ A simple initial endpoint that loads in relevant data from the server. :returns: the rendered template (see app.render for more) """ return render(json.loads(getServerStatus())) if __name__ == '__main__': app.run()