diff --git a/kdb-bot/src/bot_core/abc/client_utils_service_abc.py b/kdb-bot/src/bot_core/abc/client_utils_service_abc.py index ca6405ef..531e21c3 100644 --- a/kdb-bot/src/bot_core/abc/client_utils_service_abc.py +++ b/kdb-bot/src/bot_core/abc/client_utils_service_abc.py @@ -4,6 +4,8 @@ from typing import Callable from cpl_query.extension import List from discord.ext.commands import Context +from bot_data.model.user import User + class ClientUtilsServiceABC(ABC): @@ -33,3 +35,6 @@ class ClientUtilsServiceABC(ABC): @abstractmethod def get_auto_complete_list(self, _l: List, current: str, select: Callable = None) -> List: pass + + @abstractmethod + def get_ontime_for_user(self, user: User) -> float: pass diff --git a/kdb-bot/src/bot_core/service/client_utils_service.py b/kdb-bot/src/bot_core/service/client_utils_service.py index bf2aaef1..c4bfaba2 100644 --- a/kdb-bot/src/bot_core/service/client_utils_service.py +++ b/kdb-bot/src/bot_core/service/client_utils_service.py @@ -17,6 +17,8 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC +from bot_data.model.user import User class ClientUtilsService(ClientUtilsServiceABC): @@ -28,6 +30,7 @@ class ClientUtilsService(ClientUtilsServiceABC): bot: DiscordBotServiceABC, servers: ServerRepositoryABC, clients: ClientRepositoryABC, + user_joined_vc: UserJoinedVoiceChannelRepositoryABC, message_service: MessageServiceABC, db: DatabaseContextABC, t: TranslatePipe, @@ -39,6 +42,7 @@ class ClientUtilsService(ClientUtilsServiceABC): self._bot = bot self._servers = servers self._clients = clients + self._user_joined_voice_channel = user_joined_vc self._message_service = message_service self._db = db self._t = t @@ -80,7 +84,8 @@ class ClientUtilsService(ClientUtilsServiceABC): async def check_if_bot_is_ready_yet_and_respond(self, ctx: Context) -> bool: result = await self.check_if_bot_is_ready_yet() if not result: - await self._message_service.send_ctx_msg(ctx, self._t.transform('common.errors.bot_not_ready_yet'), without_tracking=True) + await self._message_service.send_ctx_msg(ctx, self._t.transform('common.errors.bot_not_ready_yet'), + without_tracking=True) return result @@ -106,3 +111,8 @@ class ClientUtilsService(ClientUtilsServiceABC): _l = _l.where(lambda x: x.name in sl) return _l.take(25) + + def get_ontime_for_user(self, user: User) -> float: + return self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id) \ + .where(lambda x: x.leaved_on is not None and x.joined_on is not None) \ + .sum(lambda join: round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2)) diff --git a/kdb-bot/src/modules/base/command/user_group.py b/kdb-bot/src/modules/base/command/user_group.py index 5725e5b6..6ca75b90 100644 --- a/kdb-bot/src/modules/base/command/user_group.py +++ b/kdb-bot/src/modules/base/command/user_group.py @@ -98,10 +98,6 @@ class UserGroup(DiscordCommandABC): color=int('ef9d0d', 16) ) - ontime = self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id)\ - .where(lambda x: x.leaved_on is not None and x.joined_on is not None)\ - .sum(lambda join: round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2)) - embed.add_field(name=self._t.transform('modules.base.user.atr.id'), value=member.id) embed.add_field(name=self._t.transform('modules.base.user.atr.name'), value=member.name) embed.add_field(name=self._t.transform('modules.base.user.atr.discord_join'), @@ -109,7 +105,8 @@ class UserGroup(DiscordCommandABC): embed.add_field(name=self._t.transform('modules.base.user.atr.last_join'), value=self._date.transform(member.joined_at), inline=False) embed.add_field(name=self._t.transform('modules.base.user.atr.xp'), value=str(user.xp)) - embed.add_field(name=self._t.transform('modules.base.user.atr.ontime'), value=str(ontime)) + embed.add_field(name=self._t.transform('modules.base.user.atr.ontime'), + value=str(self._client_utils.get_ontime_for_user(user))) roles = '' for role in member.roles: @@ -169,7 +166,8 @@ class UserGroup(DiscordCommandABC): )) else: - await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.error.atr_not_found').format(atr)) + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform( + 'modules.base.user.error.atr_not_found').format(atr)) return await self._message_service.send_interaction_msg( @@ -196,14 +194,16 @@ class UserGroup(DiscordCommandABC): if atr == 'xp': if not value.isnumeric(): - await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.set.error.value_type_not_numeric')) + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform( + 'modules.base.user.set.error.value_type_not_numeric')) return try: user.xp = int(value) except TypeError as te: self._logger.error(__name__, f'String value couldn\'t be converted to int', te) - await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.set.error.type_error')) + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform( + 'modules.base.user.set.error.type_error')) return else: self._users.update_user(user) @@ -211,10 +211,12 @@ class UserGroup(DiscordCommandABC): await self._level.check_level(member) else: - await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.error.atr_not_found').format(atr)) + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform( + 'modules.base.user.error.atr_not_found').format(atr)) return - await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform(f'modules.base.user.set.{atr.lower()}').format(member.mention, value)) + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform( + f'modules.base.user.set.{atr.lower()}').format(member.mention, value)) @set.autocomplete('atr') async def set_autocomplete(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: @@ -245,7 +247,8 @@ class UserGroup(DiscordCommandABC): self._db.save_changes() else: - await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.error.atr_not_found').format(atr)) + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform( + 'modules.base.user.error.atr_not_found').format(atr)) return await self._message_service.send_interaction_msg( @@ -254,5 +257,6 @@ class UserGroup(DiscordCommandABC): ) @remove.autocomplete('atr') - async def remove_autocomplete(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]: + async def remove_autocomplete(self, interaction: discord.Interaction, current: str) -> List[ + app_commands.Choice[str]]: return [app_commands.Choice(name=value, value=key) for key, value in self._atr_list] diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py index 83794725..1eeb6424 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py @@ -7,6 +7,7 @@ from cpl_core.database.context import DatabaseContextABC from cpl_core.logging import LoggerABC from cpl_discord.events import OnVoiceStateUpdateABC +from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC from bot_core.helper.event_checks import EventChecks from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -32,6 +33,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): users: UserRepositoryABC, user_joins: UserJoinedServerRepositoryABC, user_joins_vc: UserJoinedVoiceChannelRepositoryABC, + client_utils: ClientUtilsServiceABC, db: DatabaseContextABC, ): OnVoiceStateUpdateABC.__init__(self) @@ -43,6 +45,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._users = users self._user_joins = user_joins self._user_joins_vc = user_joins_vc + self._client_utils = client_utils self._db = db self._logger.info(__name__, f'Module {type(self)} loaded') @@ -72,7 +75,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): join.leaved_on = datetime.now() # ontime as hours - ontime = round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2) + ontime = self._client_utils.get_ontime_for_user(user) old_xp = user.xp user.xp += round(ontime * settings.xp_per_ontime_hour) @@ -80,12 +83,14 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._users.update_user(user) self._db.save_changes() - self._logger.debug(__name__, f'User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}') + self._logger.debug(__name__, + f'User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}') except Exception as e: self._logger.error(__name__, f'Ontime validation failed', e) @EventChecks.check_is_ready() - async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): + 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') self._logger.trace(__name__, f'Detected on_voice_state_update {member.id} from {before} to {after}') settings: BaseServerSettings = self._base_helper.get_config(member.guild.id)