crosswords/server/crossword_connection.py

139 lines
4.4 KiB
Python

import logging
import uuid
import datetime as dt
from . import json_websockets
from . import session
class CrosswordConnection(json_websockets.JsonWebsocketConnection):
sessions = {}
last_cleanup = None
def clean_sessions():
now = dt.datetime.utcnow()
if CrosswordConnection.last_cleanup is None or (now - CrosswordConnection.last_cleanup).total_seconds() > 3600:
CrosswordConnection.last_cleanup = now
sessions_to_close = []
for key, session in CrosswordConnection.sessions.items():
if session.is_expired():
sessions_to_close.append(key)
for key in sessions_to_close:
del(CrosswordConnection.sessions[key])
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._session = None
async def send_crossword(self, sessionId: str, lang: str = "en", difficulty: int = 0):
if sessionId not in CrosswordConnection.sessions:
await self.send_error(msg="unknown session")
return
sess = CrosswordConnection.sessions[sessionId]
# NOTE: if there will be the possibility of private
# sessions, this has to be changed since this is leaking
# the information that a certain session exists!
if self not in sess.get_sockets():
await self.send_error(msg="you are not registered to given session")
return
crossword = sess.get_crossword(lang=lang, difficulty=difficulty)
await self.send({
'type': 'crossword',
'crossword': crossword.serialize()
})
# sending also the status as update:
await self.send({
'type': 'update',
'updates': crossword.get_status()
})
async def user_update(self, x: int, y: int, letter: str):
if len(letter) > 1:
await self.send_error(msg="received invalid userinput")
return
update_message = self._session.get_crossword().user_input(x=x, y=y, letter=letter)
for connection in self._session.get_sockets():
await connection.send({
'type': 'update',
'updates': update_message
})
async def register(self, sessionId: str = None, lang: str = "en", difficulty: int = 0):
if sessionId is None:
sessionId = uuid.uuid4().hex
while sessionId in CrosswordConnection.sessions:
sessionId = uuid.uuid4().hex
new_session = session.Session()
CrosswordConnection.sessions[sessionId] = new_session
if sessionId not in CrosswordConnection.sessions:
await self.send_error("unknown session id")
# register with new id:
await self.register(lang=lang, difficulty=difficulty)
return
sess = CrosswordConnection.sessions[sessionId]
sess.connect_socket(self)
self._session = sess
await self.send({
'type': 'register',
'sessionId': sessionId
})
await self.send_crossword(sessionId, lang=lang, difficulty=difficulty)
# clean up old session
CrosswordConnection.clean_sessions()
async def send_error(self, msg: str):
await self.send({
'type': 'error',
'message': msg
})
async def handle_message(self, message: dict):
logging.info("incoming message: %s", str(message))
if not "type" in message:
logging.error("received malformated message")
await self.send_error(msg="i do not understand the request")
return
if message['type'] == 'register':
sessionId = None
lang = "en"
difficulty = 0
if 'sessionId' in message:
sessionId = message['sessionId']
if "lang" in message:
lang = message['lang']
if "difficulty" in message:
difficulty = message["difficulty"]
await self.register(sessionId=sessionId, lang=lang, difficulty=difficulty)
return
if self._session is None:
await self.send_error(msg="you are not registered properly")
return
if message['type'] == "update":
await self.user_update(x=message['x'], y=message['y'], letter=message['letter'])
return