Compare commits

..

2 commits

Author SHA1 Message Date
e3402fed65
Adding env var to show version is local
All checks were successful
ci/woodpecker/manual/test Pipeline was successful
ci/woodpecker/manual/deploy Pipeline was successful
2026-04-20 09:16:01 +02:00
7fe76186c7 Adding better error logs for ntfy client
All checks were successful
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
2026-04-19 22:45:54 +02:00
5 changed files with 5 additions and 142 deletions

View file

@ -41,7 +41,7 @@ export class NtfyClient {
throw new Error(`${response.status} - ${response.statusText}`)
}
} catch (error: unknown) {
this.loggerService.error('ntfy client failed', { error })
this.loggerService.error('ntfy client failed', { error: error instanceof Error ? error.message : JSON.stringify(error) })
}
}
}

View file

@ -107,39 +107,6 @@ export class NtfyProvider implements OnApplicationBootstrap {
)
}
async sendPerformingRiskyReservationNotification(
reservationId: string,
startTime: Dayjs,
endTime: Dayjs,
) {
const url = `${this.configService.get(
'BASE_URL',
)}/reservations/${reservationId}`
await this.publishQueue.add(
...NtfyProvider.defaultJob({
title: 'Handling risky reservation. Waiting for confirmation',
message: `Waiting for ${reservationId} - ${startTime.format()} to ${endTime.format()}`,
actions: [
{
action: 'http',
label: 'Accept',
url: `${url}/resume`,
method: 'POST',
clear: true,
},
{
action: 'http',
label: 'Reject',
url,
method: 'DELETE',
clear: true,
},
],
tags: [MessageTags.warning, MessageTags.passport_control],
}),
)
}
async sendErrorPerformingReservationNotification(
reservationId: string,
startTime: Dayjs,

View file

@ -49,7 +49,6 @@ export enum MessageTags {
clock11 = 'clock11',
clock1130 = 'clock1130',
badminton = 'badminton',
passport_control = 'passport_control',
}
export enum MessagePriority {
@ -60,60 +59,13 @@ export enum MessagePriority {
max = 5,
}
type MessageActionType = 'broadcast' | 'copy' | 'http' | 'view'
export interface MessageActionConfig {
action: MessageActionType
/**
* Label displayed on the action button
*/
label: string
/**
* Clear notification after action button is tapped
*/
clear?: boolean
}
export interface BroadcastActionConfig extends MessageActionConfig {
action: 'broadcast'
intent?: string
extras?: Record<string, string>
}
export interface CopyActionConfig extends MessageActionConfig {
action: 'copy'
value: string
}
export interface HttpActionConfig extends MessageActionConfig {
action: 'http'
url: string
/**
* @default 'POST'
*/
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' // there are more but if I use them I'll have gone insane
headers?: Record<string, string>
body?: string
}
export interface ViewActionConfig extends MessageActionConfig {
action: 'view'
url: string
clear?: boolean
}
export type MessageAction =
| BroadcastActionConfig
| CopyActionConfig
| HttpActionConfig
| ViewActionConfig
export interface MessageConfig {
topic: string
message?: string
title?: string
tags?: MessageTags[]
priority?: MessagePriority
actions?: MessageAction[]
actions?: object[]
markdown?: boolean
icon?: string
}

View file

@ -8,12 +8,6 @@ import { LoggerService } from '../logger/service.logger'
import { BaanReserverenService } from '../runner/baanreserveren/service'
import { Reservation, ReservationStatus } from './entity'
export enum ReservationDangerLevel {
Safe = 'safe',
Risky = 'risky',
Lethal = 'lethal',
}
@Injectable()
export class ReservationsService {
constructor(
@ -99,19 +93,6 @@ export class ReservationsService {
return await this.reservationsRepository.save(res)
}
getDangerLevel(reservation: Reservation) {
// don't book something within the ~~danger zone~~
const now = dayjs()
const hourDiff = now.diff(reservation.dateRangeStart, 'hours')
if (hourDiff > 8) {
return ReservationDangerLevel.Safe
} else if (hourDiff >= 5) {
return ReservationDangerLevel.Risky
} else {
return ReservationDangerLevel.Lethal
}
}
async update(reservationId: string, update: Partial<Reservation>) {
return await this.reservationsRepository.update(reservationId, update)
}

View file

@ -12,11 +12,7 @@ import {
RESERVATIONS_QUEUE_NAME,
ReservationsQueue,
} from '../reservations/config'
import { Reservation } from '../reservations/entity'
import {
ReservationDangerLevel,
ReservationsService,
} from '../reservations/service'
import { ReservationsService } from '../reservations/service'
import { WaitingListDetails } from './types'
const EMAIL_SUBJECT_REGEX = new RegExp(
@ -94,45 +90,12 @@ export class WaitingListService {
return
}
// don't book something within the ~~danger zone~~
const partitioned = reservations.reduce<{
safe: Reservation[]
risky: Reservation[]
lethal: Reservation[]
}>(
(acc, res) => {
switch (this.reservationsService.getDangerLevel(res)) {
case ReservationDangerLevel.Safe:
return {
safe: [...acc.safe, res],
risky: acc.risky,
lethal: acc.lethal,
}
case ReservationDangerLevel.Risky:
return {
safe: acc.safe,
risky: [...acc.risky, res],
lethal: acc.lethal,
}
case ReservationDangerLevel.Lethal:
return {
safe: acc.safe,
risky: acc.risky,
lethal: [...acc.lethal, res],
}
}
},
{ safe: [], risky: [], lethal: [] },
)
this.loggerService.debug(
`Found the reservations in given categories: ${JSON.stringify(
partitioned,
)}`,
`Found ${reservations.length} reservations on waiting list`,
)
await this.reservationsQueue.addBulk(
partitioned.safe.map((r) => ({
reservations.map((r) => ({
data: { reservation: r, speedyMode: false },
opts: { attempts: 1 },
})),