From 3573bac4a97641bbfe36b1b6d1c02ed659fa7386 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 3 Sep 2013 03:00:55 +0800 Subject: [PATCH 1/2] Far less page scraping, far more API. There's API for highlights and channels, so I need to find an information API for broadcasts next. --- plugins/twitch.py | 134 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 33 deletions(-) diff --git a/plugins/twitch.py b/plugins/twitch.py index e0d0bd3..ae20035 100644 --- a/plugins/twitch.py +++ b/plugins/twitch.py @@ -1,45 +1,113 @@ import re from util import hook, http -import json +from HTMLParser import HTMLParser twitch_re = (r'(.*:)//(twitch.tv|www.twitch.tv)(:[0-9]+)?(.*)', re.I) -valid = set('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_/') +multitwitch_re = (r'(.*:)//(www.multitwitch.tv|multitwitch.tv)/(.*)', re.I) + def test(s): - return set(s) <= valid + valid = set('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_/') + return set(s) <= valid + + +def truncate(msg): + nmsg = msg.split(" ") + out = None + x = 0 + for i in nmsg: + if x <= 7: + if out: + out = out + " " + nmsg[x] + else: + out = nmsg[x] + x = x + 1 + if x <= 7: + return out + else: + return out + "..." + + +@hook.regex(*multitwitch_re) +def multitwitch_url(match): + usernames = match.group(3).split("/") + out = "" + for i in usernames: + if not test(i): + print "Not a valid username" + return None + if out == "": + out = twitch_lookup(i) + else: + out = out + " \x02|\x02 " + twitch_lookup(i) + return out + @hook.regex(*twitch_re) -def twitch_url(match): - location = "/".join(match.group(4).split("/")[1:]) - if not test(match.group(4).split("/")[1]): - return "Not a valid username" - soup = http.get_soup("http://twitch.tv/" + location) - try: - title = soup.findAll('span', {'class': 'real_title js-title'})[0].text - except IndexError: - return "That user has no stream or videos." - isplaying = http.get_json("http://api.justin.tv/api/stream/list.json?channel=%s" % location) +def twitch_url(match, chan=''): + bit = match.group(4).split("#")[0] + location = "/".join(bit.split("/")[1:]) + if not test(location): + print "Not a valid username" + return None + return twitch_lookup(location) + + +@hook.command('twitchviewers') +@hook.command +def twviewers(inp): + inp = inp.split("/")[-1] + if test(inp): + location = inp + else: + return "Not a valid channel name." + isplaying = http.get_json("http://api.justin.tv/api/" + "stream/list.json?channel=%s" % location) if isplaying: - online = True - watchers = isplaying[0]["channel_count"] + return isplaying[0]["channel_count"] else: - online = False - try: - name = soup.findAll('a', {'class': 'channel_name'})[0].text - except IndexError: - name = soup.findAll('a', {'class': 'channelname'})[0].text - playing = soup.findAll('a', {'class': 'game js-game'})[0].text - if playing == "/directory/game/": - np = False + return "Not online" + + +def twitch_lookup(location): + locsplit = location.split("/") + if len(locsplit) > 1 and len(locsplit) == 3: + channel = locsplit[0] + type = locsplit[1] # should be b or c + id = locsplit[2] else: - np = True - if online: - if np: - return u"%s: %s playing %s (\x033\x02Online now!\x02\x0f %s viewers)" % (title, name, playing, watchers) - else: - return u"%s: %s (\x033\x02Online now!\x02\x0f %s viewers)" % (title, name, watchers) + channel = locsplit[0] + type = None + id = None + h = HTMLParser() + fmt = "{}: {} playing {} ({})" # Title: nickname playing Game (x views) + if type and id: + if type == "b": # I haven't found an API to retrieve broadcast info + soup = http.get_soup("http://twitch.tv/" + location) + title = soup.find('span', {'class': 'real_title js-title'}).text + playing = soup.find('a', {'class': 'game js-game'}).text + views = soup.find('span', {'id': 'views-count'}).text + " view" + views = views + "s" if views == "1 view" else views + return h.unescape(fmt.format(title, channel, playing, views)) + elif type == "c": + data = http.get_json("https://api.twitch.tv/kraken/videos/" + type + id) + title = data['title'] + playing = data['game'] + views = str(data['views']) + " view" + views = views + "s" if views == "1 view" else views + return h.unescape(fmt.format(title, channel, playing, views)) else: - if np: - return u"%s: %s playing %s (\x034\x02Offline\x02\x0f)" % (title, name, playing) - else: - return u"%s: %s (\x034\x02Offline\x02\x0f)" % (title, name) + data = http.get_json("http://api.justin.tv/api/stream/list.json?channel=" + channel)[0] + if data: + title = data['status'] + playing = data['game'] + viewers = "\x033\x02Online now!\x02\x0f " + + str(data["channel_count"]) + " viewer" + viewers = viewers + "s" if viewers == "1 view" else viewers + return h.unescape(fmt.format(title, channel, playing, viewers)) + else: + data = http.get_json("https://api.twitch.tv/kraken/channels/" + channel) + title = data['status'] + playing = data['game'] + viewers = "\x034\x02Offline\x02\x0f" + return h.unescape(fmt.format(title, channel, playing, viewers)) From 5d89f4d5981fa0b9f966bff137bcb149195709b1 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 3 Sep 2013 03:22:34 +0800 Subject: [PATCH 2/2] My logic is really terrible views = views + "s" if *not* views == 1, you idiot. --- plugins/twitch.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/plugins/twitch.py b/plugins/twitch.py index ae20035..c5143ab 100644 --- a/plugins/twitch.py +++ b/plugins/twitch.py @@ -61,12 +61,7 @@ def twviewers(inp): location = inp else: return "Not a valid channel name." - isplaying = http.get_json("http://api.justin.tv/api/" - "stream/list.json?channel=%s" % location) - if isplaying: - return isplaying[0]["channel_count"] - else: - return "Not online" + return twitch_lookup(location).split("(")[-1].split(")")[0].replace("Online now! ", "") def twitch_lookup(location): @@ -87,23 +82,24 @@ def twitch_lookup(location): title = soup.find('span', {'class': 'real_title js-title'}).text playing = soup.find('a', {'class': 'game js-game'}).text views = soup.find('span', {'id': 'views-count'}).text + " view" - views = views + "s" if views == "1 view" else views + views = views + "s" if not views[0:2] == "1 " else views return h.unescape(fmt.format(title, channel, playing, views)) elif type == "c": data = http.get_json("https://api.twitch.tv/kraken/videos/" + type + id) title = data['title'] playing = data['game'] views = str(data['views']) + " view" - views = views + "s" if views == "1 view" else views + views = views + "s" if not views[0:2] == "1 " else views return h.unescape(fmt.format(title, channel, playing, views)) else: data = http.get_json("http://api.justin.tv/api/stream/list.json?channel=" + channel)[0] if data: - title = data['status'] - playing = data['game'] - viewers = "\x033\x02Online now!\x02\x0f " + - str(data["channel_count"]) + " viewer" - viewers = viewers + "s" if viewers == "1 view" else viewers + title = data['title'] + playing = data['meta_game'] + viewers = "\x033\x02Online now!\x02\x0f " + str(data["channel_count"]) + " viewer" + print viewers + viewers = viewers + "s" if not " 1 view" in viewers else viewers + print viewers return h.unescape(fmt.format(title, channel, playing, viewers)) else: data = http.get_json("https://api.twitch.tv/kraken/channels/" + channel)