Compare commits

...

2 Commits

Author SHA1 Message Date
bd856d0143 Added scheduled_event handler #410 2023-11-19 12:32:42 +01:00
da57063b68 Completed frontend #410 2023-11-19 00:31:25 +01:00
8 changed files with 187 additions and 22 deletions

View File

@ -21,7 +21,7 @@ class TaskABC(commands.Cog):
@ServiceProviderABC.inject
async def _wait_until_ready(self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC):
logger.debug(__name__, f"Waiting before {type(self).__name__}")
logger.debug(__name__, f"Waiting before ready {type(self).__name__}")
await bot.wait_until_ready()
async def wait():

View File

@ -154,7 +154,7 @@ class ScheduledEvent(TableABC):
{"NULL" if self._channel_id is None else f"'{self._channel_id}'"},
'{self._start_time}',
{"NULL" if self._end_time is None else f"'{self._end_time}'"},
'{self._entity_type}',
'{self._entity_type.value}',
{"NULL" if self._location is None else f"'{self._location}'"},
{self._server.id}
);
@ -172,7 +172,7 @@ class ScheduledEvent(TableABC):
`ChannelId` = {"NULL" if self._channel_id is None else f"'{self._channel_id}'"},
`StartTime` = '{self._start_time}',
`EndTime` = {"NULL" if self._end_time is None else f"'{self._end_time}'"},
`EntityType` = '{self._entity_type}',
`EntityType` = '{self._entity_type.value}',
`Location` = {"NULL" if self._location is None else f"'{self._location}'"}
WHERE `Id` = {self._id};
"""

View File

@ -2,6 +2,7 @@ from typing import Optional
from cpl_core.database.context import DatabaseContextABC
from cpl_query.extension import List
from discord import EntityType
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.server_repository_abc import ServerRepositoryABC
@ -39,7 +40,7 @@ class ScheduledEventRepositoryService(ScheduledEventRepositoryABC):
int(self._get_value_from_result(sql_result[4])), # channel_id
self._get_value_from_result(sql_result[5]), # start_time
self._get_value_from_result(sql_result[6]), # end_time
self._get_value_from_result(sql_result[7]), # entity_type
EntityType(int(self._get_value_from_result(sql_result[7]))), # entity_type
self._get_value_from_result(sql_result[8]), # location
self._servers.get_server_by_id((sql_result[9])), # server
self._get_value_from_result(sql_result[10]), # created_at

View File

@ -45,6 +45,7 @@ from modules.base.events.base_on_voice_state_update_event_scheduled_event_bonus
from modules.base.forms.bug_report_form import BugReportForm
from modules.base.forms.complaint_form import ComplaintForm
from modules.base.helper.base_reaction_handler import BaseReactionHandler
from modules.base.scheduled_events_watcher import ScheduledEventsWatcher
from modules.base.service.event_service import EventService
from modules.base.service.user_warnings_service import UserWarningsService
@ -61,6 +62,7 @@ class BaseModule(ModuleABC):
services.add_singleton(EventService)
services.add_transient(UserWarningsService)
services.add_singleton(TaskABC, BirthdayWatcher)
services.add_singleton(TaskABC, ScheduledEventsWatcher)
# forms
services.add_transient(BugReportForm)

View File

@ -0,0 +1,126 @@
import calendar
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from cpl_core.configuration import ConfigurationABC
from cpl_core.database.context import DatabaseContextABC
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
from cpl_translation import TranslatePipe
from discord import Guild, PrivacyLevel
from discord.ext import tasks
from discord.scheduled_event import ScheduledEvent as DiscordEvent
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.scheduled_event_repository_abc import ScheduledEventRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.model.scheduled_event import ScheduledEvent
from bot_data.model.scheduled_event_interval_enum import ScheduledEventIntervalEnum
class ScheduledEventsWatcher(TaskABC):
def __init__(
self,
config: ConfigurationABC,
logger: TaskLogger,
bot: DiscordBotServiceABC,
db: DatabaseContextABC,
servers: ServerRepositoryABC,
events: ScheduledEventRepositoryABC,
message_service: MessageService,
t: TranslatePipe,
):
TaskABC.__init__(self)
self._config = config
self._logger = logger
self._bot = bot
self._db = db
self._servers = servers
self._events = events
self._message_service = message_service
self._t = t
if not self._is_maintenance():
self.watch.start()
def _append_interval(self, interval: ScheduledEventIntervalEnum, ts: datetime) -> datetime:
now = datetime.now()
if ts >= now:
return ts
if interval == ScheduledEventIntervalEnum.daily:
ts = ts + timedelta(days=1)
elif interval == ScheduledEventIntervalEnum.weekly:
ts = ts + timedelta(weeks=1)
elif interval == ScheduledEventIntervalEnum.monthly:
days_in_month = calendar.monthrange(ts.year, ts.month + 1)[1]
ts = ts + timedelta(days=days_in_month)
elif interval == ScheduledEventIntervalEnum.yearly:
ts = ts + timedelta(days=365)
return ts
@tasks.loop(minutes=1)
async def watch(self):
self._logger.info(__name__, "Watching scheduled events")
try:
for guild in self._bot.guilds:
guild: Guild = guild
server = self._servers.get_server_by_discord_id(guild.id)
scheduled_events_from_guild = self._events.get_scheduled_events_by_server_id(server.id)
for scheduled_event in scheduled_events_from_guild:
scheduled_event: ScheduledEvent = scheduled_event
from_guild = List(DiscordEvent, guild.scheduled_events).where(
lambda x: x.name == scheduled_event.name
and x.description == scheduled_event.description
and x.entity_type == scheduled_event.entity_type
)
if from_guild.count() != 0:
continue
kwargs = {"name": scheduled_event.name, "description": scheduled_event.description}
if scheduled_event.channel_id is not None:
kwargs["channel"] = guild.get_channel(scheduled_event.channel_id)
if scheduled_event.start_time is not None:
scheduled_event.start_time = self._append_interval(
scheduled_event.interval, scheduled_event.start_time
)
start_time = scheduled_event.start_time.replace(tzinfo=ZoneInfo("Europe/Berlin"))
kwargs["start_time"] = start_time
if scheduled_event.end_time is not None:
scheduled_event.end_time = self._append_interval(
scheduled_event.interval, scheduled_event.end_time
)
end_time = scheduled_event.end_time.replace(tzinfo=ZoneInfo("Europe/Berlin"))
kwargs["end_time"] = end_time
kwargs["entity_type"] = scheduled_event.entity_type
if scheduled_event.location is not None:
kwargs["location"] = scheduled_event.location
kwargs["privacy_level"] = PrivacyLevel.guild_only
try:
self._logger.debug(__name__, f"Try to create scheduled event for guild {guild.name}")
await guild.create_scheduled_event(**kwargs)
self._events.update_scheduled_event(scheduled_event)
self._db.save_changes()
except Exception as e:
self._logger.error(__name__, f"Watching scheduled events failed", e)
except Exception as e:
self._logger.error(__name__, f"Watching scheduled events failed", e)
@watch.before_loop
async def wait(self):
await self._wait_until_ready()

View File

@ -251,7 +251,7 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn
})).subscribe(result => {
this.isEditingNew = false;
this.spinner.hideSpinner();
this.toastService.success(this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_create"), this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_create_d", { name: result.scheduledEvent.createScheduledEvent?.name }));
this.toastService.success(this.translate.instant("view.server.scheduled_events.message.scheduled_event_create"), this.translate.instant("view.server.scheduled_events.message.scheduled_event_create_d", { name: result.scheduledEvent.createScheduledEvent?.name }));
this.loadNextPage();
});
return;
@ -275,14 +275,14 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn
return throwError(err);
})).subscribe(_ => {
this.spinner.hideSpinner();
this.toastService.success(this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_update"), this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_update_d", { name: newScheduledEvent.name }));
this.toastService.success(this.translate.instant("view.server.scheduled_events.message.scheduled_event_update"), this.translate.instant("view.server.scheduled_events.message.scheduled_event_update_d", { name: newScheduledEvent.name }));
this.loadNextPage();
});
}
public deleteScheduledEvent(ScheduledEvent: ScheduledEvent): void {
this.confirmDialog.confirmDialog(
this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_delete"), this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_delete_q", { name: ScheduledEvent.name }),
this.translate.instant("view.server.scheduled_events.message.scheduled_event_delete"), this.translate.instant("view.server.scheduled_events.message.scheduled_event_delete_q", { name: ScheduledEvent.name }),
() => {
this.spinner.showSpinner();
this.data.mutation<ScheduledEventMutationResult>(Mutations.deleteScheduledEvent, {
@ -293,7 +293,7 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn
return throwError(err);
})).subscribe(l => {
this.spinner.hideSpinner();
this.toastService.success(this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_deleted"), this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_deleted_d", { name: ScheduledEvent.name }));
this.toastService.success(this.translate.instant("view.server.scheduled_events.message.scheduled_event_deleted"), this.translate.instant("view.server.scheduled_events.message.scheduled_event_deleted_d", { name: ScheduledEvent.name }));
this.loadNextPage();
});
});
@ -302,15 +302,5 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn
public addScheduledEvent(): void {
this.isEditingNew = true;
this.editableScheduledEvent = JSON.parse(JSON.stringify(this.newScheduledEventTemplate));
// const newScheduledEvent = JSON.parse(JSON.stringify(this.newScheduledEventTemplate));
//
// this.scheduledEvents = [newScheduledEvent, ...this.scheduledEvents];
//
// table.initRowEdit(newScheduledEvent);
//
// const index = this.scheduledEvents.findIndex(l => l.id == newScheduledEvent.id);
// this.onRowEditInit(table, newScheduledEvent, index);
//
// this.isEditingNew = true;
}
}

View File

@ -555,11 +555,11 @@
"event_info": {
"description": "Beschreibung",
"description_input": "Erzähl den Leuten ein wenig mehr über dein Event. Markdown, neue Zeilen und Links werden unterstützt.",
"end_date_time": "Endzeitpunkt",
"event_topic": "Thema",
"event_topic_input": "Worum geht es bei deinem Event?",
"header": "Worum geht es bei deinem Event?",
"start_date_time": "Startzeitpunkt",
"end_date_time": "Endzeitpunkt",
"tab_name": "Eventinformationen"
},
"location": {
@ -567,8 +567,8 @@
"interval": "Interval",
"intervals": {
"daily": "Täglich",
"weekly": "Wöchentlich",
"monthly": "Monatlich",
"weekly": "Wöchentlich",
"yearly": "Jährlich"
},
"somewhere_else": "Irgendwo anders",
@ -581,6 +581,22 @@
}
},
"header": "Geplante Events",
"message": {
"scheduled_event_create": "Geplantes Event erstellt",
"scheduled_event_create_d": "Geplantes Event {{name}} erfolgreich erstellt",
"scheduled_event_create_failed": "Geplantes Event Erstellung fehlgeschlagen",
"scheduled_event_create_failed_d": "Die Erstellung der Geplantes Event ist fehlgeschlagen!",
"scheduled_event_delete": "Geplantes Event löschen",
"scheduled_event_delete_failed": "Geplantes Event Löschung fehlgeschlagen",
"scheduled_event_delete_failed_d": "Die Löschung der Geplantes Event {{name}} ist fehlgeschlagen!",
"scheduled_event_delete_q": "Sind Sie sich sicher, dass Sie das Geplantes Event {{name}} löschen möchten?",
"scheduled_event_deleted": "Geplantes Event gelöscht",
"scheduled_event_deleted_d": "Geplantes Event {{name}} erfolgreich gelöscht",
"scheduled_event_update": "Geplantes Event bearbeitet",
"scheduled_event_update_d": "Geplantes Event {{name}} erfolgreich bearbeitet",
"scheduled_event_update_failed": "Geplantes Event Bearbeitung fehlgeschlagen",
"scheduled_event_update_failed_d": "Die Bearbeitung der Geplantes Event ist fehlgeschlagen!"
},
"scheduled_events": "Geplante Events"
},
"short_role_names": {

View File

@ -146,6 +146,7 @@
"edit": "Edit",
"email": "E-Mail",
"emoji": "Emoji",
"end_time": "End time",
"error": "Error",
"export": "Export",
"feature_flags": "Features",
@ -179,11 +180,13 @@
},
"id": "Id",
"import": "Import",
"interval": "interval",
"joined_at": "Joined at",
"last_name": "Last name",
"leaved_at": "Leaved at",
"left_server": "Active",
"level": "Level",
"location": "Location",
"message_id": "Message Id",
"min_xp": "Min. XP",
"modified_at": "Modified at",
@ -203,10 +206,12 @@
"role": "Role",
"rule_count": "Rules",
"save": "Save",
"start_time": "Start time",
"state": {
"off": "Off",
"on": "On"
},
"type": "Type",
"user_warnings": "User warnings",
"users": "User",
"value": "Value",
@ -330,6 +335,7 @@
"config": "Configuration",
"dashboard": "Dashboard",
"members": "Members",
"scheduled_events": "Scheduled event",
"server": {
"achievements": "Achievements",
"auto_roles": "Auto role",
@ -547,16 +553,24 @@
"add_header": "Add event",
"edit_header": "Edit event",
"event_info": {
"description": "Description",
"description_input": "Tell people a little more about your event. Markdown, new lines and links are supported.",
"end_date_time": "End date",
"event_topic": "Event topic",
"event_topic_input": "What's your event?",
"header": "What's your event about?",
"start_date": "Start date",
"start_time": "Start time",
"start_date_time": "Start date",
"tab_name": "Event info"
},
"location": {
"header": "Where is your event?",
"interval": "Interval",
"intervals": {
"daily": "Daily",
"monthly": "Monthly",
"weekly": "Weekly",
"yearly": "Yearly"
},
"somewhere_else": "Somewhere else",
"somewhere_else_input": "Enter a location",
"stage": "Stage channel",
@ -567,6 +581,22 @@
}
},
"header": "Scheduled events",
"message": {
"scheduled_event_create": "Scheduled event created",
"scheduled_event_create_d": "Scheduled event {{name}} successfully created",
"scheduled_event_create_failed": "Scheduled event creation failed",
"scheduled_event_create_failed_d": "Creation of scheduled event failed!",
"scheduled_event_delete": "Delete scheduled event",
"scheduled_event_delete_failed": "Scheduled event deletion failed",
"scheduled_event_delete_failed_d": "Deletion of scheduled event {{name}} failed!",
"scheduled_event_delete_q": "Are you sure you want to delete the {{name}} scheduled_event?",
"scheduled_event_deleted": "Scheduled event deleted",
"scheduled_event_deleted_d": "Scheduled event {{name}} successfully deleted\t",
"scheduled_event_update": "Scheduled event edited",
"scheduled_event_update_d": "Scheduled event {{name}} edited successfully",
"scheduled_event_update_failed": "Scheduled event editing failed",
"scheduled_event_update_failed_d": "Scheduled event editing failed!"
},
"scheduled_events": "Scheduled events"
},
"short_role_names": {