/* eslint-disable camelcase,@typescript-eslint/explicit-module-boundary-types,@typescript-eslint/no-explicit-any */ import querystring from "querystring"; import Wreck from "@hapi/wreck"; export interface User { id: number; firstname?: string; lastname?: string; email?: string; phone?: string; } export interface Ticket { id: number; title?: string; group_id?: number; customer_id?: number; } export interface ZammadClient { ticket: { create: (data: any) => Promise; update: (id: number, data: any) => Promise; }; user: { search: (data: any) => Promise; create: (data: any) => Promise; }; get: (path: string) => Promise; } export type ZammadCredentials = | { username: string; password: string } | { token: string }; export interface ZammadClientOpts { headers?: Record; } const formatAuth = (credentials: any) => { if (credentials.username) { return ( "Basic " + Buffer.from(`${credentials.username}:${credentials.password}`).toString( "base64" ) ); } if (credentials.token) { return `Token ${credentials.token}`; } throw new Error("invalid zammad credentials type"); }; export const Zammad = ( credentials: ZammadCredentials, host: string, opts?: ZammadClientOpts ): ZammadClient => { const extraHeaders = (opts && opts.headers) || {}; const wreck = Wreck.defaults({ baseUrl: `${host}/api/v1/`, headers: { authorization: formatAuth(credentials), ...extraHeaders, }, json: true, }); return { ticket: { create: async (payload) => { const { payload: result } = await wreck.post("tickets", { payload }); return result as Ticket; }, update: async (id, payload) => { const { payload: result } = await wreck.put(`tickets/${id}`, { payload }); return result as Ticket; }, }, user: { search: async (query) => { const qp = querystring.stringify({ query }); const { payload: result } = await wreck.get(`users/search?${qp}`); return result as User[]; }, create: async (payload) => { const { payload: result } = await wreck.post("users", { payload }); return result as User; }, }, get: async (path) => { const { payload: result } = await wreck.get(path); return result; }, }; }; export const getUser = async (zammad: ZammadClient, phoneNumber: string) => { const mungedNumber = phoneNumber.replace("+", ""); const results = await zammad.user.search(`phone:${mungedNumber}`); if (results.length > 0) return results[0]; return undefined; }; export const getOrCreateUser = async (zammad: ZammadClient, phoneNumber: string) => { const customer = await getUser(zammad, phoneNumber); if (customer) return customer; return zammad.user.create({ phone: phoneNumber, note: "User created by Grabadora from incoming voice call", }); };