feat: created (partially) an admin interface

This commit is contained in:
Laureηt 2021-11-03 18:40:11 +01:00
parent 337a0618b9
commit 7c8b2d8cf1
No known key found for this signature in database
GPG key ID: D88C6B294FD40994
3 changed files with 117 additions and 11 deletions

79
src/admin.html Normal file
View file

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<title>Admin</title>
<style>
* {
padding: 0;
margin: 0;
}
#dashboard {
display: none;
}
</style>
</head>
<body>
<div id="login">
<input type="password" id="password-text">
<input type="button" id="password-button" value="Login" onclick="sendCreds();">
</div>
<div id="dashboard">
<ul id="stateList"></ul>
<button id="save">save</button>
</div>
<script>
var websocket = new WebSocket("ws://127.0.0.1:6789/");
var passwordInput = document.querySelector('#password-text');
var divLogin = document.querySelector("#login");
var divDashboard = document.querySelector("#dashboard");
var stateList = document.querySelector("#stateList");
var saveButton = document.getElementById('save');
saveButton.onclick = function (event) {
websocket.send(JSON.stringify({ 'admin': 'save' }));
}
function receiveStates(ev) {
let msg = JSON.parse(ev.data);
let states = msg.state
for (var i = 0; i < states.length; i++) {
var state = states[i];
var li = document.createElement('li');
li.appendChild(document.createTextNode(state));
stateList.appendChild(li);
}
}
function authSuccess(ev) {
let msg = JSON.parse(ev.data);
if (msg.auth === "success") {
divLogin.style.display = "none";
divDashboard.style.display = "unset";
websocket.removeEventListener('message', authSuccess);
websocket.send(JSON.stringify({ "state": "get" }));
websocket.addEventListener('message', receiveStates);
}
};
function sendCreds() {
var message = JSON.stringify({ "auth": passwordInput.value });
websocket.send(message)
websocket.addEventListener('message', authSuccess);
};
passwordInput.addEventListener("keydown", function (e) {
if (e.key === "Enter") { sendCreds(); }
});
</script>
</body>
</html>

View file

@ -1,6 +1,7 @@
import asyncio
import json
import logging
import time
import mgba.core
import mgba.image
@ -10,8 +11,8 @@ import pyvirtualcam
import websockets
from mgba._pylib import ffi
WIDTH = 240
HEIGHT = 160
WIDTH: int = 240
HEIGHT: int = 160
URI: str = "ws://127.0.0.1:6789/"
FPS: int = 60
HZ: int = 10
@ -36,7 +37,7 @@ core.set_video_buffer(screen)
core.reset()
mgba.log.silence()
logging.basicConfig(level=logging.DEBUG)
# logging.basicConfig(level=logging.DEBUG)
def parse_message(message: dict[str, str]):
@ -60,7 +61,7 @@ def parse_message(message: dict[str, str]):
data = message["admin"]
if data == "save": # voodoo magic incomming
state = core.save_raw_state()
with open("states/test.state", "wb") as state_file:
with open(f"states/{time.strftime('%Y-%m-%dT%H:%M:%S')}.state", "wb") as state_file:
for byte in state:
state_file.write(byte.to_bytes(4, byteorder="big", signed=False))
elif data == "load": # black magic incomming
@ -78,7 +79,7 @@ async def main():
with pyvirtualcam.Camera(width=WIDTH, height=HEIGHT, fps=FPS) as cam:
logging.debug(f"Using virtual camera: {cam.device}")
async with websockets.connect(URI) as websocket:
await websocket.send('{"auth":"password"}')
await websocket.send('{"auth":"emulator_password"}')
logging.debug(f"connected to: {websocket}")
while True:

View file

@ -1,6 +1,7 @@
import asyncio
import json
import logging
import os
import time
from typing import Any
@ -8,15 +9,22 @@ import websockets
from utils import User, Users, Votes
logging.basicConfig(level=logging.DEBUG)
# logging.basicConfig(level=logging.DEBUG)
PASSWORD_ADMIN: str = "password"
PASSWORD_EMU: str = "password"
PASSWORD_ADMIN: str = "admin_password"
PASSWORD_EMU: str = "emulator_password"
VOTES: Votes = Votes()
USERS: Users = Users()
async def parse_message(user: User, message: dict[str, str]):
async def send_states(user: User) -> None:
files = os.listdir("states")
states = list(filter(lambda x: x.endswith(".state"), files))
message = json.dumps({"state": states})
await user.send(message)
async def parse_message(user: User, message: dict[str, str]) -> None:
"""Parse the user's message.
Args:
@ -25,12 +33,14 @@ async def parse_message(user: User, message: dict[str, str]):
"""
if "auth" in message:
data = message["auth"]
if USERS.emulator is None and data == PASSWORD_EMU:
if USERS.emulator is None and data == PASSWORD_EMU and user != USERS.admin:
USERS.emulator = user
logging.debug(f"emulator authenticated: {user}")
elif USERS.admin is None and data == PASSWORD_ADMIN:
await user.send('{"auth":"success"}')
elif USERS.admin is None and data == PASSWORD_ADMIN and user != USERS.emulator:
USERS.admin = user
logging.debug(f"admin authenticated: {user}")
await user.send('{"auth":"success"}')
if "action" in message:
data = message["action"]
@ -65,6 +75,16 @@ async def parse_message(user: User, message: dict[str, str]):
else:
logging.error(f"user is not emulator: {user}")
if "state" in message:
data = message["state"]
if user == USERS.admin:
if data == "get":
await send_states(user)
else:
logging.error(f"unsupported state action: {data}")
else:
logging.error(f"user is not admin: {user}")
async def handler(websocket: Any, path: str):
"""Handle the messages sent by a user.
@ -84,6 +104,12 @@ async def handler(websocket: Any, path: str):
finally:
# Unregister user
USERS.unregister(user)
if user == USERS.admin:
USERS.admin = None
logging.debug(f"admin disconnected: {user}")
elif user == USERS.emulator:
logging.debug(f"emulator disconnected: {user}")
USERS.emulator = None
async def main():