brain/scripts/backfill-series-id.js

56 lines
2.0 KiB
JavaScript

// 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 <agenda-path> <title-regex>');
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 };