2026-07-14 11:14:13 +03:00

406 lines
17 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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()