Rocky_Mountain_Vending/convex/ghlMirror.ts

229 lines
5.6 KiB
TypeScript

// @ts-nocheck
type GhlMirrorConfig = {
token: string
locationId: string
baseUrl: string
version: string
}
function normalizeBaseUrl(value?: string) {
return String(value || "https://services.leadconnectorhq.com").replace(
/\/+$/,
""
)
}
export function readGhlMirrorConfig() {
const token = String(
process.env.GHL_PRIVATE_INTEGRATION_TOKEN || process.env.GHL_API_TOKEN || ""
).trim()
const locationId = String(process.env.GHL_LOCATION_ID || "").trim()
const baseUrl = normalizeBaseUrl(process.env.GHL_API_BASE_URL)
const version = String(process.env.GHL_API_VERSION || "2021-07-28").trim()
if (!token || !locationId) {
return null
}
return {
token,
locationId,
baseUrl,
version,
} satisfies GhlMirrorConfig
}
export async function fetchGhlMirrorJson(
config: GhlMirrorConfig,
pathname: string,
init?: RequestInit
) {
const response = await fetch(`${config.baseUrl}${pathname}`, {
...init,
headers: {
Authorization: `Bearer ${config.token}`,
Version: config.version,
Accept: "application/json",
"Content-Type": "application/json",
...(init?.headers || {}),
},
cache: "no-store",
})
const text = await response.text()
let body: any = null
if (text) {
try {
body = JSON.parse(text)
} catch {
body = null
}
}
if (!response.ok) {
throw new Error(
`GHL request failed (${response.status}) for ${pathname}: ${body?.message || text || "Unknown error"}`
)
}
return body
}
export async function fetchGhlContactsPage(
config: GhlMirrorConfig,
args?: {
limit?: number
cursor?: string
}
) {
const searchParams = new URLSearchParams({
locationId: config.locationId,
limit: String(Math.min(100, Math.max(1, args?.limit || 100))),
})
if (args?.cursor) {
searchParams.set("startAfterId", args.cursor)
}
const payload = await fetchGhlMirrorJson(
config,
`/contacts/?${searchParams.toString()}`
)
const contacts = Array.isArray(payload?.contacts)
? payload.contacts
: Array.isArray(payload?.data?.contacts)
? payload.data.contacts
: []
const nextCursor =
contacts.length > 0 ? String(contacts[contacts.length - 1]?.id || "") : ""
return {
items: contacts,
nextCursor: nextCursor || undefined,
}
}
export async function fetchGhlMessagesPage(
config: GhlMirrorConfig,
args?: {
limit?: number
cursor?: string
channel?: "Call" | "SMS"
}
) {
const url = new URL(`${config.baseUrl}/conversations/messages/export`)
url.searchParams.set("locationId", config.locationId)
url.searchParams.set("limit", String(Math.min(100, Math.max(1, args?.limit || 100))))
url.searchParams.set("channel", args?.channel || "SMS")
if (args?.cursor) {
url.searchParams.set("cursor", args.cursor)
}
const payload = await fetchGhlMirrorJson(config, url.pathname + url.search)
return {
items: Array.isArray(payload?.messages) ? payload.messages : [],
nextCursor:
typeof payload?.nextCursor === "string" && payload.nextCursor
? payload.nextCursor
: undefined,
}
}
export async function fetchGhlConversationsPage(
config: GhlMirrorConfig,
args?: {
limit?: number
}
) {
const url = new URL(`${config.baseUrl}/conversations/search`)
url.searchParams.set("locationId", config.locationId)
url.searchParams.set("limit", String(Math.min(100, Math.max(1, args?.limit || 100))))
const payload = await fetchGhlMirrorJson(config, url.pathname + url.search)
return {
items: Array.isArray(payload?.conversations) ? payload.conversations : [],
total:
typeof payload?.total === "number"
? payload.total
: Array.isArray(payload?.conversations)
? payload.conversations.length
: 0,
}
}
export async function fetchGhlConversationMessages(
config: GhlMirrorConfig,
args: {
conversationId: string
}
) {
const payload = await fetchGhlMirrorJson(
config,
`/conversations/${encodeURIComponent(args.conversationId)}/messages`
)
return {
items: Array.isArray(payload?.messages?.messages)
? payload.messages.messages
: Array.isArray(payload?.messages)
? payload.messages
: Array.isArray(payload?.data?.messages?.messages)
? payload.data.messages.messages
: Array.isArray(payload?.data?.messages)
? payload.data.messages
: Array.isArray(payload)
? payload
: [],
}
}
export async function sendGhlConversationMessage(
config: GhlMirrorConfig,
args: {
conversationId?: string
contactId?: string
message: string
type?: string
}
) {
return await fetchGhlMirrorJson(config, "/conversations/messages", {
method: "POST",
body: JSON.stringify({
type: args.type || "SMS",
message: args.message,
conversationId: args.conversationId,
contactId: args.contactId,
}),
})
}
export async function fetchGhlCallLogsPage(
config: GhlMirrorConfig,
args?: {
page?: number
pageSize?: number
}
) {
const url = new URL(`${config.baseUrl}/voice-ai/dashboard/call-logs`)
url.searchParams.set("locationId", config.locationId)
url.searchParams.set("page", String(Math.max(1, args?.page || 1)))
url.searchParams.set(
"pageSize",
String(Math.min(50, Math.max(1, args?.pageSize || 50)))
)
const payload = await fetchGhlMirrorJson(config, url.pathname + url.search)
return {
items: Array.isArray(payload?.callLogs) ? payload.callLogs : [],
page: Number(payload?.page || args?.page || 1),
total: Number(payload?.total || 0),
pageSize: Number(payload?.pageSize || args?.pageSize || 50),
}
}