// scripts/backfill-series-id.js const { readFileSync, writeFileSync } = require('node:fs'); const { resolve } = require('node:path'); const { getCalendarEvents } = require('./lib/o365-calendar.js'); function upsertFrontmatterField(md, key, value) { const fmMatch = md.match(/^---\n([\s\S]*?)\n---/); if (!fmMatch) return md; const fm = fmMatch[1]; const lineRegex = new RegExp(`^${key}:.*$`, 'm'); let newFm; if (lineRegex.test(fm)) { newFm = fm.replace(lineRegex, `${key}: ${value}`); } else { newFm = `${fm}\n${key}: ${value}`; } return md.replace(/^---\n[\s\S]*?\n---/, `---\n${newFm}\n---`); } async function backfill(agendaPath, titleRegex, daysAhead = 30) { const events = await getCalendarEvents(daysAhead); const re = new RegExp(titleRegex, 'i'); const match = events.find(e => re.test(e.title) && e.isRecurring); if (!match) { throw new Error(`no recurring event matching /${titleRegex}/ in next ${daysAhead} days`); } // Need raw seriesMasterId — re-fetch single event by id (parseEventToMeeting drops it) const { getEventById } = require('./lib/o365-calendar.js'); const raw = await getEventById(match.id); const seriesId = raw.seriesMasterId; if (!seriesId) { throw new Error(`event ${match.id} has no seriesMasterId`); } const md = readFileSync(agendaPath, 'utf-8'); const updated = upsertFrontmatterField(md, 'o365_series_id', seriesId); writeFileSync(agendaPath, updated, 'utf-8'); return seriesId; } async function main() { const args = process.argv.slice(2); if (args.length < 2) { console.error('Usage: node backfill-series-id.js '); process.exit(2); } const [agendaPath, titleRegex] = args; const id = await backfill(resolve(agendaPath), titleRegex); console.log(`set o365_series_id=${id} in ${agendaPath}`); } if (require.main === module) { main().catch(e => { console.error(e.stack || e.message); process.exit(1); }); } module.exports = { upsertFrontmatterField, backfill };