import Event from "../../../models/event"; export default defineEventHandler(async (event) => { const id = getRouterParam(event, "id"); if (!id) { throw createError({ statusCode: 400, statusMessage: "Event ID is required", }); } try { // Find event by ID or slug const eventData = await Event.findOne({ $or: [{ _id: id }, { slug: id }], isVisible: true, isCancelled: { $ne: true }, }).select("title slug description startDate endDate location"); if (!eventData) { throw createError({ statusCode: 404, statusMessage: "Event not found", }); } // Generate iCal format for single event const ical = generateSingleEventCalendar(eventData); // Set headers for download const filename = `${eventData.slug || eventData._id}.ics`; setHeader(event, "Content-Type", "text/calendar; charset=utf-8"); setHeader( event, "Content-Disposition", `attachment; filename="${filename}"` ); setHeader(event, "Cache-Control", "no-cache"); return ical; } catch (error) { console.error("Error generating event calendar:", error); if (error.statusCode) { throw error; } throw createError({ statusCode: 500, statusMessage: "Failed to generate calendar file", }); } }); function generateSingleEventCalendar(evt) { const now = new Date(); const timestamp = now .toISOString() .replace(/[-:]/g, "") .replace(/\.\d{3}/, ""); const eventStart = new Date(evt.startDate); const eventEnd = new Date(evt.endDate); const dtstart = eventStart .toISOString() .replace(/[-:]/g, "") .replace(/\.\d{3}/, ""); const dtend = eventEnd .toISOString() .replace(/[-:]/g, "") .replace(/\.\d{3}/, ""); // Clean description for iCal format const description = (evt.description || "") .replace(/\n/g, "\\n") .replace(/,/g, "\\,"); const eventUrl = `https://ghostguild.org/events/${evt.slug || evt._id}`; const ical = [ "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//Ghost Guild//Events//EN", "CALSCALE:GREGORIAN", "METHOD:PUBLISH", "BEGIN:VEVENT", `UID:${evt._id}@ghostguild.org`, `DTSTAMP:${timestamp}`, `DTSTART:${dtstart}`, `DTEND:${dtend}`, `SUMMARY:${evt.title}`, `DESCRIPTION:${description}\\n\\nView event: ${eventUrl}`, `LOCATION:${evt.location || "Online"}`, `URL:${eventUrl}`, `STATUS:CONFIRMED`, "END:VEVENT", "END:VCALENDAR", ]; return ical.join("\r\n"); }