#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ ФУНКЦИОНАЛЬНАЯ проверка защиты: не грепом, а вызовом. Греп по коду обманывается — после патча в файле появляются строки команд из самого блока защиты, и наивный чекер считает их незакрытыми. Поэтому здесь защита ПРОВЕРЯЕТСЯ ВЫЗОВОМ: подставляем чужой id и смотрим, вернёт ли она запрет. Токены и тексты не печатаются. """ import ast, importlib.util as il, os, re, sys PATH = sys.argv[1] if len(sys.argv) > 1 else "/opt/arena/tg_bot.py" src = open(PATH, encoding="utf-8").read() print(f"файл: {PATH}") print(f"блок защиты в файле: {'ДА' if 'def acl_block' in src else 'НЕТ'}") calls = re.findall(r"if\s+acl_block\(([^)]*)\)\s*:", src) print(f"вызов в диспетчере: {'ДА — ' + calls[0] if calls else 'НЕТ'}") after = re.search(r"if\s+acl_block\([^)]*\)\s*:\s*\n\s*(\w+)", src) print(f"действие при запрете: {after.group(1) if after else '—'}") # ВАЖНО: модуль бота НЕ импортируем целиком. # exec_module выполнил бы файл — а у бота на верхнем уровне цикл опроса # Telegram. Это и подвесило первую версию проверялки, и, что хуже, подняло бы # ВТОРОГО поллера рядом с работающим сервисом (двойная обработка команд). # Достаём и выполняем ТОЛЬКО блок защиты, между его маркерами. m = re.search(r"# --- ACL GUARD \(arena\) ---(.*?)# --- ACL GUARD \(arena\) ---", src, re.S) if not m: sys.exit("❌ блок защиты в файле не найден") ns = {} exec(compile(m.group(1), "guard", "exec"), ns) mod = type("M", (), ns) owner = None try: import json owner = json.load(open("/opt/arena/tg_acl.json"))["allow"][0] except Exception: pass print(f"список допуска: {'загружен, ' + str(len(mod._acl_allowed())) + ' id' if hasattr(mod,'_acl_allowed') else '—'}") STRANGER = 111222333 cases = [ (owner, "/kill V42", False, "владелец убивает бота"), (STRANGER, "/kill V42", True, "ЧУЖОЙ убивает бота"), (STRANGER, "/pause", True, "чужой ставит на паузу"), (STRANGER, "/promote V70", True, "чужой повышает бота"), (STRANGER, "/pnl", False, "чужой смотрит PnL"), (STRANGER, "/top", False, "чужой смотрит топ"), (None, "/kill V42", True, "отправитель неизвестен"), ] print(f"\n{'кто':>12} {'команда':12} {'ожидаем':>8} {'факт':>6} что это") bad = 0 for who, txt, want, desc in cases: if who is None and want is False: continue got = bool(mod.acl_block(who, txt)) ok = got == want bad += not ok print(f"{str(who):>12} {txt:12} {'блок' if want else 'пуск':>8} " f"{'блок' if got else 'пуск':>6} {'✅' if ok else '❌'} {desc}") print(f"\n=== {'ЗАЩИТА РАБОТАЕТ' if not bad else f'ПРОВАЛОВ: {bad}'} ===")