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[^&\s]+)" r"|youtu\.be/(?P[^&\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}")