import z from "zod"; import Sendgrid, { SendgridNewContact } from "@calcom/lib/Sendgrid"; import { symmetricDecrypt } from "@calcom/lib/crypto"; import logger from "@calcom/lib/logger"; import type { Calendar, CalendarEvent, EventBusyDate, IntegrationCalendar, NewCalendarEventType, } from "@calcom/types/Calendar"; import { CredentialPayload } from "@calcom/types/Credential"; const apiKeySchema = z.object({ encrypted: z.string(), }); const CALENDSO_ENCRYPTION_KEY = process.env.CALENDSO_ENCRYPTION_KEY || ""; /** * Authentication * Sendgrid requires Basic Auth for any request to their APIs, which is far from * ideal considering that such a strategy requires generating an API Key by the * user and input it in our system. A Setup page was created when trying to install * Sendgrid in order to instruct how to create such resource and to obtain it. */ export default class CloseComCalendarService implements Calendar { private integrationName = ""; private sendgrid: Sendgrid; private log: typeof logger; constructor(credential: CredentialPayload) { this.integrationName = "sendgrid_other_calendar"; this.log = logger.getChildLogger({ prefix: [`[[lib] ${this.integrationName}`] }); const parsedCredentialKey = apiKeySchema.safeParse(credential.key); let decrypted; if (parsedCredentialKey.success) { decrypted = symmetricDecrypt(parsedCredentialKey.data.encrypted, CALENDSO_ENCRYPTION_KEY); const { api_key } = JSON.parse(decrypted); this.sendgrid = new Sendgrid(api_key); } else { throw Error( `No API Key found for userId ${credential.userId} and appId ${credential.appId}: ${parsedCredentialKey.error}` ); } } async createEvent(event: CalendarEvent): Promise { // Proceeding to just creating the user in Sendgrid, no event entity exists in Sendgrid const contactsData = event.attendees.map((attendee) => ({ first_name: attendee.name, email: attendee.email, })); const result = await this.sendgrid.sendgridRequest({ url: `/v3/marketing/contacts`, method: "PUT", body: { contacts: contactsData, }, }); return Promise.resolve({ id: "", uid: result.job_id, password: "", url: "", type: this.integrationName, additionalInfo: { result, }, }); } async updateEvent(uid: string, event: CalendarEvent): Promise { // Unless we want to be able to support modifying an event to add more attendees // to have them created in Sendgrid, ignoring this use case for now return Promise.resolve(); } async deleteEvent(uid: string): Promise { // Unless we want to delete the contact in Sendgrid once the event // is deleted just ignoring this use case for now return Promise.resolve(); } async getAvailability( dateFrom: string, dateTo: string, selectedCalendars: IntegrationCalendar[] ): Promise { return Promise.resolve([]); } async listCalendars(event?: CalendarEvent): Promise { return Promise.resolve([]); } }