channel info support for youtube handler

This commit is contained in:
Matias Wilkman 2024-01-18 07:51:56 +02:00
parent 5d1ca4bf86
commit c13b7c1369

View File

@ -805,11 +805,53 @@ class SpiffyTitles(callbacks.Plugin):
"SpiffyTitles: error getting video id from %s (%s)" % (url, str(e)) "SpiffyTitles: error getting video id from %s (%s)" % (url, str(e))
) )
def get_channel_id_from_url(self, url, info, api_key):
"""
Get YouTube channel ID from URL
"""
try:
parsed_url = urlparse(url)
if 'youtube.com' in parsed_url.netloc:
path_parts = parsed_url.path.split('/')
# URL of the form https://www.youtube.com/user/username or https://www.youtube.com/@username:
if 'user' in path_parts:
username = path_parts[path_parts.index('user') + 1]
api_url = 'https://www.googleapis.com/youtube/v3/channels'
log.debug("SpiffyTitles: requesting %s" % (api_url))
try:
request = requests.get(
api_url, timeout=self.timeout, proxies=self.proxies,
params={
'part': 'id',
'forUsername': username,
'key': api_key
}
)
request.raise_for_status()
data = json.loads(request.content.decode())
if data['items']:
return data['items'][0]['id']
except (
requests.exceptions.RequestException,
requests.exceptions.HTTPError,
) as e:
log.error("SpiffyTitles: YouTube Error: {0}".format(e))
# URL of the form https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw:
elif 'channel' in path_parts:
return path_parts[path_parts.index('channel') + 1]
# TODO: figure out a way to handle https://www.youtube.com/@GoogleDevelopers style URLs
return None
except Exception as e:
log.error(
"SpiffyTitles: error getting channel id from %s (%s)" % (url, str(e))
)
def handler_youtube(self, url, domain, channel): def handler_youtube(self, url, domain, channel):
""" """
Uses the Youtube API to provide additional meta data about Uses the Youtube API to provide additional meta data about
Youtube Video links posted. Youtube Video links posted.
""" """
type = "video"
youtube_handler_enabled = self.registryValue("youtube.enabled", channel) youtube_handler_enabled = self.registryValue("youtube.enabled", channel)
if not youtube_handler_enabled: if not youtube_handler_enabled:
return self.handler_default(url, channel) return self.handler_default(url, channel)
@ -826,90 +868,142 @@ class SpiffyTitles(callbacks.Plugin):
log.debug( log.debug(
"SpiffyTitles: Failed to get YouTube video ID for URL: {0}".format(url) "SpiffyTitles: Failed to get YouTube video ID for URL: {0}".format(url)
) )
return self.handler_default(url, channel) channel_id = self.get_channel_id_from_url(url, domain, developer_key)
if not channel_id:
return self.handler_default(url, channel)
else:
type = "channel"
else:
type = "video"
yt_template = Template(self.registryValue("youtube.template", channel)) yt_template = Template(self.registryValue("youtube.template", channel))
title = "" title = ""
options = { if type == "video":
"part": "snippet,statistics,contentDetails", options = {
"maxResults": 1, "part": "snippet,statistics,contentDetails",
"key": developer_key, "maxResults": 1,
"id": video_id, "key": developer_key,
} "id": video_id,
api_url = "https://www.googleapis.com/youtube/v3/videos" }
log.debug("SpiffyTitles: requesting %s" % (api_url)) api_url = "https://www.googleapis.com/youtube/v3/videos"
try: log.debug("SpiffyTitles: requesting %s" % (api_url))
request = requests.get( try:
api_url, params=options, timeout=self.timeout, proxies=self.proxies request = requests.get(
) api_url, params=options, timeout=self.timeout, proxies=self.proxies
request.raise_for_status() )
except ( request.raise_for_status()
requests.exceptions.RequestException, except (
requests.exceptions.HTTPError, requests.exceptions.RequestException,
) as e: requests.exceptions.HTTPError,
log.error("SpiffyTitiles: YouTube Error: {0}".format(e)) ) as e:
return self.handler_default(url, channel) log.error("SpiffyTitles: YouTube Error: {0}".format(e))
response = json.loads(request.content.decode()) return self.handler_default(url, channel)
if not response or not response.get("items"): response = json.loads(request.content.decode())
log.error("SpiffyTitles: Failed to parse YouTube JSON response") if not response or not response.get("items"):
return self.handler_default(url, channel) log.error("SpiffyTitles: Failed to parse YouTube JSON response")
try: return self.handler_default(url, channel)
items = response["items"] try:
video = items[0] items = response["items"]
snippet = video["snippet"] video = items[0]
title = snippet["title"] snippet = video["snippet"]
statistics = video["statistics"] title = snippet["title"]
view_count = 0 statistics = video["statistics"]
like_count = 0 view_count = 0
dislike_count = 0 like_count = 0
comment_count = 0 dislike_count = 0
favorite_count = 0 comment_count = 0
restricted = False favorite_count = 0
if "viewCount" in statistics: restricted = False
view_count = "{:,}".format(int(statistics["viewCount"])) if "viewCount" in statistics:
if "likeCount" in statistics: view_count = "{:,}".format(int(statistics["viewCount"]))
like_count = "{:,}".format(int(statistics["likeCount"])) if "likeCount" in statistics:
if "dislikeCount" in statistics: like_count = "{:,}".format(int(statistics["likeCount"]))
dislike_count = "{:,}".format(int(statistics["dislikeCount"])) if "dislikeCount" in statistics:
if "favoriteCount" in statistics: dislike_count = "{:,}".format(int(statistics["dislikeCount"]))
favorite_count = "{:,}".format(int(statistics["favoriteCount"])) if "favoriteCount" in statistics:
if "commentCount" in statistics: favorite_count = "{:,}".format(int(statistics["favoriteCount"]))
comment_count = "{:,}".format(int(statistics["commentCount"])) if "commentCount" in statistics:
channel_title = snippet["channelTitle"] comment_count = "{:,}".format(int(statistics["commentCount"]))
video_duration = video["contentDetails"]["duration"] channel_title = snippet["channelTitle"]
duration_seconds = self.get_total_seconds_from_duration(video_duration) video_duration = video["contentDetails"]["duration"]
""" duration_seconds = self.get_total_seconds_from_duration(video_duration)
#23 - If duration is zero, then it"s a LIVE video """
""" #23 - If duration is zero, then it"s a LIVE video
if duration_seconds > 0: """
duration = self.get_duration_from_seconds(duration_seconds) if duration_seconds > 0:
else: duration = self.get_duration_from_seconds(duration_seconds)
duration = "LIVE" else:
if "ytRating" in video["contentDetails"]["contentRating"]: duration = "LIVE"
restricted = True if "ytRating" in video["contentDetails"]["contentRating"]:
published = snippet["publishedAt"].split("T")[0] restricted = True
timestamp = self.get_timestamp_from_youtube_url(url) published = snippet["publishedAt"].split("T")[0]
yt_logo = self.get_youtube_logo(channel) timestamp = self.get_timestamp_from_youtube_url(url)
compiled_template = yt_template.render( yt_logo = self.get_youtube_logo(channel)
{ compiled_template = yt_template.render(
"title": title, {
"duration": duration, "title": title,
"timestamp": timestamp, "duration": duration,
"view_count": view_count, "timestamp": timestamp,
"like_count": like_count, "view_count": view_count,
"dislike_count": dislike_count, "like_count": like_count,
"comment_count": comment_count, "dislike_count": dislike_count,
"favorite_count": favorite_count, "comment_count": comment_count,
"channel_title": channel_title, "favorite_count": favorite_count,
"published": published, "channel_title": channel_title,
"restricted": restricted, "published": published,
"yt_logo": yt_logo, "restricted": restricted,
} "yt_logo": yt_logo,
) }
title = compiled_template )
except IndexError as e: title = compiled_template
log.error( except IndexError as e:
"SpiffyTitles: IndexError. Youtube API JSON response: %s" % (str(e)) log.error(
) "SpiffyTitles: IndexError. Youtube API JSON response: %s" % (str(e))
)
elif type == "channel":
options = {
"part": "snippet,statistics,contentDetails",
"maxResults": 1,
"key": developer_key,
"id": channel_id,
}
api_url = "https://www.googleapis.com/youtube/v3/channels"
log.debug("SpiffyTitles: requesting %s" % (api_url))
try:
request = requests.get(
api_url, params=options, timeout=self.timeout, proxies=self.proxies
)
request.raise_for_status()
except (
requests.exceptions.RequestException,
requests.exceptions.HTTPError,
) as e:
log.error("SpiffyTitles: YouTube Error: {0}".format(e))
return self.handler_default(url, channel)
response = json.loads(request.content.decode())
if not response or not response.get("items"):
log.error("SpiffyTitles: Failed to parse YouTube JSON response")
return self.handler_default(url, channel)
try:
items = response["items"]
channel = items[0]
snippet = channel["snippet"]
title = snippet["title"]
statistics = channel["statistics"]
view_count = 0
subscriber_count = 0
video_count = 0
if "viewCount" in statistics:
view_count = "{:,}".format(int(statistics["viewCount"]))
if "subscriberCount" in statistics:
subscriber_count = "{:,}".format(int(statistics["subscriberCount"]))
if "videoCount" in statistics:
video_count = "{:,}".format(int(statistics["videoCount"]))
yt_logo = "YouTube" #self.get_youtube_logo(channel) #FIXME: why doesn't work here?
title = yt_logo + " :: " + "Channel: " + title + " :: Views: " + view_count + " :: Subscribers: " + subscriber_count + " :: Videos: " + video_count
except IndexError as e:
log.error(
"SpiffyTitles: IndexError. Youtube API JSON response: %s" % (str(e))
)
# If we found a title, return that. otherwise, use default handler # If we found a title, return that. otherwise, use default handler
if title: if title:
return title return title