Bonus XP wenn man an einem Event teilnimmt #167 #202

Merged
edraft merged 5 commits from #167 into 1.0.0 2023-02-16 22:18:11 +01:00
9 changed files with 180 additions and 3 deletions

View File

@ -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"

@ -1 +1 @@
Subproject commit b0ae87621bbe54fd9c5650071ec8c1c9ec32df48
Subproject commit ac7046820f3410f55e779797126d9410c6bcdc9f

View File

@ -25,14 +25,19 @@ 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,
)
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
class BaseModule(ModuleABC):
@ -45,6 +50,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)
@ -77,3 +84,11 @@ 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,
)

View File

@ -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" not in settings else settings["XpPerEventParticipation"]
)
for index in settings["AFKChannelIds"]:
self._afk_channel_ids.append(int(index))
self._afk_command_channel_id = settings["AFKCommandChannelId"]

View File

@ -0,0 +1,39 @@
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.model.active_event import ActiveEvent
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(ActiveEvent(after))
# delete stopped event
if before.status != after.status and (
after.status.value == EventStatus.cancelled.value or after.status.value == EventStatus.completed.value
):
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")

View File

@ -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")

View File

@ -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

View File

@ -0,0 +1,31 @@
from typing import Optional
import discord
from cpl_query.extension import List
from modules.base.model.active_event import ActiveEvent
class EventService:
def __init__(self):
self._active_events = List(ActiveEvent)
def add_event(self, event: ActiveEvent):
if self._active_events.contains(event):
return
self._active_events.add(event)
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
self._active_events.remove(event)