From d54bdf3b788e97d6b6f1be8c6e3b142f8dfea155 Mon Sep 17 00:00:00 2001 From: adavila0703 <36370758+adavila0703@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:00:07 -0500 Subject: [PATCH 1/2] fixed chat duplicaiton bug when a command was issued, tested working ocr --- src/bot/bot.py | 2 ++ src/events/messages.py | 19 +++++++------------ src/state/tournament_state.py | 23 +++++++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/bot/bot.py b/src/bot/bot.py index a7e7a76..ad55042 100644 --- a/src/bot/bot.py +++ b/src/bot/bot.py @@ -1,11 +1,13 @@ from discord.ext.commands import Bot from src.vars.vars import ENV from src.commands.tournament_commands import TournamentCommander +from src.events.messages import MessageCoordinator BOT = Bot(command_prefix='!') # TODO: Need to add message and user_commmand cog to bot BOT.add_cog(TournamentCommander(BOT)) +BOT.add_cog(MessageCoordinator(BOT)) BOT.remove_command('help') def run_bot(): diff --git a/src/events/messages.py b/src/events/messages.py index d94a289..3c337fe 100644 --- a/src/events/messages.py +++ b/src/events/messages.py @@ -1,13 +1,11 @@ from discord import Message -from discord.channel import TextChannel from src.ocr.ocr import ocr import os from src.state.tournament_state import TOURNAMENT_STATE, TournamentState from discord.ext import commands from src.utils.status import MESSAGE_STATUS as STATUS from src.utils import logger -from src.ocr import ocr class MessageCoordinator(commands.Cog): def __init__( @@ -26,15 +24,12 @@ def __init__( async def on_message(self, message: Message): """Event which handles reading the screenshot information""" if message.author == self.bot.user: - status = STATUS['BOT_MESSAGE'] - await self.logger.message_to_channel(message.channel, status, None) - return status + return STATUS['BOT_MESSAGE'] - await self.bot.process_commands(message) if message.attachments == []: - status = STATUS['BOT_MESSAGE'] - await self.logger.message_to_channel(message.channel, status, None) - return STATUS['NO_ATTACHMENTS'] + status = STATUS['NO_ATTACHMENTS'] + print(status) + return status channel = message.channel @@ -44,7 +39,7 @@ async def on_message(self, message: Message): if not self.tournament_state.valid_tournament_player(tournament_id, user): status = STATUS['TOURNAMENT_OR_PLAYER_NOT_VALID'] - await self.logger.message_to_channel(message.channel, status, None) + print(status) return status path = './' + user + '.png' @@ -64,5 +59,5 @@ async def on_message(self, message: Message): self.tournament_state.record_player_stats(tournament_id, user, stats) await channel.send(f'User: {user} Game Stats: {stats}') status = STATUS['PLAYER_STATS_RECORDED'] - await self.logger.message_to_channel(message.channel, status, None) - return status + print(status) + return status \ No newline at end of file diff --git a/src/state/tournament_state.py b/src/state/tournament_state.py index e2b8251..2dc228c 100644 --- a/src/state/tournament_state.py +++ b/src/state/tournament_state.py @@ -89,18 +89,21 @@ async def start_signups(self, ctx: Context, id: int, reaction: Reaction): def start_tournament(self, id: str) -> STATUS: """Sets tournament stats to True and sets the signed up players to the active list""" - response, content = self.client.get_data('/') - - if response.status_code != 200: - return STATUS['ERROR_STATUS_CODE'] - - tournament = self.tournaments[id] - tournament['status'] = True - tournament['players_attended'] = tournament['players_signed_up'] - - response = self.client.send_data('/start_tournament', { 'id': tournament['id'], 'tournament': tournament }, 'start_tournament') + # TODO Create method to check of if tournament exists + # labels: quick, state, duplicate + # This is code duplication, create a method for this + if (tournament := self.tournaments.get(id)) == None: + return STATUS['TOURNAMENT_NOT_FOUND'] + if tournament['status'] == False: + response = self.client.send_data('/start_tournament', { 'id': tournament['id'], 'tournament': tournament }, 'start_tournament') + + if response.status_code != 200: + return STATUS['ERROR_STATUS_CODE'] + tournament['status'] = True + tournament['players_attended'] = tournament['players_signed_up'] + return STATUS['TOURNAMENT_STARTED'] def player_signed_up(self, id, player): From b167553c6b2660719c5ec89d46f08da5caf6f0d7 Mon Sep 17 00:00:00 2001 From: adavila0703 <36370758+adavila0703@users.noreply.github.com> Date: Sun, 26 Sep 2021 14:05:15 -0500 Subject: [PATCH 2/2] revamped test for start_tournament, converted status from dictionary to enum --- src/events/messages.py | 10 +++--- src/state/tournament_state.py | 40 ++++++++++++------------ src/tests/events/test_messages.py | 12 +++---- src/tests/state/test_tournament_state.py | 34 ++++++++++---------- src/utils/status.py | 32 ++++++++++--------- test.py | 15 +++++++++ 6 files changed, 79 insertions(+), 64 deletions(-) create mode 100644 test.py diff --git a/src/events/messages.py b/src/events/messages.py index 3c337fe..92a3b53 100644 --- a/src/events/messages.py +++ b/src/events/messages.py @@ -4,7 +4,7 @@ import os from src.state.tournament_state import TOURNAMENT_STATE, TournamentState from discord.ext import commands -from src.utils.status import MESSAGE_STATUS as STATUS +from src.utils.status import MessageStatus from src.utils import logger class MessageCoordinator(commands.Cog): @@ -24,10 +24,10 @@ def __init__( async def on_message(self, message: Message): """Event which handles reading the screenshot information""" if message.author == self.bot.user: - return STATUS['BOT_MESSAGE'] + return MessageStatus.BOT_MESSAGE if message.attachments == []: - status = STATUS['NO_ATTACHMENTS'] + status = MessageStatus.NO_ATTACHMENTS print(status) return status @@ -38,7 +38,7 @@ async def on_message(self, message: Message): tournament_id = category[len(category) - 1] if not self.tournament_state.valid_tournament_player(tournament_id, user): - status = STATUS['TOURNAMENT_OR_PLAYER_NOT_VALID'] + status = MessageStatus.TOURNAMENT_OR_PLAYER_NOT_VALID print(status) return status @@ -58,6 +58,6 @@ async def on_message(self, message: Message): self.tournament_state.record_player_stats(tournament_id, user, stats) await channel.send(f'User: {user} Game Stats: {stats}') - status = STATUS['PLAYER_STATS_RECORDED'] + status = MessageStatus.PLAYER_STATS_RECORDED print(status) return status \ No newline at end of file diff --git a/src/state/tournament_state.py b/src/state/tournament_state.py index 2dc228c..a86329d 100644 --- a/src/state/tournament_state.py +++ b/src/state/tournament_state.py @@ -5,7 +5,7 @@ from src.client.tournament_client import TOURNAMENT_CLIENT as tournament_client, TournamentClient from src.bot.bot_commands import BotCommands from src.utils.output_message import OUTPUTS -from src.utils.status import TOURNAMENT_STATUS as STATUS +from src.utils.status import TournamentStatus class TournamentState: """Holds state of all created tournaments""" @@ -34,7 +34,7 @@ def get_all_tournaments(self): response, content = self.client.get_data('/get_all_tournaments') if response.status_code != 200: - return STATUS['ERROR_STATUS_CODE'] + return {} return content @@ -49,11 +49,11 @@ def create_tournament( response = self.client.send_data('/create_tournament', as_dict, 'create_tournament') print(response.status_code) if response.status_code != 200: - return STATUS['ERROR_STATUS_CODE'] + return TournamentStatus.ERROR_STATUS_CODE self.tournaments[tournament.id] = as_dict # print('Client -> ', self.tournaments) - return { STATUS['TOURNAMENT_CREATED']: as_dict } + return { TournamentStatus.TOURNAMENT_CREATED: as_dict } def delete_tournament( self, @@ -63,12 +63,12 @@ def delete_tournament( response = self.client.send_data('/delete_tournament', { 'id': id }, 'delete_tournament') if response.status_code != 200: - return STATUS['ERROR_STATUS_CODE'] + return TournamentStatus.ERROR_STATUS_CODE if self.tournaments.get(id): self.tournaments.pop(id) - return { STATUS['TOURNAMENT_DELETED']: id } + return { TournamentStatus.TOURNAMENT_DELETED: id } def show_tournament_list(self): """Shows a list of created tournaments""" @@ -85,37 +85,37 @@ async def start_signups(self, ctx: Context, id: int, reaction: Reaction): # labels: state # Do a check if the category and channel have already been created. await self.start_signup_command(ctx, self.tournaments[id]['channel_name'], f'General - {id}', reaction, OUTPUTS['SIGNUP']) - return STATUS['SIGNUPS_STARTED'] + return TournamentStatus.SIGNUPS_STARTED - def start_tournament(self, id: str) -> STATUS: + def start_tournament(self, id: str) -> TournamentStatus: """Sets tournament stats to True and sets the signed up players to the active list""" # TODO Create method to check of if tournament exists # labels: quick, state, duplicate # This is code duplication, create a method for this if (tournament := self.tournaments.get(id)) == None: - return STATUS['TOURNAMENT_NOT_FOUND'] + return TournamentStatus.TOURNAMENT_NOT_FOUND if tournament['status'] == False: response = self.client.send_data('/start_tournament', { 'id': tournament['id'], 'tournament': tournament }, 'start_tournament') if response.status_code != 200: - return STATUS['ERROR_STATUS_CODE'] + return TournamentStatus.ERROR_STATUS_CODE tournament['status'] = True tournament['players_attended'] = tournament['players_signed_up'] - return STATUS['TOURNAMENT_STARTED'] + return TournamentStatus.TOURNAMENT_STARTED def player_signed_up(self, id, player): """Stores the player who just signed up in state and sends data to API""" response = self.client.send_data('/player_signed_up', { 'id': id, 'player': player }, 'player_signed_up') - - if response == 200: - return STATUS['ERROR_STATUS_CODE'] + print(response.status_code) + if response.status_code != 200: + return TournamentStatus.ERROR_STATUS_CODE self.tournaments[id]['players_signed_up'].append(player) print('Client -> ', self.tournaments) - return STATUS['PLAYER_SIGNED_UP'] + return TournamentStatus.PLAYER_SIGNED_UP def player_removed_from_signups(self, id, player): """Removes player from signups""" @@ -123,12 +123,12 @@ def player_removed_from_signups(self, id, player): player_list = self.tournaments[id]['players_signed_up'] if response == 200: - return STATUS['ERROR_STATUS_CODE'] + return TournamentStatus.ERROR_STATUS_CODE if player in player_list: player_list.remove(player) print('Client -> ', self.tournaments) - return STATUS['PLAYER_SIGNED_UP'] + return TournamentStatus.PLAYER_SIGNED_UP def valid_tournament_player(self, id: str, player: str) -> bool: """Checks if the incoming tournment exists, is active and the player is also active""" @@ -145,10 +145,10 @@ def record_player_stats(self, id: str, player: str, stats: dict): response, content = self.client.get_data('/') if response.status_code != 200: - return STATUS['ERROR_STATUS_CODE'] + return TournamentStatus.ERROR_STATUS_CODE if (tournament := self.tournaments.get(id)) == None: - return STATUS['TOURNAMENT_NOT_FOUND'] + return TournamentStatus.TOURNAMENT_NOT_FOUND self.client.send_data('/record_player_stats', { 'id': id, 'stats': stats, 'player': player }, 'record_player_stats') @@ -158,8 +158,8 @@ def record_player_stats(self, id: str, player: str, stats: dict): player_stats[player] = { '1': stats } else: player_stats[player][str(len(player_stats[player]) + 1)] = stats - return player_stats + bot_commands = BotCommands() TOURNAMENT_STATE = TournamentState(tournament_client, uuid, bot_commands._start_sign_ups) diff --git a/src/tests/events/test_messages.py b/src/tests/events/test_messages.py index a598e37..06f85b2 100644 --- a/src/tests/events/test_messages.py +++ b/src/tests/events/test_messages.py @@ -1,10 +1,8 @@ -from discord import channel, message -from discord.ext.commands.errors import BotMissingAnyRole from src.events.messages import MessageCoordinator from unittest.mock import Mock import pytest from src.tests.future_creator import future_creator -from src.utils.status import MESSAGE_STATUS as STATUS +from src.utils.status import MessageStatus # TODO Mocks require cleanup # labels: tests @@ -36,7 +34,7 @@ async def test_on_message_bot_message(): "Tests if the incoming message is equal to a bot" message_mock.author = 'bot' result = await coordinator.on_message(message_mock) - assert result == STATUS['BOT_MESSAGE'] + assert result == MessageStatus.BOT_MESSAGE @pytest.mark.asyncio async def test_on_message_no_attachments(): @@ -44,7 +42,7 @@ async def test_on_message_no_attachments(): message_mock.attachments = [] message_mock.author = 'TestUser#1' result = await coordinator.on_message(message_mock) - assert result == STATUS['NO_ATTACHMENTS'] + assert result == MessageStatus.NO_ATTACHMENTS @pytest.mark.asyncio async def test_on_message_valid_tournament(): @@ -57,7 +55,7 @@ async def test_on_message_valid_tournament(): 'test' ] result = await coordinator.on_message(message_mock) - assert result == STATUS['TOURNAMENT_OR_PLAYER_NOT_VALID'] + assert result == MessageStatus.TOURNAMENT_OR_PLAYER_NOT_VALID @pytest.mark.asyncio async def test_on_message_success(): @@ -72,5 +70,5 @@ async def test_on_message_success(): message_mock ] result = await coordinator.on_message(message_mock) - assert result == STATUS['PLAYER_STATS_RECORDED'] + assert result == MessageStatus.PLAYER_STATS_RECORDED diff --git a/src/tests/state/test_tournament_state.py b/src/tests/state/test_tournament_state.py index 08dd1cb..a9c860d 100644 --- a/src/tests/state/test_tournament_state.py +++ b/src/tests/state/test_tournament_state.py @@ -1,7 +1,9 @@ from asyncio import Future +from src.tests.future_creator import future_creator from unittest.mock import Mock import pytest from src.state.tournament_state import TournamentState +from src.utils.status import TournamentStatus uuid = Mock() @@ -11,10 +13,8 @@ bad_status = Mock() ctx_mock = Mock() start_up_mock = Mock() -future = Future() -future.set_result('') -start_up_mock.return_value = future +start_up_mock.return_value = future_creator('') good_status.status_code = 200 bad_status.status_code = 400 @@ -42,7 +42,7 @@ def pytest_reset_mocks(): def test_create_tournament(): happy = tournament_state_happy.create_tournament('name') assert happy == { - 'TOURNAMENT_CREATED': { + TournamentStatus.TOURNAMENT_CREATED: { 'id': '123-321', 'name': 'name', 'status': False, @@ -52,21 +52,21 @@ def test_create_tournament(): 'channel_name': 'name_123-321' } } - client_happy.send_data.assert_called_with('/create_tournament', happy['TOURNAMENT_CREATED'], 'create_tournament') + client_happy.send_data.assert_called_with('/create_tournament', happy[TournamentStatus.TOURNAMENT_CREATED], 'create_tournament') sad = tournament_state_sad.create_tournament('name') - assert sad == 'ERROR_STATUS_CODE' + assert sad == TournamentStatus.ERROR_STATUS_CODE # writing this realizing we weren't doing a check if the id exists def test_delete_tournament(): happy = tournament_state_happy.delete_tournament('id') - assert happy == {'TOURNAMENT_DELETED': 'id'} + assert happy == { TournamentStatus.TOURNAMENT_DELETED: 'id' } # TODO: Assertion error in test # labels: Tests # client_happy.send_data.assert_called_with('/create_tournament', { 'id': 'id' }, 'create_tournament') sad = tournament_state_sad.delete_tournament('id') - assert sad == 'ERROR_STATUS_CODE' + assert sad == TournamentStatus.ERROR_STATUS_CODE def test_get_all_tournaments(): happy = tournament_state_happy.get_all_tournaments() @@ -85,7 +85,7 @@ def test_get_all_tournaments(): client_happy.get_data.assert_called_with('/get_all_tournaments') sad = tournament_state_sad.get_all_tournaments() - assert sad == 'ERROR_STATUS_CODE' + assert sad == {} def test_show_tournament_list(): happy = tournament_state_happy.show_tournament_list() @@ -118,26 +118,27 @@ def test_show_tournament(): @pytest.mark.asyncio async def test_start_signups(): status = await tournament_state_happy.start_signups(ctx_mock, '123-321', 'rection') - assert status == 'SIGNUPS_STARTED' + assert status == TournamentStatus.SIGNUPS_STARTED def test_start_tournament(): happy = tournament_state_happy.start_tournament('123-321') - assert happy == 'TOURNAMENT_STARTED' + assert happy == TournamentStatus.TOURNAMENT_STARTED sad = tournament_state_sad.start_tournament('123-321') - assert sad == 'ERROR_STATUS_CODE' + assert sad == TournamentStatus.TOURNAMENT_NOT_FOUND def test_player_signed_up(): happy = tournament_state_happy.player_signed_up('123-321', 'player') - assert happy == 'PLAYER_SIGNED_UP' + assert happy == TournamentStatus.PLAYER_SIGNED_UP - sad = tournament_state_sad.start_tournament('123-321') - assert sad == 'ERROR_STATUS_CODE' + sad = tournament_state_sad.player_signed_up('123-321', 'player') + assert sad == TournamentStatus.ERROR_STATUS_CODE # TODO: Tournament state reset # labels: Tests # State is retaining during this test, implement a way to reset the state after each test. def test_valid_tournament_player(): + print(tournament_state_happy.tournaments) check_all = tournament_state_happy.valid_tournament_player('123-321', 'player') check_player = tournament_state_happy.valid_tournament_player('123-321', 'other_player') @@ -154,8 +155,7 @@ def test_valid_tournament_player(): def test_record_player_stats(): happy = tournament_state_happy.record_player_stats('123-321', 'player', [1, 2, 3]) - print(happy) assert happy == {'player': {'1': [1, 2, 3]}} sad = tournament_state_sad.record_player_stats('123-321', 'player', [1, 2, 3]) - assert sad == 'ERROR_STATUS_CODE' + assert sad == TournamentStatus.ERROR_STATUS_CODE diff --git a/src/utils/status.py b/src/utils/status.py index 2380e7f..915737b 100644 --- a/src/utils/status.py +++ b/src/utils/status.py @@ -1,16 +1,18 @@ -TOURNAMENT_STATUS = { - 'TOURNAMENT_CREATED': 'TOURNAMENT_CREATED', - 'TOURNAMENT_DELETED': 'TOURNAMENT_DELETED', - 'TOURNAMENT_STARTED': 'TOURNAMENT_STARTED', - 'SIGNUPS_STARTED': 'SIGNUPS_STARTED', - 'PLAYER_SIGNED_UP': 'PLAYER_SIGNED_UP', - 'ERROR_STATUS_CODE': 'ERROR_STATUS_CODE', - 'TOURNAMENT_NOT_FOUND': 'TOURNAMENT_NOT_FOUND' -} +from enum import Enum, unique -MESSAGE_STATUS = { - 'BOT_MESSAGE': 'BOT_MESSAGE', - 'NO_ATTACHMENTS': 'NO_ATTACHMENTS', - 'TOURNAMENT_OR_PLAYER_NOT_VALID': 'TOURNAMENT_OR_PLAYER_NOT_VALID', - 'PLAYER_STATS_RECORDED': 'PLAYER_STATS_RECORDED', -} \ No newline at end of file +@unique +class TournamentStatus(Enum): + TOURNAMENT_CREATED = 'TOURNAMENT_CREATED' + TOURNAMENT_DELETED = 'TOURNAMENT_DELETED' + TOURNAMENT_STARTED = 'TOURNAMENT_STARTED' + SIGNUPS_STARTED = 'SIGNUPS_STARTED' + PLAYER_SIGNED_UP = 'PLAYER_SIGNED_UP' + ERROR_STATUS_CODE = 'ERROR_STATUS_CODE' + TOURNAMENT_NOT_FOUND = 'TOURNAMENT_NOT_FOUND' + +@unique +class MessageStatus(Enum): + BOT_MESSAGE = 'BOT_MESSAGE' + NO_ATTACHMENTS = 'NO_ATTACHMENTS' + TOURNAMENT_OR_PLAYER_NOT_VALID = 'TOURNAMENT_OR_PLAYER_NOT_VALID' + PLAYER_STATS_RECORDED = 'PLAYER_STATS_RECORDED' \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..dd987ae --- /dev/null +++ b/test.py @@ -0,0 +1,15 @@ + +from enum import Enum, unique + +@unique +class TournamentStatus(Enum): + TOURNAMENT_CREATED = 'TOURNAMENT_CREATED' + TOURNAMENT_DELETED = 'TOURNAMENT_DELETED' + TOURNAMENT_STARTED = 'TOURNAMENT_STARTED' + SIGNUPS_STARTED = 'SIGNUPS_STARTED' + PLAYER_SIGNED_UP = 'PLAYER_SIGNED_UP' + ERROR_STATUS_CODE = 'ERROR_STATUS_CODE' + TOURNAMENT_NOT_FOUND = 'TOURNAMENT_NOT_FOUND' + + +print({ TournamentStatus.ERROR_STATUS_CODE: 'id'}) \ No newline at end of file