This commit is contained in:
Michel Fedde 2025-06-18 22:53:54 +02:00
parent 441715675c
commit a79898b2e9
48 changed files with 2062 additions and 1503 deletions

View file

@ -10,17 +10,17 @@ export class DefaultEvents {
const events: TimedEvent[] = [
new ReminderEvent()
]
const eventHandler = Container.get<EventHandler>(EventHandler.name);
events.forEach((event) => {
eventHandler.addTimed(event);
})
}
public static setupHandlers() {
const eventHandler = Container.get<EventHandler>(EventHandler.name);
eventHandler.addHandler<ElementCreatedEvent<PlaydateModel>>(ElementCreatedEvent.name, sendCreatedNotificationEventHandler);
}
}

View file

@ -2,9 +2,9 @@ import {Model} from "../Models/Model";
export class ElementCreatedEvent<T extends Model = Model> {
constructor(
public readonly tableName: string,
public readonly tableName: string,
public readonly instanceValues: Partial<T>,
public readonly instanceId: number|bigint
public readonly instanceId: number | bigint
) {
}
}

View file

@ -1,8 +1,8 @@
import cron from "node-cron";
import {Class} from "../types/Class";
import {Class} from "../types/Class";
export type EventConfiguration = {
name: string,
name: string,
maxExecutions?: number,
}
@ -14,34 +14,34 @@ export interface TimedEvent {
export class EventHandler {
private eventHandlers: Map<string, CallableFunction[]> = new Map();
constructor() {
}
public addHandler<T extends Class>(eventName: string, handler: (event: T) => void) {
if (!this.eventHandlers.has(eventName)) {
this.eventHandlers.set(eventName, []);
}
this.eventHandlers.get(eventName)?.push(handler);
}
public dispatch<T extends Class>(event: T) {
const eventName = event.constructor.name;
if (!this.eventHandlers.has(eventName)) {
return;
}
this.eventHandlers.get(eventName)?.forEach((handler) => {
handler(event);
})
}
public addTimed(event: TimedEvent) {
if (!cron.validate(event.cronExpression)) {
throw new Error(`Can't create event with name '${event.configuration.name}': Invalid cron expression.`)
}
cron.schedule(event.cronExpression, event.execute.bind(event), event.configuration);
}
}

View file

@ -23,18 +23,18 @@ export async function sendCreatedNotificationEventHandler(event: ElementCreatedE
if (!playdate.group || !playdate.from_time || !playdate.to_time) {
return;
}
const configurationHandler = new GroupConfigurationHandler(
Container.get<GroupConfigurationRepository>(GroupConfigurationRepository.name),
playdate.group
);
const targetChannel = configurationHandler.getConfigurationByPath('channels.newPlaydates');
if (!targetChannel) {
return;
}
const channel = await Container.get<DiscordClient>(DiscordClient.name).Client.channels.fetch(<string>targetChannel)
if (!channel) {
return;
@ -67,7 +67,7 @@ export async function sendCreatedNotificationEventHandler(event: ElementCreatedE
embed
],
allowedMentions: {
roles: [ playdate.group.role.roleid ]
roles: [playdate.group.role.roleid]
}
})
}

View file

@ -14,24 +14,24 @@ export class ReminderEvent implements TimedEvent {
1,
7
];
private static REMINDER_NOTIFICATIONS = [
'The darkness approaches. Get ready!',
'Your aid is requested once again.',
'Grab your dice and show them evil-doers how its done!',
]
configuration: EventConfiguration = {
name: "Reminders",
}
cronExpression: string = "0 9 * * *"
private readonly groupConfigurationRepository: GroupConfigurationRepository
private playdateRepository: PlaydateRepository
private discordClient: DiscordClient
constructor() {
this.playdateRepository = Container.get<PlaydateRepository>(PlaydateRepository.name);
this.groupConfigurationRepository = Container.get<GroupConfigurationRepository>(GroupConfigurationRepository.name);
@ -40,61 +40,61 @@ export class ReminderEvent implements TimedEvent {
async execute() {
const today = new Date();
today.setHours(0,0,0,0);
today.setHours(0, 0, 0, 0);
const playdates = ReminderEvent.REMINDER_INTERVALS.flatMap((interval) => {
const fromDate = new Date(today.valueOf())
fromDate.setDate(fromDate.getDate() + interval);
const toDate = new Date(today.valueOf())
toDate.setDate(toDate.getDate() + interval);
toDate.setHours(23,59,59,999);
toDate.setHours(23, 59, 59, 999);
return this.playdateRepository.findPlaydatesInRange(fromDate, toDate);
}, this)
const promises = playdates
.map((playdate) => {
if (!playdate.group) {
return Promise.resolve();
}
const configurationHandler = new GroupConfigurationHandler(
this.groupConfigurationRepository,
playdate.group
);
const config = configurationHandler.getConfiguration();
const targetChannel = config.channels?.playdateReminders;
if (!targetChannel) {
return Promise.resolve();
}
return this.sendReminder(playdate, targetChannel);
}, this)
await Promise.all(promises);
}
private async sendReminder(playdate: PlaydateModel, targetChannel: ChannelId) {
if (!playdate.group) {
return;
}
const channel = await this.discordClient.Client.channels.fetch(targetChannel)
if (!channel) {
return;
}
if (!channel.isTextBased()) {
return;
}
if (!channel.isSendable()) {
return;
}
const embed = new EmbedBuilder()
.setTitle("Playdate reminder")
.setDescription(
@ -114,7 +114,7 @@ export class ReminderEvent implements TimedEvent {
embed
],
allowedMentions: {
roles: [ playdate.group.role.roleid ]
roles: [playdate.group.role.roleid]
}
})
}