Agenda refactor

This commit is contained in:
alma 2026-01-15 14:26:32 +01:00
parent 8f4a9da96b
commit 6fefc74fd5

View File

@ -266,6 +266,60 @@ export async function fetchMicrosoftEvents(
errorDetails.params = error.config?.params;
}
// If calendar not found (404), try using the default calendar instead
if (error.response?.status === 404 && error.response?.data?.error?.code === 'ErrorItemNotFound') {
logger.warn('Calendar not found, trying default calendar', {
userId,
email,
oldCalendarId: calendarId,
});
// Try using the default calendar endpoint
try {
const accessToken = await getMicrosoftGraphClient(userId, email);
const defaultUrl = 'https://graph.microsoft.com/v1.0/me/calendar/events';
const params: any = {
$select: 'id,subject,body,start,end,location,isAllDay',
$orderby: 'start/dateTime asc',
$top: 1000,
};
if (startDate && endDate) {
const startDateTimeStr = startDate.toISOString();
const endDateTimeStr = endDate.toISOString();
params.$filter = `start/dateTime ge '${startDateTimeStr}' and start/dateTime le '${endDateTimeStr}'`;
}
logger.info('Fetching from default calendar', {
url: defaultUrl,
params: JSON.stringify(params),
});
const response = await axios.get(defaultUrl, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
params,
});
const events = response.data.value || [];
logger.info('Successfully fetched from default calendar', {
eventCount: events.length,
});
return events;
} catch (fallbackError: any) {
logger.error('Failed to fetch from default calendar', {
userId,
email,
error: fallbackError instanceof Error ? fallbackError.message : String(fallbackError),
});
// Continue to throw original error
}
}
logger.error('Error fetching Microsoft events', errorDetails);
throw error;
}
@ -383,13 +437,128 @@ export async function syncMicrosoftCalendar(
dateRange: { start: startDate.toISOString(), end: endDate.toISOString() },
});
const microsoftEvents = await fetchMicrosoftEvents(
syncConfig.calendar.userId,
creds.email,
syncConfig.externalCalendarId || '',
startDate,
endDate
);
// Fetch events from Microsoft Graph API
// If calendar ID is invalid (404), we'll try to discover and update it
let microsoftEvents: MicrosoftEvent[];
let calendarIdToUse = syncConfig.externalCalendarId || '';
try {
microsoftEvents = await fetchMicrosoftEvents(
syncConfig.calendar.userId,
creds.email,
calendarIdToUse,
startDate,
endDate
);
} catch (error: any) {
// If calendar not found (404), try to discover available calendars and update
if (error.response?.status === 404 && error.response?.data?.error?.code === 'ErrorItemNotFound') {
logger.warn('Calendar ID not found, discovering available calendars', {
calendarSyncId,
oldCalendarId: calendarIdToUse,
email: creds.email,
});
// Discover available calendars
const availableCalendars = await discoverMicrosoftCalendars(
syncConfig.calendar.userId,
creds.email
);
if (availableCalendars.length > 0) {
// Use the first calendar (usually the default "Calendar")
const newCalendar = availableCalendars[0];
calendarIdToUse = newCalendar.id;
logger.info('Updating calendar sync with new calendar ID', {
calendarSyncId,
oldCalendarId: syncConfig.externalCalendarId,
newCalendarId: calendarIdToUse,
newCalendarName: newCalendar.name,
});
// Update the sync config with the new calendar ID
await prisma.calendarSync.update({
where: { id: calendarSyncId },
data: {
externalCalendarId: calendarIdToUse,
lastSyncError: null, // Clear previous error
},
});
// Retry fetching events with the new calendar ID
microsoftEvents = await fetchMicrosoftEvents(
syncConfig.calendar.userId,
creds.email,
calendarIdToUse,
startDate,
endDate
);
} else {
// No calendars found, try using default calendar endpoint
logger.warn('No calendars discovered, using default calendar endpoint', {
calendarSyncId,
email: creds.email,
});
// Use default calendar by fetching without a specific calendar ID
const accessToken = await getMicrosoftGraphClient(syncConfig.calendar.userId, creds.email);
const defaultUrl = 'https://graph.microsoft.com/v1.0/me/calendar/events';
const params: any = {
$select: 'id,subject,body,start,end,location,isAllDay',
$orderby: 'start/dateTime asc',
$top: 1000,
};
const startDateTimeStr = startDate.toISOString();
const endDateTimeStr = endDate.toISOString();
params.$filter = `start/dateTime ge '${startDateTimeStr}' and start/dateTime le '${endDateTimeStr}'`;
const response = await axios.get(defaultUrl, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
params,
});
microsoftEvents = response.data.value || [];
// Try to get the default calendar ID for future use
try {
const calendarResponse = await axios.get('https://graph.microsoft.com/v1.0/me/calendar', {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
const defaultCalendarId = calendarResponse.data.id;
if (defaultCalendarId) {
await prisma.calendarSync.update({
where: { id: calendarSyncId },
data: {
externalCalendarId: defaultCalendarId,
lastSyncError: null,
},
});
logger.info('Updated sync config with default calendar ID', {
calendarSyncId,
defaultCalendarId,
});
}
} catch (calendarIdError) {
logger.warn('Could not fetch default calendar ID', {
error: calendarIdError instanceof Error ? calendarIdError.message : String(calendarIdError),
});
}
}
} else {
// Re-throw other errors
throw error;
}
}
// Log all events with full details
logger.info('Fetched Microsoft events', {