383 lines
19 KiB
Python
383 lines
19 KiB
Python
# chat/consumers.py
|
|
import json
|
|
from uuid import uuid4
|
|
from channels.generic.websocket import AsyncWebsocketConsumer
|
|
from channels.db import database_sync_to_async
|
|
|
|
from users.serializers import UserSerializer
|
|
from .models import Room
|
|
|
|
|
|
class RoomConsumer(AsyncWebsocketConsumer):
|
|
async def connect(self):
|
|
print('START CONNECT')
|
|
self.accept()
|
|
self.room_id = self.scope['url_route']['kwargs']['room_id']
|
|
self.waiter = None
|
|
self.clientId = str(uuid4())
|
|
self.waiter = False
|
|
self.waiter_code = None
|
|
self.user = None
|
|
try:
|
|
self.room = await self.get_room()
|
|
print('ACCEPTED')
|
|
await self.accept()
|
|
await self.send(json.dumps({'type': 'connect', "clientId": self.clientId}))
|
|
|
|
except:
|
|
print('REJECTED')
|
|
await self.close()
|
|
|
|
async def receive(self, text_data):
|
|
text_data_json = json.loads(text_data)
|
|
type = text_data_json['data']['type']
|
|
|
|
|
|
if type == "login":
|
|
|
|
participants = await self.get_participants()
|
|
if self.scope['user'].is_anonymous:
|
|
nick = text_data_json['data']['nick']
|
|
else:
|
|
nick = self.scope['user'].username
|
|
if len(nick) == 0:
|
|
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo non valide"}))
|
|
return
|
|
if nick in list(map(lambda p: p['nick'], participants)) and self.scope['user'].is_anonymous:
|
|
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo déjà utilisé"}))
|
|
return
|
|
|
|
elif len(nick) > 30:
|
|
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo trop long"}))
|
|
return
|
|
else:
|
|
if self.room.private == True:
|
|
waiter = await self.add_waiter_db(nick, self.scope['user'].is_anonymous == False, None if self.scope['user'].is_anonymous else self.scope['user'].id_code)
|
|
|
|
if waiter != None:
|
|
self.waiter = True
|
|
self.waiter_code = waiter['code']
|
|
await self.send(json.dumps({'type': "waitingRoom", "nick": nick, 'id_code': self.room_id}))
|
|
await self.channel_layer.group_add(f'waiter__{waiter["code"]}', self.channel_name)
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "add_waiter", "code": waiter['code'], "nick": waiter['nick'], "status": waiter['status']})
|
|
else:
|
|
await self.send(json.dumps({'type': 'loginResponse', "error": "USER_INPUT", "description": "Pseudo déjà utilisé"}))
|
|
|
|
else:
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
if self.scope['user'].is_anonymous:
|
|
new_participant = await self.add_participant(nick, self.clientId)
|
|
self.user = new_participant
|
|
else:
|
|
new_participant = await self.add_user(self.scope['user'].id_code)
|
|
self.user = new_participant
|
|
|
|
await self.send(json.dumps({'type': "roomJoined", "clientId": new_participant['clientId'], 'id_code': self.room_id, 'identity': new_participant}))
|
|
await self.channel_layer.group_send(self.room_id, {'type': 'join.event', "nick": nick, "owner": False, "online": True, "code": ""})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': 'join.event', "nick": nick, "owner": False, "online": True, "code": new_participant['code']})
|
|
|
|
elif type == "acceptParticipant":
|
|
code = text_data_json['data']['code']
|
|
nick = text_data_json['data']['nick']
|
|
status = text_data_json['data']['status']
|
|
self.waiter = False
|
|
if status == 'anonymous':
|
|
new_participant = await self.add_participant(nick, str(uuid4()))
|
|
else:
|
|
new_participant = await self.add_user(code)
|
|
|
|
await self.del_waiter_db(code)
|
|
|
|
await self.channel_layer.group_send(f'waiter__{code}', {"type": "accept_room", 'id_code': self.room_id, 'code': new_participant['code']})
|
|
|
|
elif type == "refusedParticipant":
|
|
code = text_data_json['data']['code']
|
|
|
|
await self.del_waiter_db(code)
|
|
await self.channel_layer.group_send(f'waiter__{code}', {"type": "refused_participant"})
|
|
|
|
elif type == "logAcceptedWaiter":
|
|
code = text_data_json['data']['code']
|
|
participants = await self.get_participants()
|
|
if not self.scope['user'].is_anonymous:
|
|
await self.channel_layer.group_discard(f'waiter__{code}', self.channel_name)
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
self.clientId = self.scope['user'].clientId
|
|
|
|
self.user = {
|
|
'nick': self.scope['user'].username, 'code': self.scope['user'].id_code, 'clientId':self.scope['user'].clientId, "owner": False} #à continuer dsl
|
|
self.waiter = False
|
|
self.waiter_code = None
|
|
|
|
await self.send(json.dumps({'type': "roomJoined", "clientId": self.clientId, 'id_code': self.room_id, 'identity': self.user}))
|
|
|
|
await self.channel_layer.group_send(self.room_id, {"type": "join.event", "nick": self.user['nick'], "owner": False, "online": True, "code": ''})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "join.event", "nick": self.user['nick'], "owner": False, "online": True, "code": self.user['code']})
|
|
|
|
|
|
elif code in list(map(lambda p: p['code'], participants)):
|
|
participant = list(
|
|
filter(lambda p: p['code'] == code, participants))[0]
|
|
await self.channel_layer.group_discard(f'waiter__{code}', self.channel_name)
|
|
|
|
self.clientId = participant['clientId']
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
self.user = participant
|
|
self.waiter = False
|
|
self.waiter_code = None
|
|
|
|
await self.send(json.dumps({'type': "roomJoined", "clientId": self.clientId, 'id_code': self.room_id, 'identity': participant}))
|
|
|
|
await self.channel_layer.group_send(self.room_id, {"type": "join.event", "nick": participant['nick'], "owner": False, "online": True, "code": ''})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "join.event", "nick": participant['nick'], "owner": False, "online": True, "code": participant['code']})
|
|
|
|
elif type == 'relogin':
|
|
if not self.scope['user'].is_anonymous:
|
|
userInRoom = await self.userInRoom()
|
|
if not userInRoom:
|
|
await self.send(json.dumps({"type": "reloginError"}))
|
|
else:
|
|
isOwner = self.scope['user'].clientId == self.room.owner[
|
|
'clientId'] and self.scope['user'].id_code == self.room.owner['code']
|
|
self.clientId = self.scope['user'].clientId
|
|
if isOwner:
|
|
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
|
|
else:
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
|
|
self.user = {
|
|
'nick': self.scope['user'].username, 'code': self.scope['user'].id_code, 'clientId': self.scope['user'].clientId, "owner": False}
|
|
|
|
await self.connect_participant()
|
|
|
|
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
else:
|
|
code = text_data_json['data']['code']
|
|
participants = await self.get_participants()
|
|
|
|
if code in list(map(lambda p: p['code'], participants)):
|
|
participant = list(
|
|
filter(lambda p: p['code'] == code, participants))[0]
|
|
self.clientId = participant['clientId']
|
|
|
|
if participant['clientId'] == self.room.owner['clientId'] and participant['code'] == self.room.owner['code']:
|
|
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
|
|
else:
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
|
|
participant['online'] = True
|
|
self.user = participant
|
|
await self.connect_participant()
|
|
|
|
await self.send(json.dumps({'type': "reloged", "clientId": self.clientId, 'id_code': self.room_id, 'identity': participant}))
|
|
|
|
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
|
|
else:
|
|
await self.send(json.dumps({"type": "reloginError"}))
|
|
|
|
elif type == "reconnect":
|
|
client = text_data_json['data']['clientId']
|
|
print(not self.scope['user'].is_anonymous, "USERED", self.scope['user'])
|
|
if not self.scope['user'].is_anonymous:
|
|
userInRoom = await self.userInRoom()
|
|
if not userInRoom:
|
|
await self.send(json.dumps({"type": "reconnectError", 'id_code': self.room_id}))
|
|
else:
|
|
isOwner = self.scope['user'].clientId == self.room.owner[
|
|
'clientId'] and self.scope['user'].id_code == self.room.owner['code']
|
|
|
|
if isOwner:
|
|
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
|
|
else:
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
|
|
self.user = {
|
|
'code': self.scope['user'].id_code, 'nick': self.scope['user'].username, "clientId": self.scope['user'].clientId, 'online': True, 'owner': self.scope['user'].clientId == self.room.owner['clientId'] and self.scope['user'].id_code == self.room.owner['code']}
|
|
|
|
await self.connect_participant()
|
|
|
|
self.clientId = self.scope['user'].clientId
|
|
|
|
await self.send(json.dumps({'type': "reconnected", "clientId": self.scope['user'].clientId, 'id_code': self.room_id, 'identity': self.user}))
|
|
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
|
|
else:
|
|
participants = await self.get_participants()
|
|
print(client in list(
|
|
map(lambda p: p['clientId'], participants)), client, list(map(lambda p: p['clientId'], participants)))
|
|
if client in list(map(lambda p: p['clientId'], participants)):
|
|
self.clientId = client
|
|
|
|
participant = list(
|
|
filter(lambda p: p['clientId'] == client, participants))[0]
|
|
|
|
if participant['clientId'] == self.room.owner['clientId'] and participant['code'] == self.room.owner['code']:
|
|
|
|
await self.channel_layer.group_add(f'owner__{self.room_id}', self.channel_name)
|
|
else:
|
|
|
|
await self.channel_layer.group_add(self.room_id, self.channel_name)
|
|
participant['online'] = True
|
|
self.user = participant
|
|
await self.connect_participant()
|
|
await self.send(json.dumps({'type': "reconnected", "clientId": client, 'id_code': self.room_id, 'identity': participant}))
|
|
await self.channel_layer.group_send(self.room_id, {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "reconnect.event", 'nick': self.user['nick']})
|
|
else:
|
|
await self.send(json.dumps({"type": "reconnectError", 'id_code': self.room_id}))
|
|
|
|
elif type == 'ban':
|
|
code = text_data_json['data']["code"]
|
|
nick = text_data_json['data']["nick"]
|
|
status = text_data_json['data']["status"]
|
|
if status == 'anonymous':
|
|
await self.del_participant(code)
|
|
else:
|
|
await self.del_user(code)
|
|
|
|
await self.channel_layer.group_send(self.room_id, {'type': "ban_participant", "code": code, "nick": nick})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "ban_participant", "code": code, "nick": nick})
|
|
elif type == 'leave':
|
|
code = text_data_json['data']["code"]
|
|
nick = text_data_json['data']["nick"]
|
|
clientId = text_data_json['data']["clientId"]
|
|
status = 'anonymous' if len(code) == 6 else 'user'
|
|
|
|
|
|
if status == 'anonymous':
|
|
participants = await self.get_participants()
|
|
participant = [p for p in participants if p['code'] == code]
|
|
|
|
if len(participant) == 0:
|
|
pass
|
|
else:
|
|
if clientId == participant[0]['clientId']:
|
|
await self.del_participant(code)
|
|
await self.channel_layer.group_send(self.room_id, {'type': "ban_participant", "code": code, "nick": nick})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "ban_participant", "code": code, "nick": nick})
|
|
else:
|
|
user = await self.get_user(code)
|
|
|
|
if self.scope['user'] == user:
|
|
await self.del_user(code)
|
|
await self.channel_layer.group_send(self.room_id, {'type': "ban_participant", "code": code, "nick": nick})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "ban_participant", "code": code, "nick": nick})
|
|
|
|
|
|
async def join_event(self, event):
|
|
await self.send(json.dumps({'type': 'joined', 'nick': event['nick'], "owner": event['owner'], "online": event['online'], "code": event["code"]}))
|
|
|
|
async def accept_room(self, event):
|
|
await self.send(json.dumps({'type': 'accept_room', 'id_code': self.room_id, 'code': event["code"]}))
|
|
|
|
async def accept_waiter(self, event):
|
|
await self.send(json.dumps({'type': 'joined', 'nick': event['nick'], "owner": event['owner'], "online": event['online'], "code": event["code"]}))
|
|
|
|
async def add_waiter(self, event):
|
|
await self.send(json.dumps({'type': 'add_waiter', 'nick': event['nick'], "code": event["code"], "status": event['status']}))
|
|
|
|
async def new_parcours(self, event):
|
|
await self.send(json.dumps({'type': "add_parcours", "parcours": event['parcours']}))
|
|
|
|
async def refused_participant(self, event):
|
|
await self.send(json.dumps({"type": "refused"}))
|
|
|
|
async def ban_participant(self, event):
|
|
await self.send(json.dumps({"type": "banned", 'nick': event['nick'], "code": event["code"]}))
|
|
|
|
@database_sync_to_async
|
|
def get_participants(self):
|
|
return Room.objects.filter(id_code=self.room_id)[0].anonymousMembers
|
|
|
|
@database_sync_to_async
|
|
def get_users(self):
|
|
return [UserSerializer(u).data for u in Room.objects.filter(id_code=self.room_id)[0].userMembers.all()]
|
|
|
|
@database_sync_to_async
|
|
def get_user(self, code):
|
|
return Room.objects.filter(id_code=self.room_id)[0].userMembers.get(id_code = code)
|
|
|
|
@database_sync_to_async
|
|
def get_room(self):
|
|
return Room.objects.filter(id_code=self.room_id)[0]
|
|
|
|
@database_sync_to_async
|
|
def add_participant(self, new, id):
|
|
return Room.objects.add_participant(self.room_id, new, id, False, True)
|
|
|
|
@database_sync_to_async
|
|
def add_user(self, code):
|
|
return Room.objects.add_user(self.room_id, code, False, True)
|
|
|
|
@database_sync_to_async
|
|
def del_participant(self, code):
|
|
return Room.objects.del_participant(self.room_id, code)
|
|
@database_sync_to_async
|
|
def del_user(self, code):
|
|
return Room.objects.del_user(self.room_id, code)
|
|
|
|
@database_sync_to_async
|
|
def add_waiter_db(self, new, isUser, code):
|
|
return Room.objects.add_waiter(self.room_id, new, isUser, code)
|
|
|
|
@database_sync_to_async
|
|
def del_waiter_db(self, code):
|
|
return Room.objects.del_waiter(self.room_id, code)
|
|
|
|
@database_sync_to_async
|
|
def disconnect_participant(self):
|
|
if self.scope['user'].is_anonymous:
|
|
return Room.objects.disconnect(self.room_id, self.user['code'])
|
|
else:
|
|
return Room.objects.disconnect(self.room_id, self.scope['user'].id_code)
|
|
|
|
@database_sync_to_async
|
|
def connect_participant(self):
|
|
return Room.objects.connect(self.room_id, self.user['code'])
|
|
|
|
|
|
@database_sync_to_async
|
|
def userInRoom(self):
|
|
if self.scope['user'].is_anonymous:
|
|
return None
|
|
return len(self.scope['user'].room_set.filter(
|
|
id_code=self.room.id_code)) != 0
|
|
|
|
async def disconnect(self, close_code):
|
|
|
|
if self.waiter == False and self.user != None:
|
|
await self.disconnect_participant()
|
|
await self.channel_layer.group_discard(self.room_id, self.channel_name)
|
|
await self.channel_layer.group_send(self.room_id, {"type": "disconnect.event", "nick": self.user['nick']})
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {"type": "disconnect.event", "nick": self.user['nick']})
|
|
|
|
elif self.waiter == True and self.waiter_code != None:
|
|
await self.del_waiter_db(self.waiter_code)
|
|
await self.channel_layer.group_send(f'owner__{self.room_id}', {'type': "del_waiter", "code": self.waiter_code})
|
|
await self.channel_layer.group_discard(f'waiter__{self.waiter_code}', self.channel_name)
|
|
|
|
async def disconnect_event(self, event):
|
|
await self.send(json.dumps({'type': 'disconnect_participant', "nick": event['nick']}))
|
|
|
|
async def room_deleted(self, event):
|
|
await self.send(json.dumps({'type': 'room_deleted'}))
|
|
|
|
async def reconnect_event(self, event):
|
|
await self.send(json.dumps({'type': 'reconnect_participant', "nick": event['nick']}))
|
|
|
|
async def del_waiter(self, event):
|
|
await self.send(json.dumps({"type": 'del_waiter', "code": event['code']}))
|
|
|
|
async def challenge_parcours(self, event):
|
|
await self.send(json.dumps({**event}))
|
|
|
|
async def delete_parcours(self, event):
|
|
await self.send(json.dumps({**event}))
|
|
|
|
async def edit_parcours(self, event):
|
|
await self.send(json.dumps({**event}))
|