Support uploading larger files

This commit is contained in:
Nexus 2024-05-31 02:23:42 +01:00
parent 38f47b9699
commit 774e8cf3d7
Signed by: nex
GPG key ID: 0FA334385D0B689F
3 changed files with 59 additions and 23 deletions

View file

@ -66,7 +66,8 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
python3 \
python3-pip \
python3-dev \
python3-virtualenv
python3-virtualenv \
libmagic-dev
RUN virtualenv /app/venv
RUN /app/venv/bin/pip install --upgrade --no-input pip wheel setuptools

View file

@ -19,3 +19,4 @@ redis~=5.0
beautifulsoup4~=4.12
lxml~=5.1
matplotlib~=3.8
python-magic~=0.4

View file

@ -2,10 +2,12 @@ import asyncio
import functools
import hashlib
import logging
import httpx
import subprocess
import tempfile
import textwrap
import typing
import uuid
from pathlib import Path
from urllib.parse import urlparse
@ -205,6 +207,22 @@ class YTDLCog(commands.Cog):
raise RuntimeError(process.stderr.decode())
return new_file
@staticmethod
async def upload_to_0x0(name: str, data: typing.BinaryIO[bytes], mime_type: str | None = None) -> str:
if not mime_type:
import magic
mime_type = await asyncio.to_thread(magic.from_buffer, data.read(4096), mime=True)
data.seek(0)
async with httpx.AsyncClient() as client:
response = await client.post(
"https://0x0.st",
files={"file": (name, data, mime_type)},
headers={"User-Agent": "CollegeBot (matrix: @nex:nexy7574.co.uk)"},
)
if response.status_code == 200:
return urlparse(response.text).path[1:]
response.raise_for_status()
@commands.slash_command(name="yt-dl")
@commands.max_concurrency(1, wait=False)
# @commands.bot_has_permissions(send_messages=True, embed_links=True, attach_files=True)
@ -294,6 +312,7 @@ class YTDLCog(commands.Cog):
description = str(e)
thumbnail_url = webpage_url = None
likes = views = 0
chosen_format_id = str(uuid.uuid4())
else:
title = extracted_info.get("title", url)
title = textwrap.shorten(title, 100)
@ -305,7 +324,7 @@ class YTDLCog(commands.Cog):
final_extension = extracted_info.get("ext")
format_note = extracted_info.get("format_note", "%s (%s)" % (chosen_format, chosen_format_id))
resolution = extracted_info.get("resolution")
fps = extracted_info.get("fps")
fps = extracted_info.get("fps", 0.0)
vcodec = extracted_info.get("vcodec")
acodec = extracted_info.get("acodec")
filesize = extracted_info.get("filesize", extracted_info.get("filesize_approx", 1))
@ -346,7 +365,7 @@ class YTDLCog(commands.Cog):
.set_footer(text="Downloading (step 2/10)")
.set_thumbnail(url=thumbnail_url)
)
previous = await self.get_saved(webpage_url, extracted_info["format_id"], snip or "*")
previous = await self.get_saved(webpage_url, chosen_format_id, snip or "*")
if previous:
await ctx.edit(
content=previous,
@ -375,26 +394,28 @@ class YTDLCog(commands.Cog):
)
try:
if audio_only is False:
file = next(temp_dir.glob("*." + extracted_info["ext"]))
file: Path = next(temp_dir.glob("*." + extracted_info["ext"]))
else:
# can be .opus, .m4a, .mp3, .ogg, .oga
for _file in temp_dir.iterdir():
if _file.suffix in (".opus", ".m4a", ".mp3", ".ogg", ".oga", ".aac", ".wav"):
file = _file
file: Path = _file
break
else:
raise StopIteration
except StopIteration:
ext = extracted_info["ext"]
self.log.warning(
"Failed to locate downloaded file. Was supposed to be looking for a file extension of "
"%r amongst files %r, however none were found.",
extracted_info["ext"],
ext,
list(map(str, temp_dir.iterdir())),
)
return await ctx.edit(
embed=discord.Embed(
title="Error",
description="Failed to locate downloaded video file.\n"
description="Failed to locate downloaded video file."
f" Was expecting a file with the extension {ext}.\n"
f"Files: {', '.join(list(map(str, temp_dir.iterdir())))}",
colour=discord.Colour.red(),
url=webpage_url,
@ -421,7 +442,7 @@ class YTDLCog(commands.Cog):
"-preset",
"fast",
"-crf",
"28",
"24",
"-deadline",
"realtime",
"-cpu-used",
@ -464,11 +485,11 @@ class YTDLCog(commands.Cog):
if audio_only and file.suffix != ".m4a":
self.log.info("Converting %r to m4a.", file)
file = await asyncio.to_thread(self.convert_to_m4a, file)
file: Path = await asyncio.to_thread(self.convert_to_m4a, file)
stat = file.stat()
size_bytes = stat.st_size
if size_bytes >= ((25 * 1024 * 1024) - 256):
if size_bytes >= ((500 * 1024 * 1024) - 256):
return await ctx.edit(
embed=discord.Embed(
title="Error",
@ -477,9 +498,9 @@ class YTDLCog(commands.Cog):
url=webpage_url,
)
)
size_megabits = (size_bytes * 8) / 1024 / 1024
eta_seconds = size_megabits / 20
upload_file = await asyncio.to_thread(discord.File, file, filename=file.name)
await ctx.edit(
embed=discord.Embed(
title="Uploading...",
@ -488,19 +509,32 @@ class YTDLCog(commands.Cog):
timestamp=discord.utils.utcnow(),
)
)
embed = discord.Embed(
title=f"Downloaded {title}!",
description="Views: {:,} | Likes: {:,}".format(views or 0, likes or 0),
colour=discord.Colour.green(),
timestamp=discord.utils.utcnow(),
url=webpage_url,
)
try:
msg = await ctx.edit(
file=upload_file,
embed=discord.Embed(
title=f"Downloaded {title}!",
description="Views: {:,} | Likes: {:,}".format(views or 0, likes or 0),
colour=discord.Colour.green(),
timestamp=discord.utils.utcnow(),
url=webpage_url,
),
)
await self.save_link(msg, webpage_url, chosen_format_id, snip=snip or "*")
except discord.HTTPException as e:
if size_bytes >= (20 * 1024 * 1024):
with file.open("rb") as fb:
part = await self.upload_to_0x0(
file.name,
fb
)
await ctx.edit(
content="https://embeds.video/0x0/" + part,
embed=embed
)
else:
upload_file = await asyncio.to_thread(discord.File, file, filename=file.name)
msg = await ctx.edit(
file=upload_file,
embed=embed
)
await self.save_link(msg, webpage_url, chosen_format_id, snip=snip or "*")
except (discord.HTTPException, ConnectionError, httpx.HTTPStatusError) as e:
self.log.error(e, exc_info=True)
return await ctx.edit(
embed=discord.Embed(