diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index 69116ba..6f141f6 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -147,6 +147,42 @@ export type Database = { } Relationships: [] } + rodrigo_audio_messages: { + Row: { + audio_url: string | null + created_at: string + duration: number | null + id: string + instance_id: string + message_id: string | null + metadata: Json | null + sender_id: string + sender_name: string | null + } + Insert: { + audio_url?: string | null + created_at?: string + duration?: number | null + id?: string + instance_id: string + message_id?: string | null + metadata?: Json | null + sender_id: string + sender_name?: string | null + } + Update: { + audio_url?: string | null + created_at?: string + duration?: number | null + id?: string + instance_id?: string + message_id?: string | null + metadata?: Json | null + sender_id?: string + sender_name?: string | null + } + Relationships: [] + } transacoes: { Row: { categoria: string | null @@ -154,6 +190,7 @@ export type Database = { detalhes: string | null estabelecimento: string | null id: number + login: string | null quando: string | null tipo: string | null user: string | null @@ -165,6 +202,7 @@ export type Database = { detalhes?: string | null estabelecimento?: string | null id?: number + login?: string | null quando?: string | null tipo?: string | null user?: string | null @@ -176,6 +214,7 @@ export type Database = { detalhes?: string | null estabelecimento?: string | null id?: number + login?: string | null quando?: string | null tipo?: string | null user?: string | null diff --git a/src/services/whatsApp/apiHelpers.ts b/src/services/whatsApp/apiHelpers.ts new file mode 100644 index 0000000..0276f1b --- /dev/null +++ b/src/services/whatsApp/apiHelpers.ts @@ -0,0 +1,35 @@ + +import { SERVER_URL, API_KEY } from './config'; + +/** + * Makes an API request to the WhatsApp server + */ +export const makeRequest = async ( + endpoint: string, + method: 'GET' | 'POST' | 'PUT' | 'DELETE', + body?: object +): Promise => { + const url = `https://${SERVER_URL}${endpoint}`; + + console.log(`Making ${method} request to: ${url}`); + + const options: RequestInit = { + method, + headers: { + 'Content-Type': 'application/json', + 'apikey': API_KEY + }, + body: body ? JSON.stringify(body) : undefined + }; + + const response = await fetch(url, options); + + if (!response.ok) { + const errorData = await response.json(); + console.error(`API error (${response.status}):`, errorData); + throw new Error(errorData.message || `API request failed with status ${response.status}`); + } + + const data = await response.json(); + return data as T; +}; diff --git a/src/services/whatsApp/config.ts b/src/services/whatsApp/config.ts new file mode 100644 index 0000000..09c14f5 --- /dev/null +++ b/src/services/whatsApp/config.ts @@ -0,0 +1,7 @@ + +// WhatsApp API configuration +export const SERVER_URL = "evolutionapi2.innova1001.com.br"; +export const API_KEY = "beeb77fbd7f48f91db2cd539a573c130"; + +// Local storage key +export const STORAGE_KEY = 'whatsappInstances'; diff --git a/src/services/whatsApp/index.ts b/src/services/whatsApp/index.ts new file mode 100644 index 0000000..400e3a5 --- /dev/null +++ b/src/services/whatsApp/index.ts @@ -0,0 +1,5 @@ + +// Re-export all functions from the service modules +export * from './instanceManagement'; +export * from './instanceActions'; +export * from './localStorage'; diff --git a/src/services/whatsApp/instanceActions.ts b/src/services/whatsApp/instanceActions.ts new file mode 100644 index 0000000..9d398e2 --- /dev/null +++ b/src/services/whatsApp/instanceActions.ts @@ -0,0 +1,70 @@ + +import { makeRequest } from './apiHelpers'; + +/** + * Restarts a WhatsApp instance + */ +export const restartInstance = async (instanceName: string): Promise => { + try { + console.log(`Restarting instance: ${instanceName}`); + + const data = await makeRequest(`/instance/restart/${encodeURIComponent(instanceName)}`, 'PUT'); + + console.log(`Restart response for ${instanceName}:`, data); + return data; + } catch (error) { + console.error(`Error restarting instance ${instanceName}:`, error); + throw error; + } +}; + +/** + * Logs out (disconnects) a WhatsApp instance + */ +export const logoutInstance = async (instanceName: string): Promise => { + try { + console.log(`Logging out instance: ${instanceName}`); + + const data = await makeRequest(`/instance/logout/${encodeURIComponent(instanceName)}`, 'DELETE'); + + console.log(`Logout response for ${instanceName}:`, data); + return data; + } catch (error) { + console.error(`Error logging out instance ${instanceName}:`, error); + throw error; + } +}; + +/** + * Deletes a WhatsApp instance + */ +export const deleteInstance = async (instanceName: string): Promise => { + try { + console.log(`Deleting instance: ${instanceName}`); + + const data = await makeRequest(`/instance/${encodeURIComponent(instanceName)}`, 'DELETE'); + + console.log(`Delete response for ${instanceName}:`, data); + return data; + } catch (error) { + console.error(`Error deleting instance ${instanceName}:`, error); + throw error; + } +}; + +/** + * Sets the online/offline presence status for an instance + */ +export const setInstancePresence = async (instanceName: string, presence: 'online' | 'offline'): Promise => { + try { + console.log(`Setting presence to ${presence} for: ${instanceName}`); + + const data = await makeRequest(`/instance/setPresence/${encodeURIComponent(instanceName)}`, 'POST', { presence }); + + console.log(`Set presence response for ${instanceName}:`, data); + return data; + } catch (error) { + console.error(`Error setting presence to ${presence} for instance ${instanceName}:`, error); + throw error; + } +}; diff --git a/src/services/whatsApp/instanceManagement.ts b/src/services/whatsApp/instanceManagement.ts new file mode 100644 index 0000000..86f0873 --- /dev/null +++ b/src/services/whatsApp/instanceManagement.ts @@ -0,0 +1,73 @@ + +import { makeRequest } from './apiHelpers'; + +/** + * Creates a new WhatsApp instance + */ +export const createWhatsAppInstance = async ( + instanceName: string, + phoneNumber: string +): Promise => { + console.log(`Creating new WhatsApp instance: ${instanceName}, ${phoneNumber}`); + + const data = await makeRequest('/instance/create', 'POST', { + instanceName: instanceName, + number: phoneNumber, + qrcode: true, + integration: "WHATSAPP-BAILEYS" + }); + + console.log('Create instance API response:', data); + return data; +}; + +/** + * Fetches QR code for an instance + */ +export const fetchQrCode = async (instanceName: string): Promise => { + console.log(`Fetching QR code for instance: ${instanceName}`); + + const data = await makeRequest(`/instance/connect/${encodeURIComponent(instanceName)}`, 'GET'); + + console.log('QR code fetch response:', data); + return data; +}; + +/** + * Fetches connection state for an instance + */ +export const fetchConnectionState = async (instanceName: string): Promise<'open' | 'closed' | 'connecting'> => { + try { + console.log(`Fetching connection state for: ${instanceName}`); + + const data = await makeRequest(`/instance/connectionState/${encodeURIComponent(instanceName)}`, 'GET'); + + console.log(`Connection state for ${instanceName}:`, data); + return data.instance?.state || 'closed'; + } catch (error) { + console.error(`Error fetching connection state for ${instanceName}:`, error); + + if (error instanceof Error && error.message.includes("does not exist")) { + throw error; // Rethrow specific "does not exist" errors + } + + return 'closed'; + } +}; + +/** + * Fetches all WhatsApp instances + */ +export const fetchAllInstances = async (): Promise => { + try { + console.log('Fetching all instances'); + + const data = await makeRequest('/fetch-instances', 'GET'); + + console.log('All instances response:', data); + return data; + } catch (error) { + console.error("Error fetching all instances:", error); + throw error; + } +}; diff --git a/src/services/whatsApp/localStorage.ts b/src/services/whatsApp/localStorage.ts new file mode 100644 index 0000000..eec613c --- /dev/null +++ b/src/services/whatsApp/localStorage.ts @@ -0,0 +1,80 @@ + +import { WhatsAppInstance } from '@/types/whatsAppTypes'; +import { STORAGE_KEY } from './config'; + +/** + * Saves WhatsApp instances to localStorage + */ +export const saveInstancesToLocalStorage = ( + instances: WhatsAppInstance[], + currentUserId: string +): void => { + try { + console.log(`Saving ${instances.length} instances for user ${currentUserId}`); + // Get existing instances from localStorage + const savedInstancesStr = localStorage.getItem(STORAGE_KEY); + let allInstances: WhatsAppInstance[] = []; + + if (savedInstancesStr) { + try { + // Parse saved instances + const savedInstances = JSON.parse(savedInstancesStr); + + // If it's an array, filter out current user's old instances + if (Array.isArray(savedInstances)) { + allInstances = savedInstances.filter( + (instance: WhatsAppInstance) => instance.userId !== currentUserId + ); + } + } catch (parseError) { + console.error('Error parsing stored instances, resetting:', parseError); + } + } + + // Add current user's instances to the array + const updatedInstances = [...allInstances, ...instances]; + + // Save back to localStorage + localStorage.setItem(STORAGE_KEY, JSON.stringify(updatedInstances)); + console.log('All WhatsApp instances saved to localStorage:', updatedInstances); + } catch (error) { + console.error('Error saving instances to localStorage:', error); + } +}; + +/** + * Loads WhatsApp instances from localStorage for a specific user + */ +export const loadInstancesFromLocalStorage = ( + userId: string +): WhatsAppInstance[] => { + try { + console.log(`Loading instances for user: ${userId}`); + const savedInstancesStr = localStorage.getItem(STORAGE_KEY); + console.log('Raw saved instances from localStorage:', savedInstancesStr); + + if (savedInstancesStr && userId) { + try { + // Parse saved instances + const allInstances = JSON.parse(savedInstancesStr); + + // If it's an array, filter by user ID + if (Array.isArray(allInstances)) { + // Filter instances to only show those belonging to the current user + const userInstances = allInstances.filter( + (instance: WhatsAppInstance) => instance.userId === userId + ); + console.log(`Found ${userInstances.length} instances for user ${userId}:`, userInstances); + return userInstances; + } + } catch (parseError) { + console.error('Error parsing stored instances:', parseError); + } + } + console.log(`No instances found for user ${userId}`); + return []; + } catch (error) { + console.error("Error loading instances from localStorage:", error); + return []; + } +}; diff --git a/src/services/whatsAppService.ts b/src/services/whatsAppService.ts index 55c5556..0eba534 100644 --- a/src/services/whatsAppService.ts +++ b/src/services/whatsAppService.ts @@ -1,301 +1,10 @@ -import { WhatsAppInstance } from '@/types/whatsAppTypes'; +// This file is kept for backwards compatibility +// It re-exports all WhatsApp service functions from their new modular structure -const SERVER_URL = "evolutionapi2.innova1001.com.br"; -const API_KEY = "beeb77fbd7f48f91db2cd539a573c130"; +export * from './whatsApp/instanceManagement'; +export * from './whatsApp/instanceActions'; +export * from './whatsApp/localStorage'; -// Local storage key -const STORAGE_KEY = 'whatsappInstances'; - -export const createWhatsAppInstance = async ( - instanceName: string, - phoneNumber: string -): Promise => { - console.log(`Creating new WhatsApp instance: ${instanceName}, ${phoneNumber}`); - const response = await fetch(`https://${SERVER_URL}/instance/create`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - }, - body: JSON.stringify({ - instanceName: instanceName, - number: phoneNumber, - qrcode: true, - integration: "WHATSAPP-BAILEYS" - }) - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error('Error creating instance:', errorData); - throw new Error(errorData.message || 'Erro ao criar instância'); - } - - const data = await response.json(); - console.log('Create instance API response:', data); - return data; -}; - -export const fetchQrCode = async (instanceName: string): Promise => { - console.log(`Fetching QR code for instance: ${instanceName}`); - const response = await fetch(`https://${SERVER_URL}/instance/connect/${encodeURIComponent(instanceName)}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - } - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error('Error fetching QR code:', errorData); - throw new Error(errorData.message || 'Erro ao obter QR Code'); - } - - const data = await response.json(); - console.log('QR code fetch response:', data); - return data; -}; - -export const fetchConnectionState = async (instanceName: string): Promise<'open' | 'closed' | 'connecting'> => { - try { - console.log(`Fetching connection state for: ${instanceName}`); - const response = await fetch(`https://${SERVER_URL}/instance/connectionState/${encodeURIComponent(instanceName)}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - } - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error(`Connection state error for ${instanceName}:`, errorData); - - // If instance doesn't exist, throw a specific error - if (response.status === 404) { - throw new Error(`The "${instanceName}" instance does not exist`); - } - - return 'closed'; - } - - const data = await response.json(); - console.log(`Connection state for ${instanceName}:`, data); - return data.instance?.state || 'closed'; - } catch (error) { - console.error(`Error fetching connection state for ${instanceName}:`, error); - if (error instanceof Error && error.message.includes("does not exist")) { - throw error; // Rethrow specific "does not exist" errors - } - return 'closed'; - } -}; - -// Nova função para listar todas as instâncias -export const fetchAllInstances = async (): Promise => { - try { - console.log('Fetching all instances'); - const response = await fetch(`https://${SERVER_URL}/fetch-instances`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - } - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error('Error fetching instances:', errorData); - throw new Error(errorData.message || 'Erro ao buscar instâncias'); - } - - const data = await response.json(); - console.log('All instances response:', data); - return data; - } catch (error) { - console.error("Error fetching all instances:", error); - throw error; - } -}; - -// Função para reiniciar uma instância -export const restartInstance = async (instanceName: string): Promise => { - try { - console.log(`Restarting instance: ${instanceName}`); - const response = await fetch(`https://${SERVER_URL}/instance/restart/${encodeURIComponent(instanceName)}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - } - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error(`Error restarting instance ${instanceName}:`, errorData); - throw new Error(errorData.message || 'Erro ao reiniciar instância'); - } - - const data = await response.json(); - console.log(`Restart response for ${instanceName}:`, data); - return data; - } catch (error) { - console.error(`Error restarting instance ${instanceName}:`, error); - throw error; - } -}; - -// Função para desconectar (logout) uma instância -export const logoutInstance = async (instanceName: string): Promise => { - try { - console.log(`Logging out instance: ${instanceName}`); - const response = await fetch(`https://${SERVER_URL}/instance/logout/${encodeURIComponent(instanceName)}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - } - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error(`Error logging out instance ${instanceName}:`, errorData); - throw new Error(errorData.message || 'Erro ao desconectar instância'); - } - - const data = await response.json(); - console.log(`Logout response for ${instanceName}:`, data); - return data; - } catch (error) { - console.error(`Error logging out instance ${instanceName}:`, error); - throw error; - } -}; - -// Função para excluir uma instância -export const deleteInstance = async (instanceName: string): Promise => { - try { - console.log(`Deleting instance: ${instanceName}`); - const response = await fetch(`https://${SERVER_URL}/instance/${encodeURIComponent(instanceName)}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - } - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error(`Error deleting instance ${instanceName}:`, errorData); - throw new Error(errorData.message || 'Erro ao excluir instância'); - } - - const data = await response.json(); - console.log(`Delete response for ${instanceName}:`, data); - return data; - } catch (error) { - console.error(`Error deleting instance ${instanceName}:`, error); - throw error; - } -}; - -// Função para definir presença online/offline -export const setInstancePresence = async (instanceName: string, presence: 'online' | 'offline'): Promise => { - try { - console.log(`Setting presence to ${presence} for: ${instanceName}`); - const response = await fetch(`https://${SERVER_URL}/instance/setPresence/${encodeURIComponent(instanceName)}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'apikey': API_KEY - }, - body: JSON.stringify({ presence }) - }); - - if (!response.ok) { - const errorData = await response.json(); - console.error(`Error setting presence for ${instanceName}:`, errorData); - throw new Error(errorData.message || `Erro ao definir presença para ${presence}`); - } - - const data = await response.json(); - console.log(`Set presence response for ${instanceName}:`, data); - return data; - } catch (error) { - console.error(`Error setting presence to ${presence} for instance ${instanceName}:`, error); - throw error; - } -}; - -export const saveInstancesToLocalStorage = ( - instances: WhatsAppInstance[], - currentUserId: string -): void => { - try { - console.log(`Saving ${instances.length} instances for user ${currentUserId}`); - // Get existing instances from localStorage - const savedInstancesStr = localStorage.getItem(STORAGE_KEY); - let allInstances: WhatsAppInstance[] = []; - - if (savedInstancesStr) { - try { - // Parse saved instances - const savedInstances = JSON.parse(savedInstancesStr); - - // If it's an array, filter out current user's old instances - if (Array.isArray(savedInstances)) { - allInstances = savedInstances.filter( - (instance: WhatsAppInstance) => instance.userId !== currentUserId - ); - } - } catch (parseError) { - console.error('Error parsing stored instances, resetting:', parseError); - } - } - - // Add current user's instances to the array - const updatedInstances = [...allInstances, ...instances]; - - // Save back to localStorage - localStorage.setItem(STORAGE_KEY, JSON.stringify(updatedInstances)); - console.log('All WhatsApp instances saved to localStorage:', updatedInstances); - } catch (error) { - console.error('Error saving instances to localStorage:', error); - } -}; - -export const loadInstancesFromLocalStorage = ( - userId: string -): WhatsAppInstance[] => { - try { - console.log(`Loading instances for user: ${userId}`); - const savedInstancesStr = localStorage.getItem(STORAGE_KEY); - console.log('Raw saved instances from localStorage:', savedInstancesStr); - - if (savedInstancesStr && userId) { - try { - // Parse saved instances - const allInstances = JSON.parse(savedInstancesStr); - - // If it's an array, filter by user ID - if (Array.isArray(allInstances)) { - // Filter instances to only show those belonging to the current user - const userInstances = allInstances.filter( - (instance: WhatsAppInstance) => instance.userId === userId - ); - console.log(`Found ${userInstances.length} instances for user ${userId}:`, userInstances); - return userInstances; - } - } catch (parseError) { - console.error('Error parsing stored instances:', parseError); - } - } - console.log(`No instances found for user ${userId}`); - return []; - } catch (error) { - console.error("Error loading instances from localStorage:", error); - return []; - } -}; +// Export config values if needed by other parts of the app +export { SERVER_URL, API_KEY, STORAGE_KEY } from './whatsApp/config';