diff --git a/lib/calendarClient.ts b/lib/calendarClient.ts index d3d0bb3e..786a47d5 100644 --- a/lib/calendarClient.ts +++ b/lib/calendarClient.ts @@ -323,7 +323,7 @@ const calendars = (withCredentials): CalendarApiAdapter[] => withCredentials.map }).filter(Boolean); -const getBusyTimes = (withCredentials, dateFrom, dateTo) => Promise.all( +const getBusyCalendarTimes = (withCredentials, dateFrom, dateTo) => Promise.all( calendars(withCredentials).map(c => c.getAvailability(dateFrom, dateTo)) ).then( (results) => results.reduce((acc, availability) => acc.concat(availability), []) @@ -364,4 +364,4 @@ const deleteEvent = (credential, uid: String): Promise => { return Promise.resolve({}); }; -export {getBusyTimes, createEvent, updateEvent, deleteEvent, CalendarEvent}; +export {getBusyCalendarTimes, createEvent, updateEvent, deleteEvent, CalendarEvent}; diff --git a/lib/videoClient.ts b/lib/videoClient.ts index a21f2b2c..c3e3bcae 100644 --- a/lib/videoClient.ts +++ b/lib/videoClient.ts @@ -112,38 +112,24 @@ const ZoomVideo = (credential): VideoApiAdapter => { return { getAvailability: (dateFrom, dateTo) => { - /*const payload = { - schedules: [credential.key.email], - startTime: { - dateTime: dateFrom, - timeZone: 'UTC', - }, - endTime: { - dateTime: dateTo, - timeZone: 'UTC', - }, - availabilityViewInterval: 60 - }; - return auth.getToken().then( - (accessToken) => fetch('https://graph.microsoft.com/v1.0/me/calendar/getSchedule', { - method: 'post', - headers: { - 'Authorization': 'Bearer ' + accessToken, - 'Content-Type': 'application/json' - }, - body: JSON.stringify(payload) + // TODO Possibly implement pagination for cases when there are more than 300 meetings already scheduled. + (accessToken) => fetch('https://api.zoom.us/v2/users/me/meetings?type=scheduled&page_size=300', { + method: 'get', + headers: { + 'Authorization': 'Bearer ' + accessToken + } + }) + .then(handleErrorsJson) + .then(responseBody => { + return responseBody.meetings.map((meeting) => ({ + start: meeting.start_time, + end: (new Date((new Date(meeting.start_time)).getTime() + meeting.duration * 60000)).toISOString() + })) }) - .then(handleErrorsJson) - .then(responseBody => { - return responseBody.value[0].scheduleItems.map((evt) => ({ - start: evt.start.dateTime + 'Z', - end: evt.end.dateTime + 'Z' - })) - }) ).catch((err) => { - console.log(err); - });*/ + console.log(err); + }); }, createMeeting: (event: CalendarEvent) => auth.getToken().then(accessToken => fetch('https://api.zoom.us/v2/users/me/meetings', { method: 'POST', @@ -181,7 +167,7 @@ const videoIntegrations = (withCredentials): VideoApiAdapter[] => withCredential }).filter(Boolean); -const getBusyTimes = (withCredentials, dateFrom, dateTo) => Promise.all( +const getBusyVideoTimes = (withCredentials, dateFrom, dateTo) => Promise.all( videoIntegrations(withCredentials).map(c => c.getAvailability(dateFrom, dateTo)) ).then( (results) => results.reduce((acc, availability) => acc.concat(availability), []) @@ -207,7 +193,7 @@ const createMeeting = async (credential, calEvent: CalendarEvent): Promise const attendeeMail = new VideoEventAttendeeMail(calEvent, uid, videoCallData); await ownerMail.sendEmail(); - if(!creationResult || !creationResult.disableConfirmationEmail) { + if (!creationResult || !creationResult.disableConfirmationEmail) { await attendeeMail.sendEmail(); } @@ -233,4 +219,4 @@ const deleteMeeting = (credential, uid: String): Promise => { return Promise.resolve({}); }; -export {getBusyTimes, createMeeting, updateMeeting, deleteMeeting}; +export {getBusyVideoTimes, createMeeting, updateMeeting, deleteMeeting}; diff --git a/pages/api/availability/[user].ts b/pages/api/availability/[user].ts index d3dfd856..4eb70683 100644 --- a/pages/api/availability/[user].ts +++ b/pages/api/availability/[user].ts @@ -1,6 +1,7 @@ -import type { NextApiRequest, NextApiResponse } from 'next'; +import type {NextApiRequest, NextApiResponse} from 'next'; import prisma from '../../../lib/prisma'; -import { getBusyTimes } from '../../../lib/calendarClient'; +import {getBusyCalendarTimes} from '../../../lib/calendarClient'; +import {getBusyVideoTimes} from '../../../lib/videoClient'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const { user } = req.query @@ -15,6 +16,21 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } }); - const availability = await getBusyTimes(currentUser.credentials, req.query.dateFrom, req.query.dateTo); - res.status(200).json(availability); + const hasCalendarIntegrations = currentUser.credentials.filter((cred) => cred.type.endsWith('_calendar')).length > 0; + const hasVideoIntegrations = currentUser.credentials.filter((cred) => cred.type.endsWith('_video')).length > 0; + + const calendarAvailability = await getBusyCalendarTimes(currentUser.credentials, req.query.dateFrom, req.query.dateTo); + const videoAvailability = await getBusyVideoTimes(currentUser.credentials, req.query.dateFrom, req.query.dateTo); + + let commonAvailability = []; + + if(hasCalendarIntegrations && hasVideoIntegrations) { + commonAvailability = calendarAvailability.filter(availability => videoAvailability.includes(availability)); + } else if(hasVideoIntegrations) { + commonAvailability = videoAvailability; + } else if(hasCalendarIntegrations) { + commonAvailability = calendarAvailability; + } + + res.status(200).json(commonAvailability); }