mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 10:16:11 +00:00
Change emby to jellyfin in functions, variables etc.
This commit is contained in:
parent
647636430f
commit
233192863a
39 changed files with 273 additions and 278 deletions
|
@ -32,7 +32,7 @@
|
|||
<website>https://jellyfin.media/</website>
|
||||
<source>https://github.com/jellyfin/jellyfin-kodi</source>
|
||||
<summary lang="en"></summary>
|
||||
<description lang="en">Welcome to Jellyfin for Kodi A whole new way to manage and view your media library. The Jellyfin addon for Kodi combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Jellyfin - the most powerful fully open source multi-client media metadata indexer and server. Jellyfin for Kodi is the absolute best way to enjoy the incredible Kodi playback engine combined with the power of Jellyfin's centralized database. Features: Direct integration with the Kodi library for native Kodi speed Instant synchronization with the Jellyfin server Full support for Movie, TV and Music collections Jellyfin Server direct stream and transcoding support - use Kodi when you are away from home!</description>
|
||||
<description lang="en">Welcome to Jellyfin for Kodi! A whole new way to manage and view your media library. The Jellyfin addon for Kodi combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Jellyfin - the most powerful fully open source multi-client media metadata indexer and server. Jellyfin for Kodi is the absolute best way to enjoy the incredible Kodi playback engine combined with the power of Jellyfin's centralized database. Features: * Direct integration with the Kodi library for native Kodi speed * Instant synchronization with the Jellyfin server * Full support for Movie, TV and Music collections * Jellyfin Server direct stream and transcoding support - use Kodi when you are away from home!</description>
|
||||
<news>
|
||||
Rebrand in progress
|
||||
</news>
|
||||
|
|
|
@ -14,9 +14,9 @@ import client
|
|||
from database import get_credentials, save_credentials
|
||||
from dialogs import ServerConnect, UsersConnect, LoginManual, ServerManual
|
||||
from helper import _, settings, addon_id, event, api, dialog, window
|
||||
from emby import Emby
|
||||
from emby.core.connection_manager import get_server_address, CONNECTION_STATE
|
||||
from emby.core.exceptions import HTTPException
|
||||
from jellyfin import Jellyfin
|
||||
from jellyfin.core.connection_manager import get_server_address, CONNECTION_STATE
|
||||
from jellyfin.core.exceptions import HTTPException
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -65,7 +65,7 @@ class Connect(object):
|
|||
save_credentials(credentials)
|
||||
|
||||
try:
|
||||
Emby(server_id).start(True)
|
||||
Jellyfin(server_id).start(True)
|
||||
except ValueError as error:
|
||||
LOG.error(error)
|
||||
|
||||
|
@ -80,7 +80,7 @@ class Connect(object):
|
|||
|
||||
''' Get Jellyfin client.
|
||||
'''
|
||||
client = Emby(server_id)
|
||||
client = Jellyfin(server_id)
|
||||
client['config/app']("Kodi", self.info['Version'], self.info['DeviceName'], self.info['DeviceId'])
|
||||
client['config']['http.user_agent'] = "Jellyfin-Kodi/%s" % self.info['Version']
|
||||
client['config']['auth.ssl'] = self.get_ssl()
|
||||
|
@ -280,7 +280,7 @@ class Connect(object):
|
|||
|
||||
''' Stop client and remove server.
|
||||
'''
|
||||
Emby(server_id).close()
|
||||
Jellyfin(server_id).close()
|
||||
credentials = get_credentials()
|
||||
|
||||
for server in credentials['Servers']:
|
||||
|
|
|
@ -11,7 +11,7 @@ import sqlite3
|
|||
import xbmc
|
||||
import xbmcvfs
|
||||
|
||||
import emby_db
|
||||
import jellyfin_db
|
||||
from helper.utils import delete_folder
|
||||
from helper import _, settings, window, dialog
|
||||
from objects import obj
|
||||
|
@ -58,7 +58,7 @@ class Database(object):
|
|||
if not window('jellyfin_db_check.bool') and self.db_file == 'jellyfin':
|
||||
|
||||
window('jellyfin_db_check.bool', True)
|
||||
emby_tables(self.cursor)
|
||||
jellyfin_tables(self.cursor)
|
||||
self.conn.commit()
|
||||
|
||||
return self
|
||||
|
@ -183,7 +183,7 @@ class Database(object):
|
|||
self.cursor.close()
|
||||
self.conn.close()
|
||||
|
||||
def emby_tables(cursor):
|
||||
def jellyfin_tables(cursor):
|
||||
|
||||
''' Create the tables for the jellyfin database.
|
||||
jellyfin, view, version
|
||||
|
@ -231,7 +231,7 @@ def reset():
|
|||
return
|
||||
|
||||
reset_kodi()
|
||||
reset_emby()
|
||||
reset_jellyfin()
|
||||
views.delete_playlists()
|
||||
views.delete_nodes()
|
||||
|
||||
|
@ -280,20 +280,20 @@ def reset_kodi():
|
|||
|
||||
LOG.warn("[ reset kodi ]")
|
||||
|
||||
def reset_emby():
|
||||
def reset_jellyfin():
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
embydb.cursor.execute("SELECT tbl_name FROM sqlite_master WHERE type='table'")
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
jellyfindb.cursor.execute("SELECT tbl_name FROM sqlite_master WHERE type='table'")
|
||||
|
||||
for table in embydb.cursor.fetchall():
|
||||
for table in jellyfindb.cursor.fetchall():
|
||||
name = table[0]
|
||||
|
||||
if name not in ('version', 'view'):
|
||||
embydb.cursor.execute("DELETE FROM " + name)
|
||||
jellyfindb.cursor.execute("DELETE FROM " + name)
|
||||
|
||||
embydb.cursor.execute("DROP table IF EXISTS jellyfin")
|
||||
embydb.cursor.execute("DROP table IF EXISTS view")
|
||||
embydb.cursor.execute("DROP table IF EXISTS version")
|
||||
jellyfindb.cursor.execute("DROP table IF EXISTS jellyfin")
|
||||
jellyfindb.cursor.execute("DROP table IF EXISTS view")
|
||||
jellyfindb.cursor.execute("DROP table IF EXISTS version")
|
||||
|
||||
LOG.warn("[ reset jellyfin ]")
|
||||
|
||||
|
@ -396,7 +396,7 @@ def get_item(kodi_id, media):
|
|||
''' Get jellyfin item based on kodi id and media.
|
||||
'''
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
item = emby_db.EmbyDatabase(embydb.cursor).get_full_item_by_kodi_id(kodi_id, media)
|
||||
item = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_full_item_by_kodi_id(kodi_id, media)
|
||||
|
||||
if not item:
|
||||
LOG.debug("Not an jellyfin item")
|
||||
|
|
|
@ -13,7 +13,7 @@ LOG = logging.getLogger("JELLYFIN."+__name__)
|
|||
##################################################################################################
|
||||
|
||||
|
||||
class EmbyDatabase():
|
||||
class JellyfinDatabase():
|
||||
|
||||
|
||||
def __init__(self, cursor):
|
|
@ -72,7 +72,6 @@ class LoginManual(xbmcgui.WindowXMLDialog):
|
|||
def onClick(self, control):
|
||||
|
||||
if control == SIGN_IN:
|
||||
# Sign in to emby connect
|
||||
self._disable_error()
|
||||
|
||||
user = self.user_field.getText()
|
||||
|
|
|
@ -8,7 +8,7 @@ import xbmc
|
|||
import xbmcgui
|
||||
|
||||
from helper import _
|
||||
from emby.core.connection_manager import CONNECTION_STATE
|
||||
from jellyfin.core.connection_manager import CONNECTION_STATE
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import xbmcgui
|
|||
import xbmcaddon
|
||||
|
||||
from helper import _, addon_id
|
||||
from emby.core.connection_manager import CONNECTION_STATE
|
||||
from jellyfin.core.connection_manager import CONNECTION_STATE
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -72,7 +72,6 @@ class ServerManual(xbmcgui.WindowXMLDialog):
|
|||
def onClick(self, control):
|
||||
|
||||
if control == CONNECT:
|
||||
# Sign in to jellyfin connect
|
||||
self._disable_error()
|
||||
|
||||
server = self.host_field.getText()
|
||||
|
|
|
@ -16,9 +16,9 @@ import xbmcaddon
|
|||
import requests
|
||||
from helper.utils import should_stop, delete_folder
|
||||
from helper import settings, stop, event, window, kodi_version, unzip, create_id
|
||||
from emby import Emby
|
||||
from emby.core import api
|
||||
from emby.core.exceptions import HTTPException
|
||||
from jellyfin import Jellyfin
|
||||
from jellyfin.core import api
|
||||
from jellyfin.core.exceptions import HTTPException
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
@ -28,7 +28,7 @@ CACHE = xbmc.translatePath(os.path.join(xbmcaddon.Addon(id='plugin.video.jellyfi
|
|||
|
||||
#################################################################################################
|
||||
|
||||
def get_embyserver_url(handler):
|
||||
def get_jellyfinserver_url(handler):
|
||||
|
||||
if handler.startswith('/'):
|
||||
|
||||
|
@ -46,16 +46,16 @@ def browse_info():
|
|||
def _http(action, url, request={}, server_id=None):
|
||||
request.update({'url': url, 'type': action})
|
||||
|
||||
return Emby(server_id)['http/request'](request)
|
||||
return Jellyfin(server_id)['http/request'](request)
|
||||
|
||||
def _get(handler, params=None, server_id=None):
|
||||
return _http("GET", get_embyserver_url(handler), {'params': params}, server_id)
|
||||
return _http("GET", get_jellyfinserver_url(handler), {'params': params}, server_id)
|
||||
|
||||
def _post(handler, json=None, params=None, server_id=None):
|
||||
return _http("POST", get_embyserver_url(handler), {'params': params, 'json': json}, server_id)
|
||||
return _http("POST", get_jellyfinserver_url(handler), {'params': params, 'json': json}, server_id)
|
||||
|
||||
def _delete(handler, params=None, server_id=None):
|
||||
return _http("DELETE", get_embyserver_url(handler), {'params': params}, server_id)
|
||||
return _http("DELETE", get_jellyfinserver_url(handler), {'params': params}, server_id)
|
||||
|
||||
def validate_view(library_id, item_id):
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import xbmc
|
|||
import xbmcvfs
|
||||
|
||||
from helper import loghandler
|
||||
from emby import Emby
|
||||
from jellyfin import Jellyfin
|
||||
|
||||
#################################################################################################
|
||||
|
||||
Emby.set_loghandler(loghandler.LogHandler, logging.DEBUG)
|
||||
Jellyfin.set_loghandler(loghandler.LogHandler, logging.DEBUG)
|
||||
loghandler.reset()
|
||||
loghandler.config()
|
||||
LOG = logging.getLogger('JELLYFIN.entrypoint')
|
||||
|
|
|
@ -17,7 +17,7 @@ import xbmcplugin
|
|||
import xbmcaddon
|
||||
|
||||
import client
|
||||
from database import reset, get_sync, Database, emby_db, get_credentials
|
||||
from database import reset, get_sync, Database, jellyfin_db, get_credentials
|
||||
from objects import Objects, Actions
|
||||
from downloader import TheVoid
|
||||
from helper import _, event, settings, window, dialog, api, JSONRPC
|
||||
|
@ -130,14 +130,14 @@ def listing():
|
|||
|
||||
''' Display all jellyfin nodes and dynamic entries when appropriate.
|
||||
'''
|
||||
total = int(window('Emby.nodes.total') or 0)
|
||||
total = int(window('Jellyfin.nodes.total') or 0)
|
||||
sync = get_sync()
|
||||
whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
|
||||
servers = get_credentials()['Servers'][1:]
|
||||
|
||||
for i in range(total):
|
||||
|
||||
window_prop = "Emby.nodes.%s" % i
|
||||
window_prop = "Jellyfin.nodes.%s" % i
|
||||
path = window('%s.index' % window_prop)
|
||||
|
||||
if not path:
|
||||
|
@ -543,12 +543,12 @@ def get_video_extras(item_id, path, server_id=None):
|
|||
"""
|
||||
def getVideoFiles(jellyfinId,jellyfinPath):
|
||||
#returns the video files for the item as plugin listing, can be used for browsing the actual files or videoextras etc.
|
||||
emby = embyserver.Read_EmbyServer()
|
||||
if not embyId:
|
||||
if "plugin.video.jellyfin" in embyPath:
|
||||
embyId = embyPath.split("/")[-2]
|
||||
if embyId:
|
||||
item = emby.getItem(embyId)
|
||||
jellyfin = jellyfinserver.Read_JellyfinServer()
|
||||
if not jellyfinId:
|
||||
if "plugin.video.jellyfin" in jellyfinPath:
|
||||
jellyfinId = jellyfinPath.split("/")[-2]
|
||||
if jellyfinId:
|
||||
item = jellyfin.getItem(jellyfinId)
|
||||
putils = playutils.PlayUtils(item)
|
||||
if putils.isDirectPlay():
|
||||
#only proceed if we can access the files directly. TODO: copy local on the fly if accessed outside
|
||||
|
@ -571,9 +571,9 @@ def get_next_episodes(item_id, limit):
|
|||
|
||||
''' Only for synced content.
|
||||
'''
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
library = db.get_view_name(item_id)
|
||||
|
||||
if not library:
|
||||
|
@ -784,8 +784,8 @@ def get_themes():
|
|||
|
||||
return
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
all_views = emby_db.EmbyDatabase(embydb.cursor).get_views()
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
||||
views = [x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed')]
|
||||
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ import requests
|
|||
from views import Views, verify_kodi_defaults
|
||||
from helper import _, window, settings, event, dialog, find, compare_version
|
||||
from downloader import get_objects
|
||||
from emby import Emby
|
||||
from database import Database, emby_db, reset
|
||||
from jellyfin import Jellyfin
|
||||
from database import Database, jellyfin_db, reset
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
@ -143,7 +143,7 @@ class Service(xbmc.Monitor):
|
|||
def stop_default(self):
|
||||
|
||||
window('jellyfin_online', clear=True)
|
||||
Emby().close()
|
||||
Jellyfin().close()
|
||||
|
||||
if self.library_thread is not None:
|
||||
|
||||
|
@ -154,9 +154,9 @@ class Service(xbmc.Monitor):
|
|||
|
||||
''' Check the database version to ensure we do not need to do a reset.
|
||||
'''
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
version = emby_db.EmbyDatabase(embydb.cursor).get_version()
|
||||
version = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_version()
|
||||
LOG.info("---[ db/%s ]", version)
|
||||
|
||||
if version and compare_version(version, "3.1.0") < 0:
|
||||
|
@ -206,8 +206,8 @@ class Service(xbmc.Monitor):
|
|||
LOG.info("--[ new objects/%s ]", objects.version)
|
||||
|
||||
try:
|
||||
if compare_version(self.settings['addon_version'], objects.embyversion) < 0:
|
||||
dialog("ok", heading="{jellyfin}", line1="%s %s" % (_(33160), objects.embyversion))
|
||||
if compare_version(self.settings['addon_version'], objects.jellyfinversion) < 0:
|
||||
dialog("ok", heading="{jellyfin}", line1="%s %s" % (_(33160), objects.jellyfinversion))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
@ -386,7 +386,7 @@ class Service(xbmc.Monitor):
|
|||
self.library_thread.stop_client()
|
||||
self.library_thread = None
|
||||
|
||||
Emby.close_all()
|
||||
Jellyfin.close_all()
|
||||
self.monitor.server = []
|
||||
self.monitor.sleep = True
|
||||
|
||||
|
@ -506,7 +506,7 @@ class Service(xbmc.Monitor):
|
|||
for prop in properties:
|
||||
window(prop, clear=True)
|
||||
|
||||
Emby.close_all()
|
||||
Jellyfin.close_all()
|
||||
|
||||
if self.library_thread is not None:
|
||||
self.library_thread.stop_client()
|
||||
|
|
|
@ -12,7 +12,7 @@ import xbmcvfs
|
|||
|
||||
import downloader as server
|
||||
import helper.xmls as xmls
|
||||
from database import Database, get_sync, save_sync, emby_db
|
||||
from database import Database, get_sync, save_sync, jellyfin_db
|
||||
from helper import _, settings, window, progress, dialog, LibraryException
|
||||
from helper.utils import get_screensaver, set_screensaver
|
||||
from views import Views
|
||||
|
@ -104,11 +104,11 @@ class FullSync(object):
|
|||
|
||||
def get_libraries(self, library_id=None):
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
if library_id is None:
|
||||
return emby_db.EmbyDatabase(embydb.cursor).get_views()
|
||||
return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
||||
else:
|
||||
return emby_db.EmbyDatabase(embydb.cursor).get_view(library_id)
|
||||
return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_view(library_id)
|
||||
|
||||
def mapping(self):
|
||||
|
||||
|
@ -266,9 +266,9 @@ class FullSync(object):
|
|||
|
||||
with self.library.database_lock:
|
||||
with Database() as videodb:
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
obj = Movies(self.server, embydb, videodb, self.direct_path)
|
||||
obj = Movies(self.server, jellyfindb, videodb, self.direct_path)
|
||||
|
||||
for items in server.get_items(library['Id'], "Movie", False, self.sync['RestorePoint'].get('params')):
|
||||
|
||||
|
@ -283,13 +283,13 @@ class FullSync(object):
|
|||
obj.movie(movie, library=library)
|
||||
|
||||
if self.update_library:
|
||||
self.movies_compare(library, obj, embydb)
|
||||
self.movies_compare(library, obj, jellyfindb)
|
||||
|
||||
def movies_compare(self, library, obj, embydb):
|
||||
def movies_compare(self, library, obj, jellyfinydb):
|
||||
|
||||
''' Compare entries from library to what's in the jellyfindb. Remove surplus
|
||||
'''
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfinydb.cursor)
|
||||
|
||||
items = db.get_item_by_media_folder(library['Id'])
|
||||
current = obj.item_ids
|
||||
|
@ -307,8 +307,8 @@ class FullSync(object):
|
|||
|
||||
with self.library.database_lock:
|
||||
with Database() as videodb:
|
||||
with Database('jellyfin') as embydb:
|
||||
obj = TVShows(self.server, embydb, videodb, self.direct_path, True)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
obj = TVShows(self.server, jellyfindb, videodb, self.direct_path, True)
|
||||
|
||||
for items in server.get_items(library['Id'], "Series", False, self.sync['RestorePoint'].get('params')):
|
||||
|
||||
|
@ -330,13 +330,13 @@ class FullSync(object):
|
|||
obj.episode(episode)
|
||||
|
||||
if self.update_library:
|
||||
self.tvshows_compare(library, obj, embydb)
|
||||
self.tvshows_compare(library, obj, jellyfindb)
|
||||
|
||||
def tvshows_compare(self, library, obj, embydb):
|
||||
def tvshows_compare(self, library, obj, jellyfindb):
|
||||
|
||||
''' Compare entries from library to what's in the embydb. Remove surplus
|
||||
''' Compare entries from library to what's in the jellyfindb. Remove surplus
|
||||
'''
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
|
||||
items = db.get_item_by_media_folder(library['Id'])
|
||||
for x in list(items):
|
||||
|
@ -357,8 +357,8 @@ class FullSync(object):
|
|||
|
||||
with self.library.database_lock:
|
||||
with Database() as videodb:
|
||||
with Database('jellyfin') as embydb:
|
||||
obj = MusicVideos(self.server, embydb, videodb, self.direct_path)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
obj = MusicVideos(self.server, jellyfindb, videodb, self.direct_path)
|
||||
|
||||
for items in server.get_items(library['Id'], "MusicVideo", False, self.sync['RestorePoint'].get('params')):
|
||||
|
||||
|
@ -373,13 +373,13 @@ class FullSync(object):
|
|||
obj.musicvideo(mvideo, library=library)
|
||||
|
||||
if self.update_library:
|
||||
self.musicvideos_compare(library, obj, embydb)
|
||||
self.musicvideos_compare(library, obj, jellyfindb)
|
||||
|
||||
def musicvideos_compare(self, library, obj, embydb):
|
||||
def musicvideos_compare(self, library, obj, jellyfindb):
|
||||
|
||||
''' Compare entries from library to what's in the embydb. Remove surplus
|
||||
''' Compare entries from library to what's in the jellyfindb. Remove surplus
|
||||
'''
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
|
||||
items = db.get_item_by_media_folder(library['Id'])
|
||||
current = obj.item_ids
|
||||
|
@ -397,8 +397,8 @@ class FullSync(object):
|
|||
|
||||
with self.library.music_database_lock:
|
||||
with Database('music') as musicdb:
|
||||
with Database('jellyfin') as embydb:
|
||||
obj = Music(self.server, embydb, musicdb, self.direct_path)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
obj = Music(self.server, jellyfindb, musicdb, self.direct_path)
|
||||
|
||||
for items in server.get_artists(library['Id'], False, self.sync['RestorePoint'].get('params')):
|
||||
|
||||
|
@ -432,13 +432,13 @@ class FullSync(object):
|
|||
|
||||
|
||||
if self.update_library:
|
||||
self.music_compare(library, obj, embydb)
|
||||
self.music_compare(library, obj, jellyfindb)
|
||||
|
||||
def music_compare(self, library, obj, embydb):
|
||||
def music_compare(self, library, obj, jellyfindb):
|
||||
|
||||
''' Compare entries from library to what's in the embydb. Remove surplus
|
||||
''' Compare entries from library to what's in the jellyfindb. Remove surplus
|
||||
'''
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
|
||||
items = db.get_item_by_media_folder(library['Id'])
|
||||
for x in list(items):
|
||||
|
@ -459,8 +459,8 @@ class FullSync(object):
|
|||
|
||||
with self.library.database_lock:
|
||||
with Database() as videodb:
|
||||
with Database('jellyfin') as embydb:
|
||||
obj = Movies(self.server, embydb, videodb, self.direct_path)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
obj = Movies(self.server, jellyfindb, videodb, self.direct_path)
|
||||
|
||||
for items in server.get_items(library_id, "BoxSet", False, self.sync['RestorePoint'].get('params')):
|
||||
|
||||
|
@ -482,9 +482,9 @@ class FullSync(object):
|
|||
|
||||
with self.library.database_lock:
|
||||
with Database() as videodb:
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
obj = Movies(self.server, embydb, videodb, self.direct_path)
|
||||
obj = Movies(self.server, jellyfindb, videodb, self.direct_path)
|
||||
obj.boxsets_reset()
|
||||
|
||||
self.boxsets(None)
|
||||
|
@ -497,9 +497,9 @@ class FullSync(object):
|
|||
MEDIA = self.library.MEDIA
|
||||
direct_path = self.library.direct_path
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
library = db.get_view(library_id.replace('Mixed:', ""))
|
||||
items = db.get_item_by_media_folder(library_id.replace('Mixed:', ""))
|
||||
media = 'music' if library[1] == 'music' else 'video'
|
||||
|
@ -518,7 +518,7 @@ class FullSync(object):
|
|||
movies = [x for x in items if x[1] == 'Movie']
|
||||
tvshows = [x for x in items if x[1] == 'Series']
|
||||
|
||||
obj = MEDIA['Movie'](self.server, embydb, kodidb, direct_path)['Remove']
|
||||
obj = MEDIA['Movie'](self.server, jellyfindb, kodidb, direct_path)['Remove']
|
||||
|
||||
for item in movies:
|
||||
|
||||
|
@ -526,7 +526,7 @@ class FullSync(object):
|
|||
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
|
||||
count += 1
|
||||
|
||||
obj = MEDIA['Series'](self.server, embydb, kodidb, direct_path)['Remove']
|
||||
obj = MEDIA['Series'](self.server, jellyfindb, kodidb, direct_path)['Remove']
|
||||
|
||||
for item in tvshows:
|
||||
|
||||
|
@ -534,7 +534,7 @@ class FullSync(object):
|
|||
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
|
||||
count += 1
|
||||
else:
|
||||
obj = MEDIA[items[0][1]](self.server, embydb, kodidb, direct_path)['Remove']
|
||||
obj = MEDIA[items[0][1]](self.server, jellyfindb, kodidb, direct_path)['Remove']
|
||||
|
||||
for item in items:
|
||||
|
||||
|
|
|
@ -22,5 +22,5 @@ from wrapper import progress
|
|||
from wrapper import catch
|
||||
from wrapper import silent_catch
|
||||
from wrapper import stop
|
||||
from wrapper import emby_item
|
||||
from wrapper import jellyfin_item
|
||||
from wrapper import library_check
|
||||
|
|
|
@ -17,7 +17,6 @@ import collections
|
|||
import requests
|
||||
from . import _, settings, window, dialog
|
||||
from downloader import TheVoid
|
||||
from emby import Emby
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
|
|
@ -99,13 +99,13 @@ def stop(default=None):
|
|||
return wrapper
|
||||
return decorator
|
||||
|
||||
def emby_item():
|
||||
def jellyfin_item():
|
||||
|
||||
''' Wrapper to retrieve the jellyfin_db item.
|
||||
'''
|
||||
def decorator(func):
|
||||
def wrapper(self, item, *args, **kwargs):
|
||||
e_item = self.emby_db.get_item_by_id(item['Id'] if type(item) == dict else item)
|
||||
e_item = self.jellyfin_db.get_item_by_id(item['Id'] if type(item) == dict else item)
|
||||
|
||||
return func(self, item, e_item=e_item, *args, **kwargs)
|
||||
|
||||
|
@ -129,7 +129,7 @@ def library_check():
|
|||
if 'e_item' in kwargs:
|
||||
try:
|
||||
view_id = kwargs['e_item'][6]
|
||||
view_name = self.emby_db.get_view_name(view_id)
|
||||
view_name = self.jellyfin_db.get_view_name(view_id)
|
||||
view = {'Name': view_name, 'Id': view_id}
|
||||
except Exception:
|
||||
view = None
|
||||
|
@ -141,7 +141,7 @@ def library_check():
|
|||
if item['Type'] == 'MusicArtist':
|
||||
|
||||
try:
|
||||
views = self.emby_db.get_views_by_media('music')[0]
|
||||
views = self.jellyfin_db.get_views_by_media('music')[0]
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
@ -152,7 +152,7 @@ def library_check():
|
|||
for ancestor in ancestors:
|
||||
if ancestor['Type'] == 'CollectionFolder':
|
||||
|
||||
view = self.emby_db.get_view_name(ancestor['Id'])
|
||||
view = self.jellyfin_db.get_view_name(ancestor['Id'])
|
||||
view = {'Id': None, 'Name': None} if view is None else {'Name': ancestor['Name'], 'Id': ancestor['Id']}
|
||||
|
||||
break
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
import logging
|
||||
|
||||
from client import EmbyClient
|
||||
from client import JellyfinClient
|
||||
from helpers import has_attribute
|
||||
|
||||
#################################################################################################
|
||||
|
@ -21,7 +21,7 @@ LOG = logging.getLogger('Jellyfin')
|
|||
def config(level=logging.INFO):
|
||||
|
||||
logger = logging.getLogger('Jellyfin')
|
||||
logger.addHandler(Emby.loghandler())
|
||||
logger.addHandler(Jellyfin.loghandler())
|
||||
logger.setLevel(level)
|
||||
|
||||
def ensure_client():
|
||||
|
@ -38,7 +38,7 @@ def ensure_client():
|
|||
return decorator
|
||||
|
||||
|
||||
class Emby(object):
|
||||
class Jellyfin(object):
|
||||
|
||||
''' This is your Jellyfinclient, you can create more than one. The server_id is only a temporary thing
|
||||
to communicate with the JellyfinClient().
|
||||
|
@ -92,7 +92,7 @@ class Emby(object):
|
|||
cls.client[client].stop()
|
||||
|
||||
cls.client = {}
|
||||
LOG.info("---[ STOPPED ALL JELLYFINCLIENT ]---")
|
||||
LOG.info("---[ STOPPED ALL JELLYFINCLIENTS ]---")
|
||||
|
||||
@classmethod
|
||||
def get_active_clients(cls):
|
||||
|
@ -102,7 +102,7 @@ class Emby(object):
|
|||
def __setattr__(self, name, value):
|
||||
|
||||
if has_attribute(self, name):
|
||||
return super(Emby, self).__setattr__(name, value)
|
||||
return super(Jellyfin, self).__setattr__(name, value)
|
||||
|
||||
setattr(self.client[self.server_id], name, value)
|
||||
|
||||
|
@ -116,7 +116,7 @@ class Emby(object):
|
|||
|
||||
def construct(self):
|
||||
|
||||
self.client[self.server_id] = EmbyClient()
|
||||
self.client[self.server_id] = JellyfinClient()
|
||||
|
||||
if self.server_id == 'default':
|
||||
LOG.info("---[ START JELLYFINCLIENT ]---")
|
|
@ -25,7 +25,7 @@ def callback(message, data):
|
|||
pass
|
||||
|
||||
|
||||
class EmbyClient(object):
|
||||
class JellyfinClient(object):
|
||||
|
||||
logged_in = False
|
||||
|
||||
|
@ -36,7 +36,7 @@ class EmbyClient(object):
|
|||
self.http = HTTP(self)
|
||||
self.wsc = WSClient(self)
|
||||
self.auth = ConnectionManager(self)
|
||||
self.emby = api.API(self.http)
|
||||
self.jellyfin = api.API(self.http)
|
||||
self.callback_ws = callback
|
||||
self.callback = callback
|
||||
|
||||
|
@ -100,7 +100,7 @@ class EmbyClient(object):
|
|||
return self.auth.__shortcuts__(key.replace('auth/', "", 1))
|
||||
|
||||
elif key.startswith('api'):
|
||||
return self.emby
|
||||
return self.jellyfin
|
||||
|
||||
elif key == 'connected':
|
||||
return self.logged_in
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#################################################################################################
|
||||
|
||||
def emby_url(client, handler):
|
||||
def jellyfin_url(client, handler):
|
||||
return "%s/emby/%s" % (client.config['auth.server'], handler)
|
||||
|
||||
def basic_info():
|
||||
|
@ -96,9 +96,9 @@ class API(object):
|
|||
def artwork(self, item_id, art, max_width, ext="jpg", index=None):
|
||||
|
||||
if index is None:
|
||||
return emby_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext))
|
||||
return jellyfin_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext))
|
||||
|
||||
return emby_url(self.client, "Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext))
|
||||
return jellyfin_url(self.client, "Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext))
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
@ -306,13 +306,13 @@ class API(object):
|
|||
return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE")
|
||||
|
||||
def get_sync_queue(self, date, filters=None):
|
||||
return self._get("Emby.Kodi.SyncQueue/{UserId}/GetItems", params={
|
||||
return self._get("Jellyfin.Plugin.KodiSyncQueue/{UserId}/GetItems", params={
|
||||
'LastUpdateDT': date,
|
||||
'filter': filters or None
|
||||
})
|
||||
|
||||
def get_server_time(self):
|
||||
return self._get("Emby.Kodi.SyncQueue/GetServerDateTime")
|
||||
return self._get("Jellyfin.Plugin.KodiSyncQueue/GetServerDateTime")
|
||||
|
||||
def get_play_info(self, item_id, profile):
|
||||
return self.items("/%s/PlaybackInfo" % item_id, "POST", json={
|
|
@ -75,11 +75,11 @@ class ConnectionManager(object):
|
|||
elif key == "server-version":
|
||||
return self.server_version
|
||||
elif key == "user-id":
|
||||
return self.emby_user_id()
|
||||
return self.jellyfin_user_id()
|
||||
elif key == "public-users":
|
||||
return self.get_public_users()
|
||||
elif key == "token":
|
||||
return self.emby_token()
|
||||
return self.jellyfin_token()
|
||||
elif key == "manual-server":
|
||||
return self.connect_to_address
|
||||
elif key == "connect-to-server":
|
||||
|
@ -154,7 +154,7 @@ class ConnectionManager(object):
|
|||
try:
|
||||
request = {
|
||||
'type': "POST",
|
||||
'url': self.get_emby_url(server, "Users/AuthenticateByName"),
|
||||
'url': self.get_jellyfin_url(server, "Users/AuthenticateByName"),
|
||||
'json': {
|
||||
'username': username,
|
||||
'password': hashlib.sha1(password or "").hexdigest(),
|
||||
|
@ -226,10 +226,10 @@ class ConnectionManager(object):
|
|||
LOG.info("Begin connect")
|
||||
return self._connect_to_servers(self.get_available_servers(), options)
|
||||
|
||||
def emby_user_id(self):
|
||||
def jellyfin_user_id(self):
|
||||
return self.get_server_info(self.server_id)['UserId']
|
||||
|
||||
def emby_token(self):
|
||||
def jellyfin_token(self):
|
||||
return self.get_server_info(self.server_id)['AccessToken']
|
||||
|
||||
def get_server_info(self, server_id):
|
||||
|
@ -245,9 +245,9 @@ class ConnectionManager(object):
|
|||
return server
|
||||
|
||||
def get_public_users(self):
|
||||
return self.client.emby.get_public_users()
|
||||
return self.client.jellyfin.get_public_users()
|
||||
|
||||
def get_emby_url(self, base, handler):
|
||||
def get_jellyfin_url(self, base, handler):
|
||||
return "%s/emby/%s" % (base, handler)
|
||||
|
||||
def _request_url(self, request, headers=True):
|
||||
|
@ -306,7 +306,7 @@ class ConnectionManager(object):
|
|||
|
||||
def _try_connect(self, url, timeout=None, options={}):
|
||||
|
||||
url = self.get_emby_url(url, "system/info/public")
|
||||
url = self.get_jellyfin_url(url, "system/info/public")
|
||||
LOG.info("tryConnect url: %s", url)
|
||||
|
||||
return self._request_url({
|
||||
|
@ -582,7 +582,7 @@ class ConnectionManager(object):
|
|||
try:
|
||||
system_info = self._request_url({
|
||||
'type': "GET",
|
||||
'url': self.get_emby_url(get_server_address(server, connection_mode), "System/Info"),
|
||||
'url': self.get_jellyfin_url(get_server_address(server, connection_mode), "System/Info"),
|
||||
'verify': options.get('ssl'),
|
||||
'dataType': "json",
|
||||
'headers': {
|
|
@ -12,13 +12,13 @@ import xbmc
|
|||
import xbmcgui
|
||||
|
||||
from objects import Movies, TVShows, MusicVideos, Music
|
||||
from database import Database, emby_db, get_sync, save_sync
|
||||
from database import Database, jellyfin_db, get_sync, save_sync
|
||||
from full_sync import FullSync
|
||||
from views import Views
|
||||
from downloader import GetItemWorker
|
||||
from helper import _, api, stop, settings, window, dialog, event, progress, LibraryException
|
||||
from helper.utils import split_list, set_screensaver, get_screensaver
|
||||
from emby import Emby
|
||||
from jellyfin import Jellyfin
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -62,7 +62,7 @@ class Library(threading.Thread):
|
|||
self.progress_display = int(settings('syncProgress') or 50)
|
||||
self.monitor = monitor
|
||||
self.player = monitor.monitor.player
|
||||
self.server = Emby().get_client()
|
||||
self.server = Jellyfin().get_client()
|
||||
self.updated_queue = Queue.Queue()
|
||||
self.userdata_queue = Queue.Queue()
|
||||
self.removed_queue = Queue.Queue()
|
||||
|
@ -71,7 +71,7 @@ class Library(threading.Thread):
|
|||
self.removed_output = self.__new_queues__()
|
||||
self.notify_output = Queue.Queue()
|
||||
|
||||
self.emby_threads = []
|
||||
self.jellyfin_threads = []
|
||||
self.download_threads = []
|
||||
self.notify_threads = []
|
||||
self.writer_threads = {'updated': [], 'userdata': [], 'removed': []}
|
||||
|
@ -240,7 +240,7 @@ class Library(threading.Thread):
|
|||
|
||||
''' Get items based on the local jellyfin database and place item in appropriate queues.
|
||||
'''
|
||||
if self.removed_queue.qsize() and len(self.emby_threads) < 2:
|
||||
if self.removed_queue.qsize() and len(self.jellyfin_threads) < 2:
|
||||
|
||||
new_thread = SortWorker(self.removed_queue, self.removed_output)
|
||||
new_thread.start()
|
||||
|
@ -482,8 +482,8 @@ class Library(threading.Thread):
|
|||
whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
|
||||
libraries = []
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
|
||||
if mode in ('SyncLibrarySelection', 'RepairLibrarySelection', 'RemoveLibrarySelection'):
|
||||
for library in sync['Whitelist']:
|
||||
|
@ -614,7 +614,7 @@ class UpdatedWorker(threading.Thread):
|
|||
|
||||
with self.lock:
|
||||
with self.database as kodidb:
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
while True:
|
||||
|
||||
|
@ -623,7 +623,7 @@ class UpdatedWorker(threading.Thread):
|
|||
except Queue.Empty:
|
||||
break
|
||||
|
||||
obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])[item['Type']]
|
||||
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])[item['Type']]
|
||||
|
||||
try:
|
||||
if obj(item) and self.notify:
|
||||
|
@ -658,7 +658,7 @@ class UserDataWorker(threading.Thread):
|
|||
|
||||
with self.lock:
|
||||
with self.database as kodidb:
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
while True:
|
||||
|
||||
|
@ -667,7 +667,7 @@ class UserDataWorker(threading.Thread):
|
|||
except Queue.Empty:
|
||||
break
|
||||
|
||||
obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])['UserData']
|
||||
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['UserData']
|
||||
|
||||
try:
|
||||
obj(item)
|
||||
|
@ -698,8 +698,8 @@ class SortWorker(threading.Thread):
|
|||
|
||||
def run(self):
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
database = emby_db.EmbyDatabase(embydb.cursor)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
database = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
|
||||
while True:
|
||||
|
||||
|
@ -744,7 +744,7 @@ class RemovedWorker(threading.Thread):
|
|||
|
||||
with self.lock:
|
||||
with self.database as kodidb:
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
while True:
|
||||
|
||||
|
@ -753,7 +753,7 @@ class RemovedWorker(threading.Thread):
|
|||
except Queue.Empty:
|
||||
break
|
||||
|
||||
obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])['Remove']
|
||||
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['Remove']
|
||||
|
||||
try:
|
||||
obj(item['Id'])
|
||||
|
|
|
@ -17,7 +17,7 @@ import player
|
|||
from client import get_device_id
|
||||
from objects import Actions, PlaylistWorker, on_play, on_update, special_listener
|
||||
from helper import _, settings, window, dialog, event, api, JSONRPC
|
||||
from emby import Emby
|
||||
from jellyfin import Jellyfin
|
||||
from webservice import WebService
|
||||
|
||||
#################################################################################################
|
||||
|
@ -118,9 +118,9 @@ class Monitor(xbmc.Monitor):
|
|||
|
||||
return
|
||||
|
||||
server = Emby(data['ServerId'])
|
||||
server = Jellyfin(data['ServerId'])
|
||||
except Exception:
|
||||
server = Emby()
|
||||
server = Jellyfin()
|
||||
|
||||
if method == 'GetItem':
|
||||
|
||||
|
@ -169,7 +169,7 @@ class Monitor(xbmc.Monitor):
|
|||
|
||||
elif method == 'GetUsers':
|
||||
|
||||
users = server['api'].get_users(data.get('IsDisabled', True), data.get('IsHidden', True))
|
||||
users = server['api'].get_users()
|
||||
self.void_responder(data, users)
|
||||
|
||||
elif method == 'GetTranscodeOptions':
|
||||
|
@ -277,7 +277,7 @@ class Monitor(xbmc.Monitor):
|
|||
|
||||
def server_instance(self, server_id=None):
|
||||
|
||||
server = Emby(server_id)
|
||||
server = Jellyfin(server_id)
|
||||
self.post_capabilities(server)
|
||||
|
||||
if server_id is not None:
|
||||
|
|
|
@ -18,7 +18,6 @@ from downloader import TheVoid
|
|||
from obj import Objects
|
||||
from helper import _, playutils, api, window, settings, dialog, JSONRPC
|
||||
from dialogs import resume
|
||||
from emby import Emby
|
||||
from utils import get_play_action
|
||||
|
||||
#################################################################################################
|
||||
|
|
|
@ -9,8 +9,8 @@ import urllib
|
|||
import downloader as server
|
||||
from obj import Objects
|
||||
from kodi import Movies as KodiDb, queries as QU
|
||||
from database import emby_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, emby_item, library_check, values, settings, Local
|
||||
from database import jellyfin_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, jellyfin_item, library_check, values, settings, Local
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -21,14 +21,14 @@ LOG = logging.getLogger("JELLYFIN."+__name__)
|
|||
|
||||
class Movies(KodiDb):
|
||||
|
||||
def __init__(self, server, embydb, videodb, direct_path):
|
||||
def __init__(self, server, jellyfindb, videodb, direct_path):
|
||||
|
||||
self.server = server
|
||||
self.emby = embydb
|
||||
self.jellyfin = jellyfindb
|
||||
self.video = videodb
|
||||
self.direct_path = direct_path
|
||||
|
||||
self.emby_db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
self.objects = Objects()
|
||||
self.item_ids = []
|
||||
|
||||
|
@ -46,7 +46,7 @@ class Movies(KodiDb):
|
|||
return self.remove
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
@library_check()
|
||||
def movie(self, item, e_item, library):
|
||||
|
||||
|
@ -146,7 +146,7 @@ class Movies(KodiDb):
|
|||
obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj))
|
||||
|
||||
self.add(*values(obj, QU.add_movie_obj))
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_movie_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_movie_obj))
|
||||
LOG.info("ADD movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title'])
|
||||
|
||||
def movie_update(self, obj):
|
||||
|
@ -160,7 +160,7 @@ class Movies(KodiDb):
|
|||
self.update_unique_id(*values(obj, QU.update_unique_id_movie_obj))
|
||||
|
||||
self.update(*values(obj, QU.update_movie_obj))
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("UPDATE movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title'])
|
||||
|
||||
def trailer(self, obj):
|
||||
|
@ -203,7 +203,7 @@ class Movies(KodiDb):
|
|||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def boxset(self, item, e_item):
|
||||
|
||||
''' If item does not exist, entry will be added.
|
||||
|
@ -234,11 +234,11 @@ class Movies(KodiDb):
|
|||
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.emby_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj))
|
||||
self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj))
|
||||
LOG.info("DELETE from boxset [%s] %s: %s", temp_obj['SetId'], temp_obj['Title'], temp_obj['MovieId'])
|
||||
|
||||
self.artwork.add(obj['Artwork'], obj['SetId'], "set")
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_boxset_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_boxset_obj))
|
||||
LOG.info("UPDATE boxset [%s] %s", obj['SetId'], obj['Title'])
|
||||
|
||||
def boxset_current(self, obj):
|
||||
|
@ -246,7 +246,7 @@ class Movies(KodiDb):
|
|||
''' Add or removes movies based on the current movies found in the boxset.
|
||||
'''
|
||||
try:
|
||||
current = self.emby_db.get_item_id_by_parent_id(*values(obj, QUEM.get_item_id_by_parent_boxset_obj))
|
||||
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 = {}
|
||||
|
@ -261,7 +261,7 @@ class Movies(KodiDb):
|
|||
temp_obj['Id'] = movie['Id']
|
||||
|
||||
try:
|
||||
temp_obj['MovieId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
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'])
|
||||
|
||||
|
@ -270,7 +270,7 @@ class Movies(KodiDb):
|
|||
if temp_obj['Id'] not in obj['Current']:
|
||||
|
||||
self.set_boxset(*values(temp_obj, QU.update_movie_set_obj))
|
||||
self.emby_db.update_parent_id(*values(temp_obj, QUEM.update_parent_movie_obj))
|
||||
self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.update_parent_movie_obj))
|
||||
LOG.info("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'])
|
||||
|
@ -279,12 +279,12 @@ class Movies(KodiDb):
|
|||
|
||||
''' Special function to remove all existing boxsets.
|
||||
'''
|
||||
boxsets = self.emby_db.get_items_by_media('set')
|
||||
boxsets = self.jellyfin_db.get_items_by_media('set')
|
||||
for boxset in boxsets:
|
||||
self.remove(boxset[0])
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def userdata(self, item, e_item):
|
||||
|
||||
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||
|
@ -313,11 +313,11 @@ class Movies(KodiDb):
|
|||
|
||||
LOG.debug("New resume point %s: %s", obj['Id'], obj['Resume'])
|
||||
self.add_playstate(*values(obj, QU.add_bookmark_obj))
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("USERDATA movie [%s/%s] %s: %s", obj['FileId'], obj['MovieId'], obj['Id'], obj['Title'])
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def remove(self, item_id, e_item):
|
||||
|
||||
''' Remove movieid, fileid, jellyfin reference.
|
||||
|
@ -338,15 +338,15 @@ class Movies(KodiDb):
|
|||
self.delete(*values(obj, QU.delete_movie_obj))
|
||||
elif obj['Media'] == 'set':
|
||||
|
||||
for movie in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_movie_obj)):
|
||||
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.emby_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_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.emby_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
LOG.info("DELETE %s [%s/%s] %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id'])
|
||||
|
|
|
@ -9,8 +9,8 @@ import urllib
|
|||
|
||||
from obj import Objects
|
||||
from kodi import Music as KodiDb, queries_music as QU
|
||||
from database import emby_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, emby_item, values, library_check, settings, Local
|
||||
from database import jellyfin_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, jellyfin_item, values, library_check, settings, Local
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -21,14 +21,14 @@ LOG = logging.getLogger("JELLYFIN."+__name__)
|
|||
|
||||
class Music(KodiDb):
|
||||
|
||||
def __init__(self, server, embydb, musicdb, direct_path):
|
||||
def __init__(self, server, jellyfindb, musicdb, direct_path):
|
||||
|
||||
self.server = server
|
||||
self.emby = embydb
|
||||
self.jellyfin = jellyfindb
|
||||
self.music = musicdb
|
||||
self.direct_path = direct_path
|
||||
|
||||
self.emby_db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
self.objects = Objects()
|
||||
self.item_ids = []
|
||||
|
||||
|
@ -48,7 +48,7 @@ class Music(KodiDb):
|
|||
return self.remove
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
@library_check()
|
||||
def artist(self, item, e_item, library):
|
||||
|
||||
|
@ -107,19 +107,19 @@ class Music(KodiDb):
|
|||
Kodi doesn't allow that. In case that happens we just merge the artist entries.
|
||||
'''
|
||||
obj['ArtistId'] = self.get(*values(obj, QU.get_artist_obj))
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_artist_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_artist_obj))
|
||||
LOG.info("ADD artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id'])
|
||||
|
||||
def artist_update(self, obj):
|
||||
|
||||
''' Update object to kodi.
|
||||
'''
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("UPDATE artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id'])
|
||||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def album(self, item, e_item):
|
||||
|
||||
''' Update object to kodi.
|
||||
|
@ -172,14 +172,14 @@ class Music(KodiDb):
|
|||
''' Add object to kodi.
|
||||
'''
|
||||
obj['AlbumId'] = self.get_album(*values(obj, QU.get_album_obj))
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_album_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_album_obj))
|
||||
LOG.info("ADD album [%s] %s: %s", obj['AlbumId'], obj['Title'], obj['Id'])
|
||||
|
||||
def album_update(self, obj):
|
||||
|
||||
''' Update object to kodi.
|
||||
'''
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("UPDATE album [%s] %s: %s", obj['AlbumId'], obj['Title'], obj['Id'])
|
||||
|
||||
def artist_discography(self, obj):
|
||||
|
@ -193,12 +193,12 @@ class Music(KodiDb):
|
|||
temp_obj['AlbumId'] = obj['Id']
|
||||
|
||||
try:
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except TypeError:
|
||||
continue
|
||||
|
||||
self.add_discography(*values(temp_obj, QU.update_discography_obj))
|
||||
self.emby_db.update_parent_id(*values(temp_obj, QUEM.update_parent_album_obj))
|
||||
self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.update_parent_album_obj))
|
||||
|
||||
def artist_link(self, obj):
|
||||
|
||||
|
@ -212,12 +212,12 @@ class Music(KodiDb):
|
|||
temp_obj['Id'] = artist['Id']
|
||||
|
||||
try:
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except TypeError:
|
||||
|
||||
try:
|
||||
self.artist(self.server['api'].get_item(temp_obj['Id']), library=None)
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except Exception as error:
|
||||
LOG.error(error)
|
||||
continue
|
||||
|
@ -228,7 +228,7 @@ class Music(KodiDb):
|
|||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def song(self, item, e_item):
|
||||
|
||||
''' Update object to kodi.
|
||||
|
@ -310,7 +310,7 @@ class Music(KodiDb):
|
|||
obj['PathId'] = self.add_path(obj['Path'])
|
||||
|
||||
try:
|
||||
obj['AlbumId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0]
|
||||
obj['AlbumId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0]
|
||||
except TypeError:
|
||||
|
||||
try:
|
||||
|
@ -318,12 +318,12 @@ class Music(KodiDb):
|
|||
raise TypeError("No album id found associated?")
|
||||
|
||||
self.album(self.server['api'].get_item(obj['SongAlbumId']))
|
||||
obj['AlbumId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0]
|
||||
obj['AlbumId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0]
|
||||
except TypeError:
|
||||
self.single(obj)
|
||||
|
||||
self.add_song(*values(obj, QU.add_song_obj))
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_song_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_song_obj))
|
||||
LOG.debug("ADD song [%s/%s/%s] %s: %s", obj['PathId'], obj['AlbumId'], obj['SongId'], obj['Id'], obj['Title'])
|
||||
|
||||
def song_update(self, obj):
|
||||
|
@ -333,7 +333,7 @@ class Music(KodiDb):
|
|||
self.update_path(*values(obj, QU.update_path_obj))
|
||||
|
||||
self.update_song(*values(obj, QU.update_song_obj))
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("UPDATE song [%s/%s/%s] %s: %s", obj['PathId'], obj['AlbumId'], obj['SongId'], obj['Id'], obj['Title'])
|
||||
|
||||
def get_song_path_filename(self, obj, api):
|
||||
|
@ -368,12 +368,12 @@ class Music(KodiDb):
|
|||
artists.append(temp_obj['Name'])
|
||||
|
||||
try:
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except TypeError:
|
||||
|
||||
try:
|
||||
self.artist(self.server['api'].get_item(temp_obj['Id']), library=None)
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except Exception as error:
|
||||
LOG.error(error)
|
||||
continue
|
||||
|
@ -402,12 +402,12 @@ class Music(KodiDb):
|
|||
temp_obj['Index'] = index
|
||||
|
||||
try:
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except TypeError:
|
||||
|
||||
try:
|
||||
self.artist(self.server['api'].get_item(temp_obj['Id']), library=None)
|
||||
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
|
||||
except Exception as error:
|
||||
LOG.error(error)
|
||||
continue
|
||||
|
@ -422,7 +422,7 @@ class Music(KodiDb):
|
|||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def userdata(self, item, e_item):
|
||||
|
||||
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||
|
@ -446,11 +446,11 @@ class Music(KodiDb):
|
|||
|
||||
self.rate_song(*values(obj, QU.update_song_rating_obj))
|
||||
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("USERDATA %s [%s] %s: %s", obj['Media'], obj['KodiId'], obj['Id'], obj['Title'])
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def remove(self, item_id, e_item):
|
||||
|
||||
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||
|
@ -470,47 +470,47 @@ class Music(KodiDb):
|
|||
if obj['Media'] == 'song':
|
||||
|
||||
self.remove_song(obj['KodiId'], obj['Id'])
|
||||
self.emby_db.remove_wild_item(obj['id'])
|
||||
self.jellyfin_db.remove_wild_item(obj['id'])
|
||||
|
||||
for item in self.emby_get_item_by_wild_id(*values(obj, QUEM.get_item_by_wild_obj)):
|
||||
for item in self.jellyfin_db.get_item_by_wild_id(*values(obj, QUEM.get_item_by_wild_obj)):
|
||||
if item[1] == 'album':
|
||||
|
||||
temp_obj = dict(obj)
|
||||
temp_obj['ParentId'] = item[0]
|
||||
|
||||
if not self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
|
||||
if not self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
|
||||
self.remove_album(temp_obj['ParentId'], obj['Id'])
|
||||
|
||||
elif obj['Media'] == 'album':
|
||||
obj['ParentId'] = obj['KodiId']
|
||||
|
||||
for song in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_song_obj)):
|
||||
for song in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_song_obj)):
|
||||
self.remove_song(song[1], obj['Id'])
|
||||
else:
|
||||
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_song_obj))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_song_obj))
|
||||
|
||||
self.remove_album(obj['KodiId'], obj['Id'])
|
||||
|
||||
elif obj['Media'] == 'artist':
|
||||
obj['ParentId'] = obj['KodiId']
|
||||
|
||||
for album in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)):
|
||||
for album in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)):
|
||||
|
||||
temp_obj = dict(obj)
|
||||
temp_obj['ParentId'] = album[1]
|
||||
|
||||
for song in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
|
||||
for song in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
|
||||
self.remove_song(song[1], obj['Id'])
|
||||
else:
|
||||
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_song_obj))
|
||||
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_artist_obj))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_song_obj))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_artist_obj))
|
||||
self.remove_album(temp_obj['ParentId'], obj['Id'])
|
||||
else:
|
||||
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_album_obj))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_album_obj))
|
||||
|
||||
self.remove_artist(obj['KodiId'], obj['Id'])
|
||||
|
||||
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
|
||||
def remove_artist(self, kodi_id, item_id):
|
||||
|
||||
|
@ -530,7 +530,7 @@ class Music(KodiDb):
|
|||
self.delete_song(kodi_id)
|
||||
LOG.info("DELETE song [%s] %s", kodi_id, item_id)
|
||||
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def get_child(self, item_id, e_item):
|
||||
|
||||
''' Get all child elements from tv show jellyfin id.
|
||||
|
@ -548,13 +548,13 @@ class Music(KodiDb):
|
|||
|
||||
obj['ParentId'] = obj['KodiId']
|
||||
|
||||
for album in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)):
|
||||
for album in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)):
|
||||
|
||||
temp_obj = dict(obj)
|
||||
temp_obj['ParentId'] = album[1]
|
||||
child.append((album[0],))
|
||||
|
||||
for song in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
|
||||
for song in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
|
||||
child.append((song[0],))
|
||||
|
||||
return child
|
||||
|
|
|
@ -9,8 +9,8 @@ import urllib
|
|||
|
||||
from obj import Objects
|
||||
from kodi import MusicVideos as KodiDb, queries as QU
|
||||
from database import emby_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, library_check, emby_item, values, Local
|
||||
from database import jellyfin_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, library_check, jellyfin_item, values, Local
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -21,14 +21,14 @@ LOG = logging.getLogger("JELLYFIN."+__name__)
|
|||
|
||||
class MusicVideos(KodiDb):
|
||||
|
||||
def __init__(self, server, embydb, videodb, direct_path):
|
||||
def __init__(self, server, jellyfindb, videodb, direct_path):
|
||||
|
||||
self.server = server
|
||||
self.emby = embydb
|
||||
self.jellyfin = jellyfindb
|
||||
self.video = videodb
|
||||
self.direct_path = direct_path
|
||||
|
||||
self.emby_db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
self.objects = Objects()
|
||||
self.item_ids = []
|
||||
|
||||
|
@ -44,7 +44,7 @@ class MusicVideos(KodiDb):
|
|||
return self.remove
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
@library_check()
|
||||
def musicvideo(self, item, e_item, library):
|
||||
|
||||
|
@ -149,7 +149,7 @@ class MusicVideos(KodiDb):
|
|||
obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj))
|
||||
|
||||
self.add(*values(obj, QU.add_musicvideo_obj))
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_mvideo_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_mvideo_obj))
|
||||
LOG.info("ADD mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
|
||||
|
||||
def musicvideo_update(self, obj):
|
||||
|
@ -157,7 +157,7 @@ class MusicVideos(KodiDb):
|
|||
''' Update object to kodi.
|
||||
'''
|
||||
self.update(*values(obj, QU.update_musicvideo_obj))
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("UPDATE mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
|
||||
|
||||
def get_path_filename(self, obj):
|
||||
|
@ -185,7 +185,7 @@ class MusicVideos(KodiDb):
|
|||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def userdata(self, item, e_item):
|
||||
|
||||
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||
|
@ -213,11 +213,11 @@ class MusicVideos(KodiDb):
|
|||
self.remove_tag(*values(obj, QU.delete_tag_mvideo_obj))
|
||||
|
||||
self.add_playstate(*values(obj, QU.add_bookmark_obj))
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
LOG.info("USERDATA mvideo [%s/%s] %s: %s", obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def remove(self, item_id, e_item):
|
||||
|
||||
''' Remove mvideoid, fileid, pathid, jellyfin reference.
|
||||
|
@ -237,5 +237,5 @@ class MusicVideos(KodiDb):
|
|||
if self.direct_path:
|
||||
self.remove_path(*values(obj, QU.delete_path_obj))
|
||||
|
||||
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
LOG.info("DELETE musicvideo %s [%s/%s] %s", obj['MvideoId'], obj['PathId'], obj['FileId'], obj['Id'])
|
||||
|
|
|
@ -11,8 +11,8 @@ from ntpath import dirname
|
|||
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, Local
|
||||
from database import jellyfin_db, queries as QUEM
|
||||
from helper import api, catch, stop, validate, jellyfin_item, library_check, settings, values, Local
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -23,15 +23,15 @@ LOG = logging.getLogger("JELLYFIN."+__name__)
|
|||
|
||||
class TVShows(KodiDb):
|
||||
|
||||
def __init__(self, server, embydb, videodb, direct_path, update_library=False):
|
||||
def __init__(self, server, jellyfindb, videodb, direct_path, update_library=False):
|
||||
|
||||
self.server = server
|
||||
self.emby = embydb
|
||||
self.jellyfin = jellyfindb
|
||||
self.video = videodb
|
||||
self.direct_path = direct_path
|
||||
self.update_library = update_library
|
||||
|
||||
self.emby_db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
self.objects = Objects()
|
||||
self.item_ids = []
|
||||
|
||||
|
@ -51,7 +51,7 @@ class TVShows(KodiDb):
|
|||
return self.remove
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
@library_check()
|
||||
def tvshow(self, item, e_item, library):
|
||||
|
||||
|
@ -143,18 +143,18 @@ class TVShows(KodiDb):
|
|||
self.item_ids.append(season['SeriesId'])
|
||||
|
||||
try:
|
||||
self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
||||
self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
||||
|
||||
if self.update_library:
|
||||
season_episodes[season['Id']] = season['SeriesId']
|
||||
except TypeError:
|
||||
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_pool_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_pool_obj))
|
||||
LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId'])
|
||||
season_episodes[season['Id']] = season['SeriesId']
|
||||
|
||||
try:
|
||||
self.emby_db.get_item_by_id(season['Id'])[0]
|
||||
self.jellyfin_db.get_item_by_id(season['Id'])[0]
|
||||
self.item_ids.append(season['Id'])
|
||||
except TypeError:
|
||||
self.season(season, obj['ShowId'])
|
||||
|
@ -184,7 +184,7 @@ class TVShows(KodiDb):
|
|||
obj['PathId'] = self.add_path(*values(obj, QU.get_path_obj))
|
||||
|
||||
self.add(*values(obj, QU.add_tvshow_obj))
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_tvshow_obj))
|
||||
self.jellyfin_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'])
|
||||
|
||||
def tvshow_update(self, obj):
|
||||
|
@ -198,7 +198,7 @@ class TVShows(KodiDb):
|
|||
self.update_unique_id(*values(obj, QU.update_unique_id_tvshow_obj))
|
||||
|
||||
self.update(*values(obj, QU.update_tvshow_obj))
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_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'])
|
||||
|
||||
def get_path_filename(self, obj):
|
||||
|
@ -237,7 +237,7 @@ class TVShows(KodiDb):
|
|||
if obj['ShowId'] is None:
|
||||
|
||||
try:
|
||||
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
||||
obj['ShowId'] = self.jellyfin_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'])
|
||||
|
||||
|
@ -247,7 +247,7 @@ class TVShows(KodiDb):
|
|||
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
|
||||
|
||||
if obj['Location'] != "Virtual":
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_season_obj))
|
||||
self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_season_obj))
|
||||
self.item_ids.append(obj['Id'])
|
||||
|
||||
self.artwork.add(obj['Artwork'], obj['SeasonId'], "season")
|
||||
|
@ -255,7 +255,7 @@ class TVShows(KodiDb):
|
|||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def episode(self, item, e_item):
|
||||
|
||||
''' If item does not exist, entry will be added.
|
||||
|
@ -384,7 +384,7 @@ class TVShows(KodiDb):
|
|||
|
||||
return self.episode_add(obj)
|
||||
|
||||
self.emby_db.add_reference(*values(obj, QUEM.add_reference_episode_obj))
|
||||
self.jellyfin_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'])
|
||||
|
||||
def episode_update(self, obj):
|
||||
|
@ -399,8 +399,8 @@ class TVShows(KodiDb):
|
|||
|
||||
self.update_episode(*values(obj, QU.update_episode_obj))
|
||||
|
||||
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.emby_db.update_parent_id(*values(obj, QUEM.update_parent_episode_obj))
|
||||
self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
|
||||
self.jellyfin_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'])
|
||||
|
||||
def get_episode_path_filename(self, obj):
|
||||
|
@ -429,13 +429,13 @@ class TVShows(KodiDb):
|
|||
obj['Filename'] = "%s?%s" % (obj['Path'], urllib.urlencode(params))
|
||||
|
||||
def get_show_id(self, obj):
|
||||
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))
|
||||
obj['ShowId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))
|
||||
|
||||
if obj['ShowId'] is None:
|
||||
|
||||
try:
|
||||
self.tvshow(self.server['api'].get_item(obj['SeriesId']), library=None)
|
||||
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
|
||||
obj['ShowId'] = self.jellyfin_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'])
|
||||
|
||||
|
@ -449,7 +449,7 @@ class TVShows(KodiDb):
|
|||
|
||||
|
||||
@stop()
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def userdata(self, item, e_item):
|
||||
|
||||
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||
|
@ -505,11 +505,11 @@ class TVShows(KodiDb):
|
|||
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))
|
||||
self.jellyfin_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()
|
||||
@jellyfin_item()
|
||||
def remove(self, item_id, e_item):
|
||||
|
||||
''' Remove showid, fileid, pathid, jellyfin reference.
|
||||
|
@ -529,7 +529,7 @@ class TVShows(KodiDb):
|
|||
|
||||
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))
|
||||
season = self.jellyfin_db.get_full_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
|
||||
|
||||
try:
|
||||
temp_obj['Id'] = season[0]
|
||||
|
@ -537,61 +537,61 @@ class TVShows(KodiDb):
|
|||
except TypeError:
|
||||
return
|
||||
|
||||
if not self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)):
|
||||
if not self.jellyfin_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))
|
||||
self.jellyfin_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))
|
||||
temp_obj['Id'] = self.jellyfin_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)):
|
||||
for season in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_season_obj)):
|
||||
self.remove_season(season[1], obj['Id'])
|
||||
else:
|
||||
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_season_obj))
|
||||
self.jellyfin_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))
|
||||
self.jellyfin_db.remove_item(*values(temp_obj, QUEM.delete_item_obj))
|
||||
|
||||
elif obj['Media'] == 'tvshow':
|
||||
obj['ParentId'] = obj['KodiId']
|
||||
|
||||
for season in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
|
||||
for season in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
|
||||
|
||||
temp_obj = dict(obj)
|
||||
temp_obj['ParentId'] = season[1]
|
||||
|
||||
for episode in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)):
|
||||
for episode in self.jellyfin_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))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_episode_obj))
|
||||
else:
|
||||
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
|
||||
|
||||
self.remove_tvshow(obj['KodiId'], obj['Id'])
|
||||
|
||||
elif obj['Media'] == 'season':
|
||||
|
||||
for episode in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)):
|
||||
for episode in self.jellyfin_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))
|
||||
self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_episode_obj))
|
||||
|
||||
self.remove_season(obj['KodiId'], obj['Id'])
|
||||
|
||||
if not self.emby_db.get_item_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj)):
|
||||
if not self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj)):
|
||||
|
||||
self.remove_tvshow(obj['ParentId'], obj['Id'])
|
||||
self.emby_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj))
|
||||
self.jellyfin_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj))
|
||||
|
||||
# Remove any series pooling episodes
|
||||
for episode in self.emby_db.get_media_by_parent_id(obj['Id']):
|
||||
for episode in self.jellyfin_db.get_media_by_parent_id(obj['Id']):
|
||||
self.remove_episode(episode[2], episode[3], obj['Id'])
|
||||
else:
|
||||
self.emby_db.remove_media_by_parent_id(obj['Id'])
|
||||
self.jellyfin_db.remove_media_by_parent_id(obj['Id'])
|
||||
|
||||
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||
|
||||
def remove_tvshow(self, kodi_id, item_id):
|
||||
|
||||
|
@ -611,7 +611,7 @@ class TVShows(KodiDb):
|
|||
self.delete_episode(kodi_id, file_id)
|
||||
LOG.info("DELETE episode [%s/%s] %s", file_id, kodi_id, item_id)
|
||||
|
||||
@emby_item()
|
||||
@jellyfin_item()
|
||||
def get_child(self, item_id, e_item):
|
||||
|
||||
''' Get all child elements from tv show jellyfin id.
|
||||
|
@ -629,16 +629,16 @@ class TVShows(KodiDb):
|
|||
|
||||
obj['ParentId'] = obj['KodiId']
|
||||
|
||||
for season in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
|
||||
for season in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
|
||||
|
||||
temp_obj = dict(obj)
|
||||
temp_obj['ParentId'] = season[1]
|
||||
child.append(season[0])
|
||||
|
||||
for episode in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)):
|
||||
for episode in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)):
|
||||
child.append(episode[0])
|
||||
|
||||
for episode in self.emby_db.get_media_by_parent_id(obj['Id']):
|
||||
for episode in self.jellyfin_db.get_media_by_parent_id(obj['Id']):
|
||||
child.append(episode[0])
|
||||
|
||||
return child
|
||||
|
|
|
@ -11,7 +11,7 @@ import xbmcvfs
|
|||
|
||||
from objects.obj import Objects
|
||||
from helper import _, api, window, settings, dialog, event, silent_catch, JSONRPC
|
||||
from emby import Emby
|
||||
from jellyfin import Jellyfin
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
@ -148,7 +148,7 @@ class Player(xbmc.Player):
|
|||
'CurrentPosition': item.get('CurrentPosition') or int(seektime),
|
||||
'Muted': muted,
|
||||
'Volume': volume,
|
||||
'Server': Emby(item['ServerId']).get_client(),
|
||||
'Server': Jellyfin(item['ServerId']).get_client(),
|
||||
'Paused': False
|
||||
})
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ import xbmc
|
|||
import xbmcvfs
|
||||
|
||||
import downloader as server
|
||||
from database import Database, emby_db, get_sync, save_sync
|
||||
from database import Database, jellyfin_db, get_sync, save_sync
|
||||
from objects.kodi import kodi
|
||||
from helper import _, api, indent, write_xml, window, event
|
||||
from emby import Emby
|
||||
from jellyfin import Jellyfin
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
@ -144,21 +144,21 @@ class Views(object):
|
|||
def __init__(self):
|
||||
|
||||
self.sync = get_sync()
|
||||
self.server = Emby()
|
||||
self.server = Jellyfin()
|
||||
|
||||
def add_library(self, view):
|
||||
|
||||
''' Add entry to view table in jellyfin database.
|
||||
'''
|
||||
with Database('jellyfin') as embydb:
|
||||
emby_db.EmbyDatabase(embydb.cursor).add_view(view['Id'], view['Name'], view['Media'])
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
jellyfin_db.JellyfinDatabase(jellyfindb.cursor).add_view(view['Id'], view['Name'], view['Media'])
|
||||
|
||||
def remove_library(self, view_id):
|
||||
|
||||
''' Remove entry from view table in jellyfin database.
|
||||
'''
|
||||
with Database('jellyfin') as embydb:
|
||||
emby_db.EmbyDatabase(embydb.cursor).remove_view(view_id)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
jellyfin_db.JellyfinDatabase(jellyfindb.cursor).remove_view(view_id)
|
||||
|
||||
self.delete_playlist_by_id(view_id)
|
||||
self.delete_node_by_id(view_id)
|
||||
|
@ -203,9 +203,9 @@ class Views(object):
|
|||
|
||||
self.add_library(library)
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
|
||||
views = emby_db.EmbyDatabase(embydb.cursor).get_views()
|
||||
views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
||||
removed = []
|
||||
|
||||
for view in views:
|
||||
|
@ -226,8 +226,8 @@ class Views(object):
|
|||
playlist_path = xbmc.translatePath("special://profile/playlists/video").decode('utf-8')
|
||||
index = 0
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
db = emby_db.EmbyDatabase(embydb.cursor)
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||
|
||||
for library in self.sync['Whitelist']:
|
||||
|
||||
|
@ -682,8 +682,8 @@ class Views(object):
|
|||
self.window_clear()
|
||||
self.window_clear('Jellyfin.wnodes')
|
||||
|
||||
with Database('jellyfin') as embydb:
|
||||
libraries = emby_db.EmbyDatabase(embydb.cursor).get_views()
|
||||
with Database('jellyfin') as jellyfindb:
|
||||
libraries = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
||||
|
||||
libraries = self.order_media_folders(libraries or [])
|
||||
index = 0
|
||||
|
|
|
@ -34,7 +34,6 @@ sys.path.append(__base__)
|
|||
|
||||
from entrypoint import Service
|
||||
from helper import settings
|
||||
from emby import Emby
|
||||
|
||||
#################################################################################################
|
||||
|
||||
|
|
Loading…
Reference in a new issue