From d7dd296b617c9a51de426a65b815997929eab77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Mon, 22 Jun 2015 01:40:30 +0200 Subject: [PATCH] youtube: also print playlist info The plugin has been rewritten to be a little bit cleaner. --- plugins/youtube | 171 ++++++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 78 deletions(-) diff --git a/plugins/youtube b/plugins/youtube index 1ce5f47..d9efb0e 100755 --- a/plugins/youtube +++ b/plugins/youtube @@ -2,7 +2,7 @@ # # ZyklonB YouTube plugin, displaying info about YouTube links # -# Copyright 2014 Přemysl Janouch +# Copyright 2014 - 2015, Přemysl Janouch # See the file LICENSE for licensing information. # @@ -12,85 +12,100 @@ import re import json import urllib.request +class Plugin: + re_msg = re.compile ('(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?' + '([^ ]+)(?: +(.*))?\r\n$') + re_args = re.compile (':?((?<=:).*|[^ ]+) *') + + def parse (self, line): + m = self.re_msg.match (line) + if m is None: + return None + + (nick, user, host, command, args) = m.groups () + args = [] if args is None else self.re_args.findall (args) + return (nick, user, host, command, args) + + def get_config (self, key): + print ("ZYKLONB get_config :%s" % key) + (_, _, _, _, args) = self.parse (sys.stdin.readline ()) + return args[0] + + def bot_print (self, what): + print ('ZYKLONB print :%s' % what) + +class YouTube (Plugin): + re_videos = list (map (lambda x: re.compile (x), [ + r'youtube\.[a-z]+/[^ ]*[&?]v=([-\w]+)', + r'youtube\.[a-z]+/v/([-\w]+)', + r'youtu\.be/([-\w]+)' + ])) + re_playlists = list (map (lambda x: re.compile (x), [ + r'youtube\.[a-z]+/playlist[&?][^ ]*(?<=&|\?)list=([-\w]+)', + ])) + + def print_info (self, channel, url, cb): + try: + data = json.loads (urllib.request.urlopen + (url, None, 30).read ().decode ('utf-8')) + + for line in map (lambda x: "YouTube: " + cb (x), data['items']): + print ("PRIVMSG %s :%s" % (channel, + line.encode ('utf-8').decode ('iso8859-1'))) + + except Exception as err: + self.bot_print ('youtube: %s' % (err)) + + def print_video_info (self, channel, video_id): + url = 'https://www.googleapis.com/youtube/v3/' \ + + 'videos?id=%s&key=%s&part=snippet,contentDetails,statistics' \ + % (video_id, self.youtube_api_key) + self.print_info (channel, url, lambda x: "%s | %s | %sx" % ( + x['snippet']['title'], + x['contentDetails']['duration'][2:].lower (), + x['statistics']['viewCount'])) + + def print_playlist_info (self, channel, playlist_id): + url = 'https://www.googleapis.com/youtube/v3/' \ + + 'playlists?id=%s&key=%s&part=snippet,contentDetails' \ + % (playlist_id, self.youtube_api_key) + self.print_info (channel, url, lambda x: "%s | %d videos" % ( + x['snippet']['title'], + x['contentDetails']['itemCount'])) + + def process_line (self, line): + msg = self.parse (line) + if msg is None: + return + + (nick, user, host, command, args) = msg + if command != 'PRIVMSG' or len (args) < 2: + return + + ctx = args[0] + if not ctx.startswith (('#', '+', '&', '!')): + ctx = nick + + for regex in self.re_videos: + for i in regex.findall (args[1]): + self.print_video_info (ctx, i) + for regex in self.re_playlists: + for i in regex.findall (args[1]): + self.print_playlist_info (ctx, i) + + def run (self): + self.youtube_api_key = self.get_config ('youtube_api_key') + if self.youtube_api_key == "": + self.bot_print ("youtube: missing `youtube_api_key'") + + print ("ZYKLONB register") + + for line in sys.stdin: + self.process_line (line) + sys.stdin = io.TextIOWrapper (sys.__stdin__.buffer, encoding = 'iso8859-1', newline = '\r\n', line_buffering = True) sys.stdout = io.TextIOWrapper (sys.__stdout__.buffer, encoding = 'iso8859-1', newline = '\r\n', line_buffering = True) -re_msg = re.compile ('(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?' - '([^ ]+)(?: +(.*))?\r\n$') -re_args = re.compile (':?((?<=:).*|[^ ]+) *') - -def parse (line): - global re_msg - global re_args - - m = re_msg.match (line) - if m == None: - return None - - (nick, user, host, command, args) = m.groups () - if args == None: - args = [] - else: - args = re_args.findall (args) - - return (nick, user, host, command, args) - -def get_config (key): - print ("ZYKLONB get_config :%s" % key) - (_, _, _, _, args) = parse (sys.stdin.readline ()) - return args[0] - -def bot_print (what): - print ('ZYKLONB print :%s' % what) - -youtube_api_key = get_config ('youtube_api_key') -if youtube_api_key == "": - bot_print ("youtube: missing `youtube_api_key'") - -print ("ZYKLONB register") - -regexes = list (map (lambda x: re.compile (x), [ - 'youtube\\.[a-z]+/[^ ]*[&?]v=([-_A-Za-z0-9]+)', - 'youtube\\.[a-z]+/v/([-_A-Za-z0-9]+)', - 'youtu\\.be/([-_A-Za-z0-9]+)' -])) - -def print_video_info (channel, video_id): - global youtube_api_key - url = 'https://www.googleapis.com/youtube/v3/' \ - + 'videos?id=%s&key=%s&part=snippet,contentDetails,statistics' \ - % (video_id, youtube_api_key) - - try: - data = json.loads (urllib.request.urlopen - (url, None, 30).read ().decode ('utf-8')) - - for x in data['items']: - desc = "YouTube: " - desc += x['snippet']['title'] + ' | ' - desc += x['contentDetails']['duration'][2:].lower () + ' | ' - desc += x['statistics']['viewCount'] + 'x' - print ("PRIVMSG %s :%s" % (channel, - desc.encode ('utf-8').decode ('iso8859-1'))) - - except Exception as err: - bot_print ('youtube: %s' % (err)) - -for line in sys.stdin: - msg = parse (line) - if msg == None: - continue - - (nick, user, host, command, args) = msg - if command != 'PRIVMSG' or len (args) < 2: - continue - - ctx = args[0] - if not ctx.startswith (('#', '+', '&', '!')): - ctx = nick - - for regex in regexes: - for i in regex.findall (args[1]): - print_video_info (ctx, i) +YouTube ().run ()