diff --git a/frota/beszel-webhook-receiver.py b/frota/beszel-webhook-receiver.py index cc236da..699c686 100755 --- a/frota/beszel-webhook-receiver.py +++ b/frota/beszel-webhook-receiver.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 -"""Beszel Webhook Receiver — Cria tarefas Desk CRM a partir de alertas Beszel.""" +"""Beszel Webhook Receiver — Cria tickets Desk CRM a partir de alertas Beszel.""" import json, os, sys, logging +import string, random from http.server import HTTPServer, BaseHTTPRequestHandler from datetime import datetime import pymysql @@ -10,12 +11,11 @@ PORT = int(sys.argv[sys.argv.index("--port") + 1]) if "--port" in sys.argv else DB_CONFIG = {"host": "server.descomplicar.pt", "port": 3306, "user": "ealmeida_desk24", "password": "9qPRdCGGqM4o", "database": "ealmeida_desk24", "charset": "utf8mb4"} -# Configuração Desk CRM -PROJECT_ID = 65 # DES Stack Workflow -MILESTONE_ID = 355 # Sistemas de Apoio (Tecnologia) -ASSIGNEE_STAFF_ID = 28 # Izito -CREATOR_STAFF_ID = 25 # Claude/AIkTop -PRIORITY = 3 # Alta +# Configuração Desk CRM — Tickets +DEPARTMENT_ID = 7 # Tecnologia +PROJECT_ID = 65 # DES Stack Workflow +ASSIGNED_STAFF_ID = 28 # Izito +PRIORITY = 3 # Alta LOG = "/root/logs/beszel-webhook.log" os.makedirs(os.path.dirname(LOG), exist_ok=True) @@ -26,95 +26,70 @@ log = logging.getLogger("beszel-webhook") def get_db(): return pymysql.connect(**DB_CONFIG, cursorclass=pymysql.cursors.DictCursor) -def tarefa_existe(cur, padrao): - """Verifica se já existe tarefa aberta com o padrão indicado.""" +def ticket_key(): + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=32)) + +def ticket_existe(cur, padrao): cur.execute( - "SELECT id FROM tbltasks WHERE name LIKE %s AND status NOT IN (5,6) AND rel_type='project' AND rel_id=%s LIMIT 1", - (padrao, PROJECT_ID) + "SELECT ticketid FROM tbltickets WHERE subject LIKE %s AND status NOT IN (2,5) AND department=%s LIMIT 1", + (padrao, DEPARTMENT_ID) ) return cur.fetchone() -def criar_tarefa(cur, nome, descricao): - """Cria tarefa Desk CRM no projecto 65, milestone 355, atribuída a Izito.""" +def criar_ticket(cur, assunto, mensagem): now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + key = ticket_key() cur.execute( - """INSERT INTO tbltasks - (name, description, priority, status, rel_type, rel_id, milestone, - addedfrom, startdate, dateadded) - VALUES (%s, %s, %s, 1, %s, %s, %s, %s, %s, %s)""", - (nome, descricao, PRIORITY, "project", PROJECT_ID, MILESTONE_ID, - CREATOR_STAFF_ID, now[:10], now) + "INSERT INTO tbltickets (subject, message, department, priority, status, date, project_id, assigned, ticketkey, adminread, clientread, userid) VALUES (%s, %s, %s, %s, 1, %s, %s, %s, %s, 1, 0, 0)", + (assunto, mensagem, DEPARTMENT_ID, PRIORITY, now, PROJECT_ID, ASSIGNED_STAFF_ID, key) ) tid = cur.lastrowid - cur.execute( - "INSERT INTO tbltask_assigned (taskid, staffid, assigned_from) VALUES (%s, %s, 0)", - (tid, ASSIGNEE_STAFF_ID) - ) - log.info(f"Tarefa #{tid} criada — {nome}") + log.info(f"Ticket #{tid} criado — {assunto}") return tid -def fechar_tarefa(cur, tid, nota): - """Fecha tarefa (status 5 = Terminado).""" - cur.execute("UPDATE tbltasks SET status=5, datefinished=NOW() WHERE id=%s", (tid,)) - log.info(f"Tarefa #{tid} fechada: {nota}") +def fechar_ticket(cur, tid, nota): + cur.execute("UPDATE tbltickets SET status=2, lastreply=NOW() WHERE ticketid=%s", (tid,)) + now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + cur.execute( + "INSERT INTO tblticket_replies (ticketid, message, date, staffid, admin) VALUES (%s, %s, %s, %s, 1)", + (tid, f"
Auto-fecho (Beszel): {nota}
", now, ASSIGNED_STAFF_ID) + ) + log.info(f"Ticket #{tid} fechado: {nota}") class Handler(BaseHTTPRequestHandler): def do_POST(self): if self.path != "/beszel-alert": - self.send_response(404) - self.end_headers() - return - - body = self.rfile.read(int(self.headers.get("Content-Type-Length", 0))) + self.send_response(404); self.end_headers(); return + body = self.rfile.read(int(self.headers.get("Content-Length", 0))) try: data = json.loads(body) except Exception: - self.send_response(400) - self.end_headers() - return - + self.send_response(400); self.end_headers(); return titulo = data.get("title", "") mensagem = data.get("message", "") log.info(f"Webhook: {titulo} — {mensagem}") - is_down = "down" in (mensagem + titulo).lower() is_up = "up" in mensagem.lower() or "recovered" in mensagem.lower() - - # Extrair nome do sistema sname = data.get("system", "") or data.get("name", "") or data.get("host", "") if not sname: parts = mensagem.split(":") if len(parts) > 1: sname = parts[1].strip().split("(")[0].strip() - try: - db = get_db() - cur = db.cursor() - + db = get_db(); cur = db.cursor() if is_down and sname: - if not tarefa_existe(cur, f"[MONIT] {sname}%"): - criar_tarefa( - cur, - f"[MONIT] {sname} — sistema DOWN", - f"Beszel — {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
" - f"{mensagem}
" - ) + if not ticket_existe(cur, f"[MONIT] {sname}%"): + criar_ticket(cur, f"[MONIT] {sname} — sistema DOWN", + f"Beszel — {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
{mensagem}
") elif is_up and sname: - existente = tarefa_existe(cur, f"[MONIT] {sname}%") - if existente: - fechar_tarefa(cur, existente["id"], f"{sname} voltou ao normal") - - db.commit() - cur.close() - db.close() + ex = ticket_existe(cur, f"[MONIT] {sname}%") + if ex: + fechar_ticket(cur, ex["ticketid"], f"{sname} voltou ao normal") + db.commit(); cur.close(); db.close() except Exception as e: log.error(f"Erro Desk CRM: {e}") - - self.send_response(200) - self.send_header("Content-Type", "application/json") - self.end_headers() + self.send_response(200); self.send_header("Content-Type", "application/json"); self.end_headers() self.wfile.write(b'{"status":"ok"}') - def log_message(self, fmt, *args): log.info(f"{self.client_address[0]} - {fmt % args}")