hotdog/hotdog/command/youtube.py

114 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
from dataclasses import dataclass
from functools import lru_cache
from time import time as now
from typing import *
import youtube_dl
from ..functions import escape_all, pretty_duration, reply
from ..models import Message
HELP = """Gibt Informationen zu Youtube-Videos aus.
Some text containing a <Youtube URL>.
"""
youtube_re = re.compile(
r"\byoutu(\.be/|be\.com/(embed/|v/|watch\?\w*v=))(?P<id>[0-9A-Za-z_-]{10,11})\b"
)
def init(bot):
bot.on_message(handle)
@lru_cache(maxsize=5)
def load_info(url, cachetoken):
"""The cachetoken is just there to bust the LRU cache after a while."""
return Info.from_url(url)
def cachetoken(quant_m=15):
"""Return a cache token with the given time frame"""
return int(now() / 60 / quant_m)
async def handle(message: Message):
if message.command in {"u", "url"}:
return
match = youtube_re.search(message.text)
if not match:
return
youtube_id = match["id"]
info = load_info(youtube_id, cachetoken())
escape_all(info)
details = [
f"🖋 {info.author}",
f"{pretty_duration(info.duration_seconds)}",
f"📺 {info.width}×{info.height}",
f"👀 {info.view_count:_}",
]
tag = (info.categories[:1] or info.tags[:1] or [""])[0]
if tag:
details.append(f"🏷 {tag}")
text = f"<b>{info.title}</b> — {', '.join(details)}"
await reply(message, html=text)
class Nolog:
def debug(self, msg):
pass
def warning(self, msg):
pass
def error(self, msg):
pass
ytdl = youtube_dl.YoutubeDL({"skip_download": True, "logger": Nolog()})
@dataclass
class Info:
author: str
title: str
description: str
duration_seconds: int
view_count: int
thumbnail: str
width: int
height: int
categories: List[str]
tags: List[str]
@classmethod
def from_url(cls, url):
info = ytdl.extract_info(url, download=False)
new = cls(
author=info["uploader"] or info["creator"] or info["uploader_id"] or "",
title=info["title"] or info["alt_title"] or "",
description=info["description"] or "",
duration_seconds=info["duration"] or 0,
view_count=info["view_count"] or 0,
thumbnail=(
info["thumbnail"]
or (info["thumbnails"][-1] if info["thumbnails"] else "")
),
categories=info["categories"] or [],
tags=info["tags"] or [],
width=info["width"] or 0,
height=info["height"] or 0,
)
if info["formats"]:
new.width, new.height = max(
(
(f["width"] or new.width),
(f["height"] or new.height),
)
for f in info["formats"]
)
return new