import { add } from "date-fns" import { DateResolvable } from "discord.js" import { CustomError, errorCodes } from "../interfaces" export 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: Schedule } export const scheduleNames = ['daily', 'weekly', 'monthly', 'everyNWeeks', 'everyNDays', 'everyNMonths'] export type supportedSchedule = typeof scheduleNames[number] export interface IScheduleType { name: supportedSchedule, multiplier: number, duration: Duration } export const scheduleTypes: IScheduleType[] = [ { name: 'daily', multiplier: 1, duration: { days: 1 } }, { name: 'weekly', multiplier: 1, duration: { weeks: 1 } }, ] export class Schedule { private scheduleName: string private multiplier = 1 private duration: Duration private baseScheduleTypes = ['daily', 'weekly', 'monthly', 'yearly'] private _scheduleString: string constructor(scheduleString: string) { this._scheduleString = scheduleString.toLowerCase() this.scheduleName = this._scheduleString if (this.baseScheduleTypes.includes(this._scheduleString)) { this.multiplier = 1 } if (this._scheduleString.includes('every')) { this.scheduleName = this.getBaseScheduleNameFromVariableString() this.multiplier = this.getMultiplierFromVariableString() } switch (this.scheduleName) { case 'daily': this.duration = { days: 1 } break case 'weekly': this.duration = { weeks: 1 } break case 'monthly': this.duration = { months: 1 } break case 'yearly': this.duration = { years: 1 } break default: throw new CustomError('Schedule type not supported', errorCodes.schedule_not_supported) } } public getSanitizedScheduleString(): string { return this._scheduleString } private getBaseScheduleNameFromVariableString(): string { if (this._scheduleString.includes('week')) return 'weekly' if (this._scheduleString.includes('day')) return 'daily' if (this._scheduleString.includes('month')) return 'monthly' if (this._scheduleString.includes('year')) return 'yearly' return '' } public getMultiplierFromVariableString(): number { const matches = this._scheduleString.match(/\d+/) if (matches) { const multi = matches[0] if (multi) return parseInt(multi) } return 1 } public calculateDuration(): Duration { const dur: Duration = { days: this.duration.days ? this.duration.days * this.multiplier : undefined, weeks: this.duration.weeks ? this.duration.weeks * this.multiplier : undefined, months: this.duration.months ? this.duration.months * this.multiplier : undefined, years: this.duration.years ? this.duration.years * this.multiplier : undefined, } return dur } public getNewDate(oldDate: Date): Date { const newDate = add(oldDate, this.calculateDuration()) return newDate } }