diff --git a/bot/modules/message_handler/callbacks.py b/bot/modules/message_handler/callbacks.py index 2fd284e..d26826c 100644 --- a/bot/modules/message_handler/callbacks.py +++ b/bot/modules/message_handler/callbacks.py @@ -66,8 +66,8 @@ async def callback_handler(client: Client, callback_query: CallbackQuery): "\n\n" "👑 **Команды для администраторов:**\n" "• `/adduser ` - Добавить нового пользователя\n" - "• `/removeuser ` - Удалить пользователя\n" "• `/blockuser ` - Заблокировать пользователя\n" + "• `/unblockuser ` - Разблокировать пользователя\n" "• `/listusers` - Посмотреть список всех пользователей\n\n" "💼 **Управление администраторами:**\n" "• `/addadmin ` - Назначить администратора\n" @@ -161,8 +161,8 @@ async def callback_handler(client: Client, callback_query: CallbackQuery): "👥 **Управление пользователями:**\n\n" "**Управление пользователями:**\n" "• /adduser - Добавить пользователя\n" - "• /removeuser - Удалить пользователя\n" "• /blockuser - Заблокировать пользователя\n" + "• /unblockuser - Разблокировать пользователя\n" "• /listusers - Список всех пользователей\n\n" "**Управление администраторами:**\n" "• /addadmin - Назначить администратора\n" @@ -176,8 +176,8 @@ async def callback_handler(client: Client, callback_query: CallbackQuery): "👥 **Управление пользователями:**\n\n" "**Доступные команды:**\n" "• /adduser - Добавить пользователя\n" - "• /removeuser - Удалить пользователя\n" "• /blockuser - Заблокировать пользователя\n" + "• /unblockuser - Разблокировать пользователя\n" "• /listusers - Список всех пользователей\n\n" "_Управление через веб-интерфейс будет доступно позже_" ) diff --git a/bot/modules/message_handler/commands.py b/bot/modules/message_handler/commands.py index b4bb817..75fa284 100644 --- a/bot/modules/message_handler/commands.py +++ b/bot/modules/message_handler/commands.py @@ -7,7 +7,7 @@ from pyrogram.filters import command from pyrogram.handlers import MessageHandler from bot.modules.access_control.permissions import require_permission, Permission from bot.modules.access_control.user_manager import ( - add_user, remove_user, block_user, unblock_user, + add_user, block_user, unblock_user, add_admin, remove_admin ) from bot.modules.message_handler.filters import is_url_message @@ -114,8 +114,8 @@ async def help_command(client: Client, message: Message): "\n\n" "👑 **Команды для администраторов:**\n" "• `/adduser ` - Добавить нового пользователя\n" - "• `/removeuser ` - Удалить пользователя\n" "• `/blockuser ` - Заблокировать пользователя\n" + "• `/unblockuser ` - Разблокировать пользователя\n" "• `/listusers` - Посмотреть список всех пользователей\n\n" "💼 **Управление администраторами:**\n" "• `/addadmin ` - Назначить администратора\n" @@ -253,39 +253,6 @@ async def adduser_command(client: Client, message: Message): await message.reply(f"❌ Произошла ошибка: {str(e)}") -async def removeuser_command(client: Client, message: Message): - """Remove user""" - from bot.modules.access_control.auth import is_admin - from bot.utils.helpers import resolve_user_identifier - - # Check access permissions - if not await is_admin(message.from_user.id): - await message.reply("❌ Эта команда доступна только администраторам") - return - - if not message.command or len(message.command) < 2: - await message.reply("❌ Использование: /removeuser ") - return - - identifier = message.command[1] - - # Resolve identifier (user_id or username) - user_id, error_message = await resolve_user_identifier(identifier) - if not user_id: - await message.reply(f"❌ {error_message}") - return - - try: - success, message_text = await remove_user(user_id) - if success: - await message.reply(f"✅ {message_text}") - else: - await message.reply(f"❌ {message_text}") - except Exception as e: - logger.error(f"Error in removeuser_command: {e}", exc_info=True) - await message.reply(f"❌ Произошла ошибка: {str(e)}") - - async def blockuser_command(client: Client, message: Message): """Block user""" from bot.modules.access_control.auth import is_admin @@ -711,12 +678,16 @@ async def url_handler(client: Client, message: Message): if not task_executor._running: await task_executor.start() - await message.reply( - f"✅ Ссылка получена!\n\n" + # Send initial status message and save message_id for updates + from bot.modules.task_scheduler.executor import set_task_message + status_message = await message.reply( + f"📥 **Загрузка начата**\n\n" f"🔗 {url}\n\n" - f"📥 Загрузка добавлена в очередь. Я начну загрузку в ближайшее время.\n" - f"⏳ Вы получите уведомление о статусе загрузки." + f"📊 Прогресс: **0%**\n" + f"⏳ Ожидание начала загрузки..." ) + # Save message_id for task updates + set_task_message(task_id, status_message.id) def register_commands(app: Client): @@ -730,7 +701,6 @@ def register_commands(app: Client): # User management commands (admin only) app.add_handler(MessageHandler(adduser_command, filters=command("adduser"))) - app.add_handler(MessageHandler(removeuser_command, filters=command("removeuser"))) app.add_handler(MessageHandler(blockuser_command, filters=command("blockuser"))) app.add_handler(MessageHandler(unblockuser_command, filters=command("unblockuser"))) app.add_handler(MessageHandler(listusers_command, filters=command("listusers"))) diff --git a/bot/modules/task_scheduler/executor.py b/bot/modules/task_scheduler/executor.py index 10fc3cf..8050735 100644 --- a/bot/modules/task_scheduler/executor.py +++ b/bot/modules/task_scheduler/executor.py @@ -339,10 +339,10 @@ class TaskExecutor: try: from pyrogram.errors import MessageNotModified status_text = ( - f"📥 **Downloading file**\n\n" + f"📥 **Загрузка файла**\n\n" f"🔗 {task.url[:50]}...\n" - f"📊 Progress: **{percent}%**\n" - f"⏳ Please wait..." + f"📊 Прогресс: **{percent}%**\n" + f"⏳ Пожалуйста, подождите..." ) try: await app_client.edit_message_text( @@ -358,16 +358,16 @@ class TaskExecutor: # Save reference to event loop for use in progress hook progress_loop = asyncio.get_event_loop() - # Send one message about download start (will be updated) + # Check if message already exists (from url_handler), if not - create one app_client = get_app_client() - status_message = None - if app_client: + message_id = get_task_message(task.id) + if not message_id and app_client: try: status_text = ( - f"📥 **Downloading file**\n\n" + f"📥 **Загрузка начата**\n\n" f"🔗 {task.url[:50]}...\n" - f"📊 Progress: **0%**\n" - f"⏳ Please wait..." + f"📊 Прогресс: **0%**\n" + f"⏳ Ожидание начала загрузки..." ) status_message = await app_client.send_message( task.user_id, @@ -548,17 +548,120 @@ class TaskExecutor: caption = f"📥 **{result.get('title', 'File')}**" if result.get('duration'): from bot.utils.helpers import format_duration - caption += f"\n⏱ Duration: {format_duration(result['duration'])}" + caption += f"\n⏱ Длительность: {format_duration(result['duration'])}" - # Send file - logger.info(f"Calling send_file_to_user for file: {result['file_path']}") - success = await send_file_to_user( - client=app_client, - chat_id=task.user_id, - file_path=result['file_path'], - caption=caption, - thumbnail=result.get('thumbnail') - ) + # Replace status message with video/file using edit_message_media + message_id = get_task_message(task.id) + success = False + + if message_id: + try: + from pyrogram.types import InputMediaVideo, InputMediaPhoto, InputMediaAudio, InputMediaDocument + from pathlib import Path + + file = Path(result['file_path']) + file_ext = file.suffix.lower() + + # Determine media type and create appropriate InputMedia + if file_ext in ['.mp4', '.avi', '.mov', '.mkv', '.webm']: + # Video - prepare thumbnail + thumbnail_path = result.get('thumbnail') + if thumbnail_path and Path(thumbnail_path).exists(): + media = InputMediaVideo( + media=str(file), + caption=caption, + thumb=str(thumbnail_path) + ) + else: + # Try to generate thumbnail if not exists + from bot.utils.file_processor import generate_thumbnail + thumbnail_path_temp = f"downloads/thumb_{file.stem}.jpg" + if await generate_thumbnail(str(file), thumbnail_path_temp): + media = InputMediaVideo( + media=str(file), + caption=caption, + thumb=thumbnail_path_temp + ) + else: + media = InputMediaVideo( + media=str(file), + caption=caption + ) + elif file_ext in ['.jpg', '.jpeg', '.png', '.gif', '.webp']: + # Image + media = InputMediaPhoto( + media=str(file), + caption=caption + ) + elif file_ext in ['.mp3', '.wav', '.ogg', '.m4a', '.flac']: + # Audio + thumbnail_path = result.get('thumbnail') + if thumbnail_path and Path(thumbnail_path).exists(): + media = InputMediaAudio( + media=str(file), + caption=caption, + thumb=str(thumbnail_path) + ) + else: + media = InputMediaAudio( + media=str(file), + caption=caption + ) + else: + # Document + thumbnail_path = result.get('thumbnail') + if thumbnail_path and Path(thumbnail_path).exists(): + media = InputMediaDocument( + media=str(file), + caption=caption, + thumb=str(thumbnail_path) + ) + else: + media = InputMediaDocument( + media=str(file), + caption=caption + ) + + # Replace message with media + await app_client.edit_message_media( + chat_id=task.user_id, + message_id=message_id, + media=media + ) + logger.info(f"Replaced status message with media for task {task.id}") + success = True + except Exception as e: + # If edit_message_media fails, fallback to sending file normally + logger.warning(f"Failed to replace message with media for task {task.id}: {e}, sending file normally") + try: + success = await send_file_to_user( + client=app_client, + chat_id=task.user_id, + file_path=result['file_path'], + caption=caption, + thumbnail=result.get('thumbnail') + ) + # Delete old status message if file sent successfully + if success and message_id: + try: + await app_client.delete_messages( + chat_id=task.user_id, + message_ids=message_id + ) + except Exception as delete_error: + logger.debug(f"Failed to delete old message: {delete_error}") + except Exception as send_error: + logger.error(f"Failed to send file as fallback: {send_error}") + else: + # No message_id, send file normally + logger.info(f"No message_id for task {task.id}, sending file normally") + success = await send_file_to_user( + client=app_client, + chat_id=task.user_id, + file_path=result['file_path'], + caption=caption, + thumbnail=result.get('thumbnail') + ) logger.info(f"File sending result: success={success}") @@ -567,17 +670,6 @@ class TaskExecutor: await delete_file(result['file_path']) await task_queue.update_task_status(task.id, TaskStatus.COMPLETED, progress=100) task_queue.clear_cancel_event(task.id) - - # Delete download message (file already sent) - message_id = get_task_message(task.id) - if message_id: - try: - await app_client.delete_messages( - chat_id=task.user_id, - message_ids=message_id - ) - except Exception as e: - logger.debug(f"Failed to delete download message for task {task.id}: {e}") clear_task_message(task.id) else: error_msg = "Failed to send file"