Added birthday watcher #401

This commit is contained in:
Sven Heidemann 2023-10-11 21:56:49 +02:00
parent 90fce5a79a
commit 3a64c51600
14 changed files with 117 additions and 23 deletions

View File

@ -235,6 +235,7 @@
}, },
"user": { "user": {
"birthday": { "birthday": {
"has_birthday": "Alles Gute zum Geburtag {} :D",
"success": "Dein Geburtstag wurde eingetragen.", "success": "Dein Geburtstag wurde eingetragen.",
"success_team": "{} hat seinen Geburtstag eingetragen: {}" "success_team": "{} hat seinen Geburtstag eingetragen: {}"
}, },

View File

@ -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 discord.ext import commands
from bot_core.logging.task_logger import TaskLogger
class TaskABC(commands.Cog): class TaskABC(commands.Cog):
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
commands.Cog.__init__(self) commands.Cog.__init__(self)
@abstractmethod @ServiceProviderABC.inject
def start(self): async def _wait_until_ready(self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC):
pass 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()

View File

@ -1,3 +1,4 @@
import datetime
from typing import Optional from typing import Optional
from cpl_core.database.context import DatabaseContextABC from cpl_core.database.context import DatabaseContextABC
@ -29,7 +30,7 @@ class UserRepositoryService(UserRepositoryABC):
result[2], result[2],
result[3], result[3],
result[4], 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]), self._servers.get_server_by_id(result[6]),
result[7], result[7],
result[8], result[8],

View File

@ -72,6 +72,9 @@ class ServerConfigMutation(QueryABC):
server_config.xp_per_achievement = ( server_config.xp_per_achievement = (
input["xpPerAchievement"] if "xpPerAchievement" in input else 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 = ( server_config.afk_command_channel_id = (
input["afkCommandChannelId"] if "afkCommandChannelId" in input else server_config.afk_command_channel_id input["afkCommandChannelId"] if "afkCommandChannelId" in input else server_config.afk_command_channel_id
) )

View File

@ -5,7 +5,9 @@ from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
from bot_core.abc.module_abc import ModuleABC 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 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.afk_command import AFKCommand
from modules.base.command.game_server_group import GameServerGroup from modules.base.command.game_server_group import GameServerGroup
from modules.base.command.help_command import HelpCommand from modules.base.command.help_command import HelpCommand
@ -56,6 +58,7 @@ class BaseModule(ModuleABC):
services.add_transient(BaseReactionHandler) services.add_transient(BaseReactionHandler)
services.add_singleton(EventService) services.add_singleton(EventService)
services.add_transient(UserWarningsService) services.add_transient(UserWarningsService)
services.add_singleton(TaskABC, BirthdayWatcher)
# forms # forms
services.add_transient(BugReportForm) services.add_transient(BugReportForm)

View File

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

View File

@ -1,5 +1,5 @@
import asyncio import asyncio
from datetime import datetime import datetime
import bs4 import bs4
import discord import discord
@ -48,9 +48,6 @@ class SteamOfferWatcher(TaskABC):
self.watch.start() self.watch.start()
def start(self):
self.watch.start()
@staticmethod @staticmethod
def _get_max_count() -> int: def _get_max_count() -> int:
count = 0 count = 0
@ -110,7 +107,7 @@ class SteamOfferWatcher(TaskABC):
new_offers = List(SteamSpecialOffer) new_offers = List(SteamSpecialOffer)
# sale_count = self._get_max_count() + 100 # 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}") self._logger.debug(__name__, f"Get special offers from 0 to {sale_count}")
for i in range(0, sale_count, 100): for i in range(0, sale_count, 100):
new_offers.extend(self._get_games_from_page(i, 100)) new_offers.extend(self._get_games_from_page(i, 100))
@ -124,7 +121,7 @@ class SteamOfferWatcher(TaskABC):
title=offer.name, title=offer.name,
url=self._urls[offer.name], url=self._urls[offer.name],
color=int("ef9d0d", 16), color=int("ef9d0d", 16),
timestamp=datetime.now(), timestamp=datetime.datetime.now(),
) )
embed.add_field( embed.add_field(
@ -180,7 +177,7 @@ class SteamOfferWatcher(TaskABC):
self._logger.trace(__name__, "Finished watching") self._logger.trace(__name__, "Finished watching")
return offers_for_notifications return offers_for_notifications
@tasks.loop(minutes=60) @tasks.loop(time=datetime.time(hour=16, minute=30))
async def watch(self): async def watch(self):
self._logger.info(__name__, "Watching steam special offers") self._logger.info(__name__, "Watching steam special offers")
try: try:
@ -206,14 +203,5 @@ class SteamOfferWatcher(TaskABC):
self._logger.error(__name__, f"Steam offer watcher failed", e) self._logger.error(__name__, f"Steam offer watcher failed", e)
@watch.before_loop @watch.before_loop
async def before_printer(self): async def wait(self):
self._logger.debug(__name__, f"Waiting before checking steam special offers") await self._wait_until_ready()
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()

View File

@ -12,6 +12,7 @@ export interface ServerConfig extends DataWithHistory {
xpPerOntimeHour?: number; xpPerOntimeHour?: number;
xpPerEventParticipation?: number; xpPerEventParticipation?: number;
xpPerAchievement?: number; xpPerAchievement?: number;
xpForBirthday?: number;
afkCommandChannelId?: string; afkCommandChannelId?: string;
helpVoiceChannelId?: string; helpVoiceChannelId?: string;
teamChannelId?: string; teamChannelId?: string;

View File

@ -256,6 +256,7 @@ export class Mutations {
$xpPerOntimeHour: Int, $xpPerOntimeHour: Int,
$xpPerEventParticipation: Int, $xpPerEventParticipation: Int,
$xpPerAchievement: Int, $xpPerAchievement: Int,
$xpForBirthday: Int,
$afkCommandChannelId: String, $afkCommandChannelId: String,
$helpVoiceChannelId: String, $helpVoiceChannelId: String,
$teamChannelId: String, $teamChannelId: String,
@ -280,6 +281,7 @@ export class Mutations {
xpPerOntimeHour: $xpPerOntimeHour, xpPerOntimeHour: $xpPerOntimeHour,
xpPerEventParticipation: $xpPerEventParticipation, xpPerEventParticipation: $xpPerEventParticipation,
xpPerAchievement: $xpPerAchievement, xpPerAchievement: $xpPerAchievement,
xpForBirthday: $xpForBirthday,
afkCommandChannelId: $afkCommandChannelId, afkCommandChannelId: $afkCommandChannelId,
helpVoiceChannelId: $helpVoiceChannelId, helpVoiceChannelId: $helpVoiceChannelId,
teamChannelId: $teamChannelId, teamChannelId: $teamChannelId,
@ -302,6 +304,7 @@ export class Mutations {
xpPerOntimeHour xpPerOntimeHour
xpPerEventParticipation xpPerEventParticipation
xpPerAchievement xpPerAchievement
xpForBirthday
afkCommandChannelId afkCommandChannelId
helpVoiceChannelId helpVoiceChannelId
teamChannelId teamChannelId

View File

@ -525,6 +525,7 @@ export class Queries {
xpPerOntimeHour xpPerOntimeHour
xpPerEventParticipation xpPerEventParticipation
xpPerAchievement xpPerAchievement
xpForBirthday
afkCommandChannelId afkCommandChannelId
helpVoiceChannelId helpVoiceChannelId
teamChannelId teamChannelId

View File

@ -82,6 +82,14 @@
</div> </div>
</div> </div>
<div class="content-row">
<div class="content-column">
<div class="content-data-name">{{'view.server.config.bot.xp_for_birthday' | translate}}:</div>
<div class="content-data-value"><input type="number" pInputText [(ngModel)]="config.xpForBirthday"
placeholder="{{'view.server.config.bot.xp_for_birthday' | translate}}"></div>
</div>
</div>
<div class="content-row"> <div class="content-row">
<div class="content-column"> <div class="content-column">
<div class="content-data-name">{{'view.server.config.bot.afk_command_channel_id' | translate}}:</div> <div class="content-data-name">{{'view.server.config.bot.afk_command_channel_id' | translate}}:</div>

View File

@ -118,6 +118,7 @@ export class ConfigComponent implements OnInit {
xpPerOntimeHour: this.config.xpPerOntimeHour, xpPerOntimeHour: this.config.xpPerOntimeHour,
xpPerEventParticipation: this.config.xpPerEventParticipation, xpPerEventParticipation: this.config.xpPerEventParticipation,
xpPerAchievement: this.config.xpPerAchievement, xpPerAchievement: this.config.xpPerAchievement,
xpForBirthday: this.config.xpForBirthday,
afkCommandChannelId: this.config.afkCommandChannelId, afkCommandChannelId: this.config.afkCommandChannelId,
helpVoiceChannelId: this.config.helpVoiceChannelId, helpVoiceChannelId: this.config.helpVoiceChannelId,
teamChannelId: this.config.teamChannelId, teamChannelId: this.config.teamChannelId,

View File

@ -433,6 +433,7 @@
"notification_chat_id": "Benachrichtungskanal", "notification_chat_id": "Benachrichtungskanal",
"short_role_name_only_set_highest_role": "Bei Rollen Kürzeln nur die höchste Rolle verwenden", "short_role_name_only_set_highest_role": "Bei Rollen Kürzeln nur die höchste Rolle verwenden",
"team_channel_id": "Team chat", "team_channel_id": "Team chat",
"xp_for_birthday": "XP für Geburtstag",
"xp_per_achievement": "XP für Errungenschaft", "xp_per_achievement": "XP für Errungenschaft",
"xp_per_event_participation": "XP für Event Teilnahme", "xp_per_event_participation": "XP für Event Teilnahme",
"xp_per_message": "XP für eine Nachricht", "xp_per_message": "XP für eine Nachricht",

View File

@ -433,6 +433,7 @@
"notification_chat_id": "Notification channel", "notification_chat_id": "Notification channel",
"short_role_name_only_set_highest_role": "For role abbreviations use only the highest role", "short_role_name_only_set_highest_role": "For role abbreviations use only the highest role",
"team_channel_id": "Team chat", "team_channel_id": "Team chat",
"xp_for_birthday": "XP for birthday",
"xp_per_achievement": "XP for achievement", "xp_per_achievement": "XP for achievement",
"xp_per_event_participation": "XP for event participation", "xp_per_event_participation": "XP for event participation",
"xp_per_message": "XP for message", "xp_per_message": "XP for message",