From bd1d230f671c77a6afdd91fff818aac04a0fec36 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 11 Oct 2023 21:56:49 +0200 Subject: [PATCH] Added birthday watcher #401 --- kdb-bot/src/bot/translation/de.json | 1 + kdb-bot/src/bot_core/abc/task_abc.py | 23 +++++-- .../service/user_repository_service.py | 3 +- .../mutations/server_config_mutation.py | 3 + kdb-bot/src/modules/base/base_module.py | 3 + kdb-bot/src/modules/base/birthday_watcher.py | 67 +++++++++++++++++++ .../special_offers/steam_offer_watcher.py | 24 ++----- .../app/models/config/server-config.model.ts | 1 + .../src/app/models/graphql/mutations.model.ts | 3 + .../src/app/models/graphql/queries.model.ts | 1 + .../components/config/config.component.html | 8 +++ .../components/config/config.component.ts | 1 + kdb-web/src/assets/i18n/de.json | 1 + kdb-web/src/assets/i18n/en.json | 1 + 14 files changed, 117 insertions(+), 23 deletions(-) create mode 100644 kdb-bot/src/modules/base/birthday_watcher.py diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 5f394911..9f0a57fa 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -235,6 +235,7 @@ }, "user": { "birthday": { + "has_birthday": "Alles Gute zum Geburtag {} :D", "success": "Dein Geburtstag wurde eingetragen.", "success_team": "{} hat seinen Geburtstag eingetragen: {}" }, diff --git a/kdb-bot/src/bot_core/abc/task_abc.py b/kdb-bot/src/bot_core/abc/task_abc.py index 093f0893..990b95b0 100644 --- a/kdb-bot/src/bot_core/abc/task_abc.py +++ b/kdb-bot/src/bot_core/abc/task_abc.py @@ -1,13 +1,28 @@ -from abc import ABC, abstractmethod +import asyncio +from abc import abstractmethod +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from discord.ext import commands +from bot_core.logging.task_logger import TaskLogger + class TaskABC(commands.Cog): @abstractmethod def __init__(self): commands.Cog.__init__(self) - @abstractmethod - def start(self): - pass + @ServiceProviderABC.inject + async def _wait_until_ready(self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC): + logger.debug(__name__, f"Waiting before checking steam special offers") + await bot.wait_until_ready() + + async def wait(): + is_ready = config.get_configuration("IS_READY") + if is_ready != "true": + await asyncio.sleep(1) + await wait() + + await wait() diff --git a/kdb-bot/src/bot_data/service/user_repository_service.py b/kdb-bot/src/bot_data/service/user_repository_service.py index 1238fa1b..940156a8 100644 --- a/kdb-bot/src/bot_data/service/user_repository_service.py +++ b/kdb-bot/src/bot_data/service/user_repository_service.py @@ -1,3 +1,4 @@ +import datetime from typing import Optional from cpl_core.database.context import DatabaseContextABC @@ -29,7 +30,7 @@ class UserRepositoryService(UserRepositoryABC): result[2], result[3], result[4], - result[5].strftime("%d.%m.%Y") if result[5] is not None else None, + result[5], self._servers.get_server_by_id(result[6]), result[7], result[8], diff --git a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py index 94a04b4f..1f179d4a 100644 --- a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py @@ -72,6 +72,9 @@ class ServerConfigMutation(QueryABC): server_config.xp_per_achievement = ( input["xpPerAchievement"] if "xpPerAchievement" in input else server_config.xp_per_achievement ) + server_config.xp_for_birthday = ( + input["xpForBirthday"] if "xpForBirthday" in input else server_config.xp_for_birthday + ) server_config.afk_command_channel_id = ( input["afkCommandChannelId"] if "afkCommandChannelId" in input else server_config.afk_command_channel_id ) diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index 626ea4ef..949fa4ad 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -5,7 +5,9 @@ from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC +from bot_core.abc.task_abc import TaskABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from modules.base.birthday_watcher import BirthdayWatcher from modules.base.command.afk_command import AFKCommand from modules.base.command.game_server_group import GameServerGroup from modules.base.command.help_command import HelpCommand @@ -56,6 +58,7 @@ class BaseModule(ModuleABC): services.add_transient(BaseReactionHandler) services.add_singleton(EventService) services.add_transient(UserWarningsService) + services.add_singleton(TaskABC, BirthdayWatcher) # forms services.add_transient(BugReportForm) diff --git a/kdb-bot/src/modules/base/birthday_watcher.py b/kdb-bot/src/modules/base/birthday_watcher.py new file mode 100644 index 00000000..7b19638a --- /dev/null +++ b/kdb-bot/src/modules/base/birthday_watcher.py @@ -0,0 +1,67 @@ +import datetime + +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord.ext import tasks + +from bot_core.abc.task_abc import TaskABC +from bot_core.logging.task_logger import TaskLogger +from bot_core.service.message_service import MessageService +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.server_config import ServerConfig + + +class BirthdayWatcher(TaskABC): + def __init__( + self, + config: ConfigurationABC, + logger: TaskLogger, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + users: UserRepositoryABC, + message_service: MessageService, + t: TranslatePipe, + ): + TaskABC.__init__(self) + + self._config = config + self._logger = logger + self._bot = bot + self._db = db + self._users = users + self._message_service = message_service + self._t = t + + self.watch.start() + + @tasks.loop(time=datetime.time(hour=8, minute=0)) + async def watch(self): + self._logger.info(__name__, "Watching birthdays") + try: + today = datetime.date.today() + users = self._users.get_users().where(lambda x: x.birthday is not None) + for user in users: + if user.birthday.day != today.day or user.birthday.month != today.month: + continue + + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{user.server.discord_id}") + + user.xp += settings.xp_for_birthday + self._users.update_user(user) + self._db.save_changes() + + guild = self._bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + await self._message_service.send_channel_message( + self._bot.get_channel(settings.notification_chat_id), + self._t.transform("modules.base.user.birthday.has_birthday").format(member.mention), + is_persistent=True, + ) + except Exception as e: + self._logger.error(__name__, f"Watching birthdays failed", e) + + @watch.before_loop + async def wait(self): + await self._wait_until_ready() diff --git a/kdb-bot/src/modules/special_offers/steam_offer_watcher.py b/kdb-bot/src/modules/special_offers/steam_offer_watcher.py index 7830d43e..0aedda1d 100644 --- a/kdb-bot/src/modules/special_offers/steam_offer_watcher.py +++ b/kdb-bot/src/modules/special_offers/steam_offer_watcher.py @@ -1,5 +1,5 @@ import asyncio -from datetime import datetime +import datetime import bs4 import discord @@ -48,9 +48,6 @@ class SteamOfferWatcher(TaskABC): self.watch.start() - def start(self): - self.watch.start() - @staticmethod def _get_max_count() -> int: count = 0 @@ -110,7 +107,7 @@ class SteamOfferWatcher(TaskABC): new_offers = List(SteamSpecialOffer) # sale_count = self._get_max_count() + 100 - sale_count = 1500 # only look at first 1500 + sale_count = 500 # only look at first 500 self._logger.debug(__name__, f"Get special offers from 0 to {sale_count}") for i in range(0, sale_count, 100): new_offers.extend(self._get_games_from_page(i, 100)) @@ -124,7 +121,7 @@ class SteamOfferWatcher(TaskABC): title=offer.name, url=self._urls[offer.name], color=int("ef9d0d", 16), - timestamp=datetime.now(), + timestamp=datetime.datetime.now(), ) embed.add_field( @@ -180,7 +177,7 @@ class SteamOfferWatcher(TaskABC): self._logger.trace(__name__, "Finished watching") return offers_for_notifications - @tasks.loop(minutes=60) + @tasks.loop(time=datetime.time(hour=16, minute=30)) async def watch(self): self._logger.info(__name__, "Watching steam special offers") try: @@ -206,14 +203,5 @@ class SteamOfferWatcher(TaskABC): self._logger.error(__name__, f"Steam offer watcher failed", e) @watch.before_loop - async def before_printer(self): - self._logger.debug(__name__, f"Waiting before checking steam special offers") - await self._bot.wait_until_ready() - - async def wait(): - is_ready = self._config.get_configuration("IS_READY") - if is_ready != "true": - await asyncio.sleep(1) - await wait() - - await wait() + async def wait(self): + await self._wait_until_ready() diff --git a/kdb-web/src/app/models/config/server-config.model.ts b/kdb-web/src/app/models/config/server-config.model.ts index e6cd2cdf..616dbecc 100644 --- a/kdb-web/src/app/models/config/server-config.model.ts +++ b/kdb-web/src/app/models/config/server-config.model.ts @@ -12,6 +12,7 @@ export interface ServerConfig extends DataWithHistory { xpPerOntimeHour?: number; xpPerEventParticipation?: number; xpPerAchievement?: number; + xpForBirthday?: number; afkCommandChannelId?: string; helpVoiceChannelId?: string; teamChannelId?: string; diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index 23340f2e..853d4178 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -256,6 +256,7 @@ export class Mutations { $xpPerOntimeHour: Int, $xpPerEventParticipation: Int, $xpPerAchievement: Int, + $xpForBirthday: Int, $afkCommandChannelId: String, $helpVoiceChannelId: String, $teamChannelId: String, @@ -280,6 +281,7 @@ export class Mutations { xpPerOntimeHour: $xpPerOntimeHour, xpPerEventParticipation: $xpPerEventParticipation, xpPerAchievement: $xpPerAchievement, + xpForBirthday: $xpForBirthday, afkCommandChannelId: $afkCommandChannelId, helpVoiceChannelId: $helpVoiceChannelId, teamChannelId: $teamChannelId, @@ -302,6 +304,7 @@ export class Mutations { xpPerOntimeHour xpPerEventParticipation xpPerAchievement + xpForBirthday afkCommandChannelId helpVoiceChannelId teamChannelId diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index dbf49e10..bbc6a408 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -525,6 +525,7 @@ export class Queries { xpPerOntimeHour xpPerEventParticipation xpPerAchievement + xpForBirthday afkCommandChannelId helpVoiceChannelId teamChannelId diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.html b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html index 114f559f..8bc387f3 100644 --- a/kdb-web/src/app/modules/view/server/config/components/config/config.component.html +++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html @@ -82,6 +82,14 @@ +
+
+
{{'view.server.config.bot.xp_for_birthday' | translate}}:
+
+
+
+
{{'view.server.config.bot.afk_command_channel_id' | translate}}:
diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts b/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts index f295b57e..0c39cd02 100644 --- a/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts +++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts @@ -118,6 +118,7 @@ export class ConfigComponent implements OnInit { xpPerOntimeHour: this.config.xpPerOntimeHour, xpPerEventParticipation: this.config.xpPerEventParticipation, xpPerAchievement: this.config.xpPerAchievement, + xpForBirthday: this.config.xpForBirthday, afkCommandChannelId: this.config.afkCommandChannelId, helpVoiceChannelId: this.config.helpVoiceChannelId, teamChannelId: this.config.teamChannelId, diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index b1a1d87a..ade9226c 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -433,6 +433,7 @@ "notification_chat_id": "Benachrichtungskanal", "short_role_name_only_set_highest_role": "Bei Rollen Kürzeln nur die höchste Rolle verwenden", "team_channel_id": "Team chat", + "xp_for_birthday": "XP für Geburtstag", "xp_per_achievement": "XP für Errungenschaft", "xp_per_event_participation": "XP für Event Teilnahme", "xp_per_message": "XP für eine Nachricht", diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index 5acc6c23..36d7f324 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -433,6 +433,7 @@ "notification_chat_id": "Notification channel", "short_role_name_only_set_highest_role": "For role abbreviations use only the highest role", "team_channel_id": "Team chat", + "xp_for_birthday": "XP for birthday", "xp_per_achievement": "XP for achievement", "xp_per_event_participation": "XP for event participation", "xp_per_message": "XP for message",