@lautmaler/crm-connectors
Version:
Provides connectors to various CRM systems and calendar services.
135 lines (120 loc) • 4.23 kB
text/typescript
import axios from "axios";
import winston from "winston";
import { Appointment, CRMBackend } from "../crm.interfaces.js";
const CALENDLY_API_KEY = process.env.CALENDLY_API_KEY || "";
const CALENDLY_USER_URI = process.env.CALENDLY_USER_URI || ""; // Fetch this dynamically if needed
export class CalendlyBackend implements CRMBackend {
private logger: any;
private apiClient: any;
constructor() {
this.logger = winston.createLogger({
level: "info",
format: winston.format.json(),
defaultMeta: { service: "crm-service" },
transports: [
new winston.transports.Console({
format: winston.format.simple(),
}),
],
});
if (!CALENDLY_API_KEY) {
this.logger.warn("Calendly API key is missing");
}
this.apiClient = axios.create({
baseURL: "https://api.calendly.com",
headers: {
Authorization: `Bearer ${CALENDLY_API_KEY}`,
"Content-Type": "application/json",
},
});
}
fetchAppointmentTypes(): Promise<string[]> {
throw new Error("Method not implemented.");
}
bookAppointment(appointment: Appointment): Promise<string> {
try {
return this.createEvent(appointment);
} catch (error) {
this.logger.error("Error booking appointment:", error);
throw new Error("Failed to book appointment");
}
}
modifyAppointment(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
id: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
updatedInfo: Partial<Appointment>,
): Promise<Appointment> {
throw new Error("Method not implemented.");
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
findAppointmentByContactName(name: string): Promise<Appointment> {
throw new Error("Method not implemented.");
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
findAppointmentByTimestamp(timestamp: string): Promise<Appointment | null> {
throw new Error("Method not implemented.");
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
findAppointmentById(id: string): Promise<Appointment | null> {
throw new Error("Method not implemented.");
}
async fetchAvailableSlots(): Promise<string[]> {
try {
const availableSlots = await this.calendalyGetAvailability(
CALENDLY_USER_URI,
new Date().toISOString(),
new Date(Date.now() + 86400000).toISOString(),
);
return availableSlots;
} catch (error) {
this.logger.error("Error fetching available slots:", error);
throw new Error("Failed to fetch available slots");
}
}
async calendalyGetAvailability(
userUri: string,
startTime: string,
endTime: string,
): Promise<string[]> {
try {
const response = await this.apiClient.get("/scheduling_links", {
params: {
user: userUri,
start_time: startTime,
end_time: endTime,
},
});
this.logger.info("Available slots fetched successfully");
return response.data as string[];
} catch (error) {
this.logger.error("Error fetching available slots:", error);
throw new Error("Failed to fetch available slots");
}
}
async createEvent(appointment: Appointment): Promise<string> {
const attendees = [
{ email: appointment.contactEmail },
{ email: appointment.employeeEmail },
];
const startTime = appointment.timestamp;
const duration = "60"; // 60 minutes
try {
const payload = {
event_type: `${CALENDLY_USER_URI}/event_types`,
start_time: startTime,
invitees: attendees.map((attendee) => ({ email: attendee.email })),
duration: duration,
};
const response = await this.apiClient.post("/scheduled_events", payload);
this.logger.info("Event scheduled successfully", response.data);
return response.data.resource.uri; // Returns the event link
} catch (error) {
this.logger.error("Error scheduling event:", error);
throw new Error("Failed to schedule event");
}
}
async createEventToSms(appointment: Appointment): Promise<string> {
throw new Error("Method not implemented.");
}
}