Skip to content

Commit

Permalink
Merge pull request #83 from esoviscode/staging
Browse files Browse the repository at this point in the history
Release v0.1.3
  • Loading branch information
pcichowski authored Jan 19, 2023
2 parents cc1edbf + 00ff408 commit 6ecd786
Show file tree
Hide file tree
Showing 28 changed files with 877 additions and 306 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ name: "CodeQL"

on:
push:
branches: [ "main-TODO-REMOVE" ]
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main-TODO-REMOVE" ]
branches: [ "main" ]
schedule:
- cron: '22 4 * * 0'

Expand Down
Binary file added dnd-bot/dnd_bot/assets/gfx/entities/hole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dnd-bot/dnd_bot/assets/gfx/entities/rock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 19 additions & 15 deletions dnd-bot/dnd_bot/database/database_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,38 @@ class DatabaseConnection:
def connection_establish():
""" establishes connection with the database using the provided ip address, credentials and port
"""
db_address, db_name, db_user, db_password, db_port = DatabaseConnection.__connection_get_authentication__()
db_address, db_name, db_user, db_passwords, db_port = DatabaseConnection.__connection_get_authentication__()

print(f'DB: attempting connection to {db_name} database at {db_address}:{db_port}')
print(f'db: attempting connection to {db_name} database at {db_address}:{db_port}')

DatabaseConnection.connection = connect(database=db_name, user=db_user, password=db_password,
DatabaseConnection.connection = connect(database=db_name, user=db_user, password=db_passwords.pop(),
host=db_address, port=db_port)

# erase password in memory upon using it
db_passwords.clear()

DatabaseConnection.cursor = DatabaseConnection.connection.cursor()
print(f'DB: successfully connected')
print(f'db: successfully connected')

@staticmethod
def __connection_get_authentication__():
"""extracts database credentials and others from environment variables passed to the app
"""
passwords = []
address = os.getenv('DB_ADDRESS')
name = os.getenv('DB_NAME')
user = os.getenv('DB_USER')
password = os.getenv('DB_PASSWORD')
passwords.append(os.getenv('DB_PASSWORD'))
port = os.getenv('DB_PORT')

if not user:
user = 'admin'
if not password:
password = 'admin'
if passwords[0] is None:
passwords.append('admin')
if not port:
port = 5432

return address, name, user, password, port
return address, name, user, passwords, port

@staticmethod
def connection_close():
Expand All @@ -54,19 +58,19 @@ def execute_query(query: str):
DatabaseConnection.connection.commit()

@staticmethod
def add_game(token: str, id_host: int, id_campaign: int, game_state: str) -> int | None:
def add_game(token: str, id_host: int, game_state: str, campaign_name: str) -> int | None:
"""start game and add game to database
:param token: lobby/game token (5 digit password)
:param id_host: discord id of host
:param id_campaign: id of campaign
:param game_state: string enum, initial value of added game is 'LOBBY'
:param campaign_name: campaign name
:return:
on success: game id, on failure: None
"""

DatabaseConnection.cursor.execute('INSERT INTO public."Game" (token, id_host, id_campaign, game_state) VALUES '
DatabaseConnection.cursor.execute('INSERT INTO public."Game" (token, id_host, game_state, campaign_name) VALUES '
'(%s, %s, %s, %s)',
(token, id_host, id_campaign, game_state))
(token, id_host, game_state, campaign_name))
DatabaseConnection.cursor.execute('SELECT LASTVAL()')

try:
Expand Down Expand Up @@ -137,7 +141,7 @@ def find_game_by_token(token: str) -> dict | None:
def update_game_state(id_game: int, game_state: str) -> None:
"""updates game state on the one provided
"""
DatabaseConnection.cursor.execute('UPDATE public."Game" SET game_state = %s WHERE id_game = %s',
DatabaseConnection.cursor.execute('UPDATE public."Game" SET game_state = (%s) WHERE id_game = (%s)',
(game_state, id_game))

DatabaseConnection.connection.commit()
Expand All @@ -156,7 +160,7 @@ def get_all_game_tokens():
def get_id_game_from_game_token(token: str) -> int | None:
"""returns database game id based on the token, None if the query fails
"""
DatabaseConnection.cursor.execute(f'SELECT id_game FROM public."Game" WHERE token = %s', token)
DatabaseConnection.cursor.execute(f'SELECT id_game FROM public."Game" WHERE token = (%s)', (token,))
game_id = DatabaseConnection.cursor.fetchone()
DatabaseConnection.connection.commit()

Expand All @@ -169,7 +173,7 @@ def get_id_game_from_game_token(token: str) -> int | None:
def get_game_token_from_id_game(id_game: int) -> str | None:
"""returns game token based on database game id, None if the query fails
"""
DatabaseConnection.cursor.execute(f'SELECT token FROM public."Game" WHERE id_game = %s', id_game)
DatabaseConnection.cursor.execute(f'SELECT token FROM public."Game" WHERE id_game = (%s)', (id_game,))
game_token = DatabaseConnection.cursor.fetchone()
DatabaseConnection.connection.commit()

Expand Down
Empty file.
174 changes: 1 addition & 173 deletions dnd-bot/dnd_bot/dc/cogs/command_create.py
Original file line number Diff line number Diff line change
@@ -1,183 +1,11 @@
from threading import Thread

import nextcord
from nextcord import slash_command
from nextcord.ext.commands import Cog, Bot

from dnd_bot.dc.ui.message_templates import MessageTemplates
from dnd_bot.dc.ui.messager import Messager
from dnd_bot.dc.ui.views.view_movement import ViewMovement
from dnd_bot.dc.ui.views.view_lobby import HostButtons, JoinButton
from dnd_bot.dc.utils.utils import get_user_name_by_id
from dnd_bot.logic.game.game_loop import GameLoop
from dnd_bot.logic.game.handler_game import HandlerGame
from dnd_bot.logic.lobby.handler_create import HandlerCreate
from dnd_bot.logic.lobby.handler_join import HandlerJoin
from dnd_bot.logic.lobby.handler_ready import HandlerReady
from dnd_bot.logic.lobby.handler_start import HandlerStart
from dnd_bot.logic.prototype.entities.hole import Hole
from dnd_bot.logic.prototype.entities.rock import Rock
from dnd_bot.logic.prototype.multiverse import Multiverse
from dnd_bot.logic.prototype.player import Player


class JoinButton(nextcord.ui.View):

def __init__(self, token):
super().__init__()
self.value = None
self.token = token

@nextcord.ui.button(label="Join", style=nextcord.ButtonStyle.green)
async def join(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):

if interaction.user.dm_channel is None:
await interaction.user.create_dm()

status, lobby_players, error_message = await HandlerJoin.join_lobby(self.token, interaction.user.id,
interaction.user.dm_channel.id,
interaction.user.name)

if status:
await interaction.response.send_message("Check direct message!", ephemeral=True)

lobby_view_embed = MessageTemplates.lobby_view_message_template(self.token, lobby_players)

# send messages about successful join operation
await Messager.send_dm_message(interaction.user.id,
f"Welcome to lobby of game {self.token}.\nNumber of players in lob"
f"by: **{len(lobby_players)}**", embed=lobby_view_embed,
view=ReadyButton(self.token))
for user in lobby_players:
if interaction.user.name != user[0]:
if user[2]:
if user[1]:
if Multiverse.get_game(self.token).all_users_ready():
view = StartButton(self.token)
else:
view = HostButtonDisabled(self.token)
else:
view = HostButtons(self.token)
else:
if user[1]:
view = None
else:
view = ReadyButton(self.token)

await Messager.send_dm_message(user[3],
f"\n**{await get_user_name_by_id(interaction.user.id)}** has "
f"joined the lobby! Current number of "
f"players: **{len(lobby_players)}**",
embed=lobby_view_embed, view=view)
else:
await interaction.response.send_message(error_message, ephemeral=True)

self.value = False


class StartButton(nextcord.ui.View):
def __init__(self, token):
super().__init__()
self.value = None
self.token = token

@nextcord.ui.button(label="Start game", style=nextcord.ButtonStyle.blurple)
async def start(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):

status, lobby_players_identities, error_message = await HandlerStart.start_game(self.token, interaction.user.id)

if status:
await interaction.response.send_message('Starting the game!', ephemeral=True)

# send messages about successful start operation
for user in lobby_players_identities:
await Messager.send_dm_message(user, "Game has started successfully!\n")

map_view_message = MessageTemplates.map_view_template(self.token)

await Messager.send_dm_message(user, map_view_message, view=ViewMovement(self.token))

HandlerGame.handle_game(self.token)

else:
await interaction.response.send_message(error_message, ephemeral=True)


class HostButtonDisabled(nextcord.ui.View):
def __init__(self, token):
super().__init__()
self.value = None
self.token = token

@nextcord.ui.button(label='Start', style=nextcord.ButtonStyle.gray, disabled=True)
async def start(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
pass


class HostButtons(nextcord.ui.View):
def __init__(self, token):
super().__init__()
self.value = None
self.token = token

@nextcord.ui.button(label='Start', style=nextcord.ButtonStyle.gray, disabled=True)
async def start(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
pass

@nextcord.ui.button(label="Ready", style=nextcord.ButtonStyle.green)
async def ready(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):

lobby_players = await HandlerReady.on_ready(self.token, interaction.user.id)
lobby_view_embed = MessageTemplates.lobby_view_message_template(self.token, lobby_players)

for user in lobby_players:
if user[2]:
if user[1]:
if Multiverse.get_game(self.token).all_users_ready():
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=StartButton(self.token))
else:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed,
view=HostButtonDisabled(self.token))
else:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=HostButtons(self.token))
else:
if user[1]:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=None)
else:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=ReadyButton(self.token))

self.value = False


class ReadyButton(nextcord.ui.View):
def __init__(self, token):
super().__init__()
self.value = None
self.token = token

@nextcord.ui.button(label="Ready", style=nextcord.ButtonStyle.green)
async def ready(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):

lobby_players = await HandlerReady.on_ready(self.token, interaction.user.id)
lobby_view_embed = MessageTemplates.lobby_view_message_template(self.token, lobby_players)

for user in lobby_players:
if user[2]:
if user[1]:
if Multiverse.get_game(self.token).all_users_ready():
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed,
view=StartButton(self.token))
else:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed,
view=HostButtonDisabled(self.token))
else:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=HostButtons(self.token))
else:
if user[1]:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=None)
else:
await Messager.send_dm_message(user[3], "", embed=lobby_view_embed, view=ReadyButton(self.token))

self.value = False


class CommandCreate(Cog):
Expand Down
2 changes: 1 addition & 1 deletion dnd-bot/dnd_bot/dc/cogs/command_join.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from nextcord.ext.commands import Cog, Bot
from nextcord import slash_command

from dnd_bot.dc.cogs.command_create import HostButtons, HostButtonDisabled, StartButton, ReadyButton
from dnd_bot.dc.ui.views.view_lobby import StartButton, HostButtonDisabled, HostButtons, ReadyButton
from dnd_bot.dc.ui.message_templates import MessageTemplates
from dnd_bot.dc.ui.messager import Messager
from dnd_bot.dc.utils.utils import get_user_name_by_id
Expand Down
36 changes: 36 additions & 0 deletions dnd-bot/dnd_bot/dc/cogs/command_shutdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from nextcord.ext import commands
from nextcord.ext.commands import Cog, Bot
from nextcord import slash_command

from dnd_bot.logic.prototype.multiverse import Multiverse


class ShutdownCommand(Cog):
"""Handles shutting down the bot with all its threads"""
def __init__(self, bot: Bot):
self.bot = bot

@slash_command(name="shutdown", description="Shutdowns bot")
async def shutdown(self, interaction):
caller_id = interaction.user.id
# only these users can shut down the bot
if caller_id == 349553403229110274 \
or caller_id == 211188033968406530 \
or caller_id == 444538116569825290 \
or caller_id == 602785249025589259 \
or caller_id == 544262699907809309:
await interaction.response.send_message("Shutting down... :coffin:")

# stop all running game threads
for game in Multiverse.games.values():
game.game_state = "INACTIVE"
game.get_active_player().active = False
game.game_loop_thread.join()

await self.bot.close()
else:
await interaction.response.send_message("You have no permission to shutdown me :man_gesturing_no:!")


def setup(bot):
bot.add_cog(ShutdownCommand(bot))
23 changes: 0 additions & 23 deletions dnd-bot/dnd_bot/dc/cogs/command_tmp_game_view.py

This file was deleted.

4 changes: 3 additions & 1 deletion dnd-bot/dnd_bot/dc/init.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import threading

import nextcord
from nextcord.ext import commands
from nextcord import Intents
Expand Down Expand Up @@ -39,7 +41,7 @@ def bot_run():
raise KeyError(f'Failed to get configuration key. Env name: {env_token}')

print('Loading extensions:')
for filename in os.listdir('./dnd_bot/dc/cogs')[1:]:
for filename in os.listdir('./dnd_bot/dc/cogs'):
if filename.endswith('.py'):
bot.load_extension(f'dnd_bot.dc.cogs.{filename[:-3]}')
print(f' {filename[:-3]}')
Expand Down
Binary file added dnd-bot/dnd_bot/dc/ui/map1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 6ecd786

Please sign in to comment.