/** * EvolutionAPI Client * Integração com EvolutionAPI v2 para gerenciamento de instâncias WhatsApp * Documentação: https://doc.evolution-api.com/v2/ */ import type { ConnectionStateAPIResponse, InstanceStatus, LogoutResponse, QRCodeResponse, } from "@/types/whatsapp"; // Re-export InstanceStatus for convenience export type { InstanceStatus } from "@/types/whatsapp"; const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL ?? ""; const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY ?? ""; /** * Get list of instance names from env * Parse EVOLUTION_INSTANCE_NAMES (comma-separated) into array */ export function getInstanceNames(): string[] { const names = process.env.EVOLUTION_INSTANCE_NAMES || ""; return names .split(",") .map((n) => n.trim()) .filter(Boolean); } /** * Get status of a specific instance * Endpoint: GET /instance/connectionState/{instance} * Doc: https://doc.evolution-api.com/v2/api-reference/instance-controller/connection-state */ export async function getInstanceStatus( instanceName: string, ): Promise { try { console.log(`[EvolutionAPI] Fetching status for instance: ${instanceName}`); const response = await fetch( `${EVOLUTION_API_URL}/instance/connectionState/${encodeURIComponent(instanceName)}`, { method: "GET", headers: { apikey: EVOLUTION_API_KEY, "Content-Type": "application/json", }, }, ); if (!response.ok) { if (response.status === 404) { throw new Error(`Instance "${instanceName}" does not exist`); } throw new Error(`API returned ${response.status}`); } const data: ConnectionStateAPIResponse = await response.json(); console.log(`[EvolutionAPI] Status response:`, data); // Mapear estado da API para nosso formato // Estados possíveis: "open", "close", etc const status = data.instance.state === "open" ? "connected" : "disconnected"; return { instance: instanceName, status, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; console.error( `[EvolutionAPI] Error fetching status for ${instanceName}:`, error, ); return { instance: instanceName, status: "error", error: errorMessage, }; } } /** * Get status for all instances */ export async function getAllInstancesStatus(): Promise { const instances = getInstanceNames(); const promises = instances.map((name) => getInstanceStatus(name)); return Promise.all(promises); } /** * Generate pairing code for instance connection * Endpoint: GET /instance/connect/{instance} * Doc: https://doc.evolution-api.com/v2/api-reference/instance-controller/instance-connect * * @param instanceName Nome da instância * @param phoneNumber Número de telefone com código do país (opcional) * @returns QRCodeResponse com pairingCode, code e count */ export async function generateQRCode( instanceName: string, phoneNumber?: string, ): Promise { try { console.log( `[EvolutionAPI] Generating QR code for instance: ${instanceName}`, ); const url = new URL( `${EVOLUTION_API_URL}/instance/connect/${encodeURIComponent(instanceName)}`, ); if (phoneNumber) { url.searchParams.append("number", phoneNumber); } const response = await fetch(url.toString(), { method: "GET", headers: { apikey: EVOLUTION_API_KEY, "Content-Type": "application/json", }, }); if (!response.ok) { if (response.status === 404) { throw new Error(`Instance "${instanceName}" does not exist`); } throw new Error(`API returned ${response.status}`); } const data = await response.json(); console.log(`[EvolutionAPI] QR code response:`, data); return { pairingCode: data.pairingCode, code: data.code, count: data.count, base64: data.base64, qrcode: data.qrcode, instance: instanceName, }; } catch (error) { console.error( `[EvolutionAPI] Error generating QR code for ${instanceName}:`, error, ); throw error; } } /** * Disconnect instance (logout) * Endpoint: DELETE /instance/logout/{instance} * Doc: https://doc.evolution-api.com/v2/api-reference/instance-controller/logout-instance */ export async function disconnectInstance(instanceName: string): Promise { try { console.log(`[EvolutionAPI] Disconnecting instance: ${instanceName}`); const response = await fetch( `${EVOLUTION_API_URL}/instance/logout/${encodeURIComponent(instanceName)}`, { method: "DELETE", headers: { apikey: EVOLUTION_API_KEY, "Content-Type": "application/json", }, }, ); if (!response.ok) { if (response.status === 404) { throw new Error(`Instance "${instanceName}" does not exist`); } throw new Error(`API returned ${response.status}`); } const data: LogoutResponse = await response.json(); console.log( `[EvolutionAPI] Instance ${instanceName} disconnected:`, data.response.message, ); } catch (error) { console.error(`[EvolutionAPI] Error disconnecting ${instanceName}:`, error); throw error; } }