dj-embe/framework/youtube.py

81 lines
2.6 KiB
Python
Raw Normal View History

2023-05-06 01:16:26 +00:00
import re
2023-04-27 23:19:18 +00:00
from asyncio import AbstractEventLoop
2023-05-06 01:16:26 +00:00
from os import path, stat
from youtubesearchpython.__future__ import VideosSearch
from yt_dlp import YoutubeDL
2023-04-27 23:19:18 +00:00
from config import YoutubeConfig
2023-05-06 01:16:26 +00:00
from entity import File
2023-04-27 23:19:18 +00:00
class Youtube:
2023-05-06 01:16:26 +00:00
def __init__(
self, loop: AbstractEventLoop, config: YoutubeConfig, downloadDirectory: str
) -> None:
2023-04-27 23:19:18 +00:00
self.loop = loop
2023-05-06 01:16:26 +00:00
self.params = {
"format": "bestaudio/best",
"outtmpl": path.join(downloadDirectory, "%(id)s"),
2023-05-16 23:04:16 +00:00
"updatetime": False,
2023-05-06 01:16:26 +00:00
"restrictfilenames": True,
"noplaylist": True,
"ignoreerrors": True,
"logtostderr": False,
"verbose": False,
"quiet": True,
"no_warnings": True,
"noprogress": True,
}
self.client = YoutubeDL(self.params)
self.language = config.language
self.region = config.region
self.get_id_regex = re.compile(
r"https:\/\/www\.youtube\.com\/watch\?v=(?P<id>[\w-]*)"
)
2023-04-27 23:19:18 +00:00
async def searchVideo(self, query: str):
videosSearch = VideosSearch(
2023-05-06 01:16:26 +00:00
query, limit=1, language=self.language, region=self.region
2023-04-27 23:19:18 +00:00
)
2023-05-16 23:04:16 +00:00
return (await videosSearch.next())["result"]
2023-04-27 23:19:18 +00:00
2023-05-06 01:16:26 +00:00
async def fetchData(self, url: str):
info = await self.loop.run_in_executor(
2023-04-27 23:19:18 +00:00
None, lambda: self.client.extract_info(url, download=False)
)
2023-05-06 01:16:26 +00:00
return self.client.sanitize_info(info)
def getId(self, url: str) -> str | None:
match = self.get_id_regex.search(url)
if match is None or "id" not in match.groupdict():
return None
return match.groupdict()["id"]
def downloadProgress(self, progress, status):
if status["status"] == "downloading":
self.loop.create_task(
progress(
int(status["downloaded_bytes"]),
int(
status["total_bytes"]
if "total_bytes" in status
else status["total_bytes_estimate"]
),
),
)
2023-05-16 23:04:16 +00:00
async def download(self, url: str, fileName: str, progress=None) -> File:
2023-05-06 01:16:26 +00:00
if progress is not None:
progress_hook = lambda status: self.downloadProgress(progress, status)
self.client.add_progress_hook(progress_hook)
await self.loop.run_in_executor(None, lambda: self.client.download(url))
if progress is not None:
self.client._progress_hooks.remove(progress_hook)
return File(name=fileName, size=stat(fileName).st_size)