UNPKG

school-schedule-sync

Version:

Synchronization between JSON schedule and Google Calendar

85 lines 4.64 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sync = sync; const fs_1 = __importDefault(require("fs")); const google_api_wrapper_1 = require("@anmiles/google-api-wrapper"); const logger_1 = require("@anmiles/logger"); const zod_tools_1 = require("@anmiles/zod-tools"); const calendar_1 = require("googleapis/build/src/apis/calendar"); require("@anmiles/prototypes"); const types_1 = require("./types"); const getFirstDay_1 = require("./utils/getFirstDay"); const paths_1 = require("./utils/paths"); const fullScopes = [ 'https://www.googleapis.com/auth/calendar.calendars.readonly', 'https://www.googleapis.com/auth/calendar.calendarlist.readonly', 'https://www.googleapis.com/auth/calendar.events.owned', ]; async function sync(profile, calendarName) { const YEAR = new Date().getFullYear(); const TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone; const scheduleJSON = fs_1.default.readJSON((0, paths_1.getScheduleFile)()); const schedule = (0, zod_tools_1.validate)(scheduleJSON, types_1.scheduleSchema); const calendarAPI = await (0, google_api_wrapper_1.getAPI)((auth) => (0, calendar_1.calendar)({ version: 'v3', auth }), profile, { temporary: true, scopes: fullScopes }); const allCalendars = await calendarAPI.getItems((api) => api.calendarList, {}, { hideProgress: true }); if (allCalendars.length === 0) { throw new Error(`There are no available calendars for profile '${profile}'`); } const selectedCalendars = calendarName ? schedule.calendars.filter((calendar) => calendar.name === calendarName) : schedule.calendars; if (selectedCalendars.length === 0) { throw new Error(`There is no calendar '${calendarName}' for profile '${profile}'`); } for (const calendar of selectedCalendars) { (0, logger_1.info)(`Calendar '${calendar.name}'...`); const calendarId = allCalendars.find((c) => c.summary === calendar.name)?.id; if (!calendarId) { throw new Error(`Unknown calendar '${calendar.name}' for profile '${profile}'`); } (0, logger_1.log)('Clearing calendar...'); const allEvents = await calendarAPI.getItems((api) => api.events, { calendarId }, { hideProgress: true }); await allEvents.forEachAsync(async (event) => { (0, logger_1.log)(` ${event.summary}`); await calendarAPI.api.events.delete({ calendarId, eventId: event.id ?? '' }); }); (0, logger_1.log)('Creating events...'); const sectionsOrLessons = calendar.type === 'sections' ? calendar.days : calendar.days.map((day) => day.map((name, index) => { const time = calendar.lessonTimes?.[index] ?? schedule.defaults.lessonTimes?.[index]; if (!time) { throw new Error(`Cannot find time described for lesson #${index + 1} in calendar '${calendar.name}'`); } return { name, ...time }; })); await sectionsOrLessons.forEachAsync(async (events, weekDay) => { const firstDay = (0, getFirstDay_1.getFirstDay)(weekDay, YEAR); (0, logger_1.log)(` #${weekDay + 1}`); await events.forEachAsync(async (event) => { const [startHour, startMinute] = event.startTime.split(':').map((str) => parseInt(str)).toTuple(2); const startDate = new Date(firstDay); startDate.setHours(startHour); startDate.setMinutes(startMinute); const endDate = new Date(startDate); endDate.setMinutes(endDate.getMinutes() + event.length); const dayAbbr = firstDay.toLocaleDateString('en-US', { weekday: 'short' }).slice(0, 2).toUpperCase(); (0, logger_1.log)(` ${event.startTime} ${event.name}`); await calendarAPI.api.events.insert({ calendarId, requestBody: { start: { dateTime: startDate.toISOString(), timeZone: TIMEZONE }, end: { dateTime: endDate.toISOString(), timeZone: TIMEZONE }, summary: event.name, location: event.location, recurrence: [`RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=${YEAR + 1}0525T000000Z;BYDAY=${dayAbbr}`], }, }, {}); }); }); } } //# sourceMappingURL=sync.js.map