You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.1 KiB

import re
from typing import cast, Optional
try:
from googleapiclient.errors import Error as GoogleApiError # type: ignore
DEPENDENCIES_FOUND = True
except ImportError:
DEPENDENCIES_FOUND = False
from edmond.plugin import Plugin
from edmond.plugins.playlist_of_the_day import PlaylistOfTheDayPlugin
from edmond.plugins.youtube import YoutubePlugin
class YoutubeParserPlugin(Plugin):
VIDEO_URL_RE = re.compile(
r"https?:\/\/(?:[^/]+/watch\?(?:.*&)?v=(?P<code1>[^&\s]+)"
r"|youtu\.be/(?P<code2>[^&\s]+))"
)
def __init__(self, bot):
super().__init__(bot)
self.priority = -3
self._youtube_plugin: Optional[YoutubePlugin] = None
self._playlist_of_the_day_plugin: Optional[
PlaylistOfTheDayPlugin
] = None
@property
def youtube_plugin(self) -> Optional[YoutubePlugin]:
if self._youtube_plugin is None:
self._youtube_plugin = cast(
YoutubePlugin,
self.bot.get_plugin("youtube"),
)
return self._youtube_plugin
@property
def playlist_of_the_day_plugin(self) -> Optional[PlaylistOfTheDayPlugin]:
if self._playlist_of_the_day_plugin is None:
self._playlist_of_the_day_plugin = cast(
PlaylistOfTheDayPlugin,
self.bot.get_plugin("playlistoftheday"),
)
return self._playlist_of_the_day_plugin
def on_welcome(self, _):
if not (self.youtube_plugin and self.youtube_plugin.is_ready):
self.bot.log_w("Youtube plugin is not available.")
self.is_ready = False
def on_pubmsg(self, event):
if not self.respects_handling_conditions():
return False
words = event.arguments[0].split()
for word in words:
matched = self.VIDEO_URL_RE.match(word)
if matched:
title = self.get_video_title(matched)
if title:
self.bot.say(event.target, title)
self.add_to_playlist(word, title)
return True
else:
self.signal_failure(event.target)
return False
def get_video_title(self, matched) -> Optional[str]:
if self.youtube_plugin is None:
return None
groupdict = matched.groupdict()
code = groupdict.get("code1") or groupdict.get("code2")
if not code:
return None
try:
search_response = (
self.youtube_plugin.youtube.videos()
.list(id=code, part="snippet")
.execute()
)
except GoogleApiError:
return None
title = ""
for result in search_response.get("items", []):
if result["kind"] == "youtube#video":
title = result["snippet"]["title"]
break
else:
return None
return title
def add_to_playlist(self, url: str, title: str):
if self.playlist_of_the_day_plugin is None:
return
self.playlist_of_the_day_plugin.add_line(f"{url} {title}")