init commit

This commit is contained in:
2025-12-18 05:55:32 +09:00
commit a6817e487e
72 changed files with 13847 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
import logging
from typing import List, Optional, Dict
from pyrogram import Client
from pyrogram.types import Message, ChatMember
from pyrogram.errors import (
FloodWait, UserDeactivated, ChatAdminRequired,
PeerIdInvalid, ChannelInvalid, UserNotParticipant
)
from app.settings import Config
logger = logging.getLogger(__name__)
class PyrogramClientManager:
"""Менеджер для работы с Pyrogram клиентом"""
def __init__(self):
self.client: Optional[Client] = None
self.is_initialized = False
async def initialize(self) -> bool:
"""Инициализировать Pyrogram клиент"""
try:
if not Config.USE_PYROGRAM:
logger.warning("Pyrogram отключен в конфигурации")
return False
if not (Config.PYROGRAM_API_ID and Config.PYROGRAM_API_HASH):
logger.error("PYROGRAM_API_ID или PYROGRAM_API_HASH не установлены")
return False
self.client = Client(
name="tg_autoposter",
api_id=Config.PYROGRAM_API_ID,
api_hash=Config.PYROGRAM_API_HASH,
phone_number=Config.PYROGRAM_PHONE
)
await self.client.start()
self.is_initialized = True
me = await self.client.get_me()
logger.info(f"Pyrogram клиент инициализирован: {me.first_name}")
return True
except Exception as e:
logger.error(f"Ошибка при инициализации Pyrogram: {e}")
return False
async def shutdown(self):
"""Остановить Pyrogram клиент"""
if self.client and self.is_initialized:
try:
await self.client.stop()
self.is_initialized = False
logger.info("Pyrogram клиент остановлен")
except Exception as e:
logger.error(f"Ошибка при остановке Pyrogram: {e}")
async def send_message(self, chat_id: int, text: str,
parse_mode: str = "html",
disable_web_page_preview: bool = True) -> Optional[Message]:
"""Отправить сообщение в чат"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return None
try:
message = await self.client.send_message(
chat_id=chat_id,
text=text,
parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview
)
logger.info(f"Сообщение отправлено в чат {chat_id} (клиент)")
return message
except FloodWait as e:
logger.warning(f"FloodWait: нужно ждать {e.value} секунд")
raise
except (ChatAdminRequired, UserNotParticipant):
logger.error(f"Клиент не администратор или не участник чата {chat_id}")
return None
except PeerIdInvalid:
logger.error(f"Неверный ID чата: {chat_id}")
return None
except Exception as e:
logger.error(f"Ошибка при отправке сообщения: {e}")
return None
async def get_chat_members(self, chat_id: int, limit: int = None) -> List[ChatMember]:
"""Получить список участников чата"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return []
try:
members = []
async for member in self.client.get_chat_members(chat_id):
members.append(member)
if limit and len(members) >= limit:
break
logger.info(f"Получено {len(members)} участников из чата {chat_id}")
return members
except (ChatAdminRequired, UserNotParticipant):
logger.error(f"Нет прав получить участников чата {chat_id}")
return []
except Exception as e:
logger.error(f"Ошибка при получении участников: {e}")
return []
async def get_chat_info(self, chat_id: int) -> Optional[Dict]:
"""Получить информацию о чате"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return None
try:
chat = await self.client.get_chat(chat_id)
return {
'id': chat.id,
'title': chat.title,
'description': getattr(chat, 'description', None),
'members_count': getattr(chat, 'members_count', None),
'is_supergroup': chat.is_supergroup,
'linked_chat': getattr(chat, 'linked_chat_id', None)
}
except Exception as e:
logger.error(f"Ошибка при получении информации о чате {chat_id}: {e}")
return None
async def join_chat(self, chat_link: str) -> Optional[int]:
"""Присоединиться к чату по ссылке"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return None
try:
chat = await self.client.join_chat(chat_link)
logger.info(f"Присоединился к чату: {chat.id}")
return chat.id
except Exception as e:
logger.error(f"Ошибка при присоединении к чату: {e}")
return None
async def leave_chat(self, chat_id: int) -> bool:
"""Покинуть чат"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return False
try:
await self.client.leave_chat(chat_id)
logger.info(f"Покинул чат: {chat_id}")
return True
except Exception as e:
logger.error(f"Ошибка при выходе из чата: {e}")
return False
async def edit_message(self, chat_id: int, message_id: int, text: str) -> Optional[Message]:
"""Отредактировать сообщение"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return None
try:
message = await self.client.edit_message_text(
chat_id=chat_id,
message_id=message_id,
text=text,
parse_mode="html"
)
logger.info(f"Сообщение отредактировано: {chat_id}/{message_id}")
return message
except Exception as e:
logger.error(f"Ошибка при редактировании сообщения: {e}")
return None
async def delete_message(self, chat_id: int, message_id: int) -> bool:
"""Удалить сообщение"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return False
try:
await self.client.delete_messages(chat_id, message_id)
logger.info(f"Сообщение удалено: {chat_id}/{message_id}")
return True
except Exception as e:
logger.error(f"Ошибка при удалении сообщения: {e}")
return False
async def search_messages(self, chat_id: int, query: str, limit: int = 100) -> List[Message]:
"""Искать сообщения в чате"""
if not self.is_initialized:
logger.error("Pyrogram клиент не инициализирован")
return []
try:
messages = []
async for message in self.client.search_messages(chat_id, query=query, limit=limit):
messages.append(message)
logger.info(f"Найдено {len(messages)} сообщений по запросу '{query}'")
return messages
except Exception as e:
logger.error(f"Ошибка при поиске сообщений: {e}")
return []
def is_connected(self) -> bool:
"""Проверить, подключен ли клиент"""
return self.is_initialized and self.client is not None
# Глобальный экземпляр менеджера
pyrogram_manager = PyrogramClientManager()