import os from flask import Flask, render_template import psycopg2 from datetime import datetime import docker app = Flask(__name__) docker_client = docker.from_env() DB_CONFIG = { 'host': os.getenv("HOST"), 'port': os.getenv("PORT"), 'database': os.getenv("DBNAME"), 'user': os.getenv("USER"), 'password': os.getenv("PASSWORD") } def parse_log_line(line): """Парсит строку лога в формате: [timestamp] сообщение""" try: line = line.strip() if line.startswith('[') and ']' in line: return line return f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {line}" except: return line def get_parser_status(): """Получает статус парсеров из Docker""" try: containers = docker_client.containers.list(all=True) status = { 'tg-node-0': False, 'tg-node-1': False, 'total': 0, 'active': 0, 'errors': 0 } for container in containers: if container.name == 'tg-node-0': status['tg-node-0'] = container.status == 'running' elif container.name == 'tg-node-1': status['tg-node-1'] = container.status == 'running' status['active'] = sum([status['tg-node-0'], status['tg-node-1']]) status['errors'] = 2 - status['active'] # Просто для примера status['total'] = 2 return status except Exception as e: print(f"Error getting docker status: {e}") return None def get_leaks_stats(): """Получает статистику по утечкам из базы данных""" try: conn = psycopg2.connect(**DB_CONFIG) cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM leaks") total_leaks = cursor.fetchone()[0] cursor.execute(""" SELECT DATE(created_at) as day, COUNT(*) FROM leaks WHERE created_at >= CURRENT_DATE - INTERVAL '30 days' GROUP BY day ORDER BY day """) leaks_by_day = cursor.fetchall() cursor.execute(""" SELECT resource_name, COUNT(*) FROM leaks GROUP BY resource_name ORDER BY COUNT(*) DESC LIMIT 3 """) leaks_by_source = cursor.fetchall() cursor.execute(""" SELECT resource_name, message, created_at FROM leaks ORDER BY created_at DESC LIMIT 10 """) recent_leaks = cursor.fetchall() return { 'total_leaks': total_leaks, 'leaks_by_day': leaks_by_day, 'leaks_by_source': leaks_by_source, 'recent_leaks': recent_leaks } except Exception as e: print(f"Database error: {e}") return None finally: if 'conn' in locals(): conn.close() @app.route("/") @app.route("/index.html") def index(): parser_status = get_parser_status() leaks_stats = get_leaks_stats() if not leaks_stats: leaks_stats = { 'total_leaks': 150, 'leaks_by_day': [(datetime.now().date(), 5)], 'leaks_by_source': [('Telegram', 80), ('Форум', 50), ('Даркнет', 20)], 'recent_leaks': [('Telegram', 'Новая утечка данных', datetime.now())] } return render_template( "index.html", parser_status=parser_status, leaks_stats=leaks_stats ) @app.route("/logs.html") @app.route("/logs") def logs(): log_path = '/app/tg_nodes.log' try: with open(log_path, 'r', encoding='utf-8') as f: lines = f.readlines()[-100:] parsed_logs = [parse_log_line(line) for line in lines if line.strip()] except FileNotFoundError: parsed_logs = ["[ERROR] Лог-файл не найден"] except Exception as e: parsed_logs = [f"[ERROR] Ошибка чтения лог-файла: {str(e)}"] return render_template("logs.html", logs=parsed_logs) if __name__ == "__main__": app.run(host='0.0.0.0', port=5000)