Files
pyrogram-bridge/telegram_client.py
T

99 lines
3.9 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: disable=broad-exception-raised, raise-missing-from, too-many-arguments, redefined-outer-name
# pylint: disable=multiple-statements, logging-fstring-interpolation, trailing-whitespace, line-too-long
# pylint: disable=broad-exception-caught, missing-function-docstring, missing-class-docstring
# pylint: disable=f-string-without-interpolation
# pylance: disable=reportMissingImports, reportMissingModuleSource
import logging
import os
import asyncio
import sys
import signal
import uvloop
import time
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
from pyrogram import Client
from pyrogram.handlers import DisconnectHandler
from config import get_settings
logger = logging.getLogger(__name__)
settings = get_settings()
class TelegramClient:
def __init__(self):
self._ensure_session_directory()
self.client = Client(
name="pyro_bridge",
api_id=settings["tg_api_id"],
api_hash=settings["tg_api_hash"],
workdir=settings["session_path"],
)
self.disconnect_count = 0
self.max_disconnects = 3
self._setup_connection_handlers()
def _ensure_session_directory(self):
try:
os.makedirs(settings["session_path"], exist_ok=True)
logger.debug(f'Session directory created/verified: {settings["session_path"]}')
except Exception as e:
logger.error(f'Failed to create session directory {settings["session_path"]}: {str(e)}')
raise
def _setup_connection_handlers(self):
"""Sets up connection/disconnection handlers"""
self.client.add_handler(DisconnectHandler(self._on_disconnect))
logger.info("connection_handlers: connection handlers set up")
async def _on_disconnect(self, _client):
"""Handles disconnection from Telegram servers"""
self.disconnect_count += 1
logger.warning(f"connection_handler: connection lost (#{self.disconnect_count})")
if self.disconnect_count >= self.max_disconnects:
logger.critical(f"connection_handler: reached disconnect limit ({self.max_disconnects})")
self._restart_app()
async def start(self):
try:
if not self.client.is_connected:
await self.client.start()
logger.info("Telegram client connected successfully")
# Reset disconnect counter on successful connection
self.disconnect_count = 0
logger.info("connection_handler: connection established")
except Exception as e:
logger.error(f"Failed to start Telegram client: {str(e)}")
raise
def _restart_app(self):
"""Restarts the application"""
logger.warning("connection_handler: restarting application")
try:
# Properly shutdown client before restart
loop = asyncio.get_event_loop()
if loop.is_running():
loop.create_task(self.stop())
# Добавляем задержку, чтобы предыдущий процесс успел завершиться
# и освободить порт и другие ресурсы
logger.info("connection_handler: waiting for resources to be freed before restart")
time.sleep(3)
# Use os.execv to restart the process with the same arguments
os.execv(sys.executable, [sys.executable] + sys.argv)
except Exception as e:
logger.error(f"connection_handler: error during restart: {str(e)}")
# Emergency termination in case of restart failure
os.kill(os.getpid(), signal.SIGTERM)
async def stop(self):
if self.client.is_connected:
await self.client.stop()
logger.info("Telegram client disconnected")