From 6bf73fcf91ed6a3408684515b5f407c0f865509a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 13 Feb 2023 17:28:59 +0100 Subject: [PATCH 1/3] Added logic to save active events locally #167 --- kdb-bot/src/bot/bot.json | 4 +-- kdb-bot/src/modules/base/base_module.py | 8 +++++ .../configuration/base_server_settings.py | 8 +++++ .../base_on_scheduled_event_update_event.py | 35 +++++++++++++++++++ .../src/modules/base/service/event_service.py | 19 ++++++++++ 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py create mode 100644 kdb-bot/src/modules/base/service/event_service.py diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index a0297264..e5666f6a 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -19,7 +19,6 @@ "cpl-core==2022.12.1.post3", "cpl-translation==2022.12.1", "cpl-query==2022.12.2.post1", - "cpl-discord==2022.12.1.post2", "Flask==2.2.2", "Flask-Classful==0.14.2", "Flask-Cors==3.0.10", @@ -29,7 +28,8 @@ "eventlet==0.33.3", "requests-oauthlib==1.3.1", "icmplib==3.0.3", - "ariadne==0.17.1" + "ariadne==0.17.1", + "cpl-discord==2022.12.2" ], "DevDependencies": [ "cpl-cli==2022.12.1.post3" diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index 9377c6e9..b2c91348 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -23,6 +23,7 @@ from modules.base.events.base_on_message_delete_event import BaseOnMessageDelete from modules.base.events.base_on_message_event import BaseOnMessageEvent from modules.base.events.base_on_raw_reaction_add import BaseOnRawReactionAddEvent from modules.base.events.base_on_raw_reaction_remove import BaseOnRawReactionRemoveEvent +from modules.base.events.base_on_scheduled_event_update_event import BaseOnScheduledEventUpdateEvent from modules.base.events.base_on_voice_state_update_event import ( BaseOnVoiceStateUpdateEvent, ) @@ -31,6 +32,7 @@ from modules.base.events.base_on_voice_state_update_event_help_channel import ( ) from modules.base.helper.base_reaction_handler import BaseReactionHandler from modules.base.service.base_helper_service import BaseHelperService +from modules.base.service.event_service import EventService class BaseModule(ModuleABC): @@ -43,6 +45,8 @@ class BaseModule(ModuleABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(BaseHelperABC, BaseHelperService) services.add_transient(BaseReactionHandler) + services.add_singleton(EventService) + # commands self._dc.add_command(AFKCommand) self._dc.add_command(HelpCommand) @@ -73,3 +77,7 @@ class BaseModule(ModuleABC): DiscordEventTypesEnum.on_voice_state_update.value, BaseOnVoiceStateUpdateEventHelpChannel, ) + self._dc.add_event( + DiscordEventTypesEnum.on_scheduled_event_update.value, + BaseOnScheduledEventUpdateEvent, + ) diff --git a/kdb-bot/src/modules/base/configuration/base_server_settings.py b/kdb-bot/src/modules/base/configuration/base_server_settings.py index 531e44c9..f9555890 100644 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ b/kdb-bot/src/modules/base/configuration/base_server_settings.py @@ -15,6 +15,7 @@ class BaseServerSettings(ConfigurationModelABC): self._xp_per_reaction: int = 0 self._max_message_xp_per_hour: int = 0 self._xp_per_ontime_hour: int = 0 + self._xp_per_event_participation: int = 0 self._afk_channel_ids: List[int] = List(int) self._afk_command_channel_id: int = 0 self._help_command_reference_url: str = "" @@ -45,6 +46,10 @@ class BaseServerSettings(ConfigurationModelABC): def xp_per_ontime_hour(self) -> int: return self._xp_per_ontime_hour + @property + def xp_per_event_participation(self) -> int: + return self._xp_per_event_participation + @property def afk_channel_ids(self) -> List[int]: return self._afk_channel_ids @@ -73,6 +78,9 @@ class BaseServerSettings(ConfigurationModelABC): self._xp_per_reaction = int(settings["XpPerReaction"]) self._max_message_xp_per_hour = int(settings["MaxMessageXpPerHour"]) self._xp_per_ontime_hour = int(settings["XpPerOntimeHour"]) + self._xp_per_event_participation = ( + 0 if "XpPerEventParticipation" in settings else settings["XpPerEventParticipation"] + ) for index in settings["AFKChannelIds"]: self._afk_channel_ids.append(int(index)) self._afk_command_channel_id = settings["AFKCommandChannelId"] diff --git a/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py new file mode 100644 index 00000000..456599ee --- /dev/null +++ b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py @@ -0,0 +1,35 @@ +import discord +from cpl_core.logging import LoggerABC +from cpl_discord.events.on_scheduled_event_update_abc import OnScheduledEventUpdateABC +from cpl_discord.service import DiscordBotServiceABC +from discord import EventStatus + +from modules.base.service.event_service import EventService + + +class BaseOnScheduledEventUpdateEvent(OnScheduledEventUpdateABC): + def __init__( + self, + logger: LoggerABC, + bot: DiscordBotServiceABC, + events: EventService, + ): + OnScheduledEventUpdateABC.__init__(self) + + self._logger = logger + self._bot = bot + self._events = events + + async def on_scheduled_event_update(self, before: discord.ScheduledEvent, after: discord.ScheduledEvent): + self._logger.debug(__name__, f"Module {type(self)} started") + + # save started event + if before.status != after.status and after.status == EventStatus.active: + self._events.add_event(after) + # delete stopped event + if before.status != after.status and ( + after.status.value == EventStatus.cancelled.value or after.status.value == EventStatus.completed.value + ): + self._events.remove_event(after) + + self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/service/event_service.py b/kdb-bot/src/modules/base/service/event_service.py new file mode 100644 index 00000000..03cb0b02 --- /dev/null +++ b/kdb-bot/src/modules/base/service/event_service.py @@ -0,0 +1,19 @@ +from cpl_query.extension import List +from discord import ScheduledEvent + + +class EventService: + def __init__(self): + self._active_events = List(ScheduledEvent) + + def add_event(self, event: ScheduledEvent): + if self._active_events.contains(event): + return + + self._active_events.add(event) + + def remove_event(self, event: ScheduledEvent): + if not self._active_events.contains(event): + return + + self._active_events.remove(event) -- 2.45.2 From 5953c82a9b5f2741a62be4e5381d0a387f126880 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 13 Feb 2023 23:14:57 +0100 Subject: [PATCH 2/3] Fixed formatting #167 --- kdb-bot/src/bot/config | 2 +- kdb-bot/src/bot_data/model/user_role_enum.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index b0ae8762..ac704682 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit b0ae87621bbe54fd9c5650071ec8c1c9ec32df48 +Subproject commit ac7046820f3410f55e779797126d9410c6bcdc9f diff --git a/kdb-bot/src/bot_data/model/user_role_enum.py b/kdb-bot/src/bot_data/model/user_role_enum.py index edfaf85d..ad612e1d 100644 --- a/kdb-bot/src/bot_data/model/user_role_enum.py +++ b/kdb-bot/src/bot_data/model/user_role_enum.py @@ -2,7 +2,6 @@ from enum import Enum class UserRoleEnum(Enum): - member = 0 moderator = 1 admin = 2 -- 2.45.2 From 77946cb3a8bc74e3d23b24672b322d16ef178a3a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 13 Feb 2023 23:02:47 +0100 Subject: [PATCH 3/3] Added logic to add bonus xp when joining the event channel #167 --- kdb-bot/src/modules/base/base_module.py | 7 ++ .../configuration/base_server_settings.py | 2 +- .../base_on_scheduled_event_update_event.py | 8 ++- ...tate_update_event_scheduled_event_bonus.py | 66 +++++++++++++++++++ kdb-bot/src/modules/base/model/__init__.py | 0 .../src/modules/base/model/active_event.py | 18 +++++ .../src/modules/base/service/event_service.py | 20 ++++-- 7 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py create mode 100644 kdb-bot/src/modules/base/model/__init__.py create mode 100644 kdb-bot/src/modules/base/model/active_event.py diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index b2c91348..150dce4e 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -30,6 +30,9 @@ from modules.base.events.base_on_voice_state_update_event import ( from modules.base.events.base_on_voice_state_update_event_help_channel import ( BaseOnVoiceStateUpdateEventHelpChannel, ) +from modules.base.events.base_on_voice_state_update_event_scheduled_event_bonus import ( + BaseOnVoiceStateUpdateEventScheduledEventBonus, +) from modules.base.helper.base_reaction_handler import BaseReactionHandler from modules.base.service.base_helper_service import BaseHelperService from modules.base.service.event_service import EventService @@ -77,6 +80,10 @@ class BaseModule(ModuleABC): DiscordEventTypesEnum.on_voice_state_update.value, BaseOnVoiceStateUpdateEventHelpChannel, ) + self._dc.add_event( + DiscordEventTypesEnum.on_voice_state_update.value, + BaseOnVoiceStateUpdateEventScheduledEventBonus, + ) self._dc.add_event( DiscordEventTypesEnum.on_scheduled_event_update.value, BaseOnScheduledEventUpdateEvent, diff --git a/kdb-bot/src/modules/base/configuration/base_server_settings.py b/kdb-bot/src/modules/base/configuration/base_server_settings.py index f9555890..c6a7e9c4 100644 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ b/kdb-bot/src/modules/base/configuration/base_server_settings.py @@ -79,7 +79,7 @@ class BaseServerSettings(ConfigurationModelABC): self._max_message_xp_per_hour = int(settings["MaxMessageXpPerHour"]) self._xp_per_ontime_hour = int(settings["XpPerOntimeHour"]) self._xp_per_event_participation = ( - 0 if "XpPerEventParticipation" in settings else settings["XpPerEventParticipation"] + 0 if "XpPerEventParticipation" not in settings else settings["XpPerEventParticipation"] ) for index in settings["AFKChannelIds"]: self._afk_channel_ids.append(int(index)) diff --git a/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py index 456599ee..5b9cf901 100644 --- a/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py @@ -4,6 +4,7 @@ from cpl_discord.events.on_scheduled_event_update_abc import OnScheduledEventUpd from cpl_discord.service import DiscordBotServiceABC from discord import EventStatus +from modules.base.model.active_event import ActiveEvent from modules.base.service.event_service import EventService @@ -25,11 +26,14 @@ class BaseOnScheduledEventUpdateEvent(OnScheduledEventUpdateABC): # save started event if before.status != after.status and after.status == EventStatus.active: - self._events.add_event(after) + self._events.add_event(ActiveEvent(after)) # delete stopped event if before.status != after.status and ( after.status.value == EventStatus.cancelled.value or after.status.value == EventStatus.completed.value ): - self._events.remove_event(after) + event = self._events.get_active_event(after) + if event is None: + return + self._events.remove_event(event) self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py new file mode 100644 index 00000000..54050851 --- /dev/null +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py @@ -0,0 +1,66 @@ +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_core.logging import LoggerABC +from cpl_discord.events import OnVoiceStateUpdateABC + +from bot_core.helper.event_checks import EventChecks +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from modules.base.abc.base_helper_abc import BaseHelperABC +from modules.base.configuration.base_server_settings import BaseServerSettings +from modules.base.service.event_service import EventService + + +class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + base_helper: BaseHelperABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + events: EventService, + db: DatabaseContextABC, + ): + OnVoiceStateUpdateABC.__init__(self) + self._config = config + self._logger = logger + self._base_helper = base_helper + self._servers = servers + self._users = users + self._events = events + self._db = db + + self._logger.info(__name__, f"Module {type(self)} loaded") + + @EventChecks.check_is_ready() + async def on_voice_state_update( + self, + member: discord.Member, + before: discord.VoiceState, + after: discord.VoiceState, + ): + self._logger.debug(__name__, f"Module {type(self)} started") + if member.bot or after.channel is None: + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + active_event = self._events.get_active_event_by_channel_id(after.channel.id) + if active_event is None: + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + if active_event.participants.any(lambda x: x.user_id == user.user_id): + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + user.xp += settings.xp_per_event_participation + self._users.update_user(user) + self._db.save_changes() + active_event.participants.append(user) + + self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/model/__init__.py b/kdb-bot/src/modules/base/model/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/kdb-bot/src/modules/base/model/active_event.py b/kdb-bot/src/modules/base/model/active_event.py new file mode 100644 index 00000000..63861e0c --- /dev/null +++ b/kdb-bot/src/modules/base/model/active_event.py @@ -0,0 +1,18 @@ +import discord +from cpl_query.extension import List + +from bot_data.model.user import User + + +class ActiveEvent: + def __init__(self, event: discord.ScheduledEvent): + self._event = event + self._participants = List(User) + + @property + def event(self) -> discord.ScheduledEvent: + return self._event + + @property + def participants(self) -> List[User]: + return self._participants diff --git a/kdb-bot/src/modules/base/service/event_service.py b/kdb-bot/src/modules/base/service/event_service.py index 03cb0b02..8073b3d3 100644 --- a/kdb-bot/src/modules/base/service/event_service.py +++ b/kdb-bot/src/modules/base/service/event_service.py @@ -1,18 +1,30 @@ +from typing import Optional + +import discord from cpl_query.extension import List -from discord import ScheduledEvent + +from modules.base.model.active_event import ActiveEvent class EventService: def __init__(self): - self._active_events = List(ScheduledEvent) + self._active_events = List(ActiveEvent) - def add_event(self, event: ScheduledEvent): + def add_event(self, event: ActiveEvent): if self._active_events.contains(event): return self._active_events.add(event) - def remove_event(self, event: ScheduledEvent): + def get_active_event(self, event: discord.ScheduledEvent) -> Optional[ActiveEvent]: + return self._active_events.where(lambda x: x.event.id == event.id).single_or_default() + + def get_active_event_by_channel_id(self, channel_id: int) -> Optional[ActiveEvent]: + return self._active_events.where( + lambda x: x.event.channel is not None and x.event.channel.id == channel_id + ).single_or_default() + + def remove_event(self, event: ActiveEvent): if not self._active_events.contains(event): return -- 2.45.2