import { jsonError } from "../../../common.js"; export async function onRequestDelete(context: RequestContext) { const eventId = context.params.id as string; const eventData = await context.data.prisma.event.findUnique({ select: { created_by: true, day: true, month: true, performed_at: true, year: true, }, where: { id: eventId, }, }); if (!eventData) return jsonError("No event exists with that ID", 404); const { current_user: currentUser } = context.data; const isETM = [1 << 4, 1 << 12].find((int) => currentUser.permissions & int); if (eventData.created_by !== currentUser.id && !isETM) return jsonError("You are not authorized to delete that event", 403); const now = new Date(); now.setUTCHours(0, 0, 0, 0); const eventDate = new Date( eventData.year, eventData.month - 1, eventData.day, ); if (!isETM && now.getTime() >= eventDate.getTime()) return jsonError( "Event cannot be deleted on or after the scheduled date", 403, ); if (typeof eventData.performed_at === "number") return jsonError( "Event cannot be deleted because it has already been marked as completed or forgotten", 400, ); await context.data.prisma.event.delete({ where: { id: eventId, }, }); return new Response(null, { status: 204, }); } export async function onRequestPatch(context: RequestContext) { const eventId = context.params.id as string; const { body } = context.data; const eventData = await context.data.prisma.event.findUnique({ select: { created_by: true, day: true, month: true, type: true, year: true, }, where: { id: eventId, }, }); if (!eventData) return jsonError("No event exists with that ID", 404); const { current_user: currentUser } = context.data; if ( eventData.created_by !== currentUser.id && ![1 << 4, 1 << 12].find((int) => currentUser.permissions & int) ) return jsonError("You are not authorized to modify this event", 403); const date = new Date(); const currentDay = date.getUTCDate(); // Set to first of month to avoid any issues with month incrementation, then add month and subtract one day to get the last day of this month date.setUTCDate(1); date.setUTCMonth(date.getUTCMonth() + 1); date.setUTCDate(0); if ( typeof body.day !== "number" || body.day > date.getUTCDate() || body.day < 1 || // Check for nonintegers Math.floor(body.day) !== body.day || currentDay >= body.day ) return jsonError("Invalid day", 400); if ( date.getUTCFullYear() !== eventData.year || date.getUTCMonth() + 1 !== eventData.month ) return jsonError( "Only events in the current month period can be rescheduled", 400, ); if (eventData.type === "rotw") { const weekRanges: { [k: number]: number } = { 0: 7, 1: 14, 2: 21, 3: 28, 4: 35, }; const weekRange = Math.floor(body.day / 7); const matchingROTW = await context.data.prisma.event.findMany({ select: { id: true, }, where: { OR: [{ approved: true }, { pending: true }], day: { gte: weekRanges[weekRange] - 7, lte: weekRanges[weekRange], }, month: eventData.month, year: eventData.year, }, }); if (matchingROTW) return jsonError("There is already an ROTW scheduled for that week", 400); } else { const matchingEvent = await context.data.prisma.event.findMany({ select: { id: true, }, where: { OR: [{ approved: true }, { pending: true }], AND: [ { day: body.day }, { month: eventData.month }, { type: eventData.type }, { year: eventData.year }, ], }, }); if (matchingEvent) return jsonError( "There is already an event of that type scheduled for that day", 400, ); } await context.data.prisma.event.update({ data: { day: body.day, }, where: { id: eventId, }, }); await fetch(context.env.EVENTS_WEBHOOK, { body: JSON.stringify({ embeds: [ { title: "Event Rescheduled", color: 3756250, description: `${context.data.current_user.username} rescheduled their event for ${eventData.year}-${eventData.month.toString().padStart(2, "0")}-${eventData.day.toString().padStart(2, "0")} to ${eventData.year}-${eventData.month.toString().padStart(2, "0")}-${body.day}`, }, ], }), headers: { "content-type": "application/json", }, method: "POST", }); return new Response(null, { status: 204, }); } export async function onRequestPost(context: RequestContext) { const eventId = context.params.id as string; const eventData = await context.data.prisma.event.findUnique({ select: { approved: true, performed_at: true, }, where: { id: eventId, }, }); if (!eventData) return jsonError("No event exists with that ID", 404); if (!eventData.approved) return jsonError("Cannot perform unapproved event", 403); await context.data.prisma.event.update({ data: { performed_at: new Date(), }, where: { id: eventId, }, }); return new Response(null, { status: 204, }); }