commit d864b3edf91ddd85b67b6de1de6c3e1407951369 Author: iou1name Date: Thu May 7 15:31:49 2020 -0400 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..610faed --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__/ +*.swp +*.swo +config.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9813d47 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2020, iou1name + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c241165 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Scorch +A music streaming application. + +## Requirements +Python 3.8+ +Python packages: `gunicorn aiohttp aiohttp_jinja2 uvloop mutagen` + +## Install +1. Get on the floor +2. Walk the dinosaur + +## Usage +`gunicorn scorch:init_app --bind localhost:5500 --worker-class aiohttp.GunicornWebWorker` diff --git a/buckler_aiohttp.py b/buckler_aiohttp.py new file mode 100644 index 0000000..bb10047 --- /dev/null +++ b/buckler_aiohttp.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +""" +Session interface middlewares to integrate the aiohttp app with Buckler. +""" +import json +from datetime import datetime + +import aiohttp +from aiohttp import web + +import config + +@web.middleware +async def buckler_session(request, handler): + """ + Verifies the user with the configured Buckler app and retrieves any + session data they may have. Redirects them to the login page otherwise. + """ + user_id = request.cookies.get('userid', '') + user_sid = request.cookies.get('session', '') + + url = config.buckler['url'] + '/get_session' + params = { + 'app_id': config.buckler['app_id'], + 'app_key': config.buckler['app_key'], + 'userid': user_id, + 'session': user_sid + } + async with aiohttp.ClientSession() as session: + async with session.get(url, params=params) as resp: + data = await resp.json() + if data.get('error'): + raise web.HTTPFound(location=config.buckler['login_url']) + request['session'] = data['session_data'] + request['meta'] = data['meta'] + + resp = await handler(request) + + if request['session'] != data['session_data']: # session data modified + url = config.buckler['url'] + '/set_session' + data = json.dumps(request['session']) + session.post(url, params=params, data=data) # TODO: error handle? + + last_used = datetime.fromisoformat(request['meta']['last_used']) + now = datetime.now(last_used.tzinfo) + delta = now - last_used + if delta.seconds > 600: + resp.set_cookie( + 'userid', + user_id, + max_age=30*24*60*60, + secure=True, + httponly=True) + resp.set_cookie( + 'session', + user_sid, + max_age=30*24*60*60, + secure=True, + httponly=True) + + return resp diff --git a/config.py.template b/config.py.template new file mode 100644 index 0000000..70d3056 --- /dev/null +++ b/config.py.template @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +""" +Configuration settings for the Scorch musc streaming app. +`url_prefix` is the root path you wish app to reside at +eg. https://example.com/scorch. +`buckler` specifies settings pertaining to the Buckler server. +""" +url_prefix = '/scorch' +buckler = { + 'url': "http://127.0.0.1:5400/buckler", + 'app_id': 2, + 'app_key': """lol""", + 'login_url': "/buckler/login", +} diff --git a/scorch.py b/scorch.py new file mode 100644 index 0000000..38ec95b --- /dev/null +++ b/scorch.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +""" +A music streaming application. +""" +from aiohttp import web +import jinja2 +import aiohttp_jinja2 +from aiohttp_jinja2 import render_template +import uvloop + +import config +import buckler_aiohttp + +uvloop.install() +routes = web.RouteTableDef() + +@routes.get('/', name='index') +async def index(request): + """The index page.""" + return render_template('index.html', request, {}) + + +async def init_app(): + """Initializes the application.""" + app = web.Application(middlewares=[buckler_aiohttp.buckler_session]) + aiohttp_jinja2.setup( + app, + trim_blocks=True, + lstrip_blocks=True, + undefined=jinja2.StrictUndefined, + loader=jinja2.FileSystemLoader('templates'), + ) + + app.router.add_routes(routes) + + app_wrap = web.Application() + app_wrap.add_subapp(config.url_prefix, app) + return app_wrap + + +if __name__ == "__main__": + app = init_app() + aiohttp.web.run_app(app, host='0.0.0.0', port=5500) diff --git a/static/scorch.css b/static/scorch.css new file mode 100644 index 0000000..e69de29 diff --git a/static/scorch.js b/static/scorch.js new file mode 100644 index 0000000..e69de29 diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..90bdff8 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,17 @@ + + + + Scorch + + + + + + +
+

Scorch

+
+
+
+ +