Add beta ytdl command

This commit is contained in:
Nexus 2023-04-29 02:25:19 +01:00
parent 0f66384957
commit 51fbf89168
Signed by: nex
GPG key ID: 0FA334385D0B689F

View file

@ -8,6 +8,7 @@ import tempfile
import textwrap import textwrap
import gzip import gzip
from datetime import timedelta from datetime import timedelta
from functools import partial
from io import BytesIO from io import BytesIO
import dns.resolver import dns.resolver
@ -1072,6 +1073,237 @@ class OtherCog(commands.Cog):
files=files files=files
) )
@commands.slash_command(name="yt-dl-beta")
@commands.max_concurrency(1, commands.BucketType.user)
async def yt_dl_2(
self,
ctx: discord.ApplicationContext,
url: discord.Option(
description="The URL to download.",
type=str
),
list_formats: discord.Option(
name="list-formats",
description="Whether to list the formats.",
type=discord.SlashCommandOptionType.boolean,
default=False,
),
_format: discord.Option(
name="format",
description="The format to download.",
type=str,
autocomplete=format_autocomplete,
default=""
),
upload_log: discord.Option(
name="upload-log",
description="Whether to upload the log files.",
type=discord.SlashCommandOptionType.boolean,
default=False,
),
):
"""Downloads a video using youtube-dl"""
await ctx.defer()
MAX_SIZE_MB = ctx.guild.filesize_limit / 1024 / 1024
if MAX_SIZE_MB == 8.0:
MAX_SIZE_MB = 25.0
try:
import yt_dlp
except ImportError:
return await ctx.respond(
embed=discord.Embed(
title="Error",
description="`yt_dlp` is not installed.",
colour=discord.Colour.red()
)
)
with tempfile.TemporaryDirectory(prefix="jimmy-ytdl-wat") as tempdir_str:
tempdir = Path(tempdir_str).resolve()
stdout = tempdir / "stdout.txt"
stderr = tempdir / "stderr.txt"
class Logger:
def __init__(self):
self.stdout = open(stdout, "w+")
self.stderr = open(stderr, "w+")
def __del__(self):
self.stdout.close()
self.stderr.close()
def debug(self, msg: str):
if msg.startswith("[debug]"):
return
self.info(msg)
def info(self, msg: str):
self.stdout.write(msg + "\n")
self.stdout.flush()
def warning(self, msg: str):
self.stderr.write(msg + "\n")
self.stderr.flush()
def error(self, msg: str):
self.stderr.write(msg + "\n")
self.stderr.flush()
logger = Logger()
paths = {
target: str(tempdir)
for target in (
"home",
"temp",
)
}
with yt_dlp.YoutubeDL(
{
"windowsfilenames": True,
"restrictfilenames": True,
"noplaylist": True,
"nocheckcertificate": True,
"no_color": True,
"noprogress": True,
"logger": logger,
"format": _format or f"(bv*+ba/bv/ba/b)[filesize<={MAX_SIZE_MB}M]",
"paths": paths,
"outtmpl": f"{ctx.user.id}-%(title)s.%(ext)s"
}
) as downloader:
await ctx.respond(
embed=discord.Embed(
title="Downloading metadata...",
colour=discord.Colour.greyple()
)
)
try:
info = await self.bot.loop.run_in_executor(
None,
partial(downloader.extract_info, url, download=False)
)
except yt_dlp.utils.DownloadError as e:
return await ctx.respond(
embed=discord.Embed(
title="Error",
description=f"Download failed:\n```\n{e}\n```",
colour=discord.Colour.red()
)
)
info = downloader.sanitize_info(info)
if list_formats:
formats = info["formats"]
formats = {
fmt["format_id"]: fmt
for fmt in formats
}
embeds = []
for fmt in formats.keys():
fs = formats[fmt].get("filesize", 0.1) or 0.1
if fs == float("inf"):
fs = 0
units = ["B"]
else:
units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
while fs > 1024:
fs /= 1024
units.pop(0)
embeds.append(
discord.Embed(
title=fmt,
description="- Encoding: {0[vcodec]} + {0[acodec]}\n"
"- Extension: `.{0[ext]}`\n"
"- Resolution: {0[resolution]}\n"
"- Filesize: {1}\n"
"- Protocol: {0[protocol]}\n".format(formats[fmt],
f"{round(fs, 2)}{units[0]}"),
colour=discord.Colour.blurple()
).add_field(
name="Download:",
value="{} url:{} video_format:{}".format(
self.bot.get_application_command("yt-dl").mention,
url,
fmt
)
)
)
_paginator = pages.Paginator(embeds, loop_pages=True)
await ctx.delete(delay=0.1)
return await _paginator.respond(ctx.interaction)
if _format:
if _format not in info["formats"]:
return await ctx.edit(
embed=discord.Embed(
title="Error",
description="Invalid format. pass `list-formats:True` to see a list of formats.",
colour=discord.Colour.red()
)
)
try:
await ctx.respond(
embed=discord.Embed(title="Downloading...", colour=discord.Colour.blurple())
)
async with ctx.channel.typing():
await self.bot.loop.run_in_executor(None, partial(downloader.download, [url]))
except yt_dlp.utils.DownloadError as e:
return await ctx.edit(
embed=discord.Embed(
title="Error",
description=f"Download failed:\n```\n{e}\n```",
colour=discord.Colour.red()
)
)
else:
embed = discord.Embed(
title="Downloaded!",
description="",
colour=discord.Colour.green()
)
del logger
files = []
if upload_log:
if stdout.stat().st_size:
files.append(discord.File(stdout, "stdout.txt"))
if stderr.stat().st_size:
files.append(discord.File(stderr, "stderr.txt"))
for file in tempdir.glob(f"{ctx.user.id}-*"):
if file.stat().st_size == 0:
embed.description += f"\N{warning sign}\ufe0f {file.name} is empty.\n"
continue
st = file.stat().st_size
if st / 1024 / 1024 >= MAX_SIZE_MB:
units = ["B", "KB", "MB", "GB", "TB"]
st_r = st
while st_r > 1024:
st_r /= 1024
units.pop(0)
embed.description += "\N{warning sign}\ufe0f {} is too large to upload ({!s}{}" \
", max is {}MB).\n".format(
file.name,
round(st_r, 2),
units[0],
MAX_SIZE_MB
)
continue
files.append(discord.File(file, file.name))
if not files:
embed.description = "No files to upload."
return await ctx.edit(embed=embed)
else:
_desc = embed.description
embed.description = f"Uploading {len(files)} file(s)..."
await ctx.edit(embed=embed)
await ctx.channel.trigger_typing()
embed.description = _desc
await ctx.edit(embed=embed, files=files)
@commands.slash_command(name="text-to-mp3") @commands.slash_command(name="text-to-mp3")
@commands.cooldown(5, 600, commands.BucketType.user) @commands.cooldown(5, 600, commands.BucketType.user)
async def text_to_mp3( async def text_to_mp3(