feat: now possible to load and save data through redis "messages"
This commit is contained in:
parent
5ccbd3d8e4
commit
73abc7a981
|
@ -27,6 +27,7 @@ from settings import (
|
||||||
REDIS_PORT,
|
REDIS_PORT,
|
||||||
RTMP_STREAM_URI,
|
RTMP_STREAM_URI,
|
||||||
)
|
)
|
||||||
|
from utils import States
|
||||||
|
|
||||||
core = mgba.core.load_path(EMULATOR_ROM_PATH)
|
core = mgba.core.load_path(EMULATOR_ROM_PATH)
|
||||||
screen = mgba.image.Image(EMULATOR_WIDTH, EMULATOR_HEIGHT)
|
screen = mgba.image.Image(EMULATOR_WIDTH, EMULATOR_HEIGHT)
|
||||||
|
@ -37,6 +38,8 @@ logging.basicConfig(level=logging.DEBUG)
|
||||||
mgba.log.silence()
|
mgba.log.silence()
|
||||||
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
|
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
|
||||||
|
|
||||||
|
states: States = States()
|
||||||
|
|
||||||
|
|
||||||
def next_action():
|
def next_action():
|
||||||
"""Select the next key from the redis database.
|
"""Select the next key from the redis database.
|
||||||
|
@ -94,12 +97,13 @@ def state_manager(loop):
|
||||||
ps.subscribe("admin")
|
ps.subscribe("admin")
|
||||||
while True:
|
while True:
|
||||||
for message in ps.listen():
|
for message in ps.listen():
|
||||||
print(message)
|
logging.debug(message)
|
||||||
asyncio.ensure_future(save(), loop=loop)
|
if message["type"] == "message":
|
||||||
|
data = message["data"].decode("utf-8")
|
||||||
|
if data == "save":
|
||||||
async def save():
|
asyncio.ensure_future(states.save(core), loop=loop)
|
||||||
print("saving")
|
elif data.startswith("load:"):
|
||||||
|
asyncio.ensure_future(states.load(core, data.removeprefix("load:")), loop=loop)
|
||||||
|
|
||||||
|
|
||||||
async def emulator():
|
async def emulator():
|
||||||
|
@ -129,7 +133,6 @@ async def main(loop):
|
||||||
|
|
||||||
task_emulator = loop.create_task(emulator())
|
task_emulator = loop.create_task(emulator())
|
||||||
await task_emulator
|
await task_emulator
|
||||||
thread.join()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -61,7 +61,6 @@ async def parse_message(user: User, message: dict[str, str]) -> None:
|
||||||
elif data in KEYS_ID:
|
elif data in KEYS_ID:
|
||||||
r.incr(data)
|
r.incr(data)
|
||||||
user.last_message = time.time()
|
user.last_message = time.time()
|
||||||
user.has_voted = True
|
|
||||||
else:
|
else:
|
||||||
logging.error(f"unsupported action: {data}")
|
logging.error(f"unsupported action: {data}")
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ FFMPEG_BITRATE: str = getenv("FFMPEG_BIRATE", "2M")
|
||||||
|
|
||||||
PASSWORD_ADMIN: str = getenv("PASSWORD_ADMIN", "password_admin")
|
PASSWORD_ADMIN: str = getenv("PASSWORD_ADMIN", "password_admin")
|
||||||
|
|
||||||
USER_TIMEOUT: float = 0.5
|
USER_TIMEOUT: float = float(getenv("USER_TIMEOUT", 0.5))
|
||||||
|
|
||||||
KEYMAP: dict[str, int] = {
|
KEYMAP: dict[str, int] = {
|
||||||
"a": 0,
|
"a": 0,
|
||||||
|
|
42
src/utils.py
42
src/utils.py
|
@ -1,15 +1,17 @@
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
from mgba._pylib import ffi
|
||||||
|
|
||||||
|
|
||||||
class User:
|
class User:
|
||||||
"""Store infos related to a connected user."""
|
"""Store infos related to a connected user."""
|
||||||
|
|
||||||
websocket: Any
|
websocket: Any
|
||||||
last_message: float
|
last_message: float
|
||||||
has_voted: bool
|
|
||||||
|
|
||||||
def __init__(self, websocket: Any) -> None:
|
def __init__(self, websocket: Any) -> None:
|
||||||
"""Construct a User object.
|
"""Construct a User object.
|
||||||
|
@ -19,7 +21,6 @@ class User:
|
||||||
"""
|
"""
|
||||||
self.websocket = websocket
|
self.websocket = websocket
|
||||||
self.last_message = time.time()
|
self.last_message = time.time()
|
||||||
self.has_voted = False
|
|
||||||
|
|
||||||
async def send(self, data: str):
|
async def send(self, data: str):
|
||||||
"""Send data through the user's websocket.
|
"""Send data through the user's websocket.
|
||||||
|
@ -42,7 +43,6 @@ class User:
|
||||||
class Users(set):
|
class Users(set):
|
||||||
"""Store `User`s connected to the server."""
|
"""Store `User`s connected to the server."""
|
||||||
|
|
||||||
emulator: Optional[User] = None
|
|
||||||
admin: Optional[User] = None
|
admin: Optional[User] = None
|
||||||
|
|
||||||
def register(self, user: User):
|
def register(self, user: User):
|
||||||
|
@ -63,22 +63,26 @@ class Users(set):
|
||||||
self.remove(user)
|
self.remove(user)
|
||||||
logging.debug(f"user unregistered: {self}")
|
logging.debug(f"user unregistered: {self}")
|
||||||
|
|
||||||
def clear(self) -> None:
|
|
||||||
"""Clear the `has_voted` of each user in the set."""
|
|
||||||
for user in self:
|
|
||||||
user.has_voted = False
|
|
||||||
|
|
||||||
|
class States(set):
|
||||||
|
"""Save and load states from files."""
|
||||||
|
|
||||||
# class States(set):
|
def __init__(self) -> None:
|
||||||
# def save(self, core):
|
"""Construct a `States` object."""
|
||||||
# state = core.save_raw_state()
|
files = os.listdir("states")
|
||||||
# with open(f"states/{time.strftime('%Y-%m-%dT%H:%M:%S')}.state", "wb") as state_file:
|
states = list(filter(lambda x: x.endswith(".state"), files))
|
||||||
# for byte in state:
|
self.update(states)
|
||||||
# state_file.write(byte.to_bytes(4, byteorder="big", signed=False))
|
|
||||||
|
|
||||||
# def load(self, core, state):
|
async def save(self, core):
|
||||||
# state = ffi.new("unsigned char[397312]")
|
state = core.save_raw_state()
|
||||||
# with open("states/test.state", "rb") as state_file:
|
with open(f"states/{time.strftime('%Y-%m-%dT%H:%M:%S')}.state", "wb") as state_file:
|
||||||
# for i in range(len(state)):
|
for byte in state:
|
||||||
# state[i] = int.from_bytes(state_file.read(4), byteorder="big", signed=False)
|
state_file.write(byte.to_bytes(4, byteorder="big", signed=False))
|
||||||
# core.load_raw_state(state)
|
self.add(state)
|
||||||
|
|
||||||
|
async def load(self, core, filename):
|
||||||
|
state = ffi.new("unsigned char[397312]") # pulled 397312 from my ass
|
||||||
|
with open(f"states/{filename}.state", "rb") as state_file:
|
||||||
|
for i in range(len(state)):
|
||||||
|
state[i] = int.from_bytes(state_file.read(4), byteorder="big", signed=False)
|
||||||
|
core.load_raw_state(state)
|
||||||
|
|
Loading…
Reference in a new issue