Disparo unico as 08:00 Hs diariamente

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

373
app.py
View File

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