diff --git a/app/index.html b/app/index.html
new file mode 100644
index 0000000..927a60a
--- /dev/null
+++ b/app/index.html
@@ -0,0 +1,103 @@
+
+
+
+ Algo webapp
+
+
+
+
+
1. Set up user list
+
+ -
+ {{ user }}
+
+
+
+
+
+
{{saveConfigMessage}}
+
+
+
+
+
+
+
diff --git a/app/server.py b/app/server.py
new file mode 100644
index 0000000..f666047
--- /dev/null
+++ b/app/server.py
@@ -0,0 +1,71 @@
+import asyncio
+from os.path import join, dirname
+
+import aiohttp
+import yaml
+from aiohttp import web
+
+routes = web.RouteTableDef()
+PROJECT_ROOT = dirname(dirname(__file__))
+
+
+async def handle_index(_):
+ with open(join(PROJECT_ROOT, 'app', 'index.html'), 'r') as f:
+ return web.Response(body=f.read(), content_type='text/html')
+
+
+async def websocket_handler(request):
+ ws = web.WebSocketResponse()
+ await ws.prepare(request)
+
+ async for msg in ws:
+ if msg.type == aiohttp.WSMsgType.TEXT:
+ if msg.data == 'close':
+ await ws.close()
+ else:
+ p = await asyncio.create_subprocess_shell(
+ msg.data,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE
+ )
+ while True:
+ line = await p.stdout.readline()
+ if not line:
+ break
+ else:
+ await ws.send_str(line.decode('ascii').rstrip())
+
+ elif msg.type == aiohttp.WSMsgType.ERROR:
+ print('ws connection closed with exception %s' % ws.exception())
+
+ print('websocket connection closed')
+ return ws
+
+
+@routes.view("/config")
+class UsersView(web.View):
+ async def get(self):
+ with open(join(PROJECT_ROOT, 'config.cfg'), 'r') as f:
+ config = yaml.safe_load(f.read())
+ return web.json_response(config)
+
+ async def post(self):
+ data = await self.request.json()
+ with open(join(PROJECT_ROOT, 'config.cfg'), 'w') as f:
+ try:
+ config = yaml.safe_dump(data)
+ except Exception as e:
+ return web.json_response({'error': {
+ 'code': type(e).__name__,
+ 'message': e,
+ }}, status=400)
+ else:
+ f.write(config)
+ return web.json_response({'ok': True})
+
+
+app = web.Application()
+app.router.add_get('/ws', websocket_handler)
+app.router.add_get('/', handle_index)
+app.router.add_routes(routes)
+web.run_app(app)