11import { NextRequest , NextResponse } from "next/server" ;
2+ import pLimit from "p-limit" ;
23import { Client } from "@notionhq/client" ;
4+ import { google } from "googleapis" ;
35import crypto from "crypto" ;
46import fs from "fs/promises" ;
57import path from "path" ;
@@ -10,7 +12,7 @@ import {
1012 NotionApiResponse ,
1113 mapNotionResultToPage ,
1214} from "@/types/notion" ;
13- import { syncAllEventsToCalendar , getOrCreateUserCalendar } from "@/utils/googleCalendar" ;
15+ import { syncAllEventsToCalendar } from "@/utils/googleCalendar" ;
1416import { getAllUsers } from "@/utils/dbUtils" ;
1517
1618const NOTION_API_KEY = process . env . NOTION_API_KEY ! ;
@@ -58,35 +60,60 @@ async function fetchAllNotionEvents(): Promise<NotionEvent[]> {
5860 return pages . map ( parseNotionPageToEvent ) ;
5961}
6062
63+ async function getExistingNEIISTCalendars ( ) {
64+ const SCOPES = [ "https://www.googleapis.com/auth/calendar" ] ;
65+ const serviceAccountKey = JSON . parse ( process . env . GOOGLE_SERVICE_ACCOUNT_KEY ! ) ;
66+ const auth = new google . auth . GoogleAuth ( {
67+ credentials : serviceAccountKey ,
68+ scopes : SCOPES ,
69+ } ) ;
70+ const calendar = google . calendar ( { version : "v3" , auth } ) ;
71+
72+ const response = await calendar . calendarList . list ( ) ;
73+ const calendars = response . data . items || [ ] ;
74+ return calendars . filter ( ( cal ) => cal . summary ?. startsWith ( "NEIIST-" ) ) ;
75+ }
76+
6177async function syncAllEventsToGoogleCalendars ( events : NotionEvent [ ] ) {
6278 const allUsers = await getAllUsers ( ) ;
63- const users = allUsers . filter ( ( u ) => u . email && u . istid ) ;
79+ const existingCalendars = await getExistingNEIISTCalendars ( ) ;
80+ const calendarByIstid = new Map < string , { id : string ; summary : string } > ( ) ;
81+
82+ existingCalendars . forEach ( ( cal ) => {
83+ const istidMatch = cal . description ?. match ( / i s t i d : ( [ a - z A - Z 0 - 9 ] + ) / ) ;
84+ if ( istidMatch ) {
85+ calendarByIstid . set ( istidMatch [ 1 ] , { id : cal . id ! , summary : cal . summary ! } ) ;
86+ }
87+ } ) ;
88+
89+ const usersWithCalendars = allUsers . filter (
90+ ( u ) => u . email && u . istid && calendarByIstid . has ( u . istid )
91+ ) ;
92+
93+ const limit = pLimit ( 2 ) ;
6494
6595 const results = await Promise . all (
66- users . map ( async ( user ) => {
67- try {
68- const alternativeEmailRaw = user . alternativeEmailVerified
69- ? user . alternativeEmail
70- : undefined ;
71- const alternativeEmail = alternativeEmailRaw ?? undefined ;
72- const calendarId = await getOrCreateUserCalendar (
73- user . email ! ,
74- user . istid ,
75- user . name ,
76- alternativeEmail
77- ) ;
78- const stats = await syncAllEventsToCalendar (
79- calendarId ,
80- events ,
81- user . email ! ,
82- alternativeEmail
83- ) ;
84- return stats ;
85- } catch ( error ) {
86- console . error ( `✗ Error syncing calendar for ${ user . istid } :` , error ) ;
87- return { updated : 0 , deleted : 0 , unchanged : 0 } ;
88- }
89- } )
96+ usersWithCalendars . map ( ( user ) =>
97+ limit ( async ( ) => {
98+ try {
99+ const alternativeEmailRaw = user . alternativeEmailVerified
100+ ? user . alternativeEmail
101+ : undefined ;
102+ const alternativeEmail = alternativeEmailRaw ?? undefined ;
103+ const calendarId = calendarByIstid . get ( user . istid ) ! . id ;
104+ const stats = await syncAllEventsToCalendar (
105+ calendarId ,
106+ events ,
107+ user . email ! ,
108+ alternativeEmail
109+ ) ;
110+ return stats ;
111+ } catch ( error ) {
112+ console . error ( `Error syncing calendar for ${ user . istid } :` , error ) ;
113+ return { updated : 0 , deleted : 0 , unchanged : 0 } ;
114+ }
115+ } )
116+ )
90117 ) ;
91118
92119 const totals = results . reduce (
0 commit comments