Files
Monitor-N8N/app.py

191 lines
6.6 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import streamlit as st
import pandas as pd
import time
from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from monitor_logic import run_monitor_check, diagnose_n8n_webhook
# ===== Configuração da Página (DEVE ser a primeira chamada Streamlit!) =====
st.set_page_config(
page_title="Monitor Evolution API",
page_icon="🤖",
layout="wide"
)
# Função para gerar tabela HTML customizada
def gerar_tabela_html(logs):
"""Gera tabela HTML com estilos inline para garantir funcionamento."""
if not logs:
return ""
# Estilos inline
estilo_tabela = "width: 100%; border-collapse: collapse; margin-top: 10px;"
estilo_header = "background-color: #f0f2f6; padding: 12px 15px; text-align: center; font-weight: bold; font-size: 16px; border-bottom: 2px solid #ddd;"
estilo_celula = "padding: 10px 15px; text-align: center; font-size: 14px; border-bottom: 1px solid #eee;"
estilo_celula_detalhes = "padding: 10px 15px; text-align: left; font-size: 14px; border-bottom: 1px solid #eee;"
html = f'<table style="{estilo_tabela}">'
# Cabeçalho
html += '<thead><tr>'
html += f'<th style="{estilo_header}">Hora</th>'
html += f'<th style="{estilo_header}">Status</th>'
html += f'<th style="{estilo_header}">WhatsApp</th>'
html += f'<th style="{estilo_header}">Email</th>'
html += f'<th style="{estilo_header}">Detalhes</th>'
html += '</tr></thead>'
# Corpo
html += '<tbody>'
for log in logs:
html += '<tr>'
html += f'<td style="{estilo_celula}">{log["Hora"]}</td>'
html += f'<td style="{estilo_celula}">{log["Status"]}</td>'
html += f'<td style="{estilo_celula}">{log["WhatsApp"]}</td>'
html += f'<td style="{estilo_celula}">{log["Email"]}</td>'
html += f'<td style="{estilo_celula_detalhes}">{log["Detalhes"]}</td>'
html += '</tr>'
html += '</tbody></table>'
return html
# ===== Inicializar estado da sessão =====
if 'logs' not in st.session_state:
st.session_state['logs'] = []
if 'last_run' not in st.session_state:
st.session_state['last_run'] = "Nunca"
if 'intervalo_horas' not in st.session_state:
st.session_state['intervalo_horas'] = 3
# ===== Função wrapper para o Scheduler gravar logs =====
def scheduled_job():
"""Executa verificação agendada (roda em background thread)."""
print(f"[{datetime.now()}] Executando verificação agendada...")
status, messages, whatsapp_status, email_status = run_monitor_check()
print(f"Status: {status} | WhatsApp: {whatsapp_status} | Email: {email_status}")
print("\n".join(messages))
# ===== Configurar o Agendador (Singleton via cache_resource) =====
@st.cache_resource
def init_scheduler(intervalo_horas):
scheduler = BackgroundScheduler(timezone="America/Sao_Paulo")
# Job com intervalo configurável a partir de 00:00
scheduler.add_job(
scheduled_job,
'interval',
hours=intervalo_horas,
start_date='2025-01-01 00:00:00'
)
scheduler.start()
return scheduler
scheduler = init_scheduler(st.session_state['intervalo_horas'])
# ===== Interface Principal =====
st.title("🤖 Monitor Evolution API + Webhook")
st.markdown("---")
# Métricas superiores
col1, col2 = st.columns(2)
with col1:
st.metric(label="Última Verificação", value=st.session_state['last_run'])
with col2:
st.write("### Status Agendador")
intervalo_atual = st.session_state['intervalo_horas']
st.success(f"✅ Ativo (a cada {intervalo_atual}h desde 00:00)")
st.markdown("### Ações")
# Botão de execução manual
if st.button("🚀 Executar Verificação Agora", type="primary"):
with st.spinner('Verificando status dos serviços...'):
status, messages, whatsapp_status, email_status = run_monitor_check()
st.session_state['last_run'] = datetime.now().strftime("%H:%M:%S")
# Adicionar ao histórico de logs
timestamp = datetime.now().strftime("%H:%M:%S")
entry = {
"Hora": timestamp,
"Status": "✅ Sucesso" if status else "❌ Erro",
"WhatsApp": whatsapp_status,
"Email": email_status,
"Detalhes": " | ".join(messages)
}
st.session_state['logs'].insert(0, entry) # Adiciona no topo
if status:
st.success("✅ Todos os serviços estão operacionais!")
else:
st.error("❌ Falha detectada em um ou mais serviços. Verifique os logs.")
st.markdown("---")
st.markdown("### 📋 Histórico de Execuções (Sessão Atual)")
if st.session_state['logs']:
# Renderizar tabela HTML customizada
tabela_html = gerar_tabela_html(st.session_state['logs'])
st.markdown(tabela_html, unsafe_allow_html=True)
else:
st.info(" Nenhuma verificação executada nesta sessão ainda.")
# ===== Sidebar =====
st.sidebar.title(" Sobre")
st.sidebar.info(
"""
Este aplicativo monitora:
1. **Evolution API**: Verifica se a instância está online.
2. **N8N Webhook**: Verifica se o endpoint responde.
**Notificações:**
- ✅ **Sucesso**: Envia WhatsApp.
- ❌ **Erro**: Envia Email.
"""
)
st.sidebar.markdown("---")
# Configuração do Intervalo de Disparo
st.sidebar.markdown("### ⏱️ Intervalo de Disparo")
intervalo_slider = st.sidebar.slider(
"Executar a cada (horas):",
min_value=1,
max_value=12,
value=st.session_state['intervalo_horas'],
step=1,
help="Define o intervalo entre execuções automáticas a partir de 00:00"
)
# Mostrar horários de execução baseados no intervalo
horarios = [f"{h:02d}:00" for h in range(0, 24, intervalo_slider)]
st.sidebar.caption(f"Horários: {', '.join(horarios)}")
# Verificar se o intervalo mudou
if intervalo_slider != st.session_state['intervalo_horas']:
st.sidebar.warning("⚠️ Reinicie a aplicação para aplicar o novo intervalo.")
st.session_state['intervalo_horas'] = intervalo_slider
st.sidebar.markdown("---")
# Diagnóstico N8N na Sidebar
with st.sidebar.expander("🛠️ Diagnóstico N8N"):
st.write("Teste isolado do Webhook N8N")
if st.button("Testar Webhook N8N", key="btn_diag"):
with st.spinner("Enviando POST de teste..."):
success, log_data = diagnose_n8n_webhook()
if success:
st.success(f"✅ Status: {log_data['status_code']}")
else:
st.error(f"❌ Erro: {log_data.get('status_code') or log_data.get('error')}")
st.json(log_data)
# Informações de configuração
st.sidebar.markdown("---")
st.sidebar.caption(f"Intervalo atual: {st.session_state['intervalo_horas']}h")