Обновить universal.py

This commit is contained in:
yanistyle
2026-09-01 02:06:25 +03:00
parent c10df870ab
commit 4b44ae9670
+22 -43
View File
@@ -1,12 +1,14 @@
# meta developer: @origsama
# requires: yt-dlp
from .. import loader, utils
import requests
import re
import os
import subprocess
import asyncio
import tempfile
import urllib.parse
import json
import shutil
@loader.tds
class SocialDownloaderMod(loader.Module):
@@ -39,7 +41,6 @@ class SocialDownloaderMod(loader.Module):
)
return
# Определяем источник
source = self.detect_source(args)
if not source:
await utils.answer(message, "❌ Неподдерживаемая ссылка")
@@ -48,14 +49,12 @@ class SocialDownloaderMod(loader.Module):
status = await utils.answer(message, f"📥 Скачиваю с {source}...")
try:
# Скачиваем видео
video_path, info = await self.download_video(args, source)
if not video_path:
await status.edit("❌ Не удалось скачать видео")
return
# Формируем описание
caption = f"<b>📹 Видео с {source}</b>\n\n"
if info.get('title'):
caption += f"📝 {info['title']}\n"
@@ -66,7 +65,6 @@ class SocialDownloaderMod(loader.Module):
caption += f"\n🔗 <a href='{args}'>Оригинал</a>"
# Отправляем
await status.delete()
await message.client.send_file(
@@ -76,16 +74,13 @@ class SocialDownloaderMod(loader.Module):
reply_to=message.reply_to_msg_id or message.id
)
# Чистим
os.remove(video_path)
except Exception as e:
await status.edit(f"❌ Ошибка: {str(e)}")
def detect_source(self, url):
"""Определяет источник по ссылке"""
url = url.lower()
sources = {
'tiktok': ['tiktok.com', 'vm.tiktok.com'],
'instagram': ['instagram.com', 'instagr.am'],
@@ -96,54 +91,45 @@ class SocialDownloaderMod(loader.Module):
'facebook': ['facebook.com', 'fb.com'],
'pinterest': ['pinterest.com', 'pin.it']
}
for source, domains in sources.items():
for domain in domains:
if domain in url:
return source.capitalize()
return None
async def download_video(self, url, source):
"""Скачивает видео через yt-dlp"""
try:
# Создаем временную папку
with tempfile.TemporaryDirectory() as temp_dir:
output_template = os.path.join(temp_dir, '%(title)s.%(ext)s')
# Формируем команду
cmd = [
'yt-dlp',
'-f', 'best[filesize<50M]', # Лучшее качество до 50 МБ
'-f', 'best[filesize<50M]',
'--max-filesize', f"{self.config['max_size']}M",
'-o', output_template,
url
]
# Добавляем специфичные опции
if source.lower() == 'tiktok':
cmd.extend(['--cookies', 'tiktok_cookies.txt']) # Опционально
cmd.extend(['--cookies', 'tiktok_cookies.txt'])
elif source.lower() == 'instagram':
cmd.extend(['--cookies', 'instagram_cookies.txt'])
# Запускаем
result = subprocess.run(cmd, capture_output=True, text=True)
process = await asyncio.create_subprocess_exec(
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
if result.returncode != 0:
if process.returncode != 0:
return None, {}
# Ищем скачанный файл
for file in os.listdir(temp_dir):
file_path = os.path.join(temp_dir, file)
if os.path.isfile(file_path):
# Копируем в постоянное место
import shutil
final_path = os.path.join(tempfile.gettempdir(), file)
shutil.copy2(file_path, final_path)
# Получаем информацию
info = await self.get_video_info(url)
return final_path, info
return None, {}
@@ -153,19 +139,15 @@ class SocialDownloaderMod(loader.Module):
return None, {}
async def get_video_info(self, url):
"""Получает информацию о видео"""
try:
cmd = [
'yt-dlp',
'--dump-json',
'--no-playlist',
url
]
cmd = ['yt-dlp', '--dump-json', '--no-playlist', url]
process = await asyncio.create_subprocess_exec(
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
data = json.loads(result.stdout)
if process.returncode == 0:
data = json.loads(stdout.decode('utf-8'))
duration = data.get('duration', 0)
minutes = duration // 60
@@ -176,7 +158,6 @@ class SocialDownloaderMod(loader.Module):
'author': data.get('uploader', data.get('channel', '')),
'duration': f"{minutes}:{seconds:02d}" if duration else ''
}
return {}
except:
return {}
@@ -187,7 +168,6 @@ class SocialDownloaderMod(loader.Module):
if not args:
await utils.answer(message, "❌ Укажи ссылку на TikTok")
return
await self.dlcmd(message)
async def instacmd(self, message):
@@ -196,7 +176,6 @@ class SocialDownloaderMod(loader.Module):
if not args:
await utils.answer(message, "❌ Укажи ссылку на Instagram")
return
await self.dlcmd(message)
async def ytcmd(self, message):
@@ -206,7 +185,6 @@ class SocialDownloaderMod(loader.Module):
await utils.answer(message, "❌ Укажи ссылку на YouTube")
return
# Разбираем качество если указано
parts = args.split()
url = parts[0]
quality = parts[1] if len(parts) > 1 else 'best'
@@ -225,16 +203,18 @@ class SocialDownloaderMod(loader.Module):
url
]
result = subprocess.run(cmd, capture_output=True, text=True)
process = await asyncio.create_subprocess_exec(
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
if result.returncode != 0:
if process.returncode != 0:
await utils.answer(message, "❌ Ошибка скачивания")
return
for file in os.listdir(temp_dir):
file_path = os.path.join(temp_dir, file)
if os.path.isfile(file_path):
import shutil
final_path = os.path.join(tempfile.gettempdir(), file)
shutil.copy2(file_path, final_path)
@@ -267,5 +247,4 @@ class SocialDownloaderMod(loader.Module):
if not args:
await utils.answer(message, "❌ Укажи ссылку на VK видео")
return
await self.dlcmd(message)