Disparo unico as 08:00 Hs diariamente
This commit is contained in:
157
app.py
157
app.py
@@ -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)")
|
||||||
|
|||||||
Reference in New Issue
Block a user