init commit
This commit is contained in:
227
app/handlers/pyrogram_client.py
Normal file
227
app/handlers/pyrogram_client.py
Normal 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()
|
||||
Reference in New Issue
Block a user