Как можно сделать эту программу еще более красивой в визуальном стиле, чтобы все было понятно, приятно глазу и наглядно еще сильнее.

import random
import asyncio
import logging
import sys
import os
from pathlib import Path
from aiohttp_socks import ProxyType
from telethon.errors import UsernameOccupiedError, UsernameInvalidError, UsernamePurchaseAvailableError
from telethon.network.connection.tcpabridged import ConnectionTcpAbridged
from opentele.api import API
from opentele.tl import TelegramClient as OTClient
from telethon.tl.functions.account import UpdateProfileRequest, UpdateUsernameRequest
from telethon.tl.functions.photos import UploadProfilePhotoRequest

import re

Функция для проверки кириллицы в строке
def contains_cyrillic(text: str) -> bool:
return bool(re.search('[а-яёА-ЯЁ]', text))

logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[logging.StreamHandler(sys.stdout)],
)
logger = logging.getLogger("🌟AccountFormatter")

PROXIES_FILE = "proxies.txt"
SESSIONS_DIR = Path("sessions")
AVATARS_DIR = Path("avatars")
FEMALE_NAMES_FILE = "female_names.txt"
FEMALE_SURNAMES_FILE = "female_surnames.txt"

---------------------------------------
def load_names_from_file(filename: str) -> list:
if not os.path.exists(filename):
logger.warning(f"⚠️ Файл не найден: {filename}")
return []
with open(filename, "r", encoding="utf-8") as f:
names = [line.strip() for line in f if line.strip()]
logger.info(f"🟢 Загружено {len(names)} элементов из {filename}")
return names

female_names = load_names_from_file(FEMALE_NAMES_FILE)
female_surnames = load_names_from_file(FEMALE_SURNAMES_FILE)

---------------------------------------
def load_proxies():
proxies = []
try:
with open(PROXIES_FILE, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
parts = line.split(':')
if len(parts) == 4:
proxies.append({
"host": parts[0],
"port": int(parts[1]),
"username": parts[2],
"password": parts[3]
})
logger.info(f"🟢 Загружено прокси: {len(proxies)} шт.")
except Exception as e:
logger.error(f"❌ Ошибка загрузки прокси: {e}")
return proxies

def translit(text: str) -> str:
translit_dict = {
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo',
'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm',
'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
'ф': 'f', 'х': 'h', 'ц': 'ts', 'ч': 'ch', 'ш': 'sh', 'щ': 'sch', 'ъ': '',
'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya'
}
result = []
for char in text.lower():
if char in translit_dict:
result.append(translit_dict[char])
elif char.isalnum():
result.append(char)
return ''.join(result)

async def format_account(session_file: str, api_id: int, api_hash: str, female_names: list, female_surnames: list, proxies: list):
session_stem = Path(session_file).stem
logger.info(f"✨ Начинаем оформление аккаунта: {session_stem}")


if not proxies:
    logger.error(f"❌ Прокси не загружены! Пропускаем аккаунт {session_stem}")
    return False

proxy_conf = random.choice(proxies)
logger.info(f"🔗 Используем прокси {proxy_conf['host']}:{proxy_conf['port']} для {session_stem}")
proxy = (
    ProxyType.SOCKS5,
    proxy_conf["host"],
    proxy_conf["port"],
    True,
    proxy_conf["username"],
    proxy_conf["password"],
)

client = OTClient(
    session=str(session_file),
    api_id=api_id,
    api_hash=api_hash,
    api=API.TelegramDesktop.Generate(),
    connection=ConnectionTcpAbridged,
    proxy=proxy,
    use_ipv6=True
)

try:
    await client.connect()
    logger.info(f"🟢 Клиент подключен: {session_stem}")

    # Задержка перед сменой имени
    await asyncio.sleep(random.uniform(1, 3))

    # Смена имени и фамилии
    # Получаем текущие данные профиля
    me = await client.get_me()
    current_first_name = me.first_name or ""
    current_last_name = me.last_name or ""
    current_username = me.username or ""

    # Проверяем, нужно ли менять имя (если нет кириллицы - меняем, иначе - пропускаем)
    if contains_cyrillic(current_first_name):
        logger.info(f"ℹ️ [{session_stem}] Имя '{current_first_name}' уже на русском, пропускаем смену имени.")
        new_first_name = current_first_name
        new_last_name = current_last_name
    else:
        new_first_name = random.choice(female_names) if female_names else "Анастасия"
        new_last_name = random.choice(female_surnames) if female_surnames else "Иванова"

        await asyncio.sleep(random.uniform(1, 3))
        await client(UpdateProfileRequest(first_name=new_first_name, last_name=new_last_name))
        logger.info(f"✏️  [{session_stem}] Обновлен профиль на: {new_first_name} {new_last_name}")

    # Задержка перед установкой аватарки
    await asyncio.sleep(random.uniform(1, 3))

    # Проверяем, есть ли уже аватарка
    profile_photos = await client.get_profile_photos('me')
    if profile_photos.total > 0:
        logger.info(f"ℹ️ [{session_stem}] Аватарка уже установлена, пропускаем установку.")
    else:
        await asyncio.sleep(random.uniform(1, 3))
        avatar_files = [f for f in AVATARS_DIR.iterdir() if
                        f.is_file() and f.suffix.lower() in {'.jpg', '.jpeg', '.png'}]
        if avatar_files:
            avatar_path = random.choice(avatar_files)
            try:
                upfile = await client.upload_file(str(avatar_path))
                await client(UploadProfilePhotoRequest(file=upfile))
                logger.info(f"🖼 [{session_stem}] Аватарка установлена из: {avatar_path.name}")
            except Exception as e:
                logger.warning(f"⚠️ [{session_stem}] Ошибка установки аватарки: {e}")
        else:
            logger.warning(f"⚠️ [{session_stem}] Отсутствуют файлы в {AVATARS_DIR}")

    # Задержка перед установкой username
    await asyncio.sleep(random.uniform(1, 3))

    # Проверяем, есть ли username
    if current_username:
        logger.info(f"ℹ️ [{session_stem}] Username уже установлен: {current_username}, пропускаем смену username.")
        username_set = True
    else:
        await asyncio.sleep(random.uniform(1, 3))
        # Формируем username из имени и фамилии (которые точно есть после возможного обновления)
        base_username = translit(f"{new_first_name}_{new_last_name}".replace(" ", "_")).lower()
        base_username = ''.join(c for c in base_username if c.isalnum() or c == '_')

        max_attempts = 7
        username_set = False

        for attempt in range(max_attempts):
            if attempt == 0:
                username = base_username
            else:
                username = f"{base_username}_{random.randint(1, 9999)}"
            try:
                await client(UpdateUsernameRequest(username))
                logger.info(f"✅ [{session_stem}] Username установлен: {username}")
                username_set = True
                break
            except (UsernameOccupiedError, UsernameInvalidError, UsernamePurchaseAvailableError) as e:
                logger.info(
                    f"❌ [{session_stem}] Username {username} занят/невозможен для установки (попытка {attempt + 1}/{max_attempts}): {e}")
                await asyncio.sleep(2 + random.uniform(0.5, 1.5))

        if not username_set:
            username = f"user_{random.randint(100000, 999999)}"
            await asyncio.sleep(random.uniform(1, 2))
            try:
                await client(UpdateUsernameRequest(username))
                logger.info(f"✅ [{session_stem}] Установлен случайный username: {username}")
                username_set = True
            except (UsernameOccupiedError, UsernameInvalidError, UsernamePurchaseAvailableError) as e:
                logger.error(
                    f"❌ [{session_stem}] Не удалось установить username после {max_attempts + 1} попыток: {e}")

    return username_set

except Exception as e:
    logger.error(f"🔥 [{session_stem}] Ошибка в оформлении аккаунта: {e}", exc_info=True)
    return False

finally:
    await client.disconnect()
    logger.info(f"🔌 Клиент отключен: {session_stem}")
async def main():
logger.info(f"🚀 Запуск программы. Сессий для оформления: {len(list(SESSIONS_DIR.glob('*.session'))):,}")


proxies = load_proxies()
if not proxies:
    logger.error("❌ Программа остановлена — отсутствуют прокси")
    return

sessions = list(SESSIONS_DIR.glob('*.session'))
if not sessions:
    logger.error("❌ Сессии не найдены в папке sessions")
    return

total = len(sessions)
success_count = 0
failure_count = 0

# Используем одинаковые api_id и api_hash
api_id = 2040
api_hash = "b18441a1ff607e10a989891a5462e627"

# Создаём задачи на все сессии
tasks = []
for session_file in sessions:
    tasks.append(format_account(str(session_file), api_id, api_hash, female_names, female_surnames, proxies))

results = await asyncio.gather(*tasks, return_exceptions=True)

for result in results:
    if isinstance(result, Exception):
        failure_count += 1
    else:
        if result:
            success_count += 1
        else:
            failure_count += 1

logger.info(f"\n🎯 Результаты оформления аккаунтов:\n"
            f"   🟢 Успешно: {success_count}\n"
            f"   🔴 Ошибок: {failure_count}\n"
            f"   📁 Всего обработано: {total}\n")
logger.info("✅ Программа завершена.")
if name == "main":
asyncio.run(main())

Например, использовать rich