168 lines
5.3 KiB
Python
168 lines
5.3 KiB
Python
from collections import defaultdict
|
|
|
|
import xbmcgui
|
|
import xbmcplugin
|
|
import json
|
|
|
|
from . import tvdb
|
|
from .nfo import parse_episode_guide_url
|
|
from .utils import logger
|
|
from .series import get_unique_ids, ARTWORK_URL_PREFIX
|
|
|
|
|
|
# add the episodes of a series to the list
|
|
|
|
|
|
def get_series_episodes(show_ids, settings, handle):
|
|
logger.debug(f'Find episodes of tvshow with id {id}')
|
|
try:
|
|
all_ids = json.loads(show_ids)
|
|
show_id = all_ids.get('tvdb')
|
|
if not show_id:
|
|
show_id = str(show_ids)
|
|
except (ValueError, AttributeError):
|
|
show_id = str(show_ids)
|
|
if show_id.isdigit():
|
|
logger.error(
|
|
'using deprecated episodeguide format, this show should be refreshed or rescraped')
|
|
if not show_id:
|
|
raise RuntimeError(
|
|
'No tvdb show id found in episode guide, this show should be refreshed or rescraped')
|
|
elif not str(show_id).isdigit():
|
|
# Kodi has a bug: when a show directory contains an XML NFO file with
|
|
# episodeguide URL, that URL is always passed here regardless of
|
|
# the actual parsing result in get_show_id_from_nfo()
|
|
parse_result = parse_episode_guide_url(show_id)
|
|
if not parse_result:
|
|
return
|
|
|
|
if parse_result.provider == 'thetvdb':
|
|
show_id = parse_result.show_id
|
|
logger.debug(f'Changed show id to {show_id}')
|
|
|
|
client = tvdb.Client(settings)
|
|
episodes = client.get_series_episodes_api(show_id, settings)
|
|
|
|
if not episodes:
|
|
xbmcplugin.setResolvedUrl(
|
|
handle, False, xbmcgui.ListItem(offscreen=True))
|
|
return
|
|
|
|
for ep in episodes:
|
|
liz = xbmcgui.ListItem(ep['name'], offscreen=True)
|
|
details = {
|
|
'title': ep['name'],
|
|
'season': ep['seasonNumber'],
|
|
'episode': ep['number'],
|
|
}
|
|
date_string = ep.get("aired")
|
|
if date_string:
|
|
year = int(date_string.split("-")[0])
|
|
details['premiered'] = details['date'] = date_string
|
|
details['year'] = year
|
|
details['aired'] = ep['aired']
|
|
logger.debug("details in episodes.py")
|
|
logger.debug(details)
|
|
liz.setInfo('video', details)
|
|
xbmcplugin.addDirectoryItem(
|
|
handle=handle,
|
|
url=str(ep['id']),
|
|
listitem=liz,
|
|
isFolder=True
|
|
)
|
|
|
|
# get the details of the found episode
|
|
def get_episode_details(id, settings, handle):
|
|
logger.debug(f'Find info of episode with id {id}')
|
|
client = tvdb.Client(settings)
|
|
ep = client.get_episode_details_api(id, settings)
|
|
if not ep:
|
|
xbmcplugin.setResolvedUrl(
|
|
handle, False, xbmcgui.ListItem(offscreen=True))
|
|
return
|
|
liz = xbmcgui.ListItem(ep["name"], offscreen=True)
|
|
cast = get_episode_cast(ep)
|
|
rating = get_rating(ep)
|
|
tags = get_tags(ep)
|
|
duration_minutes = ep.get('runtime') or 0
|
|
|
|
details = {
|
|
'title': ep["name"],
|
|
'plot': ep["overview"],
|
|
'plotoutline': ep["overview"],
|
|
'premiered': ep["aired"],
|
|
'aired': ep["aired"],
|
|
'mediatype': 'episode',
|
|
'director': cast["directors"],
|
|
'writer': cast["writers"],
|
|
'mpaa': rating,
|
|
'duration': duration_minutes * 60,
|
|
}
|
|
|
|
if ep.get("airsAfterSeason"):
|
|
details['sortseason'] = ep.get("airsAfterSeason")
|
|
details['sortepisode'] = 4096
|
|
if ep.get("airsBeforeSeason"):
|
|
details['sortseason'] = ep.get("airsBeforeSeason")
|
|
details['sortepisode'] = 0
|
|
if ep.get("airsBeforeEpisode"):
|
|
details['sortepisode'] = ep.get("airsBeforeEpisode")
|
|
if tags:
|
|
details["tag"] = tags
|
|
|
|
|
|
liz.setInfo('video', details)
|
|
|
|
unique_ids = get_unique_ids(ep)
|
|
liz.setUniqueIDs(unique_ids, 'tvdb')
|
|
guest_stars = cast['guest_stars']
|
|
if guest_stars:
|
|
liz.setCast(guest_stars)
|
|
if ep.get("image"):
|
|
liz.addAvailableArtwork(ep["image"], 'thumb')
|
|
xbmcplugin.setResolvedUrl(
|
|
handle=handle,
|
|
succeeded=True,
|
|
listitem=liz)
|
|
|
|
|
|
def get_episode_cast(ep):
|
|
cast = defaultdict(list)
|
|
characters = ep.get('characters')
|
|
if characters:
|
|
for char in characters:
|
|
if char['peopleType'] == 'Writer':
|
|
cast['writers'].append(char['personName'])
|
|
elif char['peopleType'] == 'Director':
|
|
cast['writers'].append(char['personName'])
|
|
elif char['peopleType'] == 'Guest Star':
|
|
person_info = {'name': char.get('personName') or ''}
|
|
thumbnail = char.get('image') or char.get('personImgURL') or ''
|
|
if thumbnail and not thumbnail.startswith(ARTWORK_URL_PREFIX):
|
|
thumbnail = ARTWORK_URL_PREFIX + thumbnail
|
|
if thumbnail:
|
|
person_info['thumbnail'] = thumbnail
|
|
cast['guest_stars'].append(person_info)
|
|
return cast
|
|
|
|
|
|
def get_rating(ep):
|
|
ratings = ep.get("contentRatings", [])
|
|
rating = ''
|
|
if len(ratings) == 1:
|
|
rating = ratings[0]['country'] + ': ' + ratings[0]["name"]
|
|
if not rating:
|
|
for r in ratings:
|
|
if r["country"] == "usa":
|
|
rating = 'USA: ' + r["name"]
|
|
return rating
|
|
|
|
|
|
def get_tags(ep):
|
|
tags = []
|
|
tag_options = ep.get("tagOptions", [])
|
|
if tag_options:
|
|
for tag in tag_options:
|
|
tags.append(tag["name"])
|
|
return tags
|