Added birthday watcher #401

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

View File

@ -235,6 +235,7 @@
},
"user": {
"birthday": {
"has_birthday": "Alles Gute zum Geburtag {} :D",
"success": "Dein Geburtstag wurde 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 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()

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

@ -82,6 +82,14 @@
</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-column">
<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,
xpPerEventParticipation: this.config.xpPerEventParticipation,
xpPerAchievement: this.config.xpPerAchievement,
xpForBirthday: this.config.xpForBirthday,
afkCommandChannelId: this.config.afkCommandChannelId,
helpVoiceChannelId: this.config.helpVoiceChannelId,
teamChannelId: this.config.teamChannelId,

View File

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

View File

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