# modules/bots_module.py import tkinter as tk from tkinter import ttk, messagebox import hashlib import os import uuid import re from pathlib import Path class BotsCountTab: """ Класс для создания вкладки настройки количества ботов. """ def __init__(self, parent_frame): """ Инициализация компонента вкладки. Args: parent_frame: Родительский фрейм, куда будет помещен интерфейс """ self.parent = parent_frame # Путь для сохранения файла self.save_dir = Path.home() / "Documents" / "C4" self.file_path = self.save_dir / "BotsAmount.rr" # Переменные self.bots_var = tk.IntVar(value=1) self.mac_address = self.get_mac_address() self.loading_from_file = False # Флаг загрузки из файла # Создаем основной контейнер для вкладки self.container = ttk.Frame(parent_frame, padding=20) self.container.pack(fill=tk.BOTH, expand=True) self._build_ui() # Загружаем настройки из файла при старте (только один раз) self.load_from_file() self.update_status() def get_mac_address(self): """Получаем MAC-адрес компьютера""" try: # Получаем MAC-адрес mac = ':'.join(re.findall('..', '%012x' % uuid.getnode())) return mac.upper() except: return "00:00:00:00:00:00" def _build_ui(self): """Построение интерфейса вкладки""" # Заголовок вкладки title_frame = ttk.Frame(self.container) title_frame.pack(fill=tk.X, pady=(0, 20)) title_label = ttk.Label( title_frame, text='Настройка количества ботов', font=("Segoe UI", 12, "bold") ) title_label.pack() # Разделитель ttk.Separator(self.container, orient="horizontal").pack( fill=tk.X, pady=(0, 20) ) # Основной контент content_frame = ttk.Frame(self.container) content_frame.pack(fill=tk.BOTH, expand=True) # Левая панель - выбор количества left_panel = ttk.LabelFrame(content_frame, text="Выбор количества", padding=15) left_panel.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10)) ttk.Label(left_panel, text="Выберите количество ботов:", font=("Arial", 10)).pack(pady=(0, 10)) # Фрейм для радиокнопок self.radio_frame = ttk.Frame(left_panel) self.radio_frame.pack(pady=5) # Создаем радиокнопки для выбора количества ботов self.radio_buttons = [] for i in range(1, 6): rb = tk.Radiobutton( self.radio_frame, text=f"{i} бот{'ов' if i > 1 else ''}", variable=self.bots_var, value=i, font=("Arial", 10), command=self._on_bots_change ) rb.pack(anchor=tk.W, pady=3) self.radio_buttons.append(rb) # Кнопки управления button_frame = ttk.Frame(left_panel) button_frame.pack(pady=20) ttk.Button( button_frame, text="Сохранить настройки", command=self._save_config, width=20 ).pack(pady=5) # Правая панель - информация и статус right_panel = ttk.LabelFrame(content_frame, text="Информация", padding=15) right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(10, 0)) # MAC-адрес mac_frame = ttk.Frame(right_panel) mac_frame.pack(fill=tk.X, pady=(0, 15)) ttk.Label(mac_frame, text="MAC-адрес:", font=("Arial", 9, "bold")).pack(anchor=tk.W) self.mac_label = ttk.Label( mac_frame, text=self.mac_address, font=("Consolas", 9), foreground="blue" ) self.mac_label.pack(anchor=tk.W, pady=(2, 0)) # Путь к файлу path_frame = ttk.Frame(right_panel) path_frame.pack(fill=tk.X, pady=(0, 15)) ttk.Label(path_frame, text="Файл для сохранения:", font=("Arial", 9, "bold")).pack(anchor=tk.W) self.path_label = ttk.Label( path_frame, text=str(self.file_path), font=("Consolas", 8), wraplength=250 ) self.path_label.pack(anchor=tk.W, pady=(2, 0)) # Статус status_frame = ttk.Frame(right_panel) status_frame.pack(fill=tk.X, pady=(0, 15)) ttk.Label(status_frame, text="Текущий статус:", font=("Arial", 9, "bold")).pack(anchor=tk.W) self.status_label = ttk.Label( status_frame, text="Не сохранено", font=("Arial", 10), foreground="red" ) self.status_label.pack(anchor=tk.W, pady=(2, 0)) # Количество ботов из файла bots_frame = ttk.Frame(right_panel) bots_frame.pack(fill=tk.X) ttk.Label(bots_frame, text="Количество ботов в файле:", font=("Arial", 9, "bold")).pack(anchor=tk.W) self.bots_file_label = ttk.Label( bots_frame, text="не определено", font=("Arial", 10), foreground="orange" ) self.bots_file_label.pack(anchor=tk.W, pady=(2, 0)) def _on_bots_change(self): """Обработчик изменения выбранного количества ботов""" # Не обновляем статус при изменении пользователем # Просто сбрасываем флаг загрузки из файла if not self.loading_from_file: # Обновляем только статус файла if self.file_path.exists(): self.status_label.config(text="Файл будет перезаписан", foreground="orange") else: self.status_label.config(text="Файл будет создан", foreground="blue") def load_from_file(self): """Загрузить настройки из файла при старте""" self.loading_from_file = True # Устанавливаем флаг загрузки if not self.file_path.exists(): self.bots_file_label.config( text="файл не найден", foreground="red" ) self.loading_from_file = False return None try: with open(self.file_path, 'r', encoding='utf-8') as f: file_hash = f.read().strip() if len(file_hash) != 64: # SHA-256 hash length self.bots_file_label.config( text="неверный формат хэша", foreground="red" ) self.loading_from_file = False return None # Пробуем подобрать количество ботов от 1 до 5 found_bots = None for bots in range(1, 6): data = str(bots) + "RR_SuPeR" + self.mac_address calculated_hash = hashlib.sha256(data.encode()).hexdigest() if calculated_hash == file_hash: found_bots = bots break if found_bots: # Устанавливаем значение из файла self.bots_var.set(found_bots) self.bots_file_label.config( text=f"{found_bots} бот{'ов' if found_bots > 1 else ''}", foreground="green" ) self.status_label.config( text="✓ Загружено из файла", foreground="green" ) self.loading_from_file = False return found_bots else: # Если хэш не совпал ни с одним вариантом self.bots_file_label.config( text="не совпадает с MAC-адресом", foreground="red" ) self.status_label.config( text="Файл есть, но не совпадает", foreground="orange" ) self.loading_from_file = False return None except Exception as e: self.bots_file_label.config( text=f"ошибка чтения", foreground="red" ) self.status_label.config( text=f"Ошибка чтения файла", foreground="red" ) self.loading_from_file = False return None def update_status(self): """Обновить статус (только для отображения, без изменения выбора)""" # Проверяем существование файла if self.file_path.exists(): # Читаем хэш из файла для сравнения try: with open(self.file_path, 'r', encoding='utf-8') as f: file_hash = f.read().strip() # Вычисляем хэш для текущего выбора current_bots = self.bots_var.get() data = str(current_bots) + "RR_SuPeR" + self.mac_address current_hash = hashlib.sha256(data.encode()).hexdigest() # Сравниваем if current_hash == file_hash: self.status_label.config( text="✓ Совпадает с файлом", foreground="green" ) else: self.status_label.config( text="Отличается от файла", foreground="orange" ) except Exception: self.status_label.config( text="✓ Файл существует", foreground="green" ) else: self.status_label.config( text="Файл не найден", foreground="red" ) def check_existing_file(self): """Проверить существующий файл и показать информацию (для диалога)""" if self.file_path.exists(): try: with open(self.file_path, 'r', encoding='utf-8') as f: hash_content = f.read().strip() # Рассчитываем количество ботов из файла bots_count = None for bots in range(1, 6): data = str(bots) + "RR_SuPeR" + self.mac_address calculated_hash = hashlib.sha256(data.encode()).hexdigest() if calculated_hash == hash_content: bots_count = bots break # Показываем диалог с информацией if bots_count: info_text = ( f"В файле сохранено: {bots_count} бот{'ов' if bots_count > 1 else ''}\n" f"Текущий выбор: {self.bots_var.get()} бот{'ов' if self.bots_var.get() > 1 else ''}\n\n" ) if bots_count == self.bots_var.get(): info_text += "Текущий выбор совпадает с сохраненным в файле." result = messagebox.showinfo( "Информация о файле", info_text ) else: info_text += "Текущий выбор отличается от сохраненного в файле.\nХотите перезаписать файл?" result = messagebox.askyesno( "Файл существует", info_text ) return result else: messagebox.showinfo( "Информация о файле", f"Файл существует, но количество ботов не определено.\n" f"(хэш не совпадает с текущим MAC-адресом)" ) except Exception as e: messagebox.showerror("Ошибка", f"Не удалось прочитать файл:\n{str(e)}") return True # По умолчанию разрешаем сохранение def _save_config(self): """Сохраняет количество ботов в файл с хешированием""" # Проверяем существующий файл if self.file_path.exists(): result = self.check_existing_file() if not result: return # Пользователь отказался от перезаписи try: # Получаем выбранное значение bots = self.bots_var.get() if not 1 <= bots <= 5: messagebox.showerror("Ошибка", "Выберите количество ботов от 1 до 5") return # Создаем хэш количества ботов с солью и MAC-адресом data = str(bots) + "RR_SuPeR" + self.mac_address hash_result = hashlib.sha256(data.encode()).hexdigest() # Создаем директорию, если она не существует self.save_dir.mkdir(parents=True, exist_ok=True) # Сохраняем в файл with open(self.file_path, "w", encoding="utf-8") as f: f.write(hash_result) # Обновляем статус self.update_status() # Обновляем метку файла self.bots_file_label.config( text=f"{bots} бот{'ов' if bots > 1 else ''}", foreground="green" ) # Показываем результат messagebox.showinfo( "Сохранено", f"Количество ботов: {bots}\n\n" f"Файл сохранен: {self.file_path}" ) except Exception as e: messagebox.showerror("Ошибка", f"Не удалось сохранить файл:\n{str(e)}") def get_bots_count(self): """Получить текущее количество ботов (для использования другими модулями)""" return self.bots_var.get() def get_hash_info(self): """Получить информацию о хэше (для использования другими модулями)""" bots = self.bots_var.get() data = str(bots) + "RR_SuPeR" + self.mac_address hash_result = hashlib.sha256(data.encode()).hexdigest() return { 'bots': bots, 'mac': self.mac_address, 'hash': hash_result, 'file_path': str(self.file_path), 'data_string': data } def save_bots_amount(self): """Сохранить количество ботов (интерфейсный метод для main)""" self._save_config()