348 lines
14 KiB
Python
348 lines
14 KiB
Python
import os
|
|
import shutil
|
|
import time
|
|
import psutil
|
|
import subprocess
|
|
|
|
# ANSI escape codes for text color and formatting
|
|
RESET = '\033[0m'
|
|
BOLD = '\033[1m'
|
|
RED = '\033[91m' # Для повторяющихся цифр
|
|
GREEN = '\033[92m' # Для возрастающих последовательностей
|
|
YELLOW = '\033[93m' # Для убывающих последовательностей
|
|
BLUE = '\033[94m' # Для палиндромов
|
|
MAGENTA = '\033[95m' # Для специальных чисел (228, 1488, 322)
|
|
|
|
def find_ad_anynet_id(file_path):
|
|
"""Ищет строку ad.anynet.id в файле."""
|
|
try:
|
|
with open(file_path, 'r') as file:
|
|
for line in file:
|
|
if line.startswith('ad.anynet.id='):
|
|
return line.strip()
|
|
except Exception as e:
|
|
print(f"Error reading file {file_path}: {e}")
|
|
return None
|
|
|
|
def get_file_content(file_path):
|
|
"""Читает содержимое файла."""
|
|
try:
|
|
with open(file_path, 'r') as file:
|
|
return file.read()
|
|
except Exception as e:
|
|
print(f"Error reading file {file_path}: {e}")
|
|
return ""
|
|
|
|
def is_beautiful_id(id_str):
|
|
"""Определяет, является ли ID 'красивым'."""
|
|
# Проверка на повторяющиеся цифры (например, 1111)
|
|
for i in range(len(id_str) - 3):
|
|
if id_str[i] == id_str[i+1] == id_str[i+2] == id_str[i+3]:
|
|
# Находим все вхождения повторяющейся цифры
|
|
repeated_digit = id_str[i]
|
|
part = ''
|
|
j = i
|
|
while j < len(id_str) and id_str[j] == repeated_digit:
|
|
part += id_str[j]
|
|
j += 1
|
|
return {'type': 'repeated', 'part': part}
|
|
|
|
# Проверка на возрастающую последовательность (например, 1234)
|
|
if ''.join(sorted(id_str)) == id_str and len(set(id_str)) == len(id_str):
|
|
return {'type': 'ascending', 'part': id_str}
|
|
|
|
# Проверка на убывающую последовательность (например, 4321)
|
|
if ''.join(sorted(id_str, reverse=True)) == id_str and len(set(id_str)) == len(id_str):
|
|
return {'type': 'descending', 'part': id_str}
|
|
|
|
# Проверка на палиндром (симметричные числа, например, 1221)
|
|
if id_str == id_str[::-1]:
|
|
return {'type': 'palindrome', 'part': id_str}
|
|
|
|
# Проверка на наличие чисел 228, 1488, 322
|
|
special_numbers = ['228', '1488', '322']
|
|
for number in special_numbers:
|
|
if number in id_str:
|
|
return {'type': 'special_number', 'part': number}
|
|
|
|
# Временно закомментировано условие про короткие ID
|
|
# if len(id_str) <= 9:
|
|
# return {'type': 'short', 'part': id_str}
|
|
|
|
return None
|
|
|
|
def parse_profiles(profiles_dir):
|
|
"""Парсит профили и ищет 'красивые' ID."""
|
|
profiles = {}
|
|
beautiful_profiles = {}
|
|
|
|
# Проверяем, существует ли директория
|
|
if not os.path.exists(profiles_dir):
|
|
print(f"Profiles directory '{profiles_dir}' does not exist!")
|
|
return profiles, beautiful_profiles
|
|
|
|
# Проверяем содержимое директории
|
|
dir_contents = os.listdir(profiles_dir)
|
|
if not dir_contents:
|
|
print(f"Profiles directory '{profiles_dir}' is empty!")
|
|
return profiles, beautiful_profiles
|
|
|
|
print(f"Contents of profiles directory: {dir_contents}")
|
|
|
|
for profile_name in dir_contents:
|
|
profile_path = os.path.join(profiles_dir, profile_name)
|
|
if not os.path.isdir(profile_path):
|
|
print(f"Skipping non-directory item: {profile_name}")
|
|
continue
|
|
|
|
# Учитываем новую структуру: profiles/ADx/AnyDesk/system.conf
|
|
anydesk_dir = os.path.join(profile_path, "AnyDesk")
|
|
system_conf_path = os.path.join(anydesk_dir, "system.conf")
|
|
|
|
if not os.path.exists(system_conf_path):
|
|
print(f"system.conf not found in profile: {profile_name}")
|
|
continue
|
|
|
|
print(f"Parsing profile: {profile_name}")
|
|
ad_anynet_id = find_ad_anynet_id(system_conf_path)
|
|
if ad_anynet_id:
|
|
id_value = ad_anynet_id.split('=')[1]
|
|
profiles[profile_name] = {
|
|
'id': id_value,
|
|
'config_path': system_conf_path
|
|
}
|
|
beauty_info = is_beautiful_id(id_value)
|
|
if beauty_info:
|
|
beautiful_profiles[profile_name] = {'id': id_value, 'beauty_info': beauty_info}
|
|
else:
|
|
print(f"No ad.anynet.id found in system.conf for profile: {profile_name}")
|
|
|
|
return profiles, beautiful_profiles
|
|
|
|
|
|
def highlight_beautiful_id(id_str, beauty_info):
|
|
"""Подсвечивает 'красивую' часть ID."""
|
|
part = beauty_info['part']
|
|
type_ = beauty_info['type']
|
|
|
|
highlighted_id = id_str
|
|
|
|
if type_ == 'repeated':
|
|
# Находим все вхождения повторяющейся части и подсвечиваем их красным
|
|
start_index = 0
|
|
while True:
|
|
start_index = highlighted_id.find(part, start_index)
|
|
if start_index == -1:
|
|
break
|
|
end_index = start_index + len(part)
|
|
highlighted_part = RED + BOLD + part + RESET
|
|
highlighted_id = highlighted_id[:start_index] + highlighted_part + highlighted_id[end_index:]
|
|
start_index += len(highlighted_part) # Учитываем длину подсвеченной части
|
|
|
|
elif type_ == 'ascending':
|
|
# Подсвечиваем возрастающие последовательности зеленым
|
|
start_index = highlighted_id.find(part)
|
|
if start_index != -1:
|
|
end_index = start_index + len(part)
|
|
highlighted_part = GREEN + BOLD + part + RESET
|
|
highlighted_id = highlighted_id[:start_index] + highlighted_part + highlighted_id[end_index:]
|
|
|
|
elif type_ == 'descending':
|
|
# Подсвечиваем убывающие последовательности желтым
|
|
start_index = highlighted_id.find(part)
|
|
if start_index != -1:
|
|
end_index = start_index + len(part)
|
|
highlighted_part = YELLOW + BOLD + part + RESET
|
|
highlighted_id = highlighted_id[:start_index] + highlighted_part + highlighted_id[end_index:]
|
|
|
|
elif type_ == 'palindrome':
|
|
# Подсвечиваем палиндромы синим
|
|
start_index = highlighted_id.find(part)
|
|
if start_index != -1:
|
|
end_index = start_index + len(part)
|
|
highlighted_part = BLUE + BOLD + part + RESET
|
|
highlighted_id = highlighted_id[:start_index] + highlighted_part + highlighted_id[end_index:]
|
|
|
|
elif type_ == 'special_number':
|
|
# Подсвечиваем специальные числа магентой
|
|
start_index = highlighted_id.find(part)
|
|
if start_index != -1:
|
|
end_index = start_index + len(part)
|
|
highlighted_part = MAGENTA + BOLD + part + RESET
|
|
highlighted_id = highlighted_id[:start_index] + highlighted_part + highlighted_id[end_index:]
|
|
|
|
return highlighted_id
|
|
|
|
def kill_process(process_name):
|
|
"""Убивает процесс по имени."""
|
|
try:
|
|
for proc in psutil.process_iter(['name']):
|
|
if proc.info['name'] == process_name:
|
|
proc.kill()
|
|
except Exception as e:
|
|
pass # Игнорируем ошибки при завершении процесса
|
|
|
|
def generate_profiles(output_dir, anydesk_exe_path, num_ids, timeout_seconds):
|
|
"""Генерирует профили AnyDesk."""
|
|
appdata_dir = os.getenv('APPDATA')
|
|
anydesk_config_dir = os.path.join(appdata_dir, "AnyDesk")
|
|
|
|
# Определяем следующий доступный номер профиля
|
|
existing_profiles = [name for name in os.listdir(output_dir) if name.startswith("AD") and name[2:].isdigit()]
|
|
next_profile_number = max([int(name[2:]) for name in existing_profiles], default=0) + 1
|
|
|
|
# Прогресс-бар
|
|
print("Generating profiles:")
|
|
for i in range(next_profile_number, next_profile_number + num_ids):
|
|
progress = int((i - next_profile_number + 1) / num_ids * 100)
|
|
bar = f"[{'#' * (progress // 2):<50}] {progress}%"
|
|
print(f"\r{bar}", end="")
|
|
|
|
profile_name = f"AD{i}"
|
|
profile_dir = os.path.join(output_dir, profile_name)
|
|
anydesk_subdir = os.path.join(profile_dir, "AnyDesk")
|
|
os.makedirs(anydesk_subdir, exist_ok=True)
|
|
|
|
# Убиваем процесс AnyDesk
|
|
kill_process("AnyDesk.exe")
|
|
|
|
# Запускаем AnyDesk
|
|
subprocess.Popen([anydesk_exe_path], shell=True)
|
|
time.sleep(timeout_seconds)
|
|
|
|
# Копируем конфигурацию с обработкой ошибок
|
|
try:
|
|
if os.path.exists(anydesk_config_dir):
|
|
shutil.copytree(anydesk_config_dir, anydesk_subdir, dirs_exist_ok=True)
|
|
except Exception as e:
|
|
pass
|
|
#print(f"\nError copying files for profile {profile_name}: {e}")
|
|
|
|
# Убиваем процесс AnyDesk снова
|
|
kill_process("AnyDesk.exe")
|
|
if os.path.exists(anydesk_config_dir):
|
|
shutil.rmtree(anydesk_config_dir, ignore_errors=True)
|
|
|
|
print("\nAll profiles generated successfully!")
|
|
|
|
def apply_profile(profiles_dir, profile_name):
|
|
"""Копирует конфигурацию профиля в папку AnyDesk пользователя и запускает AnyDesk."""
|
|
appdata_dir = os.getenv('APPDATA')
|
|
anydesk_config_dir = os.path.join(appdata_dir, "AnyDesk")
|
|
|
|
# Удаляем текущую конфигурацию AnyDesk
|
|
if os.path.exists(anydesk_config_dir):
|
|
shutil.rmtree(anydesk_config_dir, ignore_errors=True)
|
|
|
|
# Находим путь к конфигурации выбранного профиля
|
|
profile_path = os.path.join(profiles_dir, profile_name)
|
|
anydesk_subdir = os.path.join(profile_path, "AnyDesk")
|
|
|
|
if not os.path.exists(anydesk_subdir):
|
|
print(f"Profile '{profile_name}' does not exist or is invalid!")
|
|
return
|
|
|
|
# Копируем конфигурацию профиля в папку AnyDesk
|
|
try:
|
|
shutil.copytree(anydesk_subdir, anydesk_config_dir, dirs_exist_ok=True)
|
|
print(f"Profile '{profile_name}' applied successfully!")
|
|
except Exception as e:
|
|
print(f"Error applying profile '{profile_name}': {e}")
|
|
return
|
|
|
|
# Запускаем AnyDesk
|
|
anydesk_exe_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "AnyDesk.exe")
|
|
if not os.path.exists(anydesk_exe_path):
|
|
print(f"Error: AnyDesk.exe not found at {anydesk_exe_path}")
|
|
return
|
|
|
|
subprocess.Popen([anydesk_exe_path], shell=True)
|
|
print("AnyDesk started with the selected profile.")
|
|
|
|
def main_menu():
|
|
# Определяем директорию для профилей
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
profiles_dir = os.path.join(script_dir, "profiles")
|
|
os.makedirs(profiles_dir, exist_ok=True)
|
|
|
|
# Путь к AnyDesk.exe по умолчанию
|
|
default_anydesk_path = os.path.join(script_dir, "AnyDesk.exe")
|
|
|
|
# Парсим профили один раз для использования в меню
|
|
profiles, beautiful_profiles = parse_profiles(profiles_dir)
|
|
|
|
while True:
|
|
print("\nMain Menu:")
|
|
print("1. Parse Profiles")
|
|
print("2. Generate Profiles")
|
|
print("3. View Beautiful IDs")
|
|
print("4. Get Configuration by ID")
|
|
print("5. Apply Profile to AnyDesk")
|
|
print("6. Exit")
|
|
choice = input("Enter your choice: ")
|
|
|
|
if choice == '1':
|
|
profiles, beautiful_profiles = parse_profiles(profiles_dir)
|
|
print("Profiles parsed successfully!")
|
|
print("Found IDs:")
|
|
for profile_name, profile_data in profiles.items():
|
|
print(f"{profile_name}: {profile_data['id']}")
|
|
|
|
elif choice == '2':
|
|
anydesk_exe_path = input(f"Enter the path to AnyDesk.exe (default: {default_anydesk_path}): ").strip()
|
|
if not anydesk_exe_path:
|
|
anydesk_exe_path = default_anydesk_path # Используем путь по умолчанию
|
|
|
|
num_ids = int(input("Enter the number of IDs to generate: "))
|
|
timeout_seconds = int(input("Enter timeout duration (in seconds): "))
|
|
|
|
generate_profiles(profiles_dir, anydesk_exe_path, num_ids, timeout_seconds)
|
|
print("Profiles generated successfully!")
|
|
|
|
# Обновляем список профилей после генерации
|
|
profiles, beautiful_profiles = parse_profiles(profiles_dir)
|
|
print("Updated Found IDs:")
|
|
for profile_name, profile_data in profiles.items():
|
|
print(f"{profile_name}: {profile_data['id']}")
|
|
|
|
elif choice == '3':
|
|
print("\nBeautiful IDs:")
|
|
if beautiful_profiles:
|
|
for profile_name, data in beautiful_profiles.items():
|
|
id_str = data['id']
|
|
beauty_info = data['beauty_info']
|
|
highlighted_id = highlight_beautiful_id(id_str, beauty_info)
|
|
print(f"{profile_name}: {highlighted_id}")
|
|
else:
|
|
print("No beautiful IDs found.")
|
|
|
|
elif choice == '4':
|
|
user_input = input("Enter ID to get configuration (or 'exit' to cancel): ")
|
|
if user_input.lower() == 'exit':
|
|
continue
|
|
|
|
found = False
|
|
for profile_name, profile_data in profiles.items():
|
|
if profile_data['id'] == user_input:
|
|
print(f"Configuration for profile {profile_name}:")
|
|
config_content = get_file_content(profile_data['config_path'])
|
|
print(config_content)
|
|
found = True
|
|
break
|
|
|
|
if not found:
|
|
print("ID not found.")
|
|
|
|
elif choice == '5':
|
|
profile_name = input("Enter the profile name to apply (e.g., AD1): ")
|
|
apply_profile(profiles_dir, profile_name)
|
|
|
|
elif choice == '6':
|
|
print("Exiting...")
|
|
break
|
|
|
|
else:
|
|
print("Invalid choice. Please try again.")
|
|
|
|
if __name__ == "__main__":
|
|
main_menu() |