mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-26 02:36:10 +00:00
Merge pull request #475 from oddstr13/plural(s)
Fix: Get specific library vs list of libraries
This commit is contained in:
commit
01b114c19e
8 changed files with 88 additions and 33 deletions
|
@ -5,6 +5,8 @@ from __future__ import division, absolute_import, print_function, unicode_litera
|
||||||
from database import queries as QU
|
from database import queries as QU
|
||||||
from helper import LazyLogger
|
from helper import LazyLogger
|
||||||
|
|
||||||
|
from jellyfin.utils import sqlite_namedtuple_factory
|
||||||
|
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
LOG = LazyLogger(__name__)
|
LOG = LazyLogger(__name__)
|
||||||
|
@ -16,6 +18,7 @@ class JellyfinDatabase():
|
||||||
|
|
||||||
def __init__(self, cursor):
|
def __init__(self, cursor):
|
||||||
self.cursor = cursor
|
self.cursor = cursor
|
||||||
|
cursor.row_factory = sqlite_namedtuple_factory
|
||||||
|
|
||||||
def get_item_by_id(self, *args):
|
def get_item_by_id(self, *args):
|
||||||
self.cursor.execute(QU.get_item, args)
|
self.cursor.execute(QU.get_item, args)
|
||||||
|
@ -124,8 +127,8 @@ class JellyfinDatabase():
|
||||||
def remove_view(self, *args):
|
def remove_view(self, *args):
|
||||||
self.cursor.execute(QU.delete_view, args)
|
self.cursor.execute(QU.delete_view, args)
|
||||||
|
|
||||||
def get_views(self, *args):
|
def get_views(self):
|
||||||
self.cursor.execute(QU.get_views, args)
|
self.cursor.execute(QU.get_views)
|
||||||
|
|
||||||
return self.cursor.fetchall()
|
return self.cursor.fetchall()
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ FROM jellyfin
|
||||||
WHERE jellyfin_parent_id = ?
|
WHERE jellyfin_parent_id = ?
|
||||||
"""
|
"""
|
||||||
get_view = """
|
get_view = """
|
||||||
SELECT view_name, media_type
|
SELECT *
|
||||||
FROM view
|
FROM view
|
||||||
WHERE view_id = ?
|
WHERE view_id = ?
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -811,7 +811,7 @@ def get_themes(api_client):
|
||||||
|
|
||||||
with Database('jellyfin') as jellyfindb:
|
with Database('jellyfin') as jellyfindb:
|
||||||
all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
||||||
views = [x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed')]
|
views = [x.view_id for x in all_views if x.media_type in ('movies', 'tvshows', 'mixed')]
|
||||||
|
|
||||||
items = {}
|
items = {}
|
||||||
server = api_client.config.data['auth.server']
|
server = api_client.config.data['auth.server']
|
||||||
|
|
|
@ -82,13 +82,13 @@ class FullSync(object):
|
||||||
for selected in libraries:
|
for selected in libraries:
|
||||||
|
|
||||||
if selected not in [x.replace('Mixed:', "") for x in self.sync['Libraries']]:
|
if selected not in [x.replace('Mixed:', "") for x in self.sync['Libraries']]:
|
||||||
library = self.get_libraries(selected)
|
library = self.get_library(selected)
|
||||||
|
|
||||||
if library:
|
if library:
|
||||||
|
|
||||||
self.sync['Libraries'].append("Mixed:%s" % selected if library[1] == 'mixed' else selected)
|
self.sync['Libraries'].append("Mixed:%s" % selected)
|
||||||
|
|
||||||
if library[1] in ('mixed', 'movies'):
|
if library.media_type in ('mixed', 'movies'):
|
||||||
self.sync['Libraries'].append('Boxsets:%s' % selected)
|
self.sync['Libraries'].append('Boxsets:%s' % selected)
|
||||||
else:
|
else:
|
||||||
self.sync['Libraries'].append(selected)
|
self.sync['Libraries'].append(selected)
|
||||||
|
@ -100,12 +100,12 @@ class FullSync(object):
|
||||||
if not xmls.advanced_settings() and self.sync['Libraries']:
|
if not xmls.advanced_settings() and self.sync['Libraries']:
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def get_libraries(self, library_id=None):
|
def get_libraries(self):
|
||||||
|
|
||||||
with Database('jellyfin') as jellyfindb:
|
with Database('jellyfin') as jellyfindb:
|
||||||
if library_id is None:
|
|
||||||
return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
|
||||||
else:
|
|
||||||
|
def get_library(self, library_id):
|
||||||
|
with Database('jellyfin') as jellyfindb:
|
||||||
return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_view(library_id)
|
return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_view(library_id)
|
||||||
|
|
||||||
def mapping(self):
|
def mapping(self):
|
||||||
|
@ -129,9 +129,8 @@ class FullSync(object):
|
||||||
libraries = []
|
libraries = []
|
||||||
|
|
||||||
for library in self.get_libraries():
|
for library in self.get_libraries():
|
||||||
|
if library.media_type in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed'):
|
||||||
if library[2] in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed'):
|
libraries.append({'Id': library.view_id, 'Name': library.view_name, 'Media': library.media_type})
|
||||||
libraries.append({'Id': library[0], 'Name': library[1], 'Media': library[2]})
|
|
||||||
|
|
||||||
libraries = self.select_libraries(libraries)
|
libraries = self.select_libraries(libraries)
|
||||||
|
|
||||||
|
@ -223,11 +222,12 @@ class FullSync(object):
|
||||||
if not sync_id or sync_id == 'Refresh':
|
if not sync_id or sync_id == 'Refresh':
|
||||||
libraries = self.get_libraries()
|
libraries = self.get_libraries()
|
||||||
else:
|
else:
|
||||||
libraries = self.get_libraries(sync_id)
|
_lib = self.get_library(sync_id)
|
||||||
|
libraries = [_lib] if _lib else []
|
||||||
|
|
||||||
for entry in libraries:
|
for entry in libraries:
|
||||||
if entry[2] == 'boxsets':
|
if entry.media_type == 'boxsets':
|
||||||
boxset_library = {'Id': entry[0], 'Name': entry[1]}
|
boxset_library = {'Id': entry.view_id, 'Name': entry.view_name}
|
||||||
break
|
break
|
||||||
|
|
||||||
if boxset_library:
|
if boxset_library:
|
||||||
|
@ -524,7 +524,7 @@ class FullSync(object):
|
||||||
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
|
||||||
library = db.get_view(library_id.replace('Mixed:', ""))
|
library = db.get_view(library_id.replace('Mixed:', ""))
|
||||||
items = db.get_item_by_media_folder(library_id.replace('Mixed:', ""))
|
items = db.get_item_by_media_folder(library_id.replace('Mixed:', ""))
|
||||||
media = 'music' if library[1] == 'music' else 'video'
|
media = 'music' if library.media_type == 'music' else 'video'
|
||||||
|
|
||||||
if media == 'music':
|
if media == 'music':
|
||||||
settings('MusicRescan.bool', False)
|
settings('MusicRescan.bool', False)
|
||||||
|
@ -535,7 +535,7 @@ class FullSync(object):
|
||||||
with self.library.music_database_lock if media == 'music' else self.library.database_lock:
|
with self.library.music_database_lock if media == 'music' else self.library.database_lock:
|
||||||
with Database(media) as kodidb:
|
with Database(media) as kodidb:
|
||||||
|
|
||||||
if library[1] == 'mixed':
|
if library.media_type == 'mixed':
|
||||||
|
|
||||||
movies = [x for x in items if x[1] == 'Movie']
|
movies = [x for x in items if x[1] == 'Movie']
|
||||||
tvshows = [x for x in items if x[1] == 'Series']
|
tvshows = [x for x in items if x[1] == 'Series']
|
||||||
|
@ -545,7 +545,7 @@ class FullSync(object):
|
||||||
for item in movies:
|
for item in movies:
|
||||||
|
|
||||||
obj(item[0])
|
obj(item[0])
|
||||||
dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library[0]))
|
dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library.view_name))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
obj = TVShows(self.server, jellyfindb, kodidb, direct_path, library).remove
|
obj = TVShows(self.server, jellyfindb, kodidb, direct_path, library).remove
|
||||||
|
@ -553,7 +553,7 @@ class FullSync(object):
|
||||||
for item in tvshows:
|
for item in tvshows:
|
||||||
|
|
||||||
obj(item[0])
|
obj(item[0])
|
||||||
dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library[0]))
|
dialog.update(int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library.view_name))
|
||||||
count += 1
|
count += 1
|
||||||
else:
|
else:
|
||||||
default_args = (self.server, jellyfindb, kodidb, direct_path)
|
default_args = (self.server, jellyfindb, kodidb, direct_path)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from six import string_types
|
from six import string_types
|
||||||
from six.moves import collections_abc
|
from six.moves import collections_abc
|
||||||
|
|
||||||
|
@ -41,3 +43,15 @@ def clean_none_dict_values(obj):
|
||||||
queue.append(value)
|
queue.append(value)
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def sqlite_namedtuple_factory(cursor, row):
|
||||||
|
"""
|
||||||
|
Usage:
|
||||||
|
con.row_factory = namedtuple_factory
|
||||||
|
|
||||||
|
http://peter-hoffmann.com/2010/python-sqlite-namedtuple-factory.html
|
||||||
|
"""
|
||||||
|
fields = [col[0] for col in cursor.description]
|
||||||
|
Row = namedtuple("Row", fields)
|
||||||
|
return Row(*row)
|
||||||
|
|
|
@ -471,10 +471,10 @@ class Library(threading.Thread):
|
||||||
available = [x for x in sync['SortedViews'] if x not in whitelist]
|
available = [x for x in sync['SortedViews'] if x not in whitelist]
|
||||||
|
|
||||||
for library in available:
|
for library in available:
|
||||||
name, media = db.get_view(library)
|
view = db.get_view(library)
|
||||||
|
|
||||||
if media in ('movies', 'tvshows', 'musicvideos', 'mixed', 'music'):
|
if view.media_type in ('movies', 'tvshows', 'musicvideos', 'mixed', 'music'):
|
||||||
libraries.append({'Id': library, 'Name': name})
|
libraries.append({'Id': view.view_id, 'Name': view.view_name})
|
||||||
|
|
||||||
choices = [x['Name'] for x in libraries]
|
choices = [x['Name'] for x in libraries]
|
||||||
choices.insert(0, translate(33121))
|
choices.insert(0, translate(33121))
|
||||||
|
|
|
@ -174,9 +174,8 @@ class Views(object):
|
||||||
removed = []
|
removed = []
|
||||||
|
|
||||||
for view in views:
|
for view in views:
|
||||||
|
if view.view_id not in self.sync['SortedViews']:
|
||||||
if view[0] not in self.sync['SortedViews']:
|
removed.append(view.view_id)
|
||||||
removed.append(view[0])
|
|
||||||
|
|
||||||
if removed:
|
if removed:
|
||||||
event('RemoveLibrary', {'Id': ','.join(removed)})
|
event('RemoveLibrary', {'Id': ','.join(removed)})
|
||||||
|
@ -204,7 +203,7 @@ class Views(object):
|
||||||
view = db.get_view(library)
|
view = db.get_view(library)
|
||||||
|
|
||||||
if view:
|
if view:
|
||||||
view = {'Id': library, 'Name': view[0], 'Tag': view[0], 'Media': view[1]}
|
view = {'Id': library, 'Name': view.view_name, 'Tag': view.view_name, 'Media': view.media_type}
|
||||||
|
|
||||||
if view['Media'] == 'mixed':
|
if view['Media'] == 'mixed':
|
||||||
for media in ('movies', 'tvshows'):
|
for media in ('movies', 'tvshows'):
|
||||||
|
@ -697,10 +696,10 @@ class Views(object):
|
||||||
except IndexError as error:
|
except IndexError as error:
|
||||||
LOG.exception(error)
|
LOG.exception(error)
|
||||||
|
|
||||||
for library in (libraries or []):
|
for library in libraries:
|
||||||
view = {'Id': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2]}
|
view = {'Id': library.view_id, 'Name': library.view_name, 'Tag': library.view_name, 'Media': library.media_type}
|
||||||
|
|
||||||
if library[0] in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]: # Synced libraries
|
if library.view_id in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]: # Synced libraries
|
||||||
|
|
||||||
if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'):
|
if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'):
|
||||||
|
|
||||||
|
|
39
typings/database/jellyfin_db.pyi
Normal file
39
typings/database/jellyfin_db.pyi
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from sqlite3 import Cursor
|
||||||
|
from typing import Any, List, Optional, NamedTuple
|
||||||
|
|
||||||
|
|
||||||
|
class ViewRow(NamedTuple):
|
||||||
|
view_id: str
|
||||||
|
view_name: str
|
||||||
|
media_type: str
|
||||||
|
|
||||||
|
|
||||||
|
class JellyfinDatabase:
|
||||||
|
cursor: Cursor = ...
|
||||||
|
def __init__(self, cursor: Cursor) -> None: ...
|
||||||
|
def get_view(self, *args: Any) -> Optional[ViewRow]: ...
|
||||||
|
def get_views(self) -> List[ViewRow]: ...
|
||||||
|
|
||||||
|
# def get_item_by_id(self, *args: Any): ...
|
||||||
|
# def add_reference(self, *args: Any) -> None: ...
|
||||||
|
# def update_reference(self, *args: Any) -> None: ...
|
||||||
|
# def update_parent_id(self, *args: Any) -> None: ...
|
||||||
|
# def get_item_id_by_parent_id(self, *args: Any): ...
|
||||||
|
# def get_item_by_parent_id(self, *args: Any): ...
|
||||||
|
# def get_item_by_media_folder(self, *args: Any): ...
|
||||||
|
# def get_item_by_wild_id(self, item_id: Any): ...
|
||||||
|
# def get_checksum(self, *args: Any): ...
|
||||||
|
# def get_item_by_kodi_id(self, *args: Any): ...
|
||||||
|
# def get_full_item_by_kodi_id(self, *args: Any): ...
|
||||||
|
# def get_media_by_id(self, *args: Any): ...
|
||||||
|
# def get_media_by_parent_id(self, *args: Any): ...
|
||||||
|
# def remove_item(self, *args: Any) -> None: ...
|
||||||
|
# def remove_items_by_parent_id(self, *args: Any) -> None: ...
|
||||||
|
# def remove_item_by_kodi_id(self, *args: Any) -> None: ...
|
||||||
|
# def remove_wild_item(self, item_id: Any) -> None: ...
|
||||||
|
# def get_view_name(self, item_id: Any): ...
|
||||||
|
# def add_view(self, *args: Any) -> None: ...
|
||||||
|
# def remove_view(self, *args: Any) -> None: ...
|
||||||
|
# def get_views_by_media(self, *args: Any): ...
|
||||||
|
# def get_items_by_media(self, *args: Any): ...
|
||||||
|
# def remove_media_by_parent_id(self, *args: Any) -> None: ...
|
Loading…
Reference in a new issue