вк вынесен в отдельный сервис
This commit is contained in:
parent
39bf9d1933
commit
d05fc6f522
9 changed files with 348 additions and 63 deletions
113
bot.py
113
bot.py
|
|
@ -9,6 +9,7 @@ from urllib.parse import urlparse
|
|||
from datetime import datetime
|
||||
|
||||
import yt_dlp
|
||||
import httpx
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, MessageHandler, filters, ContextTypes, CommandHandler
|
||||
|
||||
|
|
@ -22,6 +23,8 @@ logger = logging.getLogger(__name__)
|
|||
# Токен бота и имя бота из переменных окружения
|
||||
TELEGRAM_BOT_TOKEN = os.getenv('TELEGRAM_BOT_TOKEN')
|
||||
TELEGRAM_BOT_USERNAME = os.getenv('TELEGRAM_BOT_USERNAME', 'vrubelVideoDownload_bot')
|
||||
# URL VK сервиса для скачивания видео
|
||||
VK_DOWNLOADER_URL = os.getenv('VK_DOWNLOADER_URL', 'http://localhost:5555')
|
||||
|
||||
# Базовая директория проекта (абсолютный путь), чтобы не зависеть от рабочей директории процесса
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
|
|
@ -327,76 +330,64 @@ async def download_instagram_video(url: str, chat_id: int, max_retries: int = 3)
|
|||
|
||||
|
||||
async def download_vk_video(url: str, chat_id: int, max_retries: int = 3) -> str:
|
||||
"""Скачивает видео с VK"""
|
||||
vk_user_agent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
||||
"""Скачивает видео с VK через внешний сервис"""
|
||||
logger.info(f"VK: отправка запроса на внешний сервис {VK_DOWNLOADER_URL}")
|
||||
|
||||
last_error = None
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
# Получаем информацию о видео
|
||||
ydl_opts_info = {
|
||||
'quiet': False,
|
||||
'no_warnings': False,
|
||||
'user_agent': vk_user_agent,
|
||||
'socket_timeout': 60, # Увеличенный таймаут для VK
|
||||
'extractor_args': {
|
||||
'vk': {},
|
||||
},
|
||||
'http_headers': {
|
||||
'User-Agent': vk_user_agent,
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language': 'ru-RU,ru;q=0.9',
|
||||
'Referer': 'https://vk.com/',
|
||||
'Connection': 'keep-alive',
|
||||
},
|
||||
# Пробуем использовать более надежные настройки SSL
|
||||
'nocheckcertificate': False,
|
||||
}
|
||||
|
||||
with yt_dlp.YoutubeDL(ydl_opts_info) as ydl:
|
||||
info = ydl.extract_info(url, download=False)
|
||||
video_title = info.get('title', 'vk_video')
|
||||
logger.info(f"VK: получена информация о видео: {video_title}")
|
||||
|
||||
# Скачиваем видео
|
||||
ydl_opts_download = {
|
||||
'format': 'best',
|
||||
'outtmpl': _safe_filename(video_title, chat_id),
|
||||
'quiet': False,
|
||||
'no_warnings': False,
|
||||
'user_agent': vk_user_agent,
|
||||
'socket_timeout': 60, # Увеличенный таймаут для VK
|
||||
'extractor_args': {
|
||||
'vk': {},
|
||||
},
|
||||
'http_headers': {
|
||||
'User-Agent': vk_user_agent,
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language': 'ru-RU,ru;q=0.9',
|
||||
'Referer': 'https://vk.com/',
|
||||
},
|
||||
}
|
||||
|
||||
logger.info(f"VK: начинаем скачивание (попытка {attempt + 1}/{max_retries})")
|
||||
with yt_dlp.YoutubeDL(ydl_opts_download) as ydl:
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, lambda: ydl.download([url]))
|
||||
|
||||
# Находим скачанный файл
|
||||
downloaded_files = list(DOWNLOADS_DIR.glob(f'{chat_id}_*'))
|
||||
if downloaded_files:
|
||||
downloaded_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
|
||||
return str(downloaded_files[0])
|
||||
else:
|
||||
raise Exception("Файл не был найден после скачивания")
|
||||
async with httpx.AsyncClient(timeout=600.0) as client: # Увеличенный таймаут для VK
|
||||
# Отправляем запрос на VK сервис
|
||||
response = await client.post(
|
||||
f"{VK_DOWNLOADER_URL}/download/stream",
|
||||
json={"url": url},
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
error_text = response.text
|
||||
try:
|
||||
error_json = response.json()
|
||||
error_text = error_json.get('error', error_text)
|
||||
except:
|
||||
pass
|
||||
raise Exception(f"VK сервис вернул ошибку {response.status_code}: {error_text}")
|
||||
|
||||
# Сохраняем видео во временный файл
|
||||
video_data = response.content
|
||||
video_ext = 'mp4' # По умолчанию mp4
|
||||
|
||||
# Пробуем определить расширение из заголовков
|
||||
content_type = response.headers.get('Content-Type', '')
|
||||
if 'video/' in content_type:
|
||||
video_ext = content_type.split('/')[-1].split(';')[0]
|
||||
|
||||
# Получаем имя файла из заголовка или создаем случайное
|
||||
filename = response.headers.get('Content-Disposition', '')
|
||||
if filename and 'filename=' in filename:
|
||||
video_filename = filename.split('filename=')[1].strip('"\'')
|
||||
else:
|
||||
video_filename = f'{chat_id}_vk_video.{video_ext}'
|
||||
|
||||
# Сохраняем файл
|
||||
video_path = DOWNLOADS_DIR / video_filename
|
||||
with open(video_path, 'wb') as f:
|
||||
f.write(video_data)
|
||||
|
||||
logger.info(f"VK: видео скачано через внешний сервис: {video_path}")
|
||||
return str(video_path)
|
||||
|
||||
except httpx.TimeoutException:
|
||||
last_error = Exception(f"Таймаут при запросе к VK сервису (попытка {attempt + 1}/{max_retries})")
|
||||
logger.warning(f"VK: таймаут при запросе к сервису: {last_error}")
|
||||
except Exception as e:
|
||||
last_error = e
|
||||
logger.warning(f"VK: попытка {attempt + 1}/{max_retries} не удалась: {e}")
|
||||
if attempt < max_retries - 1:
|
||||
await asyncio.sleep((attempt + 1) * 2)
|
||||
|
||||
if attempt < max_retries - 1:
|
||||
await asyncio.sleep((attempt + 1) * 2)
|
||||
|
||||
raise last_error or Exception("Неизвестная ошибка при скачивании с VK")
|
||||
raise last_error or Exception("Неизвестная ошибка при скачивании с VK через внешний сервис")
|
||||
|
||||
|
||||
async def download_video(url: str, chat_id: int, max_retries: int = 3) -> str:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue