есть скрипт "import socket
import re
import time
import argparse
import threading
import os


def load_ban_list(filename):
    """
    Загружает запрещённые никнеймы из файла.
    """
    if not os.path.isfile(filename):  # Проверка, существует ли файл
        print(f"WARNING: Файл запретных никнеймов '{filename}' не найден. Бан-лист будет пустым.")
        return set()
    with open(filename, "r", encoding="utf-8") as f:
        return {line.strip().lower() for line in f if line.strip()}


def load_target_messages(filename):
    """
    Загружает целевые сообщения из файла.
    """
    if not os.path.isfile(filename):
        raise FileNotFoundError(f"ERROR: Файл целевых сообщений '{filename}' не найден.")
    with open(filename, "r", encoding="utf-8") as f:
        return [line.strip() for line in f if line.strip()]


def load_commands(filename):
    """
    Загрузка команд из файла.
    """
    if filename and not os.path.isfile(filename):
        print(f"WARNING: Файл команд '{filename}' не найден. Будет запущено без команд.")
        return []
    elif filename is None or filename == "":
        return []

    with open(filename, "r", encoding="utf-8") as f:
        return [line.strip() for line in f if line.strip()]


def is_disallowed_nickname(nickname, ban_list):
    """
    Проверка, нужно ли банить никнейм:
    - Если ник состоит только из цифр.
    - Если ник указан в запрещённом списке.
    """
    if nickname.isdigit():
        return True
    if nickname.lower() in ban_list:
        return True
    return False


def extract_ip_from_log(line):
    """
    Извлекает IP-адрес из строки лога (формат "addr=").
    """
    ip_match = re.search(r"addr=<{([\d\.]+):", line)
    if ip_match:
        return ip_match.group(1)  # Возвращаем IP-адрес
    return None


def connect_to_econ(host, port, password):
    """
    Устанавливает соединение с ECON сервером.
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    while True:
        try:
            s.connect((host, port))
            print(f"[ECON] Подключено к серверу {host}:{port}")
            s.sendall((password + '\n').encode())
            time.sleep(5)  # Небольшая пауза для обработки
            return s
        except Exception as e:
            print(f"[ERROR] Не удалось подключиться к {host}:{port}: {e}. Повторное подключение через 5 секунд...")
            time.sleep(30)


def send_command(sock, command):
    """
    Отправка команды на ECON сервер.
    """
    sock.sendall((command + '\n').encode('utf-8'))
    print(f"[CMD] Команда отправлена: {command}")
    time.sleep(1)  # Ожидание перед следующей командой (чтобы не нагружать сервер)


### Подпроцессы ###
def ban_handler(sock, ban_list, econ_client_ip):
    """
    Обработчик для автоматического бана игроков при подключении, основываясь на запрещённых никнеймах.
    """
    last_ip = None

    while True:
        try:
            data = sock.recv(4096)
            if not data:
                print("[BAN_HANDLER] Соединение потеряно. Завершаем работу хендлера банов.")
                break

            message = data.decode('utf-8')

            if "addr=" in message:  # Если строка содержит IP
                last_ip = extract_ip_from_log(message)

            if "' entered and joined the game" in message:  # Ловим никнейм
                nickname_match = re.search(r"\'([^\']*)\' entered and joined the game", message)
                if nickname_match:
                    nickname = nickname_match.group(1)
                    print(f"[BAN_HANDLER] Никнейм={nickname}, IP={last_ip}")

                    # Проверить, игнорировать передачи ECON IP
                    if last_ip == econ_client_ip:
                        print(f"[BAN_HANDLER] Игнорирование ECON клиента с IP {econ_client_ip}")
                        continue

                    # Если никнейм запрещён, выполнить бан
                    if last_ip and is_disallowed_nickname(nickname, ban_list):
                        ban_command = f"ban {last_ip} 10 Bad nickname or name blacklist"
                        send_command(sock, ban_command)
        except Exception as e:
            print(f"[BAN_HANDLER] Ошибка: {e}")
            break


def target_messages_handler(sock, target_messages, econ_client_ip):
    """
    Отвечает за обработку целевых сообщений (например, из чата или whisper).
    """
    last_processed_time = {}
    REPROCESS_INTERVAL = 600  # 10 минут на повторную обработку

    while True:
        try:
            data = sock.recv(4096)
            if not data:
                print("[MSG_HANDLER] Соединение потеряно. Завершаем обработку сообщений.")
                break

            message = data.decode('utf-8')

            for target_message in target_messages:
                whisper_pattern = re.compile(
                    rf"\[whisper\]: (\d+):\d+:.*? -> \d+:.*?:.*{re.escape(target_message)}.*",
                    re.IGNORECASE
                )
                general_pattern = re.compile(
                    rf"\[chat\]: (\d+):\d+:[^:]+(?:<[^>]+>)?:.*{re.escape(target_message)}.*",
                    re.IGNORECASE
                )

                whisper_match = whisper_pattern.search(message)
                general_match = general_pattern.search(message)

                if whisper_match or general_match:
                    player_id = whisper_match.group(1) if whisper_match else general_match.group(1)
                    current_time = time.time()

                    if player_id in last_processed_time:
                        elapsed_time = current_time - last_processed_time[player_id]
                        if elapsed_time < REPROCESS_INTERVAL:
                            continue

                    last_processed_time[player_id] = current_time

                    command = (f"jail_arrest {player_id} 1200;"
                               f"say Читер арестован;"
                               f"sound 19;"
                               f"sendmotd {player_id} 0 Ты был арестован за читы. ВОЗМОЖНЫЕ ПРИЧИНЫ АРЕСТА: 1. Нечестная игра. 2. Ты пользуешься KRX клиентом. 3. Рекламируешь читы. 4. Не используешь чистый DDNet клиент. 5. Шутишь/говоришь за читы. Если ты сюда попал то по факту. Античит работает в автономном режиме\n")
                    send_command(sock, command)
        except Exception as e:
            print(f"[MSG_HANDLER] Ошибка: {e}")
            break


def commands_handler(sock, commands):
    """
    Выполняет периодическую отправку команд из списка каждые 60 секунд.
    """
    command_index = 0
    while True:
        try:
            if commands:
                send_command(sock, commands[command_index])
                command_index = (command_index + 1) % len(commands)
            time.sleep(60)  # Интервал между командами
        except Exception as e:
            print(f"[CMD_HANDLER] Ошибка: {e}")
            break


### Основной обработчик ###
def server_handler(host, port, password, commands_file, ban_list, target_messages):
    """
    Основной обработчик каждого сервера:
    - Подключается к ECON серверу.
    - Запускает потоки для банов, целевых сообщений и выполнения автономных команд.
    """
    sock = connect_to_econ(host, port, password)

    # Определяем ECON IP
    econ_client_ip = None
    try:
        econ_client_ip = extract_ip_from_log(sock.getsockname()[0])
        print(f"[ECON] IP клиента ECON: {econ_client_ip}")
    except Exception as e:
        print(f"[ECON] Не удалось определить ECON IP: {e}")

    # Загружаем команды
    commands = load_commands(commands_file)

    # Запускаем хендлеры
    threading.Thread(target=ban_handler, args=(sock, ban_list, econ_client_ip)).start()
    threading.Thread(target=target_messages_handler, args=(sock, target_messages, econ_client_ip)).start()
    threading.Thread(target=commands_handler, args=(sock, commands)).start()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Подключение к ECON серверам')
    parser.add_argument('--hosts', type=str, default='localhost', nargs='+', required=True, help='Список IP-адресов серверов')
    parser.add_argument('--ports', type=int, nargs='+', required=True, help='Список портов серверов')
    parser.add_argument('--password', type=str, default='2000ublocker', required=True, help='Пароль к серверу ECON')
    parser.add_argument('--commands_files', type=str, nargs='+', required=True, help='Список файлов с командами')
    parser.add_argument('--ban_list_file', type=str, default='/root/servers/anticheat/badnames.txt', required=True, help='Путь к файлу с запрещёнными никнеймами')
    parser.add_argument('--target_messages_file', type=str, default='/root/servers/anticheat/target_messages.txt', required=True, help='Путь к файлу с целевыми сообщениями')

    args = parser.parse_args()

    ban_list = load_ban_list(args.ban_list_file)
    target_messages = load_target_messages(args.target_messages_file)

    # Проверяем, что количество хостов, портов и файлов с командами совпадает
    if len(args.hosts) != len(args.ports) or len(args.hosts) != len(args.commands_files):
        print("ERROR: Количество хостов, портов и файлов с командами должно совпадать.")
        exit(1)

    threads = []

    # Запуск обработчиков для каждого сервера
    for host, port, commands_file in zip(args.hosts, args.ports, args.commands_files):
        thread = threading.Thread(
            target=server_handler,
            args=(host, port, args.password, commands_file, ban_list, target_messages),
        )
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()
" он не определяет запрещенные имена в файле тоесть бан срабатывает на цифры но на имена нет можешь исправить?