import os import requests import smtplib from email.mime.text import MIMEText from datetime import datetime import pytz from dotenv import load_dotenv # Carregar variáveis de ambiente load_dotenv() # Configurações EVOLUTION_API_URL = os.getenv("EVOLUTION_API_URL") EVOLUTION_INSTANCE_ID = os.getenv("EVOLUTION_INSTANCE_ID") EVOLUTION_API_TOKEN = os.getenv("EVOLUTION_API_TOKEN") EVOLUTION_SENDER_INSTANCE = os.getenv("EVOLUTION_SENDER_INSTANCE", "Wander") N8N_WEBHOOK_URL = os.getenv("N8N_WEBHOOK_URL") WHATSAPP_NUMBER = os.getenv("WHATSAPP_NUMBER") SMTP_SERVER = os.getenv("SMTP_SERVER", "smtp-mail.outlook.com") SMTP_PORT = int(os.getenv("SMTP_PORT", 587)) SMTP_EMAIL = os.getenv("SMTP_EMAIL") SMTP_PASSWORD = os.getenv("SMTP_PASSWORD") EMAIL_TO = os.getenv("EMAIL_TO") # Timezone configurável via variável de ambiente TIMEZONE = os.getenv("TIMEZONE", "America/Sao_Paulo") tz = pytz.timezone(TIMEZONE) def get_now(): """Retorna datetime atual com timezone configurado.""" return datetime.now(tz) def get_headers(): return { "apikey": EVOLUTION_API_TOKEN, "Authorization": f"Bearer {EVOLUTION_API_TOKEN}", "Content-Type": "application/json" } def send_email_error(error_details): """Envia email de erro caso algo falhe.""" try: now = get_now() subject = "🚨 ERRO - Monitor Evolution API" body = f"Falha no monitoramento.\nHorário: {now.strftime('%d/%m/%Y %H:%M:%S')}\n\nDetalhes do Erro:\n{error_details}" msg = MIMEText(body) msg['Subject'] = subject msg['From'] = SMTP_EMAIL msg['To'] = EMAIL_TO # Ler configuração de segurança (Default: STARTTLS) smtp_security = os.getenv("SMTP_SECURITY", "STARTTLS").upper() if smtp_security == "SSL": server = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) else: server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT) if smtp_security == "STARTTLS": server.starttls() with server: server.login(SMTP_EMAIL, SMTP_PASSWORD) server.send_message(msg) return True, "Email de erro enviado com sucesso." except Exception as e: return False, f"Falha ao enviar email: {str(e)}" def send_whatsapp_success(): """Envia mensagem de sucesso via Evolution API.""" try: url = f"{EVOLUTION_API_URL}/message/sendText/{EVOLUTION_SENDER_INSTANCE}" now = get_now() message_text = ( f"✅ *MONITOR OK*\n\n" f"📅 Data: {now.strftime('%d/%m/%Y')}\n" f"🕐 Horário: {now.strftime('%H:%M:%S')}\n\n" f"• Evolution API: Online\n" f"• Webhook Instância: Habilitado\n" f"• Webhook N8N: Funcionando\n\n" f"Todos os serviços operacionais." ) payload = { "number": WHATSAPP_NUMBER, "text": message_text } # A Evolution API às vezes aceita apikey no header ou como query param, # mas o padrão aqui é usar o header configurado. response = requests.post(url, json=payload, headers=get_headers(), timeout=10) if response.status_code == 200 or response.status_code == 201: return True, "WhatsApp de sucesso enviado." else: return False, f"Falha ao enviar WhatsApp: {response.text}" except Exception as e: return False, f"Erro na requisição WhatsApp: {str(e)}" def run_monitor_check(): """Executa o fluxo de verificação completo.""" log_messages = [] whatsapp_status = "-" email_status = "-" # Passo 1: Verificar Health Evolution API try: # Endpoint correto: /instance/connectionState/{instanceName} # Usa o nome da instância (EVOLUTION_SENDER_INSTANCE) e não o ID health_url = f"{EVOLUTION_API_URL}/instance/connectionState/{EVOLUTION_SENDER_INSTANCE}" resp_health = requests.get(health_url, headers=get_headers(), timeout=10) if resp_health.status_code == 200: # Validar se a instância está realmente conectada (state: open) try: data = resp_health.json() instance_data = data.get('instance', {}) state = instance_data.get('state') or data.get('state') if state == 'open': log_messages.append("✅ Evolution API Online") else: # Estado não é 'open' (ex: close, closed, connecting) = ERRO! error_msg = f"Evolution API Desconectada (State: {state})" log_messages.append(f"❌ {error_msg}") # Enviar email de erro email_ok, _ = send_email_error(error_msg) email_status = "Sucesso" if email_ok else "Erro" return False, log_messages, whatsapp_status, email_status except Exception as json_err: # Se falhar ler JSON mas deu 200 OK, verificar se é HTML raw_text = resp_health.text.strip() if raw_text.startswith(' Enviar WhatsApp # Se está tudo OK, email de erro não é enviado, então mantemos email_status como "-" ou podemos por "N/A" # O usuário pediu "Sucesso ou Error". Se não enviou nada, talvez "-" seja melhor que "Error". success, msg = send_whatsapp_success() if success: log_messages.append(f"✅ {msg}") whatsapp_status = "Sucesso" return True, log_messages, whatsapp_status, email_status else: # Se falhar enviar o whats, é um erro também? whatsapp_status = "Erro" # O fluxo original manda email de erro se o check falhar. # Se o envio do whats falhar, vamos mandar email error_msg = f"Serviços Online, mas falha ao enviar WhatsApp: {msg}" log_messages.append(f"⚠️ {error_msg}") email_ok, _ = send_email_error(error_msg) email_status = "Sucesso" if email_ok else "Erro" return False, log_messages, whatsapp_status, email_status def diagnose_n8n_webhook(): """Realiza um teste detalhado do Webhook N8N para diagnóstico.""" try: url = N8N_WEBHOOK_URL now = get_now() payload = {"check": "diagnosis_ping", "timestamp": str(now)} # Preparar log log = { "url": url, "method": "POST", "payload_sent": payload, "status_code": None, "response_body": None, "headers_received": None, "error": None } response = requests.post(url, json=payload, timeout=10) log["status_code"] = response.status_code log["response_body"] = response.text log["headers_received"] = dict(response.headers) if response.status_code == 200: return True, log else: return False, log except Exception as e: log["error"] = str(e) return False, log if __name__ == "__main__": # Teste rápido se rodar direto status, logs, wa_status, em_status = run_monitor_check() print(f"Status: {status}") print(f"WhatsApp: {wa_status} | Email: {em_status}") print("\n".join(logs))