From 7125f30bfc01b85cc1cc117728a1b61046ce1664 Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Sun, 22 Feb 2026 09:44:04 -0800 Subject: [PATCH] Remove inline base64 image embedding from iCal output No major calendar client renders these inline binary attachments. The ATTACH URL is kept, which links to the publicly hosted image. Co-Authored-By: Claude Opus 4.6 --- app/data/updaters/DataUpdater.mjs | 36 +++++-------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/app/data/updaters/DataUpdater.mjs b/app/data/updaters/DataUpdater.mjs index 6573778..9afb683 100644 --- a/app/data/updaters/DataUpdater.mjs +++ b/app/data/updaters/DataUpdater.mjs @@ -89,13 +89,13 @@ export default class DataUpdater await this.updateLocalizations(this.defaultLocale, data); // Download any new images - const images = await this.downloadImages(data); + await this.downloadImages(data); // Write the data to disk await this.saveData(data); // Update iCal data - await this.updateCalendarEvents(data, images); + await this.updateCalendarEvents(data); this.console.info('Done'); } @@ -223,11 +223,11 @@ export default class DataUpdater // Calendar output - async updateCalendarEvents(data, images) { + async updateCalendarEvents(data) { const events = this.getCalendarEntries(data); if (!events) return; - const ical = await this.getiCalData(events, images); + const ical = await this.getiCalData(events); await this.writeFile(this.getCalendarPath(this.calendarFilename ?? this.filename), ical); } @@ -239,7 +239,7 @@ export default class DataUpdater // } - async getiCalData(events, images) { + async getiCalData(events) { // Create a calendar object const calendar = ical({ name: this.calendarName ?? this.name, @@ -252,9 +252,6 @@ export default class DataUpdater timezone: 'UTC', }); - // Create a map of image URLs to image data - const imageData = {}; - // Add event entries for (let event of events) { let calEvent = calendar.createEvent({ @@ -265,34 +262,11 @@ export default class DataUpdater url: event.url, }); calEvent.createAttachment(event.imageUrl); - - const filename = images[event.imageUrl]; - if (filename) { - try { - const data = await fs.readFile(this.imageProcessor.localPath(filename)); - imageData[event.imageUrl] = data; - } catch { - // Image not available locally (may only exist in S3); skip inline embed - } - } } // Convert the calendar to an ICS string let ics = calendar.toString(); - // Embed image attachments - ics = ics.replaceAll(/^ATTACH:((.|\r\n )*)$/gm, (match, url) => { - url = url.replaceAll('\r\n ', ''); - - const filename = images[url]; - const data = imageData[url]; - if (!filename || !data) return match; - - const ical = `ATTACH;ENCODING=BASE64;VALUE=BINARY;X-APPLE-FILENAME=${path.basename(filename)}:${data.toString('base64')}`; - - return ical.replace(/(.{72})/g, '$1\r\n ').trim(); - }); - return ics; } }