-
-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use thought when calling to vfs for esoteric media
- Loading branch information
1 parent
68c49ea
commit 10a545f
Showing
2 changed files
with
1,011 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,361 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import division, absolute_import, print_function, unicode_literals | ||
|
||
################################################################################################## | ||
|
||
from six.moves.urllib.parse import urlencode | ||
from kodi_six.utils import py2_encode | ||
|
||
from .. import downloader as server | ||
from ..database import jellyfin_db, queries as QUEM | ||
from ..helper import api, stop, validate, validate_bluray_dir, validate_dvd_dir, jellyfin_item, values, Local | ||
from ..helper import LazyLogger | ||
from ..helper.utils import find_library | ||
from ..helper.exceptions import PathValidationException | ||
|
||
from .obj import Objects | ||
from .kodi import Movies as KodiDb, queries as QU | ||
|
||
################################################################################################## | ||
|
||
LOG = LazyLogger(__name__) | ||
|
||
################################################################################################## | ||
|
||
|
||
class Movies(KodiDb): | ||
|
||
def __init__(self, server, jellyfindb, videodb, direct_path, library=None): | ||
|
||
self.server = server | ||
self.jellyfin = jellyfindb | ||
self.video = videodb | ||
self.direct_path = direct_path | ||
|
||
self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor) | ||
self.objects = Objects() | ||
self.item_ids = [] | ||
self.library = library | ||
|
||
KodiDb.__init__(self, videodb.cursor) | ||
|
||
@stop | ||
@jellyfin_item | ||
def movie(self, item, e_item): | ||
|
||
''' If item does not exist, entry will be added. | ||
If item exists, entry will be updated. | ||
''' | ||
server_address = self.server.auth.get_server_info(self.server.auth.server_id)['address'] | ||
API = api.API(item, server_address) | ||
obj = self.objects.map(item, 'Movie') | ||
update = True | ||
|
||
try: | ||
obj['MovieId'] = e_item[0] | ||
obj['FileId'] = e_item[1] | ||
obj['PathId'] = e_item[2] | ||
obj['LibraryId'] = e_item[6] | ||
obj['LibraryName'] = self.jellyfin_db.get_view_name(obj['LibraryId']) | ||
except TypeError: | ||
update = False | ||
LOG.debug("MovieId %s not found", obj['Id']) | ||
|
||
library = self.library or find_library(self.server, item) | ||
if not library: | ||
# This item doesn't belong to a whitelisted library | ||
return | ||
|
||
obj['MovieId'] = self.create_entry() | ||
obj['LibraryId'] = library['Id'] | ||
obj['LibraryName'] = library['Name'] | ||
else: | ||
if self.get(*values(obj, QU.get_movie_obj)) is None: | ||
|
||
update = False | ||
LOG.info("MovieId %s missing from kodi. repairing the entry.", obj['MovieId']) | ||
|
||
obj['Path'] = API.get_file_path(obj['Path']) | ||
obj['Genres'] = obj['Genres'] or [] | ||
obj['Studios'] = [API.validate_studio(studio) for studio in (obj['Studios'] or [])] | ||
obj['People'] = obj['People'] or [] | ||
obj['Genre'] = " / ".join(obj['Genres']) | ||
obj['Writers'] = " / ".join(obj['Writers'] or []) | ||
obj['Directors'] = " / ".join(obj['Directors'] or []) | ||
obj['Plot'] = API.get_overview(obj['Plot']) | ||
obj['Mpaa'] = API.get_mpaa(obj['Mpaa']) | ||
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']) | ||
obj['DateAdded'] = Local(obj['DateAdded']).split('.')[0].replace('T', " ") | ||
obj['DatePlayed'] = None if not obj['DatePlayed'] else Local(obj['DatePlayed']).split('.')[0].replace('T', " ") | ||
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']) | ||
if obj['Premiere'] is not None: | ||
obj['Premiere'] = str(obj['Premiere']).split('T')[0] | ||
|
||
self.get_path_filename(obj) | ||
self.trailer(obj) | ||
|
||
if obj['Countries']: | ||
self.add_countries(*values(obj, QU.update_country_obj)) | ||
|
||
tags = list(obj['Tags'] or []) | ||
tags.append(obj['LibraryName']) | ||
|
||
if obj['Favorite']: | ||
tags.append('Favorite movies') | ||
|
||
obj['Tags'] = tags | ||
|
||
if update: | ||
self.movie_update(obj) | ||
else: | ||
self.movie_add(obj) | ||
|
||
self.update_path(*values(obj, QU.update_path_movie_obj)) | ||
self.update_file(*values(obj, QU.update_file_obj)) | ||
self.add_tags(*values(obj, QU.add_tags_movie_obj)) | ||
self.add_genres(*values(obj, QU.add_genres_movie_obj)) | ||
self.add_studios(*values(obj, QU.add_studios_movie_obj)) | ||
self.add_playstate(*values(obj, QU.add_bookmark_obj)) | ||
self.add_people(*values(obj, QU.add_people_movie_obj)) | ||
self.add_streams(*values(obj, QU.add_streams_obj)) | ||
self.artwork.add(obj['Artwork'], obj['MovieId'], "movie") | ||
self.item_ids.append(obj['Id']) | ||
|
||
return not update | ||
|
||
def movie_add(self, obj): | ||
|
||
''' Add object to kodi. | ||
''' | ||
obj['RatingId'] = self.create_entry_rating() | ||
self.add_ratings(*values(obj, QU.add_rating_movie_obj)) | ||
|
||
obj['Unique'] = self.create_entry_unique_id() | ||
self.add_unique_id(*values(obj, QU.add_unique_id_movie_obj)) | ||
|
||
obj['PathId'] = self.add_path(*values(obj, QU.add_path_obj)) | ||
obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj)) | ||
|
||
self.add(*values(obj, QU.add_movie_obj)) | ||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_movie_obj)) | ||
LOG.debug("ADD movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title']) | ||
|
||
def movie_update(self, obj): | ||
|
||
''' Update object to kodi. | ||
''' | ||
obj['RatingId'] = self.get_rating_id(*values(obj, QU.get_rating_movie_obj)) | ||
self.update_ratings(*values(obj, QU.update_rating_movie_obj)) | ||
|
||
obj['Unique'] = self.get_unique_id(*values(obj, QU.get_unique_id_movie_obj)) | ||
self.update_unique_id(*values(obj, QU.update_unique_id_movie_obj)) | ||
|
||
self.update(*values(obj, QU.update_movie_obj)) | ||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj)) | ||
LOG.debug("UPDATE movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title']) | ||
|
||
def trailer(self, obj): | ||
|
||
try: | ||
if obj['LocalTrailer']: | ||
|
||
trailer = self.server.jellyfin.get_local_trailers(obj['Id']) | ||
obj['Trailer'] = "plugin://plugin.video.jellyfin/trailer?id=%s&mode=play" % trailer[0]['Id'] | ||
|
||
elif obj['Trailer']: | ||
obj['Trailer'] = "plugin://plugin.video.youtube/play/?video_id=%s" % obj['Trailer'].rsplit('=', 1)[1] | ||
except Exception as error: | ||
|
||
LOG.exception("Failed to get trailer: %s", error) | ||
obj['Trailer'] = None | ||
|
||
def get_path_filename(self, obj): | ||
|
||
''' Get the path and filename and build it into protocol://path | ||
''' | ||
obj['Filename'] = obj['Path'].rsplit('\\', 1)[1] if '\\' in obj['Path'] else obj['Path'].rsplit('/', 1)[1] | ||
|
||
if self.direct_path: | ||
|
||
if not validate(obj['Path']): | ||
raise PathValidationException("Failed to validate path. User stopped.") | ||
|
||
obj['Path'] = obj['Path'].replace(obj['Filename'], "") | ||
|
||
'''check dvd directories and point it to ./VIDEO_TS/VIDEO_TS.IFO''' | ||
if ('Container' not in obj or ('Container' in obj and obj['Container'] == 'dvd')) and validate_dvd_dir(obj['Path'] + obj['Filename']): | ||
obj['Path'] = obj['Path'] + obj['Filename'] + '/VIDEO_TS/' | ||
obj['Filename'] = 'VIDEO_TS.IFO' | ||
LOG.debug("DVD directory %s", obj['Path']) | ||
|
||
'''check bluray directories and point it to ./BDMV/index.bdmv''' | ||
if ('Container' not in obj or ('Container' in obj and obj['Container'] == 'bluray')) and validate_bluray_dir(obj['Path'] + obj['Filename']): | ||
obj['Path'] = obj['Path'] + obj['Filename'] + '/BDMV/' | ||
obj['Filename'] = 'index.bdmv' | ||
LOG.debug("Bluray directory %s", obj['Path']) | ||
|
||
else: | ||
obj['Path'] = "plugin://plugin.video.jellyfin/%s/" % obj['LibraryId'] | ||
params = { | ||
'filename': py2_encode(obj['Filename'], 'utf-8'), | ||
'id': obj['Id'], | ||
'dbid': obj['MovieId'], | ||
'mode': "play" | ||
} | ||
obj['Filename'] = "%s?%s" % (obj['Path'], urlencode(params)) | ||
|
||
@stop | ||
@jellyfin_item | ||
def boxset(self, item, e_item): | ||
|
||
''' If item does not exist, entry will be added. | ||
If item exists, entry will be updated. | ||
Process movies inside boxset. | ||
Process removals from boxset. | ||
''' | ||
server_address = self.server.auth.get_server_info(self.server.auth.server_id)['address'] | ||
API = api.API(item, server_address) | ||
obj = self.objects.map(item, 'Boxset') | ||
|
||
obj['Overview'] = API.get_overview(obj['Overview']) | ||
|
||
try: | ||
obj['SetId'] = e_item[0] | ||
self.update_boxset(*values(obj, QU.update_set_obj)) | ||
except TypeError: | ||
LOG.debug("SetId %s not found", obj['Id']) | ||
obj['SetId'] = self.add_boxset(*values(obj, QU.add_set_obj)) | ||
|
||
self.boxset_current(obj) | ||
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork')) | ||
|
||
for movie in obj['Current']: | ||
|
||
temp_obj = dict(obj) | ||
temp_obj['Movie'] = movie | ||
temp_obj['MovieId'] = obj['Current'][temp_obj['Movie']] | ||
self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj)) | ||
self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj)) | ||
LOG.debug("DELETE from boxset [%s] %s: %s", temp_obj['SetId'], temp_obj['Title'], temp_obj['MovieId']) | ||
|
||
self.artwork.add(obj['Artwork'], obj['SetId'], "set") | ||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_boxset_obj)) | ||
LOG.debug("UPDATE boxset [%s] %s", obj['SetId'], obj['Title']) | ||
|
||
def boxset_current(self, obj): | ||
|
||
''' Add or removes movies based on the current movies found in the boxset. | ||
''' | ||
try: | ||
current = self.jellyfin_db.get_item_id_by_parent_id(*values(obj, QUEM.get_item_id_by_parent_boxset_obj)) | ||
movies = dict(current) | ||
except ValueError: | ||
movies = {} | ||
|
||
obj['Current'] = movies | ||
|
||
for all_movies in server.get_movies_by_boxset(obj['Id']): | ||
for movie in all_movies['Items']: | ||
|
||
temp_obj = dict(obj) | ||
temp_obj['Title'] = movie['Name'] | ||
temp_obj['Id'] = movie['Id'] | ||
|
||
try: | ||
temp_obj['MovieId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] | ||
except TypeError: | ||
LOG.info("Failed to process %s to boxset.", temp_obj['Title']) | ||
|
||
continue | ||
|
||
if temp_obj['Id'] not in obj['Current']: | ||
|
||
self.set_boxset(*values(temp_obj, QU.update_movie_set_obj)) | ||
self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.update_parent_movie_obj)) | ||
LOG.debug("ADD to boxset [%s/%s] %s: %s to boxset", temp_obj['SetId'], temp_obj['MovieId'], temp_obj['Title'], temp_obj['Id']) | ||
else: | ||
obj['Current'].pop(temp_obj['Id']) | ||
|
||
def boxsets_reset(self): | ||
|
||
''' Special function to remove all existing boxsets. | ||
''' | ||
boxsets = self.jellyfin_db.get_items_by_media('set') | ||
for boxset in boxsets: | ||
self.remove(boxset[0]) | ||
|
||
@stop | ||
@jellyfin_item | ||
def userdata(self, item, e_item): | ||
|
||
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks | ||
Poster with progress bar | ||
''' | ||
server_address = self.server.auth.get_server_info(self.server.auth.server_id)['address'] | ||
API = api.API(item, server_address) | ||
obj = self.objects.map(item, 'MovieUserData') | ||
|
||
try: | ||
obj['MovieId'] = e_item[0] | ||
obj['FileId'] = e_item[1] | ||
except TypeError: | ||
return | ||
|
||
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']) | ||
|
||
if obj['DatePlayed']: | ||
obj['DatePlayed'] = Local(obj['DatePlayed']).split('.')[0].replace('T', " ") | ||
|
||
if obj['Favorite']: | ||
self.get_tag(*values(obj, QU.get_tag_movie_obj)) | ||
else: | ||
self.remove_tag(*values(obj, QU.delete_tag_movie_obj)) | ||
|
||
LOG.debug("New resume point %s: %s", obj['Id'], obj['Resume']) | ||
self.add_playstate(*values(obj, QU.add_bookmark_obj)) | ||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj)) | ||
LOG.debug("USERDATA movie [%s/%s] %s: %s", obj['FileId'], obj['MovieId'], obj['Id'], obj['Title']) | ||
|
||
@stop | ||
@jellyfin_item | ||
def remove(self, item_id, e_item): | ||
|
||
''' Remove movieid, fileid, jellyfin reference. | ||
Remove artwork, boxset | ||
''' | ||
obj = {'Id': item_id} | ||
|
||
try: | ||
obj['KodiId'] = e_item[0] | ||
obj['FileId'] = e_item[1] | ||
obj['Media'] = e_item[4] | ||
except TypeError: | ||
return | ||
|
||
self.artwork.delete(obj['KodiId'], obj['Media']) | ||
|
||
if obj['Media'] == 'movie': | ||
self.delete(*values(obj, QU.delete_movie_obj)) | ||
elif obj['Media'] == 'set': | ||
|
||
for movie in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_movie_obj)): | ||
|
||
temp_obj = dict(obj) | ||
temp_obj['MovieId'] = movie[1] | ||
temp_obj['Movie'] = movie[0] | ||
self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj)) | ||
self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj)) | ||
|
||
self.delete_boxset(*values(obj, QU.delete_set_obj)) | ||
|
||
self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj)) | ||
LOG.debug("DELETE %s [%s/%s] %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id']) |
Oops, something went wrong.