Add download video by link

This commit is contained in:
2025-12-05 21:57:25 +03:00
parent 97c85572e9
commit 5c280a4d3a
3 changed files with 301 additions and 0 deletions

View File

@@ -212,6 +212,124 @@ async def callback_handler(client: Client, callback_query: CallbackQuery):
await callback_query.edit_message_text(stats_text, reply_markup=keyboard)
await callback_query.answer()
elif data.startswith("video_select:"):
# Handle video selection from webpage
video_url = data.replace("video_select:", "", 1)
# Create task for selected video
try:
from bot.modules.task_scheduler.queue import task_queue, Task, TaskStatus
from bot.modules.task_scheduler.executor import task_executor, set_app_client
from bot.utils.helpers import generate_unique_task_id
from shared.database.models import Task as DBTask
from shared.database.session import get_async_session_local
from shared.database.user_helpers import ensure_user_exists
from datetime import datetime
from sqlalchemy.exc import IntegrityError
from bot.modules.task_scheduler.executor import set_task_message
user_id = callback_query.from_user.id
# Check concurrent tasks count
from bot.config import settings
active_tasks_count = await task_queue.get_user_active_tasks_count(user_id)
if active_tasks_count >= settings.MAX_CONCURRENT_TASKS:
await callback_query.answer(
f"❌ Превышен лимит одновременных задач ({settings.MAX_CONCURRENT_TASKS})",
show_alert=True
)
return
# Generate task_id
task_id = generate_unique_task_id()
existing_task = await task_queue.get_task_by_id(task_id)
max_retries = 10
retries = 0
while existing_task and retries < max_retries:
task_id = generate_unique_task_id()
existing_task = await task_queue.get_task_by_id(task_id)
retries += 1
if existing_task:
await callback_query.answer("❌ Ошибка при создании задачи", show_alert=True)
return
# Create task
task = Task(
id=task_id,
user_id=user_id,
task_type="download",
url=video_url,
status=TaskStatus.PENDING
)
# Save to database
try:
async with get_async_session_local()() as session:
await ensure_user_exists(user_id, session)
db_task = DBTask(
id=task_id,
user_id=user_id,
task_type=task.task_type,
status=task.status.value,
url=task.url,
progress=0,
created_at=datetime.utcnow(),
updated_at=datetime.utcnow()
)
session.add(db_task)
await session.commit()
except Exception as e:
logger.error(f"Error saving task to database: {e}", exc_info=True)
await callback_query.answer("❌ Ошибка при создании задачи", show_alert=True)
return
# Add to queue
success = await task_queue.add_task(task, check_duplicate_url=True)
if not success:
try:
async with get_async_session_local()() as session:
db_task = await session.get(DBTask, task_id)
if db_task:
await session.delete(db_task)
await session.commit()
except Exception as e:
logger.error(f"Error deleting task from database: {e}")
await callback_query.answer("⚠️ Задача с этим URL уже обрабатывается", show_alert=True)
return
# Start executor if needed
set_app_client(client)
if not task_executor._running:
await task_executor.start()
# Send status message
status_message = await callback_query.message.reply(
f"📥 **Загрузка начата**\n\n"
f"🔗 {video_url[:50]}...\n\n"
f"📊 Прогресс: **0%**\n"
f"⏳ Ожидание начала загрузки..."
)
set_task_message(task_id, status_message.id)
await callback_query.answer("✅ Загрузка начата")
# Update original message to show selection
try:
await callback_query.edit_message_reply_markup(
reply_markup=None # Remove buttons
)
original_text = callback_query.message.text or ""
await callback_query.message.edit_text(
original_text + f"\n\n✅ Выбрано: {video_url[:50]}..."
)
except Exception as e:
logger.debug(f"Failed to update selection message: {e}")
except Exception as e:
logger.error(f"Error handling video selection: {e}", exc_info=True)
await callback_query.answer("❌ Ошибка при запуске загрузки", show_alert=True)
else:
await callback_query.answer("❓ Неизвестная команда")

View File

@@ -535,6 +535,9 @@ async def url_handler(client: Client, message: Message):
from bot.modules.access_control.auth import is_authorized
from bot.modules.task_scheduler.queue import task_queue, Task, TaskStatus
from bot.modules.task_scheduler.executor import task_executor, set_app_client
from bot.modules.message_handler.filters import is_youtube_url, is_instagram_url
from bot.modules.media_loader.ytdlp import get_videos_list
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
import time
# Check authorization
@@ -554,6 +557,68 @@ async def url_handler(client: Client, message: Message):
)
return
# Check if URL is YouTube or Instagram (direct download)
is_youtube = is_youtube_url(url)
is_instagram = is_instagram_url(url)
# For non-YouTube/Instagram URLs, check if there are multiple videos
if not is_youtube and not is_instagram:
# Check if URL contains video selection callback data
if url.startswith('video_select:'):
# This is a callback from video selection - extract actual URL
actual_url = url.replace('video_select:', '', 1)
url = actual_url
else:
# Try to get list of videos from webpage
try:
status_msg = await message.reply("🔍 Анализирую страницу...")
from shared.config import settings
videos_info = await get_videos_list(url, cookies_file=settings.COOKIES_FILE)
if videos_info and videos_info.get('videos'):
videos = videos_info['videos']
if len(videos) > 1:
# Multiple videos found - show selection menu
await status_msg.delete()
playlist_title = videos_info.get('playlist_title', 'Найдено видео')
text = f"📹 **{playlist_title}**\n\n"
text += f"Найдено видео: **{len(videos)}**\n\n"
text += "Выберите видео для загрузки:\n\n"
# Create inline keyboard with video selection buttons
buttons = []
for idx, video in enumerate(videos[:10], 1): # Limit to 10 videos
title = video.get('title', f'Видео {idx}')[:50] # Limit title length
duration = video.get('duration')
if duration:
from bot.utils.helpers import format_duration
duration_str = format_duration(duration)
title += f" ({duration_str})"
# Use callback data format: video_select:<video_url>
callback_data = f"video_select:{video['url']}"
buttons.append([InlineKeyboardButton(f"{idx}. {title}", callback_data=callback_data)])
keyboard = InlineKeyboardMarkup(buttons)
await message.reply(text, reply_markup=keyboard)
return
elif len(videos) == 1:
# Single video found - use its URL
url = videos[0]['url']
await status_msg.delete()
else:
# No videos found, but continue with original URL (might be direct video link)
await status_msg.delete()
except Exception as e:
logger.error(f"Error getting videos list: {e}", exc_info=True)
# Continue with original URL if error occurs
try:
await status_msg.delete()
except:
pass
# Check concurrent tasks count
from bot.config import settings
active_tasks_count = await task_queue.get_user_active_tasks_count(user_id)