twitch: handle clips/streams/videos/channels

This commit is contained in:
Gordon Shumway 2019-12-11 18:40:09 -05:00 committed by GitHub
parent 7288c00f99
commit 348fe57d11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 195 additions and 68 deletions

View File

@ -14,6 +14,7 @@ import supybot.utils as utils
import re
import requests
import urllib
import sys
try:
from urllib import urlencode
from urlparse import urlparse, parse_qsl
@ -755,9 +756,9 @@ class SpiffyTitles(callbacks.Plugin):
def get_twitch_logo(self):
use_bold = self.registryValue("useBold", dynamic.channel)
if use_bold:
twitch_logo = "{0}\x0F\x02".format(self.registryValue("twitchLogo", dynamic.channel))
twitch_logo = "{0}\x0F\x02".format(self.registryValue("twitch.twitchLogo", dynamic.channel))
else:
twitch_logo = "{0}\x0F".format(self.registryValue("twitchLogo", dynamic.channel))
twitch_logo = "{0}\x0F".format(self.registryValue("twitch.twitchLogo", dynamic.channel))
return twitch_logo
@ -825,76 +826,190 @@ class SpiffyTitles(callbacks.Plugin):
else:
log.debug("SpiffyTitles: default handler fired but doing nothing because disabled")
def handler_twitch(self, url, info, channel):
def handler_twitch(self, url, domain, channel):
"""
Handles twitch.tv links, querying the Twitch API for additional info
Typical Twitch URL:
Queries twitch API for additional information about twitch links.
This handler is for (www.)twitch.tv
"""
apikey = self.registryValue('twitchAPI')
headers = {'Client-ID': apikey}
result = None
if not self.registryValue("twitchHandlerEnabled", channel=channel):
log.debug("SpiffyTitles: Twitch handler disabled. Falling back to default handler.")
twitch_client_id = self.registryValue("twitch.clientID")
twitch_handler_enabled = self.registryValue("twitchHandlerEnabled", channel=channel)
if not twitch_handler_enabled or not twitch_client_id:
return self.handler_default(url, channel)
twitch_template = Template(self.registryValue("twitchTemplate"))
url = url.split("?")[0]
twitch_id = url.split("/")[-1].rstrip("/")
stream_url = "https://api.twitch.tv/helix/streams?user_login=%s" % (twitch_id)
user_url = "https://api.twitch.tv/helix/users?login=%s" % (twitch_id)
request_stream = requests.get(stream_url, timeout=10, headers=headers)
request_user = requests.get(user_url, timeout=10, headers=headers)
title, live, game_name, stream_viewers, total_viewers, started_at, display_name, description = "", "", "", "", "", "", "", ""
if request_stream.status_code == requests.codes.ok:
stream = json.loads(request_stream.text)
#log.debug("SpiffyTitles: Twitch stream data: %s" % (stream))
result = None
no_stream = "Error" in request_stream
if no_stream or not stream["data"]:
log.debug("SpiffyTitles: Twitch stream error for %s" % (stream_url))
else:
items = stream["data"][0]
title = items["title"]
live = True
if items["game_id"]:
game_id = items["game_id"]
get_game = requests.get("https://api.twitch.tv/helix/games?id={}".format(game_id), timeout=10, headers=headers)
game_data = json.loads(get_game.text)
game_name = game_data["data"][0]["name"]
stream_viewers = items["viewer_count"]
started_at = self._time_created_at(items["started_at"])
else:
log.error("SpiffyTitles Twitch Stream API %s - %s" % (request_stream.status_code, request_stream.text))
if request_user.status_code == requests.codes.ok:
user_data = json.loads(request_user.text)
#log.debug("SpiffyTitles: Twitch user data: %s" % (user_data))
result = None
no_user = "Error" in request_user
if no_user or not user_data["data"]:
log.debug("SpiffyTitles: Twitch user error for %s" % (user_url))
else:
items = user_data["data"][0]
display_name = items["display_name"]
description = items["description"]
total_viewers = items["view_count"]
else:
log.error("SpiffyTitles Twitch User API %s - %s" % (request_user.status_code, request_user.text))
twitch_logo = self.get_twitch_logo()
compiled_template = twitch_template.render({
"title": title,
"display_name": display_name,
"description": description,
"live": live,
"started_at": started_at,
"game_name": game_name,
"total_viewers": total_viewers,
"stream_viewers": stream_viewers,
"twitch_logo": twitch_logo})
result = compiled_template
if result is not None:
return result
else:
log.debug("SpiffyTitles: Twitch handler failed. calling default handler")
self.log.debug("SpiffyTitles: calling twitch handler for %s" % (url))
patterns = {
"video": {
"pattern": r"^http(s)?:\/\/(www\.|go\.|player\.)?twitch\.tv\/(videos/|\?video=v)(?P<video_id>[0-9]+)",
"url": "https://api.twitch.tv/helix/videos?id={video_id}"
},
"clip": {
"pattern": r"http(s)?:\/\/clips\.twitch\.tv\/(?P<clip>.+)$",
"url": "https://api.twitch.tv/helix/clips?id={clip}"
},
"channel": {
"pattern": r"^http(s)?:\/\/(www\.|go\.)?twitch\.tv\/(?P<channel_name>[^\/]+)",
"url": "https://api.twitch.tv/helix/streams?user_login={channel_name}"
}
}
for name in patterns:
match = re.search(patterns[name]['pattern'], url)
if match:
link_type = name
link_info = match.groupdict()
data_url = patterns[name]['url'].format(**link_info)
break
if not match:
self.log.debug("SpiffyTitles: twitch - no title found.")
return self.handler_default(url, channel)
agent = self.get_user_agent()
headers = {
"Client-ID": twitch_client_id
}
self.log.debug("SpiffyTitles: twitch - requesting %s" % (data_url))
request = requests.get(data_url, timeout=10, headers=headers)
ok = request.status_code == requests.codes.ok
data = {}
extract = ""
if ok:
response = json.loads(request.text)
if response:
self.log.debug("SpiffyTitles: twitch - got response:\n%s" % (response))
if 'error' in response:
return "[ Twitch ] - Error!"
try:
if link_type == "channel":
self.log.debug("SpiffyTitles: Twitch: link_type is channel")
if 'data' in response and response['data']:
self.log.debug("SpiffyTitles: Twitch: Got data[0]")
data = response['data'][0]
link_type = 'stream'
else:
self.log.debug("SpiffyTitles: Twitch: No data[0]")
data_url = 'https://api.twitch.tv/helix/users?login={channel_name}'.format(**link_info)
request = requests.get(data_url, timeout=10, headers=headers)
ok = request.status_code == requests.codes.ok
user_data = {}
if not ok:
self.log.error("SpiffyTitles: twitch HTTP %s: %s" % (request.status_code, request.text))
else:
response = json.loads(request.text)
if not response:
self.log.error("SpiffyTitles: Error parsing Twitch JSON response")
else:
if 'error' in response:
self.log.error("SpiffyTitles: twitch - error in JSON response")
return self.handler_default(url, channel)
try:
user_data = response['data'][0]
display_name = user_data['display_name']
description = user_data['description']
view_count = user_data['view_count']
except KeyError as e:
self.log.error("SpiffyTitles: KeyError parsing Twitch.TV JSON response: %s" % (str(e)))
elif link_type == "video":
data = response
elif link_type == 'clip':
data = response
except KeyError as e:
self.log.error("SpiffyTitles: KeyError parsing Twitch.TV JSON response: %s" % (str(e)))
if data or user_data:
self.log.debug("SpiffyTitles: twitch - Got data '%s'" % (data))
twitch_template = self.get_template(''.join(["twitch.", link_type, "Template"]), channel)
twitch_logo = self.get_twitch_logo()
if not twitch_template:
self.log.debug("SpiffyTitles - twitch: bad template for %s" % (link_type))
reply = "[ Twitch.TV ] - Got data, but template was bad"
elif link_type == 'stream':
display_name = data['user_name']
game_id = data['game_id']
game_name = game_id
title = data['title']
view_count = data['viewer_count']
created_at = self._time_created_at(data['started_at'])
if game_id:
get_game = requests.get("https://api.twitch.tv/helix/games?id={}".format(game_id), timeout=10, headers=headers)
game_data = json.loads(get_game.text)
game_name = game_data["data"][0]["name"]
template_vars = {
"display_name": display_name,
"game_name": game_name,
"title": title,
"view_count": view_count,
"description": description,
"created_at": created_at,
"twitch_logo": twitch_logo
}
reply = twitch_template.render(template_vars)
elif link_type == 'clip':
data = response['data'][0]
display_name = data['broadcaster_name']
game_id = data['game_id']
game_name = game_id
title = data['title']
view_count = data['view_count']
created_at = self._time_created_at(data['created_at'])
if game_id:
get_game = requests.get("https://api.twitch.tv/helix/games?id={}".format(game_id), timeout=10, headers=headers)
game_data = json.loads(get_game.text)
game_name = game_data["data"][0]["name"]
template_vars = {
"display_name": display_name,
"game_name": game_name,
"title": title,
"view_count": view_count,
"description": description,
"created_at": created_at,
"twitch_logo": twitch_logo
}
reply = twitch_template.render(template_vars)
elif link_type == 'video':
data = response['data'][0]
display_name = data['user_name']
data_url = 'https://api.twitch.tv/helix/users?login={}'.format(display_name)
request = requests.get(data_url, timeout=10, headers=headers)
ok = request.status_code == requests.codes.ok
user_data = {}
if not ok:
self.log.error("SpiffyTitles: twitch HTTP %s: %s" % (request.status_code, request.text))
else:
response = json.loads(request.text)
if not response:
self.log.error("SpiffyTitles: Error parsing Twitch JSON response")
else:
if 'error' in response:
self.log.error("SpiffyTitles: twitch - error in JSON response")
return self.handler_default(url, channel)
try:
user_data = response['data'][0]
display_name = user_data['display_name']
description = user_data['description']
view_count = user_data['view_count']
except KeyError as e:
self.log.error("SpiffyTitles: KeyError parsing Twitch.TV JSON response: %s" % (str(e)))
display_name = data['user_name']
title = data['title']
view_count = data['view_count']
created_at = self._time_created_at(data['created_at'])
duration = data['duration']
template_vars = {
"display_name": display_name,
"title": title,
"view_count": view_count,
"created_at": created_at,
"description": description,
"duration": duration,
"twitch_logo": twitch_logo
}
reply = twitch_template.render(template_vars)
else:
template_vars = {
"display_name": display_name,
"description": description,
"view_count": view_count,
"twitch_logo": twitch_logo
}
reply = twitch_template.render(template_vars)
self.log.debug("SpiffyTitles: twitch - reply = '%s'" % (reply))
return reply
def _time_created_at(self, s):
"""
@ -1548,4 +1663,16 @@ class SpiffyTitles(callbacks.Plugin):
return has_cap
def get_template(self, handler_template, channel):
"""
Returns the requested template object.
"""
if sys.version_info[0] >= 3:
template = Template(self.registryValue(handler_template,
channel=channel))
else:
template = Template(self.registryValue(handler_template,
channel=channel).decode("utf-8"))
return template
Class = SpiffyTitles