146 lines
4.2 KiB
Python
146 lines
4.2 KiB
Python
"""
|
|
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...")
|
|
|
|
# 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)
|
|
|