Disparo unico as 08:00 Hs diariamente

This commit is contained in:
2026-03-26 22:55:17 -03:00
parent 55fccd657c
commit 09a31f42e0

157
app.py
View File

@@ -1,155 +1,156 @@
import streamlit as st
import pandas as pd
import time
import os import os
from datetime import datetime from datetime import datetime
import pytz
from apscheduler.schedulers.background import BackgroundScheduler
from monitor_logic import run_monitor_check, diagnose_n8n_webhook
# Carregar timezone da variável de ambiente (padrão: America/Sao_Paulo) import pytz
import streamlit as st
from apscheduler.schedulers.background import BackgroundScheduler
from monitor_logic import diagnose_n8n_webhook, run_monitor_check
# Timezone configuravel via variavel de ambiente (padrao: America/Sao_Paulo)
TIMEZONE = os.getenv("TIMEZONE", "America/Sao_Paulo") TIMEZONE = os.getenv("TIMEZONE", "America/Sao_Paulo")
tz = pytz.timezone(TIMEZONE) tz = pytz.timezone(TIMEZONE)
# ===== Configuração da Página (DEVE ser a primeira chamada Streamlit!) =====
st.set_page_config( st.set_page_config(
page_title="Monitor Evolution API", page_title="Monitor Evolution API",
page_icon="🤖", page_icon="🤖",
layout="wide" layout="wide",
) )
# Função para gerar tabela HTML customizada
def gerar_tabela_html(logs): def gerar_tabela_html(logs):
"""Gera tabela HTML com estilos inline para garantir funcionamento.""" """Gera tabela HTML com estilos inline para garantir funcionamento."""
if not logs: if not logs:
return "" return ""
# Estilos inline
estilo_tabela = "width: 100%; border-collapse: collapse; margin-top: 10px;" 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_header = (
estilo_celula = "padding: 10px 15px; text-align: center; font-size: 14px; border-bottom: 1px solid #eee;" "background-color: #f0f2f6; padding: 12px 15px; text-align: center; "
estilo_celula_detalhes = "padding: 10px 15px; text-align: left; font-size: 14px; border-bottom: 1px solid #eee;" "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}">' html = f'<table style="{estilo_tabela}">'
# Cabeçalho html += "<thead><tr>"
html += '<thead><tr>'
html += f'<th style="{estilo_header}">Hora</th>' html += f'<th style="{estilo_header}">Hora</th>'
html += f'<th style="{estilo_header}">Status</th>' html += f'<th style="{estilo_header}">Status</th>'
html += f'<th style="{estilo_header}">WhatsApp</th>' html += f'<th style="{estilo_header}">WhatsApp</th>'
html += f'<th style="{estilo_header}">Email</th>' html += f'<th style="{estilo_header}">Email</th>'
html += f'<th style="{estilo_header}">Detalhes</th>' html += f'<th style="{estilo_header}">Detalhes</th>'
html += '</tr></thead>' html += "</tr></thead>"
# Corpo html += "<tbody>"
html += '<tbody>'
for log in logs: for log in logs:
html += '<tr>' html += "<tr>"
html += f'<td style="{estilo_celula}">{log["Hora"]}</td>' 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["Status"]}</td>'
html += f'<td style="{estilo_celula}">{log["WhatsApp"]}</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}">{log["Email"]}</td>'
html += f'<td style="{estilo_celula_detalhes}">{log["Detalhes"]}</td>' html += f'<td style="{estilo_celula_detalhes}">{log["Detalhes"]}</td>'
html += '</tr>' html += "</tr>"
html += '</tbody></table>' html += "</tbody></table>"
return html 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: if "logs" not in st.session_state:
st.session_state['last_run'] = "Nunca" 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(): def scheduled_job():
"""Executa verificação agendada (roda em background thread).""" """Executa verificacao agendada (background thread)."""
now = datetime.now(tz) now = datetime.now(tz)
print(f"[{now}] Executando verificação agendada...") print(f"[{now}] Executando verificacao agendada...")
status, messages, whatsapp_status, email_status = run_monitor_check() status, messages, whatsapp_status, email_status = run_monitor_check()
print(f"Status: {status} | WhatsApp: {whatsapp_status} | Email: {email_status}") print(f"Status: {status} | WhatsApp: {whatsapp_status} | Email: {email_status}")
print("\n".join(messages)) print("\n".join(messages))
# ===== Configurar o Agendador (Singleton via cache_resource) =====
@st.cache_resource @st.cache_resource
def init_scheduler(intervalo_horas): def init_scheduler():
scheduler = BackgroundScheduler(timezone=TIMEZONE) scheduler = BackgroundScheduler(timezone=TIMEZONE)
# Job com intervalo configurável a partir de 00:00
scheduler.add_job( scheduler.add_job(
scheduled_job, scheduled_job,
'interval', "cron",
hours=intervalo_horas, hour=8,
start_date='2025-01-01 00:00:00' minute=0,
second=0,
id="daily_080000_check",
replace_existing=True,
) )
scheduler.start() scheduler.start()
return scheduler return scheduler
scheduler = init_scheduler(st.session_state['intervalo_horas'])
# ===== Interface Principal ===== scheduler = init_scheduler()
st.title("🤖 Monitor Evolution API + Webhook") st.title("🤖 Monitor Evolution API + Webhook")
st.markdown("---") st.markdown("---")
# Métricas superiores
col1, col2 = st.columns(2) col1, col2 = st.columns(2)
with col1: with col1:
st.metric(label="Última Verificação", value=st.session_state['last_run']) st.metric(label="Ultima Verificacao", value=st.session_state["last_run"])
with col2: with col2:
st.write("### Status Agendador") st.write("### Status Agendador")
intervalo_atual = st.session_state['intervalo_horas'] st.success("✅ Ativo (diariamente as 08:00:00 | intervalo 24h)")
st.success(f"✅ Ativo (a cada {intervalo_atual}h desde 00:00)")
st.markdown("### Ações") st.markdown("### Acoes")
# Botão de execução manual if st.button("🚀 Executar Verificacao Agora", type="primary"):
if st.button("🚀 Executar Verificação Agora", type="primary"): with st.spinner("Verificando status dos servicos..."):
with st.spinner('Verificando status dos serviços...'):
status, messages, whatsapp_status, email_status = run_monitor_check() status, messages, whatsapp_status, email_status = run_monitor_check()
now = datetime.now(tz) now = datetime.now(tz)
st.session_state['last_run'] = now.strftime("%H:%M:%S") st.session_state["last_run"] = now.strftime("%H:%M:%S")
# Adicionar ao histórico de logs
timestamp = now.strftime("%H:%M:%S")
entry = { entry = {
"Hora": timestamp, "Hora": now.strftime("%H:%M:%S"),
"Status": "✅ Sucesso" if status else "❌ Erro", "Status": "✅ Sucesso" if status else "❌ Erro",
"WhatsApp": whatsapp_status, "WhatsApp": whatsapp_status,
"Email": email_status, "Email": email_status,
"Detalhes": " | ".join(messages) "Detalhes": " | ".join(messages),
} }
st.session_state['logs'].insert(0, entry) # Adiciona no topo st.session_state["logs"].insert(0, entry)
if status: if status:
st.success("✅ Todos os serviços estão operacionais!") st.success("✅ Todos os servicos estao operacionais!")
else: else:
st.error("❌ Falha detectada em um ou mais serviços. Verifique os logs.") st.error("❌ Falha detectada em um ou mais servicos. Verifique os logs.")
st.markdown("---") st.markdown("---")
st.markdown("### 📋 Histórico de Execuções (Sessão Atual)") st.markdown("### Historico de Execucoes (Sessao Atual)")
if st.session_state['logs']: if st.session_state["logs"]:
# Renderizar tabela HTML customizada tabela_html = gerar_tabela_html(st.session_state["logs"])
tabela_html = gerar_tabela_html(st.session_state['logs'])
st.markdown(tabela_html, unsafe_allow_html=True) st.markdown(tabela_html, unsafe_allow_html=True)
else: else:
st.info(" Nenhuma verificação executada nesta sessão ainda.") st.info(" Nenhuma verificacao executada nesta sessao ainda.")
# ===== Sidebar =====
st.sidebar.title(" Sobre") st.sidebar.title(" Sobre")
st.sidebar.info( st.sidebar.info(
""" """
Este aplicativo monitora: Este aplicativo monitora:
1. **Evolution API**: Verifica se a instância está online. 1. **Evolution API**: Verifica se a instancia esta online.
2. **N8N Webhook**: Verifica se o endpoint responde. 2. **N8N Webhook**: Verifica se o endpoint responde.
**Notificações:** **Notificacoes:**
- ✅ **Sucesso**: Envia WhatsApp. - ✅ **Sucesso**: Envia WhatsApp.
- ❌ **Erro**: Envia Email. - ❌ **Erro**: Envia Email.
""" """
@@ -157,30 +158,7 @@ st.sidebar.info(
st.sidebar.markdown("---") st.sidebar.markdown("---")
# Configuração do Intervalo de Disparo with st.sidebar.expander("🛠️ Diagnostico N8N"):
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") st.write("Teste isolado do Webhook N8N")
if st.button("Testar Webhook N8N", key="btn_diag"): if st.button("Testar Webhook N8N", key="btn_diag"):
with st.spinner("Enviando POST de teste..."): with st.spinner("Enviando POST de teste..."):
@@ -193,6 +171,5 @@ with st.sidebar.expander("🛠️ Diagnóstico N8N"):
st.json(log_data) st.json(log_data)
# Informações de configuração
st.sidebar.markdown("---") st.sidebar.markdown("---")
st.sidebar.caption(f"Intervalo atual: {st.session_state['intervalo_horas']}h") st.sidebar.caption("Disparador automatico: diariamente as 08:00:00 (24h)")