jellyfin-kodi/jellyfin_kodi/objects/musicvideos.py
2023-06-13 18:48:07 +02:00

251 lines
9.5 KiB
Python

# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function, unicode_literals
##################################################################################################
import datetime
import re
from six.moves.urllib.parse import urlencode
from kodi_six.utils import py2_encode
from ..database import jellyfin_db, queries as QUEM
from ..helper import api, stop, validate, jellyfin_item, values, Local, LazyLogger
from ..helper.utils import find_library
from ..helper.exceptions import PathValidationException
from .obj import Objects
from .kodi import MusicVideos as KodiDb, queries as QU
##################################################################################################
LOG = LazyLogger(__name__)
##################################################################################################
class MusicVideos(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 musicvideo(self, item, e_item):
''' If item does not exist, entry will be added.
If item exists, entry will be updated.
If we don't get the track number from Jellyfin, see if we can infer it
from the sortname attribute.
'''
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, 'MusicVideo')
update = True
try:
obj['MvideoId'] = 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
library = self.library or find_library(self.server, item)
if not library:
# This item doesn't belong to a whitelisted library
return
LOG.debug("MvideoId for %s not found", obj['Id'])
obj['MvideoId'] = self.create_entry()
obj['LibraryId'] = library['Id']
obj['LibraryName'] = library['Name']
else:
if self.get(*values(obj, QU.get_musicvideo_obj)) is None:
update = False
LOG.info("MvideoId %s missing from kodi. repairing the entry.", obj['MvideoId'])
if (obj.get('ProductionYear') or 0) > 9999:
obj['ProductionYear'] = int(str(obj['ProductionYear'])[:4])
if (obj.get('Year') or 0) > 9999:
obj['Year'] = int(str(obj['Year'])[:4])
obj['Path'] = API.get_file_path(obj['Path'])
obj['LibraryId'] = self.library['Id']
obj['LibraryName'] = self.library['Name']
obj['Genres'] = obj['Genres'] or []
obj['ArtistItems'] = obj['ArtistItems'] or []
obj['Studios'] = [API.validate_studio(studio) for studio in (obj['Studios'] or [])]
obj['Plot'] = API.get_overview(obj['Plot'])
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['Resume'] = API.adjust_resume((obj['Resume'] or 0) / 10000000.0)
obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
obj['Premiere'] = Local(obj['Premiere']) if obj['Premiere'] else datetime.date(obj['Year'] or 1970, 1, 1)
obj['Genre'] = " / ".join(obj['Genres'])
obj['Studio'] = " / ".join(obj['Studios'])
obj['Artists'] = " / ".join(obj['Artists'] or [])
obj['Directors'] = " / ".join(obj['Directors'] or [])
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'])
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
self.get_path_filename(obj)
if obj['Premiere']:
obj['Premiere'] = str(obj['Premiere']).split('.')[0].replace('T', " ")
for artist in obj['ArtistItems']:
artist['Type'] = "Artist"
obj['People'] = obj['People'] or [] + obj['ArtistItems']
obj['People'] = API.get_people_artwork(obj['People'])
if obj['Index'] is None and obj['SortTitle'] is not None:
search = re.search(r'^\d+\s?', obj['SortTitle'])
if search:
obj['Index'] = search.group()
tags = []
tags.extend(obj['Tags'] or [])
tags.append(obj['LibraryName'])
if obj['Favorite']:
tags.append('Favorite musicvideos')
obj['Tags'] = tags
if update:
self.musicvideo_update(obj)
else:
self.musicvideo_add(obj)
self.update_path(*values(obj, QU.update_path_mvideo_obj))
self.update_file(*values(obj, QU.update_file_obj))
self.add_tags(*values(obj, QU.add_tags_mvideo_obj))
self.add_genres(*values(obj, QU.add_genres_mvideo_obj))
self.add_studios(*values(obj, QU.add_studios_mvideo_obj))
self.add_playstate(*values(obj, QU.add_bookmark_obj))
self.add_people(*values(obj, QU.add_people_mvideo_obj))
self.add_streams(*values(obj, QU.add_streams_obj))
self.artwork.add(obj['Artwork'], obj['MvideoId'], "musicvideo")
self.item_ids.append(obj['Id'])
return not update
def musicvideo_add(self, obj):
''' Add object to kodi.
'''
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_musicvideo_obj))
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_mvideo_obj))
LOG.debug("ADD mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
def musicvideo_update(self, obj):
''' Update object to kodi.
'''
self.update(*values(obj, QU.update_musicvideo_obj))
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.debug("UPDATE mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
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'], "")
else:
obj['Path'] = "plugin://plugin.video.jellyfin/%s/" % obj['LibraryId']
params = {
'filename': py2_encode(obj['Filename'], 'utf-8'),
'id': obj['Id'],
'dbid': obj['MvideoId'],
'mode': "play"
}
obj['Filename'] = "%s?%s" % (obj['Path'], urlencode(params))
@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, 'MusicVideoUserData')
try:
obj['MvideoId'] = 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_mvideo_obj))
else:
self.remove_tag(*values(obj, QU.delete_tag_mvideo_obj))
self.add_playstate(*values(obj, QU.add_bookmark_obj))
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.debug("USERDATA mvideo [%s/%s] %s: %s", obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
@stop
@jellyfin_item
def remove(self, item_id, e_item):
''' Remove mvideoid, fileid, pathid, jellyfin reference.
'''
obj = {'Id': item_id}
try:
obj['MvideoId'] = e_item[0]
obj['FileId'] = e_item[1]
obj['PathId'] = e_item[2]
except TypeError:
return
self.artwork.delete(obj['MvideoId'], "musicvideo")
self.delete(*values(obj, QU.delete_musicvideo_obj))
if self.direct_path:
self.remove_path(*values(obj, QU.delete_path_obj))
self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
LOG.debug("DELETE musicvideo %s [%s/%s] %s", obj['MvideoId'], obj['PathId'], obj['FileId'], obj['Id'])