Compare commits

..

6 Commits

Author SHA1 Message Date
mightypanders
790a0d65f4 use repetitionstring validator in new and updated events
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2022-04-23 21:32:32 +02:00
mightypanders
b22cb1167d implement repetitionstring validator
parses repetition string and sends a message on fail to the creator
which contains the offending error code
2022-04-23 21:31:47 +02:00
mightypanders
0d28fce640 remove unused property 2022-04-23 21:31:09 +02:00
mightypanders
dec3a3070f add CustomError Class as wrapper for "Error"
throw new CustomError('message','errorCode')
2022-04-23 21:30:11 +02:00
mightypanders
99386b1662 adjust an error message 2022-04-23 21:29:35 +02:00
mightypanders
6ff3e68921 adjust npm scripts 2022-04-23 21:26:08 +02:00
7 changed files with 88 additions and 16 deletions

View File

@ -7,7 +7,7 @@
"build": "tsc", "build": "tsc",
"clean": "rimraf build", "clean": "rimraf build",
"watch": "yarn run clean && yarn run build -- -w", "watch": "yarn run clean && yarn run build -- -w",
"monitor": "nodemon index.ts", "monitor": "nodemon build/index.js",
"start": "node build/index.js", "start": "node build/index.js",
"buildstart": "yarn run build && node build/index.js", "buildstart": "yarn run build && node build/index.js",
"lint": "eslint . --ext .ts --fix", "lint": "eslint . --ext .ts --fix",

View File

@ -1,9 +1,11 @@
import { GuildScheduledEvent } from 'discord.js' import { GuildScheduledEvent } from 'discord.js'
import { validateRepetitionStringAndSendMessageOnFail } from '../handler/repeatingEvents/helper'
export const name = 'guildScheduledEventCreate' export const name = 'guildScheduledEventCreate'
export function execute(guildScheduledEvent: GuildScheduledEvent) { export async function execute(guildScheduledEvent: GuildScheduledEvent) {
try{ try {
console.log(`${JSON.stringify(guildScheduledEvent)} has been created.`) console.log(`${JSON.stringify(guildScheduledEvent)} has been created.`)
}catch(error) { validateRepetitionStringAndSendMessageOnFail(guildScheduledEvent)
} catch (error) {
console.error(error) console.error(error)
} }
} }

View File

@ -1,13 +1,19 @@
import { GuildScheduledEvent } from "discord.js" import { GuildScheduledEvent } from "discord.js"
import { repetitionMarkerIsFound } from "../handler/repeatingEvents/helper" import { config } from "../configuration"
import { repetitionMarkerIsFound, validateRepetitionStringAndSendMessageOnFail } from "../handler/repeatingEvents/helper"
import { handleRepeatingEvent } from "../handler/repeatingEvents/repeatingEvents.controller" import { handleRepeatingEvent } from "../handler/repeatingEvents/repeatingEvents.controller"
export const name = 'guildScheduledEventUpdate' export const name = 'guildScheduledEventUpdate'
export function execute(oldguildScheduledEvent: GuildScheduledEvent, newguildScheduledEvent: GuildScheduledEvent) { export function execute(oldguildScheduledEvent: GuildScheduledEvent, newguildScheduledEvent: GuildScheduledEvent) {
if (config.debug) {
console.dir(oldguildScheduledEvent) console.dir(oldguildScheduledEvent)
console.dir(newguildScheduledEvent) console.dir(newguildScheduledEvent)
}
if (oldguildScheduledEvent.description !== newguildScheduledEvent.description) {
validateRepetitionStringAndSendMessageOnFail(newguildScheduledEvent)
}
if (oldguildScheduledEvent.description && repetitionMarkerIsFound(oldguildScheduledEvent.description)) { if (oldguildScheduledEvent.description && repetitionMarkerIsFound(oldguildScheduledEvent.description)) {
// valid repeating event // valid repeating event
if (newguildScheduledEvent.status === 'COMPLETED') if (newguildScheduledEvent.status === 'COMPLETED')

View File

@ -1,8 +1,9 @@
import { format } from "date-fns" import { format } from "date-fns"
import add from "date-fns/add" import add from "date-fns/add"
import { DateResolvable, Guild, GuildScheduledEvent, GuildScheduledEventCreateOptions } from "discord.js" import { DateResolvable, Guild, GuildScheduledEvent, GuildScheduledEventCreateOptions } from "discord.js"
import { client } from "../../.."
import { findInScheduleTypes } from "../../helper/typeFind" import { findInScheduleTypes } from "../../helper/typeFind"
import { Maybe } from "../../interfaces" import { CustomError, errorCodes, Maybe } from "../../interfaces"
import { RepetitonInfo, supportedSchedule } from "../../types/scheduledEventTypes" import { RepetitonInfo, supportedSchedule } from "../../types/scheduledEventTypes"
export const repetitionMarkerIsFound = (desc: string): boolean => desc.includes('$rep') export const repetitionMarkerIsFound = (desc: string): boolean => desc.includes('$rep')
@ -14,7 +15,7 @@ export function getRepetitonInfo(description: string): RepetitonInfo {
const lines = description.split(`\n`) const lines = description.split(`\n`)
const repetitionString = lines.find(x => x.startsWith('$rep:')) const repetitionString = lines.find(x => x.startsWith('$rep:'))
if (!repetitionString) if (!repetitionString)
throw new Error('Cant find repetition string') throw new CustomError('Cant find repetition string', errorCodes.no_string_present)
const schedule: supportedSchedule = determineSchedule(repetitionString) const schedule: supportedSchedule = determineSchedule(repetitionString)
const { totalAmount, alreadyOccured } = determineRepetitionCount(repetitionString) const { totalAmount, alreadyOccured } = determineRepetitionCount(repetitionString)
const endDate = determineEndDate(repetitionString) const endDate = determineEndDate(repetitionString)
@ -33,14 +34,18 @@ export function determineSchedule(repetitionLine: string): supportedSchedule {
if (easilyKnownScheduleName) if (easilyKnownScheduleName)
return easilyKnownScheduleName return easilyKnownScheduleName
else else
throw new Error('Inferring schedule names is not yet supported') throw new CustomError('Inferring schedule names is not yet supported', errorCodes.schedule_not_supported)
} }
export function determineRepetitionCount(description: string): { totalAmount: number; alreadyOccured: number } { export function determineRepetitionCount(description: string): { totalAmount: number; alreadyOccured: number } {
const segments = description.split(':') const segments = description.split(':')
const amountSegment = segments[2] const amountSegment = segments[2]
if (amountSegment) {
const amounts = amountSegment.split('/') const amounts = amountSegment.split('/')
return { totalAmount: Number(amounts[1]) ?? 0, alreadyOccured: Number(amounts[0]) ?? 0 } return { totalAmount: Number(amounts[1]) ?? 0, alreadyOccured: Number(amounts[0]) ?? 0 }
} else {
throw new CustomError('No amount was defined', errorCodes.no_repetition_amount)
}
} }
export function buildNewRepetitionString(repetitionInfo: RepetitonInfo) { export function buildNewRepetitionString(repetitionInfo: RepetitonInfo) {
@ -72,7 +77,7 @@ export function getNewScheduledStart(oldguildScheduledEvent: GuildScheduledEvent
monthsToAdd = 1 monthsToAdd = 1
break break
default: default:
throw new Error('No schedule found, cant add days') throw new CustomError('No schedule found, cant add days', errorCodes.no_schedule)
} }
const duration: Duration = { const duration: Duration = {
days: daysToAdd, days: daysToAdd,
@ -102,4 +107,45 @@ function determineEndDate(description: string): Maybe<Date> {
} }
return return
} }
export function checkIfRepetitionStringIsValid(description: string): string {
if (!description) return 'not_present'
if (repetitionMarkerIsFound(description)) {
let repetitionInfo
try {
repetitionInfo = getRepetitonInfo(description)
if (!repetitionInfo.schedule) return 'no_schedule'
if (!repetitionInfo.totalAmount && !repetitionInfo.alreadyOccured && !repetitionInfo.endDate) {
if (!repetitionInfo.totalAmount || !repetitionInfo.alreadyOccured) return 'no_amount'
if (!repetitionInfo.endDate) return 'no_end'
}
return 'valid'
} catch (error) {
if (error instanceof CustomError) {
return error.getCode()
}
return 'invalid'
}
} return 'not_present'
}
export async function validateRepetitionStringAndSendMessageOnFail(event: GuildScheduledEvent): Promise<void> {
const validResponses = [
'valid',
'not_present'
]
const resultstring: string = checkIfRepetitionStringIsValid(event.description ?? "")
if (validResponses.includes(resultstring)) {
// do success things?
} else {
const creatorMessage = `The repetition string in your event could not be parsed. Reason: ${resultstring}`
console.log(creatorMessage)
if (!event.creatorId) throw new CustomError('No creator ID present', errorCodes.no_creator_id)
const creator = await client.users.fetch(event.creatorId)
console.log(`Creator ${JSON.stringify(creator)}`)
if (creator)
if (!creator.dmChannel)
await creator.createDM()
await creator.dmChannel?.send(creatorMessage)
}
}

View File

@ -1,3 +1,4 @@
import { CustomError, errorCodes } from "../interfaces";
import { scheduleNames, supportedSchedule } from "../types/scheduledEventTypes"; import { scheduleNames, supportedSchedule } from "../types/scheduledEventTypes";
export function findInScheduleTypes(inputString: string): supportedSchedule { export function findInScheduleTypes(inputString: string): supportedSchedule {
@ -7,7 +8,7 @@ export function findInScheduleTypes(inputString: string): supportedSchedule {
// `sheepName` comes from the list of `sheepNames` so the compiler is happy. // `sheepName` comes from the list of `sheepNames` so the compiler is happy.
return scheduleName; return scheduleName;
} }
throw new Error('That is not a schedule name.'); throw new CustomError('That is not a schedule name.', errorCodes.schedule_not_supported);
} }

View File

@ -9,3 +9,21 @@ export interface localized_string {
[k in supported_languages]: string [k in supported_languages]: string
} }
} }
export class CustomError extends Error {
private code: string
public constructor(message: string, errorCode: string) {
super(message)
this.code = errorCode
}
public getCode() { return this.code }
}
export const errorCodes = {
no_end_date: 'no_end_date',
no_string_present: 'no_string_present',
no_schedule: 'no_schedule',
schedule_not_supported: 'schedule_not_supported',
no_repetition_amount: 'no_repetition_amount',
invalid_repetition_string: 'invalid_repetition_string',
no_creator_id: "no_creator_id",
}

View File

@ -5,7 +5,6 @@ export interface RepetitonInfo {
totalAmount: number, totalAmount: number,
alreadyOccured: number, alreadyOccured: number,
schedule: supportedSchedule schedule: supportedSchedule
numberOfDays?: number
} }
export const scheduleNames = ['daily', 'weekly', 'monthly', 'everyTwoWeeks', 'everyNDays'] export const scheduleNames = ['daily', 'weekly', 'monthly', 'everyTwoWeeks', 'everyNDays']
export type supportedSchedule = typeof scheduleNames[number] export type supportedSchedule = typeof scheduleNames[number]