2016-10-10 08:19:00 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
##################################################################################################
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
import json
|
2016-10-10 08:19:00 +00:00
|
|
|
import logging
|
|
|
|
from ntpath import dirname
|
2018-09-06 08:36:32 +00:00
|
|
|
import urllib
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
from obj import Objects
|
|
|
|
from kodi import TVShows as KodiDb, queries as QU
|
|
|
|
import downloader as server
|
|
|
|
from database import emby_db, queries as QUEM
|
|
|
|
from helper import api, catch, stop, validate, emby_item, library_check, settings, values
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
##################################################################################################
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
LOG = logging.getLogger("EMBY."+__name__)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
##################################################################################################
|
|
|
|
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
class TVShows(KodiDb):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def __init__(self, server, embydb, videodb, direct_path):
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.server = server
|
|
|
|
self.emby = embydb
|
|
|
|
self.video = videodb
|
|
|
|
self.direct_path = direct_path
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.emby_db = emby_db.EmbyDatabase(embydb.cursor)
|
|
|
|
self.objects = Objects()
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
KodiDb.__init__(self, videodb.cursor)
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def __getitem__(self, key):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if key == 'Series':
|
|
|
|
return self.tvshow
|
|
|
|
elif key == 'Season':
|
|
|
|
return self.season
|
|
|
|
elif key == 'Episode':
|
|
|
|
return self.episode
|
|
|
|
elif key == 'UserData':
|
|
|
|
return self.userdata
|
|
|
|
elif key in 'Removed':
|
|
|
|
return self.remove
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
@stop()
|
|
|
|
@emby_item()
|
|
|
|
@library_check()
|
|
|
|
def tvshow(self, item, e_item, library):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
''' If item does not exist, entry will be added.
|
|
|
|
If item exists, entry will be updated.
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
If the show is empty, try to remove it.
|
|
|
|
Process seasons.
|
|
|
|
Apply series pooling.
|
|
|
|
'''
|
|
|
|
API = api.API(item, self.server['auth/server-address'])
|
|
|
|
obj = self.objects.map(item, 'Series')
|
|
|
|
update = True
|
2018-03-13 10:32:45 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not settings('syncEmptyShows.bool') and not obj['RecursiveCount']:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
LOG.info("Skipping empty show %s: %s", obj['Title'], obj['Id'])
|
|
|
|
self.remove(obj['Id'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
return False
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
try:
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['ShowId'] = e_item[0]
|
|
|
|
obj['PathId'] = e_item[2]
|
|
|
|
except TypeError as error:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
update = False
|
|
|
|
LOG.debug("ShowId %s not found", obj['Id'])
|
|
|
|
obj['ShowId'] = self.create_entry()
|
|
|
|
else:
|
|
|
|
if self.get(*values(obj, QU.get_tvshow_obj)) is None:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
update = False
|
|
|
|
LOG.info("ShowId %s missing from kodi. repairing the entry.", obj['ShowId'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Path'] = API.get_file_path(obj['Path'])
|
|
|
|
obj['LibraryId'] = library['Id']
|
|
|
|
obj['LibraryName'] = library['Name']
|
|
|
|
obj['Genres'] = obj['Genres'] or []
|
|
|
|
obj['People'] = obj['People'] or []
|
2018-09-06 19:46:20 +00:00
|
|
|
obj['Mpaa'] = API.get_mpaa(obj['Mpaa'])
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Studios'] = [API.validate_studio(studio) for studio in (obj['Studios'] or [])]
|
|
|
|
obj['Genre'] = " / ".join(obj['Genres'])
|
|
|
|
obj['People'] = API.get_people_artwork(obj['People'])
|
|
|
|
obj['Plot'] = API.get_overview(obj['Plot'])
|
|
|
|
obj['Studio'] = " / ".join(obj['Studios'])
|
|
|
|
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.get_path_filename(obj)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Premiere']:
|
|
|
|
obj['Premiere'] = str(obj['Premiere']).split('.')[0].replace('T', " ")
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
tags = []
|
|
|
|
tags.extend(obj['Tags'] or [])
|
|
|
|
tags.append(obj['LibraryName'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Favorite']:
|
|
|
|
tags.append('Favorite tvshows')
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Tags'] = tags
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if update:
|
|
|
|
self.tvshow_update(obj)
|
|
|
|
else:
|
|
|
|
self.tvshow_add(obj)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.link(*values(obj, QU.update_tvshow_link_obj))
|
|
|
|
self.update_path(*values(obj, QU.update_path_tvshow_obj))
|
|
|
|
self.add_tags(*values(obj, QU.add_tags_tvshow_obj))
|
|
|
|
self.add_people(*values(obj, QU.add_people_tvshow_obj))
|
|
|
|
self.add_genres(*values(obj, QU.add_genres_tvshow_obj))
|
|
|
|
self.add_studios(*values(obj, QU.add_studios_tvshow_obj))
|
|
|
|
self.artwork.add(obj['Artwork'], obj['ShowId'], "tvshow")
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
season_episodes = []
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
for season in self.server['api'].get_seasons(obj['Id'])['Items']:
|
|
|
|
self.season(season, obj['ShowId'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if season['SeriesId'] != obj['Id']:
|
|
|
|
obj['SeriesId'] = season['SeriesId']
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
try:
|
|
|
|
self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
|
|
|
except TypeError:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.emby_db.add_reference(*values(obj, QUEM.add_reference_pool_obj))
|
|
|
|
season_episodes.append(season['Id'])
|
|
|
|
LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId'])
|
|
|
|
else:
|
|
|
|
season_id = self.get_season(*values(obj, QU.get_season_special_obj))
|
|
|
|
self.artwork.add(obj['Artwork'], season_id, "season")
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
for season in season_episodes:
|
|
|
|
for episodes in server.get_items(season, "Episode"):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
for episode in episodes['Items']:
|
|
|
|
self.episode(episode)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def tvshow_add(self, obj):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
''' Add object to kodi.
|
|
|
|
'''
|
|
|
|
obj['RatingId'] = self.create_entry_rating()
|
|
|
|
self.add_ratings(*values(obj, QU.add_rating_tvshow_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Unique'] = self.create_entry_unique_id()
|
|
|
|
self.add_unique_id(*values(obj, QU.add_unique_id_tvshow_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['TopPathId'] = self.add_path(obj['TopLevel'])
|
|
|
|
self.update_path(*values(obj, QU.update_path_toptvshow_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['PathId'] = self.add_path(*values(obj, QU.get_path_obj))
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.add(*values(obj, QU.add_tvshow_obj))
|
|
|
|
self.emby_db.add_reference(*values(obj, QUEM.add_reference_tvshow_obj))
|
|
|
|
LOG.info("ADD tvshow [%s/%s/%s] %s: %s", obj['TopPathId'], obj['PathId'], obj['ShowId'], obj['Title'], obj['Id'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def tvshow_update(self, obj):
|
|
|
|
|
|
|
|
''' Update object to kodi.
|
|
|
|
'''
|
|
|
|
obj['RatingId'] = self.get_rating_id(*values(obj, QU.get_unique_id_tvshow_obj))
|
|
|
|
self.update_ratings(*values(obj, QU.update_rating_tvshow_obj))
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_tvshow_obj))
|
|
|
|
self.update_unique_id(*values(obj, QU.update_unique_id_tvshow_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.update(*values(obj, QU.update_tvshow_obj))
|
|
|
|
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
|
|
|
LOG.info("UPDATE tvshow [%s/%s] %s: %s", obj['PathId'], obj['ShowId'], obj['Title'], obj['Id'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def get_path_filename(self, obj):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
''' Get the path and build it into protocol://path
|
|
|
|
'''
|
|
|
|
if self.direct_path:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if '\\' in obj['Path']:
|
|
|
|
obj['Path'] = "%s\\" % obj['Path']
|
|
|
|
obj['TopLevel'] = "%s\\" % dirname(dirname(obj['Path']))
|
|
|
|
else:
|
|
|
|
obj['Path'] = "%s/" % obj['Path']
|
|
|
|
obj['TopLevel'] = "%s/" % dirname(dirname(obj['Path']))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not validate(obj['Path']):
|
|
|
|
raise Exception("Failed to validate path. User stopped.")
|
|
|
|
else:
|
|
|
|
obj['TopLevel'] = "plugin://plugin.video.emby.tvshows/"
|
|
|
|
obj['Path'] = "%s%s/" % (obj['TopLevel'], obj['Id'])
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
@stop()
|
|
|
|
def season(self, item, show_id=None):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
''' If item does not exist, entry will be added.
|
|
|
|
If item exists, entry will be updated.
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
If the show is empty, try to remove it.
|
|
|
|
'''
|
|
|
|
API = api.API(item, self.server['auth/server-address'])
|
|
|
|
obj = self.objects.map(item, 'Season')
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['ShowId'] = show_id
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['ShowId'] is None:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
try:
|
|
|
|
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
|
|
|
except (KeyError, TypeError):
|
|
|
|
LOG.error("Unable to add series %s", obj['SeriesId'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
return False
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['SeasonId'] = self.get_season(*values(obj, QU.get_season_obj))
|
|
|
|
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
|
2018-01-08 02:13:11 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Location'] != "Virtual":
|
|
|
|
self.emby_db.add_reference(*values(obj, QUEM.add_reference_season_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.artwork.add(obj['Artwork'], obj['SeasonId'], "season")
|
|
|
|
LOG.info("UPDATE season [%s/%s] %s: %s", obj['ShowId'], obj['SeasonId'], obj['Title'] or obj['Index'], obj['Id'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
@stop()
|
|
|
|
@emby_item()
|
|
|
|
def episode(self, item, e_item):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
''' If item does not exist, entry will be added.
|
|
|
|
If item exists, entry will be updated.
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
Create additional entry for widgets.
|
|
|
|
This is only required for plugin/episode.
|
|
|
|
'''
|
|
|
|
API = api.API(item, self.server['auth/server-address'])
|
|
|
|
obj = self.objects.map(item, 'Episode')
|
|
|
|
update = True
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Location'] == "Virtual":
|
|
|
|
LOG.info("Skipping virtual episode %s: %s", obj['Title'], obj['Id'])
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
return
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
elif obj['SeriesId'] is None:
|
|
|
|
LOG.info("Skipping episode %s with missing SeriesId", obj['Id'])
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
return
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
try:
|
|
|
|
obj['EpisodeId'] = e_item[0]
|
|
|
|
obj['FileId'] = e_item[1]
|
|
|
|
obj['PathId'] = e_item[2]
|
|
|
|
except TypeError as error:
|
|
|
|
|
|
|
|
update = False
|
|
|
|
LOG.debug("EpisodeId %s not found", obj['Id'])
|
|
|
|
obj['EpisodeId'] = self.create_entry_episode()
|
2017-09-03 19:10:04 +00:00
|
|
|
else:
|
2018-09-06 08:36:32 +00:00
|
|
|
if self.get_episode(*values(obj, QU.get_episode_obj)) is None:
|
|
|
|
|
|
|
|
update = False
|
|
|
|
LOG.info("EpisodeId %s missing from kodi. repairing the entry.", obj['EpisodeId'])
|
|
|
|
|
|
|
|
|
|
|
|
obj['Path'] = API.get_file_path(obj['Path'])
|
|
|
|
obj['Index'] = obj['Index'] or -1
|
|
|
|
obj['Writers'] = " / ".join(obj['Writers'] or [])
|
|
|
|
obj['Directors'] = " / ".join(obj['Directors'] or [])
|
|
|
|
obj['Plot'] = API.get_overview(obj['Plot'])
|
|
|
|
obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
|
|
|
|
obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
|
|
|
|
obj['People'] = API.get_people_artwork(obj['People'] or [])
|
|
|
|
obj['DateAdded'] = obj['DateAdded'].split('.')[0].replace('T', " ")
|
2018-09-07 18:18:31 +00:00
|
|
|
obj['DatePlayed'] = None if not obj['Played'] else (obj['DatePlayed'] or obj['DateAdded']).split('.')[0].replace('T', " ")
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])
|
|
|
|
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
|
|
|
|
obj['Video'] = API.video_streams(obj['Video'] or [], obj['Container'])
|
|
|
|
obj['Audio'] = API.audio_streams(obj['Audio'] or [])
|
|
|
|
obj['Streams'] = API.media_streams(obj['Video'], obj['Audio'], obj['Subtitles'])
|
|
|
|
|
|
|
|
self.get_episode_path_filename(obj)
|
|
|
|
|
|
|
|
if obj['Premiere']:
|
|
|
|
obj['Premiere'] = obj['Premiere'].split('.')[0].replace('T', " ")
|
|
|
|
|
|
|
|
if obj['Season'] is None:
|
|
|
|
if obj['AbsoluteNumber']:
|
|
|
|
|
|
|
|
obj['Season'] = 1
|
|
|
|
obj['Index'] = obj['AbsoluteNumber']
|
|
|
|
else:
|
|
|
|
obj['Season'] = 0
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['AirsAfterSeason']:
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['AirsBeforeSeason'] = obj['AirsAfterSeason']
|
|
|
|
obj['AirsBeforeEpisode'] = 4096 # Kodi default number for afterseason ordering
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['MultiEpisode']:
|
|
|
|
obj['MultiEpisode'] = "| %02d | %s" % (obj['MultiEpisode'], obj['Title'])
|
2017-01-01 16:06:40 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not self.get_show_id(obj):
|
|
|
|
return False
|
2017-01-01 16:06:40 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['SeasonId'] = self.get_season(*values(obj, QU.get_season_episode_obj))
|
2018-01-08 02:13:11 +00:00
|
|
|
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if update:
|
|
|
|
self.episode_update(obj)
|
2016-10-10 08:19:00 +00:00
|
|
|
else:
|
2018-09-06 08:36:32 +00:00
|
|
|
self.episode_add(obj)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.update_path(*values(obj, QU.update_path_episode_obj))
|
|
|
|
self.update_file(*values(obj, QU.update_file_obj))
|
|
|
|
self.add_people(*values(obj, QU.add_people_episode_obj))
|
|
|
|
self.add_streams(*values(obj, QU.add_streams_obj))
|
|
|
|
self.add_playstate(*values(obj, QU.add_bookmark_obj))
|
|
|
|
self.artwork.update(obj['Artwork']['Primary'], obj['EpisodeId'], "episode", "thumb")
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not self.direct_path and obj['Resume']:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
temp_obj = dict(obj)
|
|
|
|
temp_obj['Path'] = "plugin://plugin.video.emby.tvshows/"
|
|
|
|
temp_obj['PathId'] = self.get_path(*values(temp_obj, QU.get_path_obj))
|
|
|
|
temp_obj['FileId'] = self.add_file(*values(temp_obj, QU.add_file_obj))
|
|
|
|
self.update_file(*values(temp_obj, QU.update_file_obj))
|
|
|
|
self.add_playstate(*values(temp_obj, QU.add_bookmark_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def episode_add(self, obj):
|
|
|
|
|
|
|
|
''' Add object to kodi.
|
|
|
|
'''
|
|
|
|
obj['RatingId'] = self.create_entry_rating()
|
|
|
|
self.add_ratings(*values(obj, QU.add_rating_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Unique'] = self.create_entry_unique_id()
|
|
|
|
self.add_unique_id(*values(obj, QU.add_unique_id_episode_obj))
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['PathId'] = self.add_path(*values(obj, QU.add_path_obj))
|
|
|
|
obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj))
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.add_episode(*values(obj, QU.add_episode_obj))
|
|
|
|
self.emby_db.add_reference(*values(obj, QUEM.add_reference_episode_obj))
|
|
|
|
LOG.debug("ADD episode [%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['Id'], obj['Title'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def episode_update(self, obj):
|
|
|
|
|
|
|
|
''' Update object to kodi.
|
|
|
|
'''
|
|
|
|
obj['RatingId'] = self.get_rating_id(*values(obj, QU.get_rating_episode_obj))
|
|
|
|
self.update_ratings(*values(obj, QU.update_rating_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_episode_obj))
|
|
|
|
self.update_unique_id(*values(obj, QU.update_unique_id_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.update_episode(*values(obj, QU.update_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
|
|
|
self.emby_db.update_parent_id(*values(obj, QUEM.update_parent_episode_obj))
|
|
|
|
LOG.debug("UPDATE episode [%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['Id'], obj['Title'])
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def get_episode_path_filename(self, obj):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
''' Get the path and build it into protocol://path
|
|
|
|
'''
|
|
|
|
if '\\' in obj['Path']:
|
|
|
|
obj['Filename'] = obj['Path'].rsplit('\\', 1)[1]
|
2016-10-10 08:19:00 +00:00
|
|
|
else:
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Filename'] = obj['Path'].rsplit('/', 1)[1]
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if self.direct_path:
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not validate(obj['Path']):
|
|
|
|
raise Exception("Failed to validate path. User stopped.")
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Path'] = obj['Path'].replace(obj['Filename'], "")
|
2016-10-10 08:19:00 +00:00
|
|
|
else:
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['Path'] = "plugin://plugin.video.emby.tvshows/%s/" % obj['SeriesId']
|
|
|
|
params = {
|
|
|
|
'filename': obj['Filename'].encode('utf-8'),
|
|
|
|
'id': obj['Id'],
|
|
|
|
'dbid': obj['EpisodeId'],
|
|
|
|
'mode': "play"
|
|
|
|
}
|
|
|
|
obj['Filename'] = "%s?%s" % (obj['Path'], urllib.urlencode(params))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def get_show_id(self, obj):
|
|
|
|
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))
|
|
|
|
|
|
|
|
if obj['ShowId'] is None:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
try:
|
2018-09-14 07:11:18 +00:00
|
|
|
self.tvshow(self.server['api'].get_item(obj['SeriesId']), library=None)
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
|
|
|
except (TypeError, KeyError):
|
|
|
|
LOG.error("Unable to add series %s", obj['SeriesId'])
|
|
|
|
|
2016-10-10 08:19:00 +00:00
|
|
|
return False
|
2018-09-06 08:36:32 +00:00
|
|
|
else:
|
|
|
|
obj['ShowId'] = obj['ShowId'][0]
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
return True
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
@stop()
|
|
|
|
@emby_item()
|
|
|
|
def userdata(self, item, e_item):
|
|
|
|
|
|
|
|
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
|
|
|
Poster with progress bar
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
Make sure there's no other bookmarks created by widget.
|
|
|
|
Create additional entry for widgets. This is only required for plugin/episode.
|
|
|
|
'''
|
|
|
|
API = api.API(item, self.server['auth/server-address'])
|
|
|
|
obj = self.objects.map(item, 'EpisodeUserData')
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
try:
|
|
|
|
obj['KodiId'] = e_item[0]
|
|
|
|
obj['FileId'] = e_item[1]
|
|
|
|
obj['Media'] = e_item[4]
|
|
|
|
except TypeError:
|
|
|
|
return
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Media'] == "tvshow":
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Favorite']:
|
|
|
|
self.get_tag(*values(obj, QU.get_tag_episode_obj))
|
|
|
|
else:
|
|
|
|
self.remove_tag(*values(obj, QU.delete_tag_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
elif obj['Media'] == "episode":
|
|
|
|
|
|
|
|
obj['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
|
|
|
|
obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
|
|
|
|
obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount'])
|
2016-12-31 16:30:11 +00:00
|
|
|
|
2018-09-07 18:18:31 +00:00
|
|
|
if not obj['Played']:
|
|
|
|
obj['DatePlayed'] = None
|
|
|
|
elif obj['DatePlayed']:
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['DatePlayed'] = obj['DatePlayed'].split('.')[0].replace('T', " ")
|
2016-12-31 16:30:11 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['DateAdded']:
|
|
|
|
obj['DateAdded'] = obj['DateAdded'].split('.')[0].replace('T', " ")
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.add_playstate(*values(obj, QU.add_bookmark_obj))
|
2016-10-12 10:01:36 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not self.direct_path and not obj['Resume']:
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
temp_obj = dict(obj)
|
|
|
|
temp_obj['Filename'] = self.get_filename(*values(temp_obj, QU.get_file_obj))
|
|
|
|
temp_obj['Path'] = "plugin://plugin.video.emby.tvshows/"
|
|
|
|
self.remove_file(*values(temp_obj, QU.delete_file_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
elif not self.direct_path and obj['Resume']:
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
temp_obj = dict(obj)
|
|
|
|
temp_obj['Filename'] = self.get_filename(*values(temp_obj, QU.get_file_obj))
|
|
|
|
temp_obj['PathId'] = self.get_path("plugin://plugin.video.emby.tvshows/")
|
|
|
|
temp_obj['FileId'] = self.add_file(*values(temp_obj, QU.add_file_obj))
|
|
|
|
self.update_file(*values(temp_obj, QU.update_file_obj))
|
|
|
|
self.add_playstate(*values(temp_obj, QU.add_bookmark_obj))
|
|
|
|
|
|
|
|
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
|
|
|
LOG.info("USERDATA %s [%s/%s] %s: %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id'], obj['Title'])
|
|
|
|
|
|
|
|
@stop()
|
|
|
|
@emby_item()
|
|
|
|
def remove(self, item_id, e_item):
|
|
|
|
|
|
|
|
''' Remove showid, fileid, pathid, emby reference.
|
|
|
|
There's no episodes left, delete show and any possible remaining seasons
|
|
|
|
'''
|
|
|
|
obj = {'Id': item_id}
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
try:
|
2018-09-06 08:36:32 +00:00
|
|
|
obj['KodiId'] = e_item[0]
|
|
|
|
obj['FileId'] = e_item[1]
|
|
|
|
obj['ParentId'] = e_item[3]
|
|
|
|
obj['Media'] = e_item[4]
|
2016-10-10 08:19:00 +00:00
|
|
|
except TypeError:
|
|
|
|
return
|
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if obj['Media'] == 'episode':
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
temp_obj = dict(obj)
|
|
|
|
self.remove_episode(obj['KodiId'], obj['FileId'], obj['Id'])
|
|
|
|
season = self.emby_db.get_full_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
|
|
|
try:
|
2018-09-06 08:36:32 +00:00
|
|
|
temp_obj['Id'] = season[0]
|
|
|
|
temp_obj['ParentId'] = season[1]
|
2016-10-10 08:19:00 +00:00
|
|
|
except TypeError:
|
|
|
|
return
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)):
|
|
|
|
|
|
|
|
self.remove_season(obj['ParentId'], obj['Id'])
|
|
|
|
self.emby_db.remove_item(*values(temp_obj, QUEM.delete_item_obj))
|
|
|
|
|
|
|
|
temp_obj['Id'] = self.emby_db.get_item_by_kodi_id(*values(temp_obj, QUEM.get_item_by_parent_tvshow_obj))
|
|
|
|
|
|
|
|
if not self.get_total_episodes(*values(temp_obj, QU.get_total_episodes_obj)):
|
|
|
|
|
|
|
|
for season in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_season_obj)):
|
|
|
|
self.remove_season(season[1], obj['Id'])
|
2016-10-10 08:19:00 +00:00
|
|
|
else:
|
2018-09-06 08:36:32 +00:00
|
|
|
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_season_obj))
|
|
|
|
|
|
|
|
self.remove_tvshow(temp_obj['ParentId'], obj['Id'])
|
|
|
|
self.emby_db.remove_item(*values(temp_obj, QUEM.delete_item_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
elif obj['Media'] == 'tvshow':
|
|
|
|
obj['ParentId'] = obj['KodiId']
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
for season in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
|
|
|
|
|
|
|
|
temp_obj = dict(obj)
|
|
|
|
temp_obj['ParentId'] = season[1]
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
for episode in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)):
|
|
|
|
self.remove_episode(episode[1], episode[2], obj['Id'])
|
|
|
|
else:
|
|
|
|
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
else:
|
2018-09-06 08:36:32 +00:00
|
|
|
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
|
2016-10-10 11:14:10 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.remove_tvshow(obj['KodiId'], obj['Id'])
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
elif obj['Media'] == 'season':
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
for episode in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)):
|
|
|
|
self.remove_episode(episode[1], episode[2], obj['Id'])
|
|
|
|
else:
|
|
|
|
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_episode_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.remove_season(obj['KodiId'], obj['Id'])
|
2016-10-12 10:43:19 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
if not self.emby_db.get_item_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj)):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.remove_show(obj['ParentId'], obj['Id'])
|
|
|
|
self.emby_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj))
|
2016-10-12 10:43:19 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def remove_tvshow(self, kodi_id, item_id):
|
|
|
|
|
|
|
|
self.artwork.delete(kodi_id, "tvshow")
|
|
|
|
self.delete_tvshow(kodi_id)
|
|
|
|
LOG.debug("DELETE tvshow [%s] %s", kodi_id, item_id)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def remove_season(self, kodi_id, item_id):
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.artwork.delete(kodi_id, "season")
|
|
|
|
self.delete_season(kodi_id)
|
|
|
|
LOG.info("DELETE season [%s] %s", kodi_id, item_id)
|
2016-10-10 08:19:00 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
def remove_episode(self, kodi_id, file_id, item_id):
|
2017-09-03 19:10:04 +00:00
|
|
|
|
2018-09-06 08:36:32 +00:00
|
|
|
self.artwork.delete(kodi_id, "episode")
|
|
|
|
self.delete_episode(kodi_id, file_id)
|
|
|
|
LOG.info("DELETE episode [%s/%s] %s", file_id, kodi_id, item_id)
|