Доработка взаимодействия с подключением
This commit is contained in:
parent
89431be9ed
commit
a5e3234568
2 changed files with 70 additions and 23 deletions
3
game.py
3
game.py
|
@ -222,3 +222,6 @@ class Room:
|
|||
def remove_user(self, user: User):
|
||||
if user in self.users:
|
||||
self.users.remove(user)
|
||||
|
||||
def is_empty(self):
|
||||
return not len(self.users) > 0
|
||||
|
|
90
main.py
90
main.py
|
@ -17,8 +17,12 @@ import logging
|
|||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi_socketio import SocketManager
|
||||
from cachetools import TTLCache
|
||||
from game import Room, User, load_streets
|
||||
from objects import ErrCode, UserCheck
|
||||
from threading import Timer
|
||||
|
||||
ROOM_DISCONNECT_TIMEOUT = 60*5 # TODO: Сохранить остаток таймера для каждого пользователя
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s:\t%(asctime)s\t%(message)s")
|
||||
load_streets()
|
||||
|
@ -33,9 +37,10 @@ app.add_middleware(
|
|||
allow_headers=["*"],
|
||||
)
|
||||
sio = SocketManager(app=app, mount_location="/ws", socketio_path="game", cors_allowed_origins=[])
|
||||
# sio_sessions = TTLCache(maxsize=10000, ttl=24 * 60 * 60)
|
||||
rooms = []
|
||||
users = [] # TODO: implement as dict
|
||||
sio_sessions = TTLCache(maxsize=10000, ttl=24 * 60 * 60)
|
||||
rooms = dict()
|
||||
users = dict()
|
||||
users_to_disconnect = dict()
|
||||
|
||||
|
||||
# TODO: Time-based tokens
|
||||
|
@ -44,15 +49,14 @@ def check_user(username, password=None, token=None):
|
|||
return False
|
||||
else:
|
||||
global users
|
||||
selected_users = tuple(filter(lambda usr: usr.username == username, users))
|
||||
if len(selected_users) == 0:
|
||||
if username not in users:
|
||||
if token:
|
||||
logging.debug(f"Invalid token for user {username}")
|
||||
return UserCheck.INVALID_CREDENTIALS
|
||||
logging.debug(f"Invalid user {username}")
|
||||
return UserCheck.USER_DOESNT_EXISTS
|
||||
else:
|
||||
user = selected_users[0]
|
||||
user = users[username]
|
||||
if user.token == token or user.password == password:
|
||||
logging.debug(f"Valid credentials for user {username}")
|
||||
return user
|
||||
|
@ -68,38 +72,47 @@ async def sio_create_room(sid, username, token, password):
|
|||
new_room = Room(password)
|
||||
logging.info(f"User {username} created room {new_room.room_id}")
|
||||
new_room.add_user(user)
|
||||
rooms.append(new_room)
|
||||
user.in_room = new_room.room_id # TODO: not add user on creation
|
||||
user.room_password = new_room.password
|
||||
await sio_send_user_info(sid, user)
|
||||
rooms[new_room.room_id] = new_room
|
||||
await sio.emit("roomCreated", {"room_id": new_room.room_id, "room_password": new_room.password}, room=sid)
|
||||
case _:
|
||||
return False # TODO: some errors
|
||||
|
||||
|
||||
async def sio_send_user_info(sid, user):
|
||||
userdata = user.get_dict()
|
||||
userdata["token"] = user.token
|
||||
if user.in_room:
|
||||
userdata["in_room"] = user.in_room
|
||||
userdata["password"] = user.password
|
||||
userdata["room_password"] = user.room_password
|
||||
await sio.emit("userInfo", userdata, room=sid)
|
||||
|
||||
|
||||
@sio.on("joinRoom")
|
||||
async def sio_join_room(sid, room_id, room_password): # TODO: Check if user already in room
|
||||
global rooms
|
||||
selected_room = tuple(filter(lambda room: room.room_id == room_id, rooms))
|
||||
if len(selected_room) == 0:
|
||||
await sio_throw_error(sid, ErrCode.ROOM_DOESNT_EXIST)
|
||||
else:
|
||||
room = selected_room[0]
|
||||
room_data = room.get_dict()
|
||||
sio.enter_room(sid, room.room_id)
|
||||
if room.password == room_password:
|
||||
await sio.emit("roomInfo", room_data, room=sid)
|
||||
async def sio_join_room(sid, username, token, room_id, room_password): # TODO: Check if user already in room
|
||||
match check_user(username, token=token):
|
||||
case User(username=username) as user:
|
||||
global rooms
|
||||
if room_id not in rooms:
|
||||
logging.debug(f"Room {room_id} doesn't found")
|
||||
await sio_throw_error(sid, ErrCode.ROOM_DOESNT_EXIST)
|
||||
else:
|
||||
room = rooms[room_id]
|
||||
if room.password == room_password:
|
||||
user.in_room = room.room_id
|
||||
user.room_password = room.password
|
||||
room_data = room.get_dict()
|
||||
sio.enter_room(sid, room.room_id)
|
||||
await sio_send_user_info(sid, user)
|
||||
await sio.emit("roomInfo", room_data, room=sid)
|
||||
case _:
|
||||
await sio_throw_error(sid, ErrCode.INVALID_CREDENTIALS)
|
||||
return False
|
||||
|
||||
|
||||
@sio.on("connect")
|
||||
async def sio_connect(sid, _, auth):
|
||||
if sid in sio_sessions:
|
||||
return False
|
||||
if not ("username" in auth and ("password" in auth or "token" in auth))\
|
||||
or not auth["username"].isalnum()\
|
||||
or len(auth["username"]) > 16:
|
||||
|
@ -110,12 +123,20 @@ async def sio_connect(sid, _, auth):
|
|||
password = auth.get("password", None)
|
||||
match check_user(username, password, token):
|
||||
case User(username=username) as user:
|
||||
user.sid = sid
|
||||
sio_sessions[sid] = user
|
||||
if username in users_to_disconnect:
|
||||
timer = users_to_disconnect[username]
|
||||
timer.cancel()
|
||||
del users_to_disconnect[username]
|
||||
await sio_send_user_info(sid, user)
|
||||
case UserCheck.USER_DOESNT_EXISTS:
|
||||
if not password:
|
||||
return False
|
||||
user = User(username, password)
|
||||
users.append(user)
|
||||
users[username] = user
|
||||
user.sid = sid
|
||||
sio_sessions[sid] = user
|
||||
await sio_send_user_info(sid, user)
|
||||
case UserCheck.INVALID_CREDENTIALS:
|
||||
await sio_throw_error(sid, ErrCode.INVALID_CREDENTIALS)
|
||||
|
@ -132,7 +153,30 @@ async def sio_throw_error(sid, error):
|
|||
|
||||
@sio.on("disconnect")
|
||||
async def sio_disconnect(sid):
|
||||
user = sio_sessions[sid]
|
||||
logging.debug(f"{sid} disconnected")
|
||||
if user.in_room:
|
||||
logging.info(f"User {user.username} disconnected while in the room {user.in_room}")
|
||||
global users_to_disconnect
|
||||
t = Timer(ROOM_DISCONNECT_TIMEOUT, disconnect_user, args=[user])
|
||||
users_to_disconnect[user.username] = t
|
||||
t.start()
|
||||
|
||||
def disconnect_user(user):
|
||||
global rooms
|
||||
room = rooms[user.in_room]
|
||||
room.remove_user(user)
|
||||
logging.info(f"User {user.username} disconnected from room {room.room_id}")
|
||||
if room.is_empty():
|
||||
logging.info(f"Room {room.room_id} is closed")
|
||||
del rooms[room.room_id]
|
||||
del room
|
||||
t = users_to_disconnect[user.username]
|
||||
t.cancel()
|
||||
del t
|
||||
del users_to_disconnect[user.username]
|
||||
|
||||
|
||||
|
||||
|
||||
@sio.on("rollDices")
|
||||
|
|
Loading…
Add table
Reference in a new issue