Archived
discord login
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import requests
|
||||
import os
|
||||
|
||||
|
||||
def discord_process_code(code: str) -> dict | None:
|
||||
response = requests.post(
|
||||
url="https://discord.com/api/oauth2/token",
|
||||
headers={
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data={
|
||||
"client_id": os.environ["DISCORD_CLIENTID"],
|
||||
"client_secret": os.environ["DISCORD_CLIENTSECRET"],
|
||||
"code": code,
|
||||
"grant_type": "authorization_code",
|
||||
"redirect_uri": os.environ["FRONTEND_ENDPOINT"] + "/login",
|
||||
"scope": "identify",
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
json_data = response.json()
|
||||
if "error" in json_data:
|
||||
print(json_data)
|
||||
return None
|
||||
|
||||
token_type = json_data["token_type"]
|
||||
access_token = json_data["access_token"]
|
||||
|
||||
response = requests.get(
|
||||
url="https://discord.com/api/users/@me",
|
||||
headers={
|
||||
"authorization": token_type + " " + access_token,
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
return response.json()
|
||||
+134
-76
@@ -4,11 +4,14 @@ from typing import Callable, Any, TYPE_CHECKING
|
||||
from pydantic import ValidationError
|
||||
|
||||
from websockets.server import WebSocketServerProtocol
|
||||
from websockets.exceptions import ConnectionClosedOK
|
||||
|
||||
from netcode.models import Message, LoginMessage
|
||||
from netcode.models import Message, LoginMessage, MessageType
|
||||
|
||||
from model import Player
|
||||
|
||||
from .auth import discord_process_code
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from controller import GameController
|
||||
|
||||
@@ -55,7 +58,7 @@ class ClientController:
|
||||
"""Hooks the client to the correct listen callbacks"""
|
||||
await self.send(
|
||||
Message(
|
||||
type="context",
|
||||
type=MessageType.CONTEXT,
|
||||
data_type="game_context_id",
|
||||
data="login",
|
||||
)
|
||||
@@ -68,15 +71,18 @@ class ClientController:
|
||||
|
||||
async def send(self, message: Message) -> None:
|
||||
"""Send a Message object to the connected client"""
|
||||
await self.websocket.send(message.model_dump_json())
|
||||
try:
|
||||
await self.websocket.send(message.model_dump_json())
|
||||
except ConnectionClosedOK:
|
||||
print("Connection Closed")
|
||||
|
||||
async def send_error(self, error: str) -> None:
|
||||
"""Send an error string to the connected client"""
|
||||
await self.send(Message(type="error", data_type="error", data=error))
|
||||
await self.send(Message(type=MessageType.ERROR, data_type="error", data=error))
|
||||
|
||||
async def send_announce_dict(
|
||||
self,
|
||||
notification_type: str,
|
||||
notification_type: MessageType,
|
||||
data: dict,
|
||||
player_filter: Callable[[Player], Any] = lambda x: True,
|
||||
):
|
||||
@@ -89,65 +95,15 @@ class ClientController:
|
||||
Message(type=notification_type, data_type="object", data=data)
|
||||
)
|
||||
|
||||
@vibe_check(Message)
|
||||
async def game_context(self, message: Message) -> None:
|
||||
"""Handles all messages related to when the current client is logged in
|
||||
and connected to a running game"""
|
||||
|
||||
if message.type == "temp_action":
|
||||
if message.data_type == "set_health":
|
||||
self.player.team.health = message.data
|
||||
return await self.game_controller.game.notify_controller(
|
||||
"update", self.player.team.serialize_guest()
|
||||
)
|
||||
|
||||
if self.player.team != self.game_controller.game.current_turn:
|
||||
return await self.send_error("it is not your turn to play!")
|
||||
if message.type == "action":
|
||||
# TODO : pydantic type check for message.data
|
||||
match message.data_type:
|
||||
case "play_card":
|
||||
return await self.player.play_card(message.data)
|
||||
|
||||
case "discard":
|
||||
return await self.player.turn.discard_card(message.data)
|
||||
|
||||
case "lock_card":
|
||||
return await self.player.turn.lock_card(message.data)
|
||||
|
||||
case "use_effect":
|
||||
return await self.player.turn.use_effect_with_check(
|
||||
message.data.get("effect_id"), message.data.get("target")
|
||||
)
|
||||
|
||||
case "buy":
|
||||
return await self.player.turn.buy_card(message.data)
|
||||
|
||||
case "heal":
|
||||
return await self.player.turn.heal(message.data)
|
||||
|
||||
case "damage_team":
|
||||
return await self.player.turn.damage_team(message.data)
|
||||
|
||||
case "damage_champion":
|
||||
return await self.player.turn.damage_champion(message.data)
|
||||
|
||||
case "end_turn":
|
||||
return await self.player.turn.end_turn()
|
||||
|
||||
return await self.send_error(
|
||||
"Couldn't process action with data_type : " + message.data_type
|
||||
)
|
||||
|
||||
@vibe_check(LoginMessage)
|
||||
async def login_context(self, message: LoginMessage) -> None:
|
||||
"""Handles all messages related to when the current client isn't yet logged in"""
|
||||
username = message.data
|
||||
if self.game_controller.game.started:
|
||||
return await self.send_error(
|
||||
"you cannot interact with a game that has already started"
|
||||
)
|
||||
if message.type == "register":
|
||||
if message.type == MessageType.REGISTER:
|
||||
if self.game_controller.game.started:
|
||||
return await self.send_error(
|
||||
"you cannot interact with a game that has already started"
|
||||
)
|
||||
if len(username) < 3:
|
||||
return await self.send_error(
|
||||
"username must be longer than 3 characters"
|
||||
@@ -157,36 +113,81 @@ class ClientController:
|
||||
return await self.send_error("username already exists")
|
||||
|
||||
player = await self.game_controller.game.create_player(username)
|
||||
elif message.type == "login":
|
||||
elif message.type == MessageType.LOGIN:
|
||||
player2 = self.game_controller.game.get_player(username)
|
||||
|
||||
if player2 is None:
|
||||
return await self.send_error("player doesn't exists")
|
||||
|
||||
player = player2
|
||||
elif message.type == MessageType.DISCORD_LOGIN:
|
||||
user = discord_process_code(message.data)
|
||||
if user is None:
|
||||
await self.send_error("discord login not successful")
|
||||
return
|
||||
username = user["global_name"]
|
||||
player = next(
|
||||
(
|
||||
p
|
||||
for p in self.game_controller.game.players
|
||||
if p.discord_id == user["id"]
|
||||
),
|
||||
None,
|
||||
)
|
||||
if player is None:
|
||||
if self.game_controller.game.started:
|
||||
return await self.send_error(
|
||||
"you cannot interact with a game that has already started"
|
||||
)
|
||||
player = await self.game_controller.game.create_player(username)
|
||||
|
||||
player.discord_id = user["id"]
|
||||
player.image = (
|
||||
"https://cdn.discordapp.com/avatars/"
|
||||
+ user["id"]
|
||||
+ "/"
|
||||
+ user["avatar"]
|
||||
+ ".webp"
|
||||
)
|
||||
else:
|
||||
return await self.send_error("invalid message type for context")
|
||||
|
||||
self.player = player
|
||||
self.player.team.listeners.append(self.send_announce_dict)
|
||||
self.on_message = self.pregame_context
|
||||
if self.game_controller.game.started:
|
||||
self.on_message = self.game_context
|
||||
await self.send(
|
||||
Message(
|
||||
type=MessageType.CONTEXT, data_type="game_context_id", data="game"
|
||||
)
|
||||
)
|
||||
for p in self.game_controller.game.players:
|
||||
if p.team == player.team:
|
||||
await self.send(
|
||||
Message(
|
||||
type=MessageType.UPDATE,
|
||||
data_type="object",
|
||||
data=player.serialize_team(),
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.on_message = self.pregame_context
|
||||
await self.send(
|
||||
Message(
|
||||
type=MessageType.CONTEXT,
|
||||
data_type="game_context_id",
|
||||
data="pregame",
|
||||
)
|
||||
)
|
||||
print("user logged in : " + username)
|
||||
|
||||
await self.send(
|
||||
Message(
|
||||
type="set",
|
||||
type=MessageType.SET,
|
||||
data_type="self",
|
||||
data=self.player.uuid,
|
||||
)
|
||||
)
|
||||
await self.send(
|
||||
Message(
|
||||
type="context",
|
||||
data_type="game_context_id",
|
||||
data="pregame",
|
||||
)
|
||||
)
|
||||
|
||||
@vibe_check(Message)
|
||||
async def pregame_context(self, message: Message) -> None:
|
||||
@@ -197,9 +198,66 @@ class ClientController:
|
||||
if all(p.ready for p in self.game_controller.game.players):
|
||||
await self.game_controller.start_game()
|
||||
|
||||
elif message.type == "temp_action":
|
||||
if message.data_type == "set_health":
|
||||
self.player.team.health = message.data
|
||||
await self.game_controller.game.notify_controller(
|
||||
"update", self.player.team.serialize_guest()
|
||||
)
|
||||
@vibe_check(Message)
|
||||
async def game_context(self, message: Message) -> None:
|
||||
"""Handles all messages related to when the current client is logged in
|
||||
and connected to a running game"""
|
||||
|
||||
# if message.type == "temp_action":
|
||||
# if message.data_type == "set_health":
|
||||
# self.player.team.health = message.data
|
||||
# return await self.game_controller.game.notify_controller(
|
||||
# "update", self.player.team.serialize_guest()
|
||||
# )
|
||||
|
||||
if self.player.team != self.game_controller.game.current_turn:
|
||||
return await self.send_error("it is not your turn to play!")
|
||||
if message.type == "action":
|
||||
# TODO : pydantic type check for message.data
|
||||
match message.data_type:
|
||||
case "play_card":
|
||||
if not isinstance(message.data, str):
|
||||
return
|
||||
return await self.player.play_card(message.data)
|
||||
|
||||
case "discard":
|
||||
if not isinstance(message.data, str):
|
||||
return
|
||||
return await self.player.turn.discard_card(message.data)
|
||||
|
||||
case "lock_card":
|
||||
if not isinstance(message.data, str):
|
||||
return
|
||||
return await self.player.turn.lock_card(message.data)
|
||||
|
||||
case "use_effect":
|
||||
return await self.player.turn.use_effect_with_check(
|
||||
message.data.get("effect_id"), message.data.get("target")
|
||||
)
|
||||
|
||||
case "buy":
|
||||
if not isinstance(message.data, str):
|
||||
return
|
||||
return await self.player.turn.buy_card(message.data)
|
||||
|
||||
case "heal":
|
||||
if not isinstance(message.data, int):
|
||||
return
|
||||
return await self.player.turn.heal(message.data)
|
||||
|
||||
case "damage_team":
|
||||
if not isinstance(message.data, str):
|
||||
return
|
||||
return await self.player.turn.damage_team(message.data)
|
||||
|
||||
case "damage_champion":
|
||||
if not isinstance(message.data, str):
|
||||
return
|
||||
return await self.player.turn.damage_champion(message.data)
|
||||
|
||||
case "end_turn":
|
||||
return await self.player.turn.end_turn()
|
||||
|
||||
return await self.send_error(
|
||||
"Couldn't process action with data_type : " + message.data_type
|
||||
)
|
||||
|
||||
+15
-11
@@ -1,8 +1,9 @@
|
||||
import asyncio
|
||||
from typing import Callable, List, Any
|
||||
from websockets.exceptions import ConnectionClosedOK
|
||||
from netcode import WSServer
|
||||
from netcode.ws_server import WebSocketServerProtocol
|
||||
from netcode.models import Message
|
||||
from netcode.models import Message, MessageType
|
||||
from model import Game, Player
|
||||
from controller import (
|
||||
ClientController,
|
||||
@@ -31,14 +32,17 @@ class GameController:
|
||||
self.clients.remove(client)
|
||||
|
||||
async def send(self, message: Message, websocket: WebSocketServerProtocol):
|
||||
await websocket.send(message.model_dump_json())
|
||||
try:
|
||||
await websocket.send(message.model_dump_json())
|
||||
except ConnectionClosedOK:
|
||||
print("Connection Closed")
|
||||
|
||||
async def broadcast(self, message: Message):
|
||||
await self.server.broadcast(message.model_dump_json())
|
||||
|
||||
async def broadcast_announce_dict(
|
||||
self,
|
||||
notification_type: str,
|
||||
notification_type: MessageType,
|
||||
data: dict,
|
||||
player_filter: Callable[[Player], Any],
|
||||
):
|
||||
@@ -58,7 +62,7 @@ class GameController:
|
||||
|
||||
async def announce_dict(
|
||||
self,
|
||||
notification_type: str,
|
||||
notification_type: MessageType,
|
||||
data: dict,
|
||||
websocket: WebSocketServerProtocol,
|
||||
):
|
||||
@@ -74,39 +78,39 @@ class GameController:
|
||||
async def announce_game(self, websocket: WebSocketServerProtocol):
|
||||
for effect in self.game.effects:
|
||||
await self.announce_dict(
|
||||
"create",
|
||||
MessageType.CREATE,
|
||||
effect.serialize(),
|
||||
websocket,
|
||||
)
|
||||
|
||||
for card in self.game.cards:
|
||||
await self.announce_dict(
|
||||
"create",
|
||||
MessageType.CREATE,
|
||||
card.serialize(),
|
||||
websocket,
|
||||
)
|
||||
|
||||
for team in self.game.teams:
|
||||
await self.announce_dict(
|
||||
"create",
|
||||
MessageType.CREATE,
|
||||
team.serialize(),
|
||||
websocket,
|
||||
)
|
||||
|
||||
for player in self.game.players:
|
||||
await self.announce_dict(
|
||||
"create",
|
||||
MessageType.CREATE,
|
||||
player.turn.serialize(),
|
||||
websocket,
|
||||
)
|
||||
await self.announce_dict(
|
||||
"create",
|
||||
MessageType.CREATE,
|
||||
player.serialize_guest(),
|
||||
websocket,
|
||||
)
|
||||
|
||||
await self.announce_dict(
|
||||
"create",
|
||||
MessageType.CREATE,
|
||||
self.game.serialize_guest(),
|
||||
websocket,
|
||||
)
|
||||
@@ -119,5 +123,5 @@ class GameController:
|
||||
for c in self.clients:
|
||||
c.on_message = c.game_context
|
||||
await self.broadcast(
|
||||
Message(type="context", data_type="game_context_id", data="game")
|
||||
Message(type=MessageType.CONTEXT, data_type="game_context_id", data="game")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user