Fix n8n workflow activation and trigger.
Adjusted the n8n workflow activation request and moved the trigger to group creation. Implemented email standardization to lowercase and WhatsApp number field improvements. Edited `src/services/whatsAppInstance/workflowOperations.ts`, `src/components/whatsapp/CreateInstanceForm.tsx`, and `src/services/n8nWorkflowService.ts`.
This commit is contained in:
parent
aeb9fa261d
commit
27cad3b98b
@ -1,285 +1,225 @@
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import React, { useState } from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { MessageCircle, AlertCircle } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { createWhatsAppInstance } from '@/services/whatsAppService';
|
||||
import { updateUserWhatsAppInstance, getUserWhatsAppInstance, activateUserWorkflow } from '@/services/whatsAppInstanceService';
|
||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { Loader2, Plus, AlertCircle } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { createInstance } from '@/services/whatsAppService';
|
||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
||||
import { updateUserWhatsAppInstance } from '@/services/whatsAppInstanceService';
|
||||
import { createEvolutionWebhook } from '@/services/whatsApp/webhookService';
|
||||
|
||||
interface CreateInstanceFormProps {
|
||||
onInstanceCreated: (instance: WhatsAppInstance) => void;
|
||||
initialInstanceName?: string;
|
||||
}
|
||||
|
||||
const CreateInstanceForm = ({
|
||||
onInstanceCreated,
|
||||
initialInstanceName = ''
|
||||
}: CreateInstanceFormProps) => {
|
||||
const CreateInstanceForm = ({ onInstanceCreated, initialInstanceName = '' }: CreateInstanceFormProps) => {
|
||||
const { toast } = useToast();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [userEmail, setUserEmail] = useState(initialInstanceName);
|
||||
const [ddd, setDdd] = useState('');
|
||||
const [phoneNumber, setPhoneNumber] = useState('');
|
||||
const [hasExistingInstance, setHasExistingInstance] = useState(false);
|
||||
const [checkingExistingInstance, setCheckingExistingInstance] = useState(true);
|
||||
const currentUserId = localStorage.getItem('userId') || '';
|
||||
const userEmail = localStorage.getItem('userEmail') || '';
|
||||
|
||||
// Nome da instância será sempre o email do usuário
|
||||
const instanceName = userEmail;
|
||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||
|
||||
// Verificar se o usuário já tem uma instância
|
||||
useEffect(() => {
|
||||
const checkExistingInstance = async () => {
|
||||
if (!userEmail) {
|
||||
setCheckingExistingInstance(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('Verificando se usuário já tem instância:', userEmail);
|
||||
const existingInstance = await getUserWhatsAppInstance(userEmail);
|
||||
|
||||
if (existingInstance && existingInstance.instancia_zap) {
|
||||
console.log('Usuário já possui instância:', existingInstance.instancia_zap);
|
||||
setHasExistingInstance(true);
|
||||
} else {
|
||||
console.log('Usuário não possui instância');
|
||||
setHasExistingInstance(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar instância existente:', error);
|
||||
setHasExistingInstance(false);
|
||||
} finally {
|
||||
setCheckingExistingInstance(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkExistingInstance();
|
||||
}, [userEmail]);
|
||||
|
||||
const handleCreateInstance = async () => {
|
||||
// Validate form fields
|
||||
if (!userEmail) {
|
||||
const handleCreateInstance = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!userEmail.trim()) {
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Email do usuário não encontrado. Faça login novamente.",
|
||||
description: "Por favor, informe seu email",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!phoneNumber.trim() || !/^[0-9]{10,15}$/.test(phoneNumber)) {
|
||||
if (!ddd.trim() || ddd.length !== 2) {
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Por favor, informe um DDD válido (2 dígitos)",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!phoneNumber.trim() || phoneNumber.length < 8) {
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Insira um número válido com DDD e país (ex: 559999999999)",
|
||||
description: "Por favor, informe um número de telefone válido",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure user is logged in
|
||||
if (!currentUserId) {
|
||||
toast({
|
||||
title: "Erro de autenticação",
|
||||
description: "Você precisa estar logado para criar uma instância",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Verificar novamente se já existe instância antes de criar
|
||||
if (hasExistingInstance) {
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Você já possui uma instância WhatsApp. Apenas uma instância por usuário é permitida.",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setIsCreating(true);
|
||||
|
||||
try {
|
||||
console.log(`🚀 Iniciando criação de instância com nome ${instanceName} e número ${phoneNumber}`);
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
// 1. Criar instância na API
|
||||
console.log('📡 Passo 1: Criando instância na API...');
|
||||
const data = await createWhatsAppInstance(instanceName, phoneNumber);
|
||||
console.log('✅ Resposta da API de criação de instância:', data);
|
||||
// Construir o número completo: +55 + DDD + número
|
||||
const fullPhoneNumber = `55${ddd}${phoneNumber}`;
|
||||
|
||||
console.log(`🚀 Criando instância para: ${normalizedEmail} com número: ${fullPhoneNumber}`);
|
||||
|
||||
// 2. Atualizar o banco de dados com status "conectado"
|
||||
console.log('💾 Passo 2: Atualizando banco de dados...');
|
||||
await updateUserWhatsAppInstance(userEmail, instanceName, 'conectado');
|
||||
console.log('✅ Instância registrada no banco de dados com status "conectado"');
|
||||
// Criar a instância no Evolution API
|
||||
const response = await createInstance(normalizedEmail, fullPhoneNumber);
|
||||
|
||||
if (response && response.instance) {
|
||||
const instanceData: WhatsAppInstance = {
|
||||
instanceId: `${normalizedEmail}-${Date.now()}`,
|
||||
instanceName: normalizedEmail,
|
||||
phoneNumber: fullPhoneNumber,
|
||||
connectionState: response.instance.state || 'closed',
|
||||
qrcode: response.qrcode || null,
|
||||
status: response.instance.state === 'open' ? 'connected' : 'disconnected',
|
||||
createdAt: new Date().toISOString(),
|
||||
lastSeen: new Date().toISOString(),
|
||||
presence: 'offline'
|
||||
};
|
||||
|
||||
console.log('✅ Instância criada:', instanceData);
|
||||
|
||||
// Atualizar no banco de dados local
|
||||
await updateUserWhatsAppInstance(normalizedEmail, normalizedEmail, 'conectado');
|
||||
|
||||
// Criar webhook na Evolution API
|
||||
await createEvolutionWebhook(normalizedEmail);
|
||||
|
||||
// 3. Ativar o workflow do usuário no n8n
|
||||
console.log('🔄 Passo 3: Ativando workflow do usuário no n8n...');
|
||||
try {
|
||||
await activateUserWorkflow(userEmail);
|
||||
console.log('✅ Workflow ativado com sucesso no n8n');
|
||||
} catch (workflowError) {
|
||||
console.error('⚠️ Erro ao ativar workflow, mas instância foi criada:', workflowError);
|
||||
// Não bloquear o fluxo se o workflow falhar, apenas loggar
|
||||
toast({
|
||||
title: "Aviso",
|
||||
description: "Instância criada, mas houve um problema ao ativar a automação. Entre em contato com o suporte.",
|
||||
variant: "destructive",
|
||||
title: "Sucesso!",
|
||||
description: "Instância criada com sucesso. Use o QR Code para conectar.",
|
||||
});
|
||||
|
||||
onInstanceCreated(instanceData);
|
||||
|
||||
} else {
|
||||
throw new Error('Resposta inválida da API');
|
||||
}
|
||||
|
||||
// 4. Criar objeto da instância
|
||||
const newInstance: WhatsAppInstance = {
|
||||
instanceName,
|
||||
instanceId: instanceName,
|
||||
phoneNumber,
|
||||
userId: currentUserId,
|
||||
status: data.instance?.status || 'created',
|
||||
qrcode: data.qrcode?.base64 || null,
|
||||
connectionState: 'closed'
|
||||
};
|
||||
|
||||
console.log('✅ Nova instância criada:', newInstance);
|
||||
|
||||
// 5. Atualizar estado para evitar nova criação
|
||||
setHasExistingInstance(true);
|
||||
|
||||
// 6. Notificar componente pai
|
||||
onInstanceCreated(newInstance);
|
||||
|
||||
toast({
|
||||
title: "Sucesso!",
|
||||
description: "Instância do WhatsApp criada e ativada com sucesso!"
|
||||
});
|
||||
|
||||
// Reset form fields
|
||||
setPhoneNumber('');
|
||||
|
||||
} catch (error) {
|
||||
console.error("💥 Erro ao criar instância WhatsApp:", error);
|
||||
console.error('❌ Erro ao criar instância:', error);
|
||||
|
||||
// Se houve erro na API, tentar reverter no banco de dados
|
||||
try {
|
||||
await updateUserWhatsAppInstance(userEmail, '', 'desconectado');
|
||||
console.log('🔄 Instância removida do banco devido ao erro na API');
|
||||
} catch (dbError) {
|
||||
console.error('❌ Erro ao reverter instância no banco:', dbError);
|
||||
let errorMessage = 'Erro desconhecido ao criar instância';
|
||||
if (error instanceof Error) {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
|
||||
|
||||
toast({
|
||||
title: "Erro na criação da instância",
|
||||
description: "Ocorreu um erro ao conectar com a API. Tente novamente mais tarde.",
|
||||
title: "Erro ao criar instância",
|
||||
description: errorMessage,
|
||||
variant: "destructive",
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setIsCreating(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (checkingExistingInstance) {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent className="flex items-center justify-center py-8">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-green-600 mx-auto mb-4"></div>
|
||||
<p>Verificando instâncias existentes...</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
if (hasExistingInstance) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center mb-2">
|
||||
<MessageCircle className="h-6 w-6 mr-2 text-green-600" />
|
||||
<CardTitle>WhatsApp já Conectado</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Você já possui uma instância WhatsApp vinculada ao seu email
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Alert>
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Apenas uma instância WhatsApp por usuário é permitida.
|
||||
Sua instância atual: <strong>{instanceName}</strong>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div className="mt-4 p-4 bg-green-50 border border-green-200 rounded">
|
||||
<p className="text-green-800 text-sm">
|
||||
<strong>✓ Instância ativa:</strong> {instanceName}
|
||||
</p>
|
||||
<p className="text-green-700 text-sm mt-1">
|
||||
Para gerenciar sua instância, utilize os botões na lista de instâncias acima.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center mb-2">
|
||||
<MessageCircle className="h-6 w-6 mr-2 text-green-600" />
|
||||
<CardTitle>Vincular WhatsApp ao App</CardTitle>
|
||||
</div>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Plus className="h-5 w-5" />
|
||||
Conectar WhatsApp
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Preencha os campos abaixo para conectar sua conta WhatsApp
|
||||
Conecte uma nova instância do WhatsApp para enviar mensagens automáticas
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="instanceName">Nome da Instância</Label>
|
||||
<Input
|
||||
id="instanceName"
|
||||
value={instanceName}
|
||||
disabled
|
||||
className="bg-gray-100"
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
O nome da instância será automaticamente seu email de login
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="phoneNumber">Número do WhatsApp</Label>
|
||||
<Input
|
||||
id="phoneNumber"
|
||||
value={phoneNumber}
|
||||
onChange={(e) => setPhoneNumber(e.target.value)}
|
||||
placeholder="559999999999"
|
||||
required
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">Digite o número com DDD e código do país</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="w-full mt-4"
|
||||
onClick={handleCreateInstance}
|
||||
disabled={loading || !userEmail || !phoneNumber.trim()}
|
||||
>
|
||||
{loading ? "Criando..." : "Criar Instância"}
|
||||
</Button>
|
||||
|
||||
<div className="mt-4 p-4 bg-blue-50 border border-blue-200 rounded">
|
||||
<h4 className="font-medium text-blue-800 mb-2">Importante:</h4>
|
||||
<ul className="text-sm text-blue-700 space-y-1">
|
||||
<li>• Apenas uma instância por usuário é permitida</li>
|
||||
<li>• O nome da instância será seu email de login</li>
|
||||
<li>• Após criar, você precisará escanear o QR Code para conectar</li>
|
||||
<li>• Sua automação financeira será ativada automaticamente</li>
|
||||
</ul>
|
||||
</div>
|
||||
<CardContent>
|
||||
<form onSubmit={handleCreateInstance} className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="userEmail">Email do usuário</Label>
|
||||
<Input
|
||||
id="userEmail"
|
||||
type="email"
|
||||
placeholder="seu.email@exemplo.com"
|
||||
value={userEmail}
|
||||
onChange={(e) => setUserEmail(e.target.value)}
|
||||
disabled={isCreating}
|
||||
required
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Este será o identificador único da sua instância
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Número do WhatsApp</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Código do país fixo */}
|
||||
<div className="flex items-center">
|
||||
<Input
|
||||
value="+55"
|
||||
disabled
|
||||
className="w-16 bg-gray-100 text-center font-medium"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Campo DDD */}
|
||||
<div className="flex-shrink-0">
|
||||
<Input
|
||||
placeholder="(XX)"
|
||||
value={ddd}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replace(/\D/g, '').slice(0, 2);
|
||||
setDdd(value);
|
||||
}}
|
||||
disabled={isCreating}
|
||||
className="w-16 text-center"
|
||||
maxLength={2}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Campo número */}
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
placeholder="9XXXX-XXXX"
|
||||
value={phoneNumber}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replace(/\D/g, '').slice(0, 9);
|
||||
setPhoneNumber(value);
|
||||
}}
|
||||
disabled={isCreating}
|
||||
maxLength={9}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Digite seu DDD e o número do seu celular
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button type="submit" disabled={isCreating} className="w-full">
|
||||
{isCreating ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Criando instância...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Conectar WhatsApp
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
{showAdvanced && (
|
||||
<Alert>
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Após criar a instância, você precisará escanear o QR Code com o WhatsApp
|
||||
do seu celular para estabelecer a conexão.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
@ -9,6 +8,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { findOrCreateWhatsAppGroup } from '@/services/whatsAppGroupsService';
|
||||
import { getUserWhatsAppInstance } from '@/services/whatsAppInstanceService';
|
||||
import { createWhatsAppGroup, updateGroupRemoteJid } from '@/services/whatsAppGroupCreationService';
|
||||
import { activateUserWorkflow } from '@/services/whatsAppInstanceService';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
|
||||
interface CreateGroupFormProps {
|
||||
@ -39,9 +39,11 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
|
||||
setCheckingInstance(true);
|
||||
try {
|
||||
console.log('Verificando instância para:', userEmail);
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
console.log('Verificando instância para:', normalizedEmail);
|
||||
|
||||
const instanceData = await getUserWhatsAppInstance(userEmail);
|
||||
const instanceData = await getUserWhatsAppInstance(normalizedEmail);
|
||||
console.log('Dados da instância:', instanceData);
|
||||
|
||||
if (instanceData) {
|
||||
@ -108,6 +110,9 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
|
||||
setCadastrando(true);
|
||||
try {
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
console.log("Iniciando processo de cadastro de grupo...");
|
||||
|
||||
// 1. Cadastrar grupo no banco de dados local
|
||||
@ -119,24 +124,32 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
|
||||
// 2. Criar grupo no WhatsApp via API com o nome escolhido pelo usuário
|
||||
try {
|
||||
const groupResponse = await createWhatsAppGroup(userEmail, nomeGrupo.trim());
|
||||
const groupResponse = await createWhatsAppGroup(normalizedEmail, nomeGrupo.trim());
|
||||
|
||||
console.log('Resposta da criação do grupo:', groupResponse);
|
||||
|
||||
// 3. Atualizar remote_jid no banco de dados
|
||||
if (groupResponse.id) {
|
||||
await updateGroupRemoteJid(grupo.id, groupResponse.id);
|
||||
}
|
||||
|
||||
// 4. 🚀 NOVO: Ativar workflow n8n após criar o grupo com sucesso
|
||||
try {
|
||||
console.log('🔔 Ativando workflow n8n para o usuário após criação do grupo...');
|
||||
await activateUserWorkflow(normalizedEmail);
|
||||
|
||||
toast({
|
||||
title: 'Sucesso!',
|
||||
description: `Grupo "${nomeGrupo}" criado com sucesso no seu WhatsApp!`,
|
||||
description: `Grupo "${nomeGrupo}" criado e automação ativada com sucesso!`,
|
||||
variant: 'default',
|
||||
});
|
||||
} else {
|
||||
} catch (workflowError) {
|
||||
console.error('Erro ao ativar workflow:', workflowError);
|
||||
// Não falhar o processo todo se o workflow não ativar
|
||||
toast({
|
||||
title: 'Atenção',
|
||||
description: 'Grupo cadastrado no sistema, mas não foi possível criar no WhatsApp',
|
||||
variant: 'destructive',
|
||||
title: 'Grupo criado!',
|
||||
description: `Grupo "${nomeGrupo}" criado com sucesso. Automação será ativada em breve.`,
|
||||
variant: 'default',
|
||||
});
|
||||
}
|
||||
|
||||
@ -261,6 +274,7 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
<li>O grupo será criado automaticamente no seu WhatsApp</li>
|
||||
<li>Você será adicionado como participante do grupo</li>
|
||||
<li>O grupo terá o nome que você escolheu: {nomeGrupo || 'Digite um nome acima'}</li>
|
||||
<li>A automação será ativada automaticamente após a criação</li>
|
||||
</ul>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@ -6,16 +6,19 @@ import { makeRequest } from './apiHelpers';
|
||||
*/
|
||||
export const createEvolutionWebhook = async (userEmail: string): Promise<any> => {
|
||||
try {
|
||||
console.log(`Criando webhook para o usuário: ${userEmail}`);
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
console.log(`Criando webhook para o usuário: ${normalizedEmail}`);
|
||||
|
||||
// URL do endpoint - mantém o @ normal no email
|
||||
const endpoint = `/webhook/set/${userEmail}`;
|
||||
const endpoint = `/webhook/set/${normalizedEmail}`;
|
||||
|
||||
// Agora mantemos o email original com @ também na URL do webhook
|
||||
const webhookBody = {
|
||||
webhook: {
|
||||
enabled: true,
|
||||
url: `https://webhookn8n.innova1001.com.br/webhook/${userEmail}`,
|
||||
url: `https://webhookn8n.innova1001.com.br/webhook/${normalizedEmail}`,
|
||||
webhookByEvents: true,
|
||||
webhookBase64: true,
|
||||
events: [
|
||||
@ -26,17 +29,17 @@ export const createEvolutionWebhook = async (userEmail: string): Promise<any> =>
|
||||
|
||||
console.log('Dados do webhook:', {
|
||||
endpoint,
|
||||
emailOriginal: userEmail,
|
||||
emailOriginal: normalizedEmail,
|
||||
webhookUrl: webhookBody.webhook.url
|
||||
});
|
||||
|
||||
const response = await makeRequest(endpoint, 'POST', webhookBody);
|
||||
|
||||
console.log(`✅ Webhook criado com sucesso para ${userEmail}:`, response);
|
||||
console.log(`✅ Webhook criado com sucesso para ${normalizedEmail}:`, response);
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Erro ao criar webhook for ${userEmail}:`, error);
|
||||
console.error(`❌ Erro ao criar webhook for ${normalizedEmail}:`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
@ -42,7 +42,7 @@ export async function findOrCreateWhatsAppGroup(nomeGrupo?: string): Promise<Wha
|
||||
return null;
|
||||
}
|
||||
|
||||
// Normalizar o email (minúsculo e sem espaços)
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
// Verificar se já existe um grupo pendente para este usuário
|
||||
@ -151,7 +151,7 @@ export async function listWhatsAppGroups(): Promise<WhatsAppGroup[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Normalizar o email (minúsculo e sem espaços)
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
// Buscar grupos associados ao email do usuário
|
||||
|
||||
@ -1,21 +1,191 @@
|
||||
|
||||
import { getUserWhatsAppInstance } from './databaseOperations';
|
||||
import { supabase } from "@/integrations/supabase/client";
|
||||
|
||||
/**
|
||||
* User-related WhatsApp instance operations
|
||||
* Updates user WhatsApp instance information in the database
|
||||
*/
|
||||
export async function updateUserWhatsAppInstance(
|
||||
userEmail: string,
|
||||
instanceName: string,
|
||||
status: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
const normalizedInstanceName = instanceName.trim().toLowerCase();
|
||||
|
||||
console.log(`Atualizando instância WhatsApp para usuário: ${normalizedEmail}`);
|
||||
|
||||
// Verificar se já existe um registro para este usuário
|
||||
const { data: existingUser, error: fetchError } = await supabase
|
||||
.from('usuarios')
|
||||
.select('*')
|
||||
.eq('email', normalizedEmail)
|
||||
.single();
|
||||
|
||||
if (fetchError && fetchError.code !== 'PGRST116') { // PGRST116 = no rows returned
|
||||
console.error('Erro ao buscar usuário:', fetchError);
|
||||
throw fetchError;
|
||||
}
|
||||
|
||||
if (existingUser) {
|
||||
// Atualizar registro existente
|
||||
const { error: updateError } = await supabase
|
||||
.from('usuarios')
|
||||
.update({
|
||||
instancia_zap: normalizedInstanceName,
|
||||
status_instancia: status,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('email', normalizedEmail);
|
||||
|
||||
if (updateError) {
|
||||
console.error('Erro ao atualizar instância WhatsApp:', updateError);
|
||||
throw updateError;
|
||||
}
|
||||
|
||||
console.log(`✅ Instância WhatsApp atualizada para ${normalizedEmail}: ${normalizedInstanceName} (${status})`);
|
||||
} else {
|
||||
// Criar novo registro
|
||||
const { error: insertError } = await supabase
|
||||
.from('usuarios')
|
||||
.insert({
|
||||
email: normalizedEmail,
|
||||
instancia_zap: normalizedInstanceName,
|
||||
status_instancia: status,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
});
|
||||
|
||||
if (insertError) {
|
||||
console.error('Erro ao criar registro de instância WhatsApp:', insertError);
|
||||
throw insertError;
|
||||
}
|
||||
|
||||
console.log(`✅ Novo registro de instância WhatsApp criado para ${normalizedEmail}: ${normalizedInstanceName} (${status})`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro ao atualizar instância WhatsApp do usuário:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has an active WhatsApp instance
|
||||
* Gets user WhatsApp instance information from the database
|
||||
*/
|
||||
export async function getUserWhatsAppInstance(userEmail: string): Promise<{
|
||||
instancia_zap: string | null;
|
||||
status_instancia: string | null;
|
||||
whatsapp: string | null;
|
||||
} | null> {
|
||||
try {
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
console.log(`Buscando instância WhatsApp para usuário: ${normalizedEmail}`);
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('usuarios')
|
||||
.select('instancia_zap, status_instancia, whatsapp')
|
||||
.eq('email', normalizedEmail)
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
if (error.code === 'PGRST116') { // No rows returned
|
||||
console.log(`Nenhuma instância encontrada para ${normalizedEmail}`);
|
||||
return null;
|
||||
}
|
||||
console.error('Erro ao buscar instância WhatsApp:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log(`✅ Instância encontrada para ${normalizedEmail}:`, data);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Erro ao buscar instância WhatsApp do usuário:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes user WhatsApp instance information from the database
|
||||
*/
|
||||
export async function removeUserWhatsAppInstance(userEmail: string): Promise<void> {
|
||||
try {
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
console.log(`Removendo instância WhatsApp para usuário: ${normalizedEmail}`);
|
||||
|
||||
const { error } = await supabase
|
||||
.from('usuarios')
|
||||
.update({
|
||||
instancia_zap: null,
|
||||
status_instancia: null,
|
||||
whatsapp: null,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('email', normalizedEmail);
|
||||
|
||||
if (error) {
|
||||
console.error('Erro ao remover instância WhatsApp:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log(`✅ Instância WhatsApp removida para ${normalizedEmail}`);
|
||||
} catch (error) {
|
||||
console.error('Erro ao remover instância WhatsApp do usuário:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has a WhatsApp instance
|
||||
*/
|
||||
export async function checkUserHasInstance(userEmail: string): Promise<boolean> {
|
||||
try {
|
||||
const instanceData = await getUserWhatsAppInstance(userEmail);
|
||||
const hasInstance = !!(instanceData && instanceData.instancia_zap && instanceData.instancia_zap.trim() !== '');
|
||||
console.log(`Usuário ${userEmail} tem instância:`, hasInstance, instanceData);
|
||||
return hasInstance;
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
const instanceData = await getUserWhatsAppInstance(normalizedEmail);
|
||||
|
||||
return !!(instanceData && instanceData.instancia_zap && instanceData.instancia_zap.trim() !== '');
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar se usuário tem instância:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets debug information for user WhatsApp instance
|
||||
*/
|
||||
export async function getUserDebugInfo(userEmail: string): Promise<any> {
|
||||
try {
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
console.log(`Buscando informações de debug para: ${normalizedEmail}`);
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('usuarios')
|
||||
.select('*')
|
||||
.eq('email', normalizedEmail)
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
if (error.code === 'PGRST116') {
|
||||
return { message: 'Usuário não encontrado', email: normalizedEmail };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
return {
|
||||
...data,
|
||||
email_normalizado: normalizedEmail,
|
||||
debug_timestamp: new Date().toISOString()
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Erro ao buscar informações de debug:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,19 +5,57 @@ import { N8N_CONFIG } from './config';
|
||||
* N8N workflow operations
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ativa um workflow específico no n8n via API direta
|
||||
*/
|
||||
export async function activateN8nWorkflow(workflowId: string): Promise<void> {
|
||||
try {
|
||||
console.log(`🔔 Ativando workflow no n8n: ${workflowId}`);
|
||||
|
||||
const apiUrl = `${N8N_CONFIG.BASE_URL}/workflows/${workflowId}/activate`;
|
||||
console.log(`🔗 URL da API: ${apiUrl}`);
|
||||
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-N8N-API-KEY': N8N_CONFIG.API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`📡 Status da resposta da API: ${response.status}`);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`❌ Erro ao ativar workflow: ${response.status} - ${errorText}`);
|
||||
throw new Error(`Erro ao ativar workflow: ${response.status} - ${errorText}`);
|
||||
}
|
||||
|
||||
const responseData = await response.json();
|
||||
console.log('✅ Workflow ativado com sucesso:', responseData);
|
||||
|
||||
} catch (error) {
|
||||
console.error('💥 Erro crítico ao ativar workflow:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifica o n8n para ativar o workflow do usuário via webhook
|
||||
*/
|
||||
export async function activateUserWorkflow(userEmail: string): Promise<void> {
|
||||
try {
|
||||
console.log(`🔔 Enviando webhook para ativar workflow do usuário: ${userEmail}`);
|
||||
// ⚠️ PADRONIZAÇÃO CRÍTICA: Converter email para lowercase
|
||||
const normalizedEmail = userEmail.trim().toLowerCase();
|
||||
|
||||
console.log(`🔔 Enviando webhook para ativar workflow do usuário: ${normalizedEmail}`);
|
||||
|
||||
// Nova lógica: webhook simples para o n8n
|
||||
const webhookUrl = 'https://webhookn8n.innova1001.com.br/webhook/ativarworkflow';
|
||||
console.log(`🔗 URL do webhook: ${webhookUrl}`);
|
||||
|
||||
const webhookBody = {
|
||||
email: userEmail
|
||||
email: normalizedEmail
|
||||
};
|
||||
|
||||
console.log('📦 Dados do webhook:', JSON.stringify(webhookBody, null, 2));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user