import { add } from "date-fns" import { DateResolvable, GuildScheduledEvent, GuildScheduledEventCreateOptions, InternalDiscordGatewayAdapterCreator } from "discord.js" export const name = 'guildScheduledEventUpdate' export function execute(oldguildScheduledEvent: GuildScheduledEvent, newguildScheduledEvent: GuildScheduledEvent) { console.dir(oldguildScheduledEvent) console.dir(newguildScheduledEvent) if (oldguildScheduledEvent.description && repetitionMarkerFound(oldguildScheduledEvent.description)) { // valid repeating event if (newguildScheduledEvent.status === 'COMPLETED') { const repetitionInfo = getRepetitonInfo(oldguildScheduledEvent.description) if (needsToBeRepeated(repetitionInfo)) { try { const newRepetitonString = buildNewRepetitionString(repetitionInfo) const newEventOptions: GuildScheduledEventCreateOptions = { name: oldguildScheduledEvent.name, description: addRepetitonStringToEventDescription(oldguildScheduledEvent.description, newRepetitonString), scheduledStartTime: getNewScheduledStart(oldguildScheduledEvent, repetitionInfo), privacyLevel: oldguildScheduledEvent.privacyLevel, entityType: oldguildScheduledEvent.entityType, channel: oldguildScheduledEvent.channel?.id, reason: 'Repetition' } newguildScheduledEvent.guild?.scheduledEvents.create(newEventOptions) } catch (err) { console.error(err) } } } } } interface RepetitonInfo { startDate?: Date, // If defined will take precedence over repetitonAmount endDate?: Date,// If defined will take precedence over repetitonAmount totalAmount: number, alreadyOccured: number, schedule: supportedSchedules numberOfDays?: number } type supportedSchedules = 'daily' | 'weekly' | 'monthly' | 'everyTwoWeeks' | 'everyNDays' function getRepetitonInfo(description: string): RepetitonInfo { const lines = description.split(`\n`) const repetitionString = lines.find(x => x.startsWith('$rep:')) if (!repetitionString) throw new Error('Cant find repetition string') const schedule: supportedSchedules = determineSchedule(repetitionString) const { totalAmount, alreadyOccured } = determineRepetitionCount(repetitionString) return { totalAmount, alreadyOccured, schedule } } function repetitionMarkerFound(description: string): boolean { return description.includes('$rep:') } function needsToBeRepeated(rInfo: RepetitonInfo): boolean { return rInfo.alreadyOccured < rInfo.totalAmount } function determineSchedule(description: string): supportedSchedules { return 'daily' } function determineRepetitionCount(description: string): { totalAmount: number; alreadyOccured: number } { const segments = description.split(':') const amountSegment = segments[2] const amounts = amountSegment.split('/') return { totalAmount: Number(amounts[1]) ?? 0, alreadyOccured: Number(amounts[0]) ?? 0 } } function buildNewRepetitionString(repetitionInfo: RepetitonInfo) { return `$rep:${repetitionInfo.schedule}:${repetitionInfo.alreadyOccured + 1}/${repetitionInfo.totalAmount}` } function addRepetitonStringToEventDescription(oldguildScheduledEvent: string, newRepetitonString: string): string | undefined { const lines = oldguildScheduledEvent.split(`\n`) const repLineIndex = lines.findIndex(x => x.startsWith('$rep:')) const newLines = lines.filter((_, index) => repLineIndex !== index) newLines.push(newRepetitonString) return newLines.join('\n') } function getNewScheduledStart(oldguildScheduledEvent: GuildScheduledEvent<"SCHEDULED" | "ACTIVE" | "COMPLETED" | "CANCELED">, rInfo: RepetitonInfo): DateResolvable { const oldDate = oldguildScheduledEvent.scheduledStartAt let daysToAdd = 0 switch (rInfo.schedule) { case 'daily': daysToAdd = 1 break case 'weekly': daysToAdd = 7 break default: throw new Error('No schedule found, cant add days') } const duration: Duration = { days: daysToAdd } const newDate = add(oldDate, duration) return newDate }