const CALENDAR_READONLY_SCOPE = 'https://www.googleapis.com/auth/calendar.readonly' const GMAIL_READONLY_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly' export const GOOGLE_CALENDAR_CONNECT_URL = 'https://kody.codes/connect/oauth?provider=google' export const GOOGLE_INBOX_CONNECT_URL = 'https://kody.codes/connect/oauth?provider=google&authorizeUrl=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fv2%2Fauth&tokenUrl=https%3A%2F%2Foauth2.googleapis.com%2Ftoken&flow=confidential&scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.readonly&allowedHosts=www.googleapis.com%2Cgmail.googleapis.com&extraAuthorizeParams=%7B%22access_type%22%3A%22offline%22%2C%22prompt%22%3A%22consent%22%7D' function errorMessage(error: unknown): string { if (error instanceof Error && error.message) return error.message if (error && typeof error === 'object' && 'message' in error) { const message = (error as { message?: unknown }).message if (typeof message === 'string' && message.trim()) return message } return String(error || 'Unknown error') } function httpStatus(error: unknown): number | undefined { if (!error || typeof error !== 'object') return undefined const status = (error as { status?: unknown }).status return typeof status === 'number' ? status : undefined } function looksLikeInsufficientScope(error: unknown): boolean { const status = httpStatus(error) const message = errorMessage(error) return ( status === 403 || /insufficient[\s._-]?scope|ACCESS_TOKEN_SCOPE|accessNotConfigured|has not been used in project/i.test( message, ) ) } function looksLikeMissingAuth(error: unknown): boolean { return /Could not authenticate|not found|no refresh|Missing required Google account/i.test( errorMessage(error), ) } export function googleCalendarSetupError(error: unknown, account: string): Error { const original = errorMessage(error) if (!looksLikeInsufficientScope(error) && !looksLikeMissingAuth(error)) { return error instanceof Error ? error : new Error(original) } return new Error( `Google Calendar could not run for account "${account}". It needs the ${CALENDAR_READONLY_SCOPE} scope (or calendar.events.readonly). Connect or reconnect the google integration at ${GOOGLE_CALENDAR_CONNECT_URL} and grant Calendar, then retry. Original error: ${original}`, ) } export function googleInboxSetupError(error: unknown, account: string): Error { const original = errorMessage(error) if (!looksLikeInsufficientScope(error) && !looksLikeMissingAuth(error)) { return error instanceof Error ? error : new Error(original) } return new Error( `Gmail inbox reading could not run for account "${account}". Inbox access needs the ${GMAIL_READONLY_SCOPE} scope. Register a Google OAuth client, enable the Gmail API, publish the app to Production (Testing refresh tokens expire after 7 days), and connect at ${GOOGLE_INBOX_CONNECT_URL}. Original error: ${original}`, ) }