diff --git a/edmond/bot.py b/edmond/bot.py index 25d5d86..5ea89a3 100644 --- a/edmond/bot.py +++ b/edmond/bot.py @@ -139,6 +139,10 @@ class Bot(irc.client.SimpleIRCClient, Logger): self.values[plugin_name] = {} self.log_d(f"Loaded {class_name}.") + def get_plugin(self, name): + """Get a loaded plugin by its name (e.g. 'mood'), or None.""" + return next(filter(lambda p: p.name == name, self.plugins), None) + def say(self, target, message): """Send message to target after a slight delay.""" time.sleep(self.config["speak_delay"]) diff --git a/edmond/plugins/youtube_parser.py b/edmond/plugins/youtube_parser.py new file mode 100644 index 0000000..27a36e3 --- /dev/null +++ b/edmond/plugins/youtube_parser.py @@ -0,0 +1,58 @@ +import re + +try: + from googleapiclient.errors import Error as GoogleApiError + DEPENDENCIES_FOUND = True +except ImportError: + DEPENDENCIES_FOUND = False + +from edmond.plugin import Plugin + + +class YoutubeParserPlugin(Plugin): + + VIDEO_URL_RE = re.compile( + r"https:\/\/www\.youtube\.com\/watch\?(?:.*&)?v=([^&]+)" + ) + + def __init__(self, bot): + super().__init__(bot) + self.priority = -3 + self._youtube_plugin = None + + @property + def youtube_plugin(self): + if self._youtube_plugin is None: + self._youtube_plugin = self.bot.get_plugin("youtube") + return self._youtube_plugin + + def on_welcome(self, _): + if not (self.youtube_plugin and self.youtube_plugin.is_ready): + self.log_w("Youtube plugin is not available.") + self.is_ready = False + + def on_pubmsg(self, event): + match = self.VIDEO_URL_RE.match(event.arguments[0]) + if match: + self.tell_video_title(match.group(1), event.target) + return True + return False + + def tell_video_title(self, video_id, target): + try: + search_response = self.youtube_plugin.youtube.videos().list( + id=video_id, + part="snippet", + ).execute() + except GoogleApiError: + self.signal_failure(target) + return + title = "" + for result in search_response.get("items", []): + if result["kind"] == "youtube#video": + title = result["snippet"]["title"] + break + else: + self.signal_failure(target) + return + self.bot.say(target, title)