Обновить universal.py
This commit is contained in:
+30
-116
@@ -1,20 +1,17 @@
|
|||||||
# meta developer: @origsama
|
# meta developer: @HoroshoVse
|
||||||
# requires: yt-dlp curl_cffi
|
# requires: yt-dlp
|
||||||
from .. import loader, utils
|
from .. import loader, utils
|
||||||
import requests
|
|
||||||
import re
|
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import tempfile
|
import tempfile
|
||||||
import urllib.parse
|
|
||||||
import json
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@loader.tds
|
@loader.tds
|
||||||
class SocialDownloaderMod(loader.Module):
|
class YIDownloaderMod(loader.Module):
|
||||||
"""Скачивание видео из TikTok, Instagram, YouTube, VK"""
|
"""Универсальный скачиватель видео"""
|
||||||
strings = {"name": "SocialDownloader"}
|
strings = {"name": "YI downloader"}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.config = loader.ModuleConfig(
|
self.config = loader.ModuleConfig(
|
||||||
@@ -67,19 +64,25 @@ class SocialDownloaderMod(loader.Module):
|
|||||||
|
|
||||||
caption += f"\n🔗 <a href='{args}'>Оригинал</a>"
|
caption += f"\n🔗 <a href='{args}'>Оригинал</a>"
|
||||||
|
|
||||||
await status.delete()
|
try:
|
||||||
|
await message.client.send_file(
|
||||||
await message.client.send_file(
|
message.chat_id,
|
||||||
message.chat_id,
|
video_path,
|
||||||
video_path,
|
caption=caption,
|
||||||
caption=caption,
|
reply_to=message.reply_to_msg_id or message.id
|
||||||
reply_to=message.reply_to_msg_id or message.id
|
)
|
||||||
)
|
await status.delete()
|
||||||
|
except Exception as e:
|
||||||
os.remove(video_path)
|
await status.edit(f"❌ Ошибка отправки в Telegram: {str(e)}")
|
||||||
|
finally:
|
||||||
|
if os.path.exists(video_path):
|
||||||
|
os.remove(video_path)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await status.edit(f"❌ Ошибка: {str(e)}")
|
try:
|
||||||
|
await status.edit(f"❌ Ошибка: {str(e)}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def detect_source(self, url):
|
def detect_source(self, url):
|
||||||
url = url.lower()
|
url = url.lower()
|
||||||
@@ -107,15 +110,16 @@ class SocialDownloaderMod(loader.Module):
|
|||||||
cmd = [
|
cmd = [
|
||||||
sys.executable, '-m', 'yt_dlp',
|
sys.executable, '-m', 'yt_dlp',
|
||||||
'-f', 'bestvideo+bestaudio/best',
|
'-f', 'bestvideo+bestaudio/best',
|
||||||
|
'--merge-output-format', 'mp4',
|
||||||
'--max-filesize', f"{self.config['max_size']}M",
|
'--max-filesize', f"{self.config['max_size']}M",
|
||||||
'-o', output_template,
|
'-o', output_template,
|
||||||
url
|
url
|
||||||
]
|
]
|
||||||
|
|
||||||
if source.lower() == 'tiktok':
|
if source.lower() == 'tiktok':
|
||||||
cmd.extend(['--cookies', 'tiktok_cookies.txt'])
|
cmd.extend(['--cookies', 'tiktok_cookies.txt', '--downloader', 'default', '--compat-options', 'no-impersonate'])
|
||||||
elif source.lower() == 'instagram':
|
elif source.lower() == 'instagram':
|
||||||
cmd.extend(['--cookies', 'instagram_cookies.txt'])
|
cmd.extend(['--cookies', 'instagram_cookies.txt', '--downloader', 'default', '--compat-options', 'no-impersonate'])
|
||||||
|
|
||||||
process = await asyncio.create_subprocess_exec(
|
process = await asyncio.create_subprocess_exec(
|
||||||
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
||||||
@@ -131,18 +135,20 @@ class SocialDownloaderMod(loader.Module):
|
|||||||
final_path = os.path.join(tempfile.gettempdir(), file)
|
final_path = os.path.join(tempfile.gettempdir(), file)
|
||||||
shutil.copy2(file_path, final_path)
|
shutil.copy2(file_path, final_path)
|
||||||
|
|
||||||
info = await self.get_video_info(url)
|
info = await self.get_video_info(url, source)
|
||||||
return final_path, info
|
return final_path, info
|
||||||
|
|
||||||
return None, "Файл не найден после скачивания"
|
return None, "Файл не найден после скачивания"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Download error: {e}")
|
|
||||||
return None, str(e)
|
return None, str(e)
|
||||||
|
|
||||||
async def get_video_info(self, url):
|
async def get_video_info(self, url, source):
|
||||||
try:
|
try:
|
||||||
cmd = [sys.executable, '-m', 'yt_dlp', '--dump-json', '--no-playlist', url]
|
cmd = [sys.executable, '-m', 'yt_dlp', '--dump-json', '--no-playlist', url]
|
||||||
|
if source.lower() in ['tiktok', 'instagram']:
|
||||||
|
cmd.extend(['--downloader', 'default', '--compat-options', 'no-impersonate'])
|
||||||
|
|
||||||
process = await asyncio.create_subprocess_exec(
|
process = await asyncio.create_subprocess_exec(
|
||||||
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
||||||
)
|
)
|
||||||
@@ -150,7 +156,6 @@ class SocialDownloaderMod(loader.Module):
|
|||||||
|
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
data = json.loads(stdout.decode('utf-8'))
|
data = json.loads(stdout.decode('utf-8'))
|
||||||
|
|
||||||
duration = data.get('duration', 0)
|
duration = data.get('duration', 0)
|
||||||
minutes = duration // 60
|
minutes = duration // 60
|
||||||
seconds = duration % 60
|
seconds = duration % 60
|
||||||
@@ -164,94 +169,3 @@ class SocialDownloaderMod(loader.Module):
|
|||||||
except:
|
except:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
async def tiktokcmd(self, message):
|
|
||||||
"""<ссылка> - Скачать видео с TikTok"""
|
|
||||||
args = utils.get_args_raw(message)
|
|
||||||
if not args:
|
|
||||||
await utils.answer(message, "❌ Укажи ссылку на TikTok")
|
|
||||||
return
|
|
||||||
await self.dlcmd(message)
|
|
||||||
|
|
||||||
async def instacmd(self, message):
|
|
||||||
"""<ссылка> - Скачать видео/фото с Instagram"""
|
|
||||||
args = utils.get_args_raw(message)
|
|
||||||
if not args:
|
|
||||||
await utils.answer(message, "❌ Укажи ссылку на Instagram")
|
|
||||||
return
|
|
||||||
await self.dlcmd(message)
|
|
||||||
|
|
||||||
async def ytcmd(self, message):
|
|
||||||
"""<ссылка> [качество] - Скачать видео с YouTube"""
|
|
||||||
args = utils.get_args_raw(message)
|
|
||||||
if not args:
|
|
||||||
await utils.answer(message, "❌ Укажи ссылку на YouTube")
|
|
||||||
return
|
|
||||||
|
|
||||||
parts = args.split()
|
|
||||||
url = parts[0]
|
|
||||||
quality = parts[1] if len(parts) > 1 else 'best'
|
|
||||||
|
|
||||||
await utils.answer(message, f"📥 Скачиваю с YouTube ({quality})...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
|
||||||
output_template = os.path.join(temp_dir, '%(title)s.%(ext)s')
|
|
||||||
|
|
||||||
format_str = f'bestvideo[height<={quality}]+bestaudio/best[height<={quality}]/best' if quality != 'best' else 'bestvideo+bestaudio/best'
|
|
||||||
|
|
||||||
cmd = [
|
|
||||||
sys.executable, '-m', 'yt_dlp',
|
|
||||||
'-f', format_str,
|
|
||||||
'--max-filesize', f"{self.config['max_size']}M",
|
|
||||||
'-o', output_template,
|
|
||||||
url
|
|
||||||
]
|
|
||||||
|
|
||||||
process = await asyncio.create_subprocess_exec(
|
|
||||||
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
|
||||||
)
|
|
||||||
stdout, stderr = await process.communicate()
|
|
||||||
|
|
||||||
if process.returncode != 0:
|
|
||||||
err_msg = stderr.decode('utf-8', errors='ignore')
|
|
||||||
await utils.answer(message, f"❌ Ошибка скачивания:\n<code>{utils.escape_html(err_msg)}</code>")
|
|
||||||
return
|
|
||||||
|
|
||||||
for file in os.listdir(temp_dir):
|
|
||||||
file_path = os.path.join(temp_dir, file)
|
|
||||||
if os.path.isfile(file_path):
|
|
||||||
final_path = os.path.join(tempfile.gettempdir(), file)
|
|
||||||
shutil.copy2(file_path, final_path)
|
|
||||||
|
|
||||||
info = await self.get_video_info(url)
|
|
||||||
|
|
||||||
caption = f"<b>🎥 YouTube</b>\n"
|
|
||||||
if info.get('title'):
|
|
||||||
caption += f"📝 {info['title']}\n"
|
|
||||||
if info.get('author'):
|
|
||||||
caption += f"👤 {info['author']}\n"
|
|
||||||
if info.get('duration'):
|
|
||||||
caption += f"⏱ {info['duration']}\n"
|
|
||||||
caption += f"\n⚙️ {quality}"
|
|
||||||
|
|
||||||
await message.client.send_file(
|
|
||||||
message.chat_id,
|
|
||||||
final_path,
|
|
||||||
caption=caption
|
|
||||||
)
|
|
||||||
|
|
||||||
os.remove(final_path)
|
|
||||||
return
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
await utils.answer(message, f"❌ Ошибка: {str(e)}")
|
|
||||||
|
|
||||||
async def vkcmd(self, message):
|
|
||||||
"""<ссылка> - Скачать видео с VK"""
|
|
||||||
args = utils.get_args_raw(message)
|
|
||||||
if not args:
|
|
||||||
await utils.answer(message, "❌ Укажи ссылку на VK видео")
|
|
||||||
return
|
|
||||||
await self.dlcmd(message)
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user