Files

233 lines
9.2 KiB
Python

import logging
from dataclasses import dataclass
from pathlib import Path
from phonenumbers import parse, geocoder
from typing import List, Optional
from telethon.types import User, Chat, Channel
from telethon.tl.functions.payments import GetStarsStatusRequest
from telethon.tl.functions.contacts import GetContactsRequest
from opentele2.exception import OpenTeleException
from modules.tdata import TDATA
logger = logging.getLogger(__name__)
class SessionInvalid(Exception):
pass
# Unified Result class
@dataclass
class Result:
me: Optional[User] = None
stars: Optional[int] = None
country: Optional[str] = None
spamblock: Optional[bool] = None
contacts: Optional[List[User]] = None
chats: Optional[List[Chat]] = None
channels: Optional[List[Channel]] = None
admin_channels: Optional[List[Channel]] = None
class Checker:
def __init__(self, path: Path, temp_path: Path, lang_code: str = "en"):
self.path = path
self.temp_path = temp_path
self.lang_code = lang_code
self.client = None
logger.debug(f"Создание экземпляра Checker для пути: {path}")
try:
self.desktop = TDATA(path=self.path, temp_path=self.temp_path)
logger.debug("TDATA успешно инициализирована")
except Exception as e:
logger.error(f"Ошибка инициализации TDATA: {e}")
self.desktop = None
async def __aenter__(self):
logger.debug("Вход в контекстный менеджер Checker")
if self.desktop is None:
logger.error("TDATA не инициализирована")
raise SessionInvalid()
try:
await self.__ensure_client(lang_code=self.lang_code)
except (OpenTeleException, Exception) as e:
logger.error(f"Не удалось инициализировать клиент: {e}")
raise SessionInvalid()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
logger.debug("Выход из контекстного менеджера Checker")
if self.client:
try:
await self.client.disconnect()
logger.debug("Telethon клиент отключен")
except Exception as e:
logger.warning(f"Ошибка при отключении клиента: {e}")
async def __ensure_client(self, lang_code: str = "en"):
if self.client is None:
logger.debug(f"Конвертация TDATA в Telethon клиент с языком '{lang_code}'")
self.client = await self.desktop.convert(lang_code=lang_code)
logger.debug("Telethon клиент успешно создан")
async def check_stars(self, me: User) -> int:
logger.debug("Запрос баланса звезд")
try:
stars_status = await self.client(GetStarsStatusRequest(peer=me))
stars = stars_status.balance.amount
logger.debug(f"Баланс звезд: {stars}")
return stars
except Exception as e:
logger.warning(f"Не удалось получить баланс звезд: {e}")
return 0
async def check_country(self, me: User) -> str:
logger.debug(f"Определение страны для номера +{me.phone}")
try:
phone_parse = parse(str(f"+{me.phone}"))
country = geocoder.description_for_number(phone_parse, "en")
logger.debug(f"Страна определена: {country}")
return country
except Exception as e:
logger.warning(f"Не удалось определить страну: {e}")
return "N/A"
async def check_contacts(self) -> List[User]:
logger.debug("Запрос списка контактов")
try:
result = await self.client(GetContactsRequest(hash=0))
contacts = result.users
logger.debug(f"Получено контактов: {len(contacts)}")
return contacts
except Exception as e:
logger.warning(f"Не удалось получить контакты: {e}")
return []
async def check_chats(self) -> List[Chat]:
logger.debug("Запрос всех диалогов")
try:
chats = []
async for dialog in self.client.iter_dialogs():
chats.append(dialog.entity)
logger.debug(f"Получено диалогов: {len(chats)}")
return chats
except Exception as e:
logger.warning(f"Не удалось получить чаты: {e}")
return []
async def check_channels(self, chats: List[Chat]) -> List[Channel]:
logger.debug(f"Фильтрация каналов из {len(chats)} чатов")
try:
channels = [chat for chat in chats if isinstance(chat, Channel)]
logger.debug(f"Найдено каналов: {len(channels)}")
return channels
except Exception as e:
logger.warning(f"Не удалось отфильтровать каналы: {e}")
return []
async def check_admin_channels(self, channels: List[Channel]) -> List[Channel]:
logger.debug("Проверка прав администратора в каналах")
try:
admin_channels = []
checked = 0
for channel in channels:
checked += 1
try:
permissions = await self.client.get_permissions(channel, "me")
if permissions.is_admin or permissions.is_creator:
admin_channels.append(channel)
logger.debug(f"Найден админ канал: {channel.title}")
except Exception as e:
logger.debug(f"Не удалось проверить права для канала: {e}")
logger.debug(
f"Проверено каналов: {checked}, найдено админских: {len(admin_channels)}"
)
return admin_channels
except Exception as e:
logger.warning(f"Не удалось проверить админские права: {e}")
return []
async def check_spamblock(self) -> bool:
logger.debug("Проверка spamblock через @SpamBot")
try:
await self.client.send_message("@SpamBot", "/start")
logger.debug("Отправлено сообщение /start в @SpamBot")
# Ждем ответ от SpamBot
import asyncio
await asyncio.sleep(2)
# Получаем последние сообщения от SpamBot
messages = await self.client.get_messages("@SpamBot", limit=1)
if messages and len(messages) > 0:
response_text = messages[0].message
logger.debug(f"Ответ от SpamBot: {response_text[:50]}...")
# Проверяем, содержит ли ответ текст об отсутствии ограничений
if "свободен от каких-либо ограничений" in response_text.lower():
logger.debug("Аккаунт не имеет spamblock")
return False
else:
logger.debug("Аккаунт имеет spamblock")
return True
else:
logger.warning("Не удалось получить ответ от SpamBot")
return None
except Exception as e:
logger.warning(f"Не удалось проверить spamblock: {e}")
return None
async def check_all(self) -> Result:
logger.debug("Начало полной проверки аккаунта")
try:
me = await self.client.get_me()
if not me:
logger.error("Не удалось получить информацию о пользователе")
raise SessionInvalid()
logger.debug(f"Получен пользователь: {me.first_name} (+{me.phone})")
stars = await self.check_stars(me=me)
country = await self.check_country(me=me)
spamblock = await self.check_spamblock()
contacts = await self.check_contacts()
chats = await self.check_chats()
channels = await self.check_channels(chats=chats) if chats else []
admin_channels = (
await self.check_admin_channels(channels=channels) if channels else []
)
logger.debug("Полная проверка завершена успешно")
return Result(
me=me,
stars=stars,
country=country,
spamblock=spamblock,
contacts=contacts,
chats=chats,
channels=channels,
admin_channels=admin_channels,
)
except Exception as e:
logger.error(f"Критическая ошибка при проверке: {e}")
raise SessionInvalid()