1 import { c } from 'ttag';
3 import type { EventComponentIdentifiers } from '@proton/shared/lib/calendar/icsSurgery/interface';
5 import type { ICAL_ATTENDEE_STATUS } from '../constants';
6 import { ICAL_METHOD, ICAL_METHODS_ATTENDEE } from '../constants';
8 export enum INVITATION_ERROR_TYPE {
10 INVITATION_UNSUPPORTED,
25 export enum EVENT_INVITATION_ERROR_TYPE {
31 MISSING_ORIGINAL_ORGANIZER,
34 UNEXPECTED_FLOATING_TIME,
35 X_WR_TIMEZONE_UNSUPPORTED,
40 DTSTART_OUT_OF_BOUNDS,
45 SINGLE_EDIT_UNSUPPORTED,
53 INVITATION_UNSUPPORTED,
66 } = INVITATION_ERROR_TYPE;
68 export const getErrorMessage = (errorType: INVITATION_ERROR_TYPE, config?: EventInvitationErrorConfig) => {
69 const isUnknown = !config?.method;
70 const isImport = config?.method === ICAL_METHOD.PUBLISH;
71 const isResponse = config?.method && ICAL_METHODS_ATTENDEE.includes(config?.method);
72 const isProtonInvite = !!config?.isProtonInvite;
74 if (errorType === INVITATION_INVALID) {
76 return c('Attached ics file error').t`Invalid ICS file`;
79 return c('Attached ics file error').t`Invalid event`;
82 ? c('Event invitation error').t`Invalid response`
83 : c('Event invitation error').t`Invalid invitation`;
85 if (errorType === INVITATION_UNSUPPORTED) {
87 return c('Attached ics file error').t`Unsupported event`;
90 ? c('Event invitation error').t`Unsupported response`
91 : c('Event invitation error').t`Unsupported invitation`;
93 if (errorType === NO_COMPONENT) {
94 return c('Attached ics file error').t`Empty ICS file`;
96 if (errorType === NO_VEVENT) {
97 return c('Attached ics file error').t`Unsupported calendar component`;
99 if (errorType === INVALID_METHOD) {
101 return c('Attached ics file error').t`Invalid method`;
103 // Here we invert response <-> invitation as we take the perspective of the sender
105 ? c('Event invitation error').t`Invalid invitation`
106 : c('Event invitation error').t`Invalid response`;
108 if (errorType === PARSING_ERROR) {
109 return c('Event invitation error').t`Attached ICS file could not be read`;
111 if (errorType === DECRYPTION_ERROR) {
112 return c('Event invitation error').t`Attached ICS file could not be decrypted`;
114 if (errorType === FETCHING_ERROR) {
115 return c('Event invitation error').t`We could not retrieve the event from your calendar`;
117 if (errorType === UPDATING_ERROR) {
118 return c('Event invitation error').t`We could not update the event in your calendar`;
120 if (errorType === EVENT_CREATION_ERROR) {
121 return isProtonInvite
122 ? c('Event invitation error').t`The event could not be added to your calendar. No answer was sent`
123 : c('Event invitation error').t`Your answer was sent, but the event could not be added to your calendar`;
125 if (errorType === EVENT_UPDATE_ERROR) {
126 return isProtonInvite
127 ? c('Event invitation error').t`The event could not be updated in your calendar. No answer was sent`
128 : c('Event invitation error').t`Your answer was sent, but the event could not be updated in your calendar`;
130 if (errorType === CANCELLATION_ERROR) {
131 return c('Event invitation error').t`We could not cancel the event in your calendar`;
133 if (errorType === UNEXPECTED_ERROR) {
134 return c('Event invitation error').t`Unexpected error`;
136 if (errorType === EXTERNAL_ERROR) {
137 return config?.externalError?.message || '';
142 interface EventInvitationErrorConfig {
144 componentIdentifiers?: EventComponentIdentifiers;
145 extendedType?: EVENT_INVITATION_ERROR_TYPE;
146 externalError?: Error;
147 partstat?: ICAL_ATTENDEE_STATUS;
149 isProtonInvite?: boolean;
150 method?: ICAL_METHOD;
151 originalUniqueIdentifier?: string;
154 export class EventInvitationError extends Error {
155 type: INVITATION_ERROR_TYPE;
159 componentIdentifiers?: EventComponentIdentifiers;
161 extendedType?: EVENT_INVITATION_ERROR_TYPE;
163 method?: ICAL_METHOD;
165 partstat?: ICAL_ATTENDEE_STATUS;
169 isProtonInvite?: boolean;
171 externalError?: Error;
173 originalUniqueIdentifier?: string;
175 constructor(errorType: INVITATION_ERROR_TYPE, config?: EventInvitationErrorConfig) {
176 super(getErrorMessage(errorType, config));
177 this.type = errorType;
178 this.hashedIcs = config?.hashedIcs || '';
179 this.componentIdentifiers = config?.componentIdentifiers;
180 this.extendedType = config?.extendedType;
181 this.method = config?.method;
182 this.partstat = config?.partstat;
183 this.timestamp = config?.timestamp;
184 this.isProtonInvite = config?.isProtonInvite;
185 this.externalError = config?.externalError;
186 this.originalUniqueIdentifier = config?.originalUniqueIdentifier;
187 Object.setPrototypeOf(this, EventInvitationError.prototype);
193 hashedIcs: this.hashedIcs,
194 extendedType: this.extendedType,
195 componentIdentifiers: this.componentIdentifiers,
196 partstat: this.partstat,
197 timestamp: this.timestamp,
198 isProtonInvite: this.isProtonInvite,
199 externalError: this.externalError,
201 originalUniqueIdentifier: this.originalUniqueIdentifier,
206 export const cloneEventInvitationErrorWithConfig = (
207 error: EventInvitationError,
208 config: EventInvitationErrorConfig
211 ...error.getConfig(),
214 return new EventInvitationError(error.type, newConfig);