Files
tg_loader/main.py
2025-12-04 00:33:20 +03:00

171 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Unified entry point for bot and web interface
"""
import asyncio
import logging
from pyrogram import Client
from shared.config import settings
from shared.database.session import init_db
from bot.modules.message_handler.commands import register_commands
from bot.modules.message_handler.callbacks import register_callbacks
from bot.modules.access_control.middleware import setup_middleware
from bot.modules.task_scheduler.executor import task_executor, set_app_client
from bot.modules.task_scheduler.queue import task_queue
from bot.utils.logger import setup_logger
from web.app import app as web_app
import uvicorn
# Setup logging
setup_logger()
logger = logging.getLogger(__name__)
async def run_web_server():
"""Run web server in the same event loop"""
config = uvicorn.Config(
app=web_app,
host=settings.WEB_HOST,
port=settings.WEB_PORT,
log_level="info",
loop="asyncio"
)
server = uvicorn.Server(config)
logger.info(f"Starting web server on {settings.WEB_HOST}:{settings.WEB_PORT}")
await server.serve()
async def run_bot():
"""Run Telegram bot"""
logger.info("Starting Telegram bot...")
# Check cookies file if configured
from shared.config import settings
if settings.COOKIES_FILE:
from pathlib import Path
import os
cookies_paths = [
Path(settings.COOKIES_FILE),
Path(__file__).parent / settings.COOKIES_FILE,
Path(os.getcwd()) / settings.COOKIES_FILE,
]
cookies_found = False
for path in cookies_paths:
if path.exists() and path.is_file():
logger.info(f"✅ Cookies file found: {path} (configured as: {settings.COOKIES_FILE})")
cookies_found = True
break
if not cookies_found:
logger.warning(
f"⚠️ Cookies file not found: {settings.COOKIES_FILE}. "
f"Searched in: {[str(p) for p in cookies_paths]}. "
f"Instagram downloads may fail without cookies."
)
else:
logger.info(" No cookies file configured (COOKIES_FILE not set)")
# Initialize database
await init_db()
logger.info("Database initialized")
# Initialize task queue
await task_queue.initialize()
logger.info("Task queue initialized")
# Create Pyrogram client
app = Client(
"tgloader_bot",
api_id=settings.TELEGRAM_API_ID,
api_hash=settings.TELEGRAM_API_HASH,
bot_token=settings.BOT_TOKEN,
)
# Setup middleware for access control
setup_middleware(app)
# Set client for task executor
set_app_client(app)
# Register handlers
register_commands(app)
register_callbacks(app)
logger.info("Bot ready")
# Start bot
await app.start()
logger.info(f"Bot started. Owner ID: {settings.OWNER_ID}")
# Start task executor AFTER bot is started
await task_executor.start()
logger.info("Task executor started")
# Start background task for cleaning old files
from bot.utils.file_cleanup import cleanup_files_periodically
cleanup_task = asyncio.create_task(cleanup_files_periodically())
logger.info("File cleanup task started")
# Start background task for updating user information
from bot.utils.user_info_updater import update_users_without_info_periodically
user_info_task = asyncio.create_task(update_users_without_info_periodically())
logger.info("User info update task started")
return app
async def main():
"""Main startup function"""
logger.info("=" * 50)
logger.info("Starting TGLoader (Bot + Web Interface)")
logger.info("=" * 50)
# Start bot
bot_app = await run_bot()
# Start web server in the same event loop
web_task = asyncio.create_task(run_web_server())
logger.info("Web server started in the same event loop")
# Wait for completion (running in parallel)
try:
# Wait for web server to complete (runs indefinitely)
await web_task
except KeyboardInterrupt:
logger.info("Received stop signal (Ctrl+C)")
except asyncio.CancelledError:
logger.info("Received cancellation signal")
finally:
logger.info("Starting graceful shutdown...")
# Stop web server
web_task.cancel()
try:
await web_task
except asyncio.CancelledError:
pass
# Stop task executor
try:
await task_executor.stop()
logger.info("Task executor stopped")
except Exception as e:
logger.error(f"Error stopping executor: {e}")
# Stop bot
try:
await bot_app.stop()
logger.info("Bot stopped")
except Exception as e:
logger.error(f"Error stopping bot: {e}")
logger.info("Application terminated")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
logger.info("Получен сигнал остановки (KeyboardInterrupt)")
except Exception as e:
logger.error(f"Критическая ошибка: {e}", exc_info=True)