mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 10:16:11 +00:00
Merge pull request #6 from cvium/fix_some_style_issues
Fix some style issues
This commit is contained in:
commit
d3c6d9158a
5 changed files with 264 additions and 273 deletions
|
@ -2,20 +2,18 @@
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import Queue
|
import Queue
|
||||||
import threading
|
import threading
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from helper.utils import should_stop, delete_folder
|
from helper.utils import delete_folder
|
||||||
from helper import settings, stop, event, window, kodi_version, unzip, create_id
|
from helper import settings, stop, event, window, unzip, create_id
|
||||||
from jellyfin import Jellyfin
|
from jellyfin import Jellyfin
|
||||||
from jellyfin.core import api
|
from jellyfin.core import api
|
||||||
from jellyfin.core.exceptions import HTTPException
|
from jellyfin.core.exceptions import HTTPException
|
||||||
|
@ -28,6 +26,7 @@ CACHE = xbmc.translatePath(os.path.join(xbmcaddon.Addon(id='plugin.video.jellyfi
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
|
||||||
def get_jellyfinserver_url(handler):
|
def get_jellyfinserver_url(handler):
|
||||||
|
|
||||||
if handler.startswith('/'):
|
if handler.startswith('/'):
|
||||||
|
@ -35,27 +34,33 @@ def get_jellyfinserver_url(handler):
|
||||||
handler = handler[1:]
|
handler = handler[1:]
|
||||||
LOG.warn("handler starts with /: %s", handler)
|
LOG.warn("handler starts with /: %s", handler)
|
||||||
|
|
||||||
return "{server}/emby/%s" % handler
|
return "{server}/emby/%s" % handler
|
||||||
|
|
||||||
|
|
||||||
def browse_info():
|
def browse_info():
|
||||||
return (
|
return (
|
||||||
"DateCreated,EpisodeCount,SeasonCount,Path,Genres,Studios,Taglines,MediaStreams,Overview,Etag,"
|
"DateCreated,EpisodeCount,SeasonCount,Path,Genres,Studios,Taglines,MediaStreams,Overview,Etag,"
|
||||||
"ProductionLocations,Width,Height,RecursiveItemCount,ChildCount"
|
"ProductionLocations,Width,Height,RecursiveItemCount,ChildCount"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _http(action, url, request={}, server_id=None):
|
def _http(action, url, request={}, server_id=None):
|
||||||
request.update({'url': url, 'type': action})
|
request.update({'url': url, 'type': action})
|
||||||
|
|
||||||
return Jellyfin(server_id)['http/request'](request)
|
return Jellyfin(server_id)['http/request'](request)
|
||||||
|
|
||||||
|
|
||||||
def _get(handler, params=None, server_id=None):
|
def _get(handler, params=None, server_id=None):
|
||||||
return _http("GET", get_jellyfinserver_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):
|
def _post(handler, json=None, params=None, server_id=None):
|
||||||
return _http("POST", get_jellyfinserver_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):
|
def _delete(handler, params=None, server_id=None):
|
||||||
return _http("DELETE", get_jellyfinserver_url(handler), {'params': params}, server_id)
|
return _http("DELETE", get_jellyfinserver_url(handler), {'params': params}, server_id)
|
||||||
|
|
||||||
|
|
||||||
def validate_view(library_id, item_id):
|
def validate_view(library_id, item_id):
|
||||||
|
|
||||||
|
@ -73,13 +78,15 @@ def validate_view(library_id, item_id):
|
||||||
|
|
||||||
return True if len(result['Items']) else False
|
return True if len(result['Items']) else False
|
||||||
|
|
||||||
|
|
||||||
def get_single_item(parent_id, media):
|
def get_single_item(parent_id, media):
|
||||||
return _get("Users/{UserId}/Items", {
|
return _get("Users/{UserId}/Items", {
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'Limit': 1,
|
'Limit': 1,
|
||||||
'IncludeItemTypes': media
|
'IncludeItemTypes': media
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None, sort=None, sort_order=None,
|
def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None, sort=None, sort_order=None,
|
||||||
filters=None, extra=None, server_id=None):
|
filters=None, extra=None, server_id=None):
|
||||||
|
@ -99,9 +106,7 @@ def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None,
|
||||||
'Fields': browse_info()
|
'Fields': browse_info()
|
||||||
}
|
}
|
||||||
if filters:
|
if filters:
|
||||||
|
|
||||||
if 'Boxsets' in filters:
|
if 'Boxsets' in filters:
|
||||||
|
|
||||||
filters.remove('Boxsets')
|
filters.remove('Boxsets')
|
||||||
params['CollapseBoxSetItems'] = settings('groupedSets.bool')
|
params['CollapseBoxSetItems'] = settings('groupedSets.bool')
|
||||||
|
|
||||||
|
@ -116,13 +121,15 @@ def get_filtered_section(parent_id=None, media=None, limit=None, recursive=None,
|
||||||
if extra is not None:
|
if extra is not None:
|
||||||
params.update(extra)
|
params.update(extra)
|
||||||
|
|
||||||
return _get("Users/{UserId}/Items", params, server_id)
|
return _get("Users/{UserId}/Items", params, server_id)
|
||||||
|
|
||||||
|
|
||||||
def get_movies_by_boxset(boxset_id):
|
def get_movies_by_boxset(boxset_id):
|
||||||
|
|
||||||
for items in get_items(boxset_id, "Movie"):
|
for items in get_items(boxset_id, "Movie"):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
def get_episode_by_show(show_id):
|
def get_episode_by_show(show_id):
|
||||||
|
|
||||||
query = {
|
query = {
|
||||||
|
@ -137,6 +144,7 @@ def get_episode_by_show(show_id):
|
||||||
for items in _get_items(query):
|
for items in _get_items(query):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
def get_episode_by_season(show_id, season_id):
|
def get_episode_by_season(show_id, season_id):
|
||||||
|
|
||||||
query = {
|
query = {
|
||||||
|
@ -152,6 +160,7 @@ def get_episode_by_season(show_id, season_id):
|
||||||
for items in _get_items(query):
|
for items in _get_items(query):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
def get_items(parent_id, item_type=None, basic=False, params=None):
|
def get_items(parent_id, item_type=None, basic=False, params=None):
|
||||||
|
|
||||||
query = {
|
query = {
|
||||||
|
@ -176,6 +185,7 @@ def get_items(parent_id, item_type=None, basic=False, params=None):
|
||||||
for items in _get_items(query):
|
for items in _get_items(query):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
def get_artists(parent_id=None, basic=False, params=None, server_id=None):
|
def get_artists(parent_id=None, basic=False, params=None, server_id=None):
|
||||||
|
|
||||||
query = {
|
query = {
|
||||||
|
@ -201,6 +211,7 @@ def get_artists(parent_id=None, basic=False, params=None, server_id=None):
|
||||||
for items in _get_items(query, server_id):
|
for items in _get_items(query, server_id):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
def get_albums_by_artist(artist_id, basic=False):
|
def get_albums_by_artist(artist_id, basic=False):
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
|
@ -210,6 +221,7 @@ def get_albums_by_artist(artist_id, basic=False):
|
||||||
for items in get_items(None, "MusicAlbum", basic, params):
|
for items in get_items(None, "MusicAlbum", basic, params):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
def get_songs_by_artist(artist_id, basic=False):
|
def get_songs_by_artist(artist_id, basic=False):
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
|
@ -219,6 +231,7 @@ def get_songs_by_artist(artist_id, basic=False):
|
||||||
for items in get_items(None, "Audio", basic, params):
|
for items in get_items(None, "Audio", basic, params):
|
||||||
yield items
|
yield items
|
||||||
|
|
||||||
|
|
||||||
@stop()
|
@stop()
|
||||||
def _get_items(query, server_id=None):
|
def _get_items(query, server_id=None):
|
||||||
|
|
||||||
|
@ -263,6 +276,7 @@ def _get_items(query, server_id=None):
|
||||||
del items['Items'][:]
|
del items['Items'][:]
|
||||||
index += LIMIT
|
index += LIMIT
|
||||||
|
|
||||||
|
|
||||||
class GetItemWorker(threading.Thread):
|
class GetItemWorker(threading.Thread):
|
||||||
|
|
||||||
is_done = False
|
is_done = False
|
||||||
|
@ -275,10 +289,8 @@ class GetItemWorker(threading.Thread):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
with requests.Session() as s:
|
with requests.Session() as s:
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
item_ids = self.queue.get(timeout=1)
|
item_ids = self.queue.get(timeout=1)
|
||||||
except Queue.Empty:
|
except Queue.Empty:
|
||||||
|
@ -320,6 +332,7 @@ class GetItemWorker(threading.Thread):
|
||||||
if window('jellyfin_should_stop.bool'):
|
if window('jellyfin_should_stop.bool'):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
class TheVoid(object):
|
class TheVoid(object):
|
||||||
|
|
||||||
def __init__(self, method, data):
|
def __init__(self, method, data):
|
||||||
|
@ -359,6 +372,7 @@ class TheVoid(object):
|
||||||
xbmc.sleep(100)
|
xbmc.sleep(100)
|
||||||
LOG.info("--[ void/%s ]", self.data['VoidName'])
|
LOG.info("--[ void/%s ]", self.data['VoidName'])
|
||||||
|
|
||||||
|
|
||||||
def get_objects(src, filename):
|
def get_objects(src, filename):
|
||||||
|
|
||||||
''' Download objects dependency to temp cache folder.
|
''' Download objects dependency to temp cache folder.
|
||||||
|
@ -383,7 +397,7 @@ def get_objects(src, filename):
|
||||||
|
|
||||||
LOG.error(error)
|
LOG.error(error)
|
||||||
response = requests.get(src, stream=True, verify=False)
|
response = requests.get(src, stream=True, verify=False)
|
||||||
except Exception as error:
|
except Exception:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
dl = xbmcvfs.File(path, 'w')
|
dl = xbmcvfs.File(path, 'w')
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
import json
|
|
||||||
import datetime
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
@ -16,8 +14,6 @@ LOG = logging.getLogger("JELLYFIN."+__name__)
|
||||||
|
|
||||||
|
|
||||||
class API(object):
|
class API(object):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, item, server=None):
|
def __init__(self, item, server=None):
|
||||||
|
|
||||||
''' Get item information in special cases.
|
''' Get item information in special cases.
|
||||||
|
@ -71,7 +67,7 @@ class API(object):
|
||||||
return cast
|
return cast
|
||||||
|
|
||||||
def media_streams(self, video, audio, subtitles):
|
def media_streams(self, video, audio, subtitles):
|
||||||
return {
|
return {
|
||||||
'video': video or [],
|
'video': video or [],
|
||||||
'audio': audio or [],
|
'audio': audio or [],
|
||||||
'subtitle': subtitles or []
|
'subtitle': subtitles or []
|
||||||
|
@ -161,7 +157,6 @@ class API(object):
|
||||||
def validate_studio(self, studio_name):
|
def validate_studio(self, studio_name):
|
||||||
# Convert studio for Kodi to properly detect them
|
# Convert studio for Kodi to properly detect them
|
||||||
studios = {
|
studios = {
|
||||||
|
|
||||||
'abc (us)': "ABC",
|
'abc (us)': "ABC",
|
||||||
'fox (us)': "FOX",
|
'fox (us)': "FOX",
|
||||||
'mtv (us)': "MTV",
|
'mtv (us)': "MTV",
|
||||||
|
|
|
@ -1,31 +1,30 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#################################################################################################
|
|
||||||
|
|
||||||
def jellyfin_url(client, handler):
|
def jellyfin_url(client, handler):
|
||||||
return "%s/emby/%s" % (client.config['auth.server'], handler)
|
return "%s/emby/%s" % (client.config['auth.server'], handler)
|
||||||
|
|
||||||
|
|
||||||
def basic_info():
|
def basic_info():
|
||||||
return "Etag"
|
return "Etag"
|
||||||
|
|
||||||
|
|
||||||
def info():
|
def info():
|
||||||
return (
|
return (
|
||||||
"Path,Genres,SortName,Studios,Writer,Taglines,LocalTrailerCount,"
|
"Path,Genres,SortName,Studios,Writer,Taglines,LocalTrailerCount,"
|
||||||
"OfficialRating,CumulativeRunTimeTicks,ItemCounts,"
|
"OfficialRating,CumulativeRunTimeTicks,ItemCounts,"
|
||||||
"Metascore,AirTime,DateCreated,People,Overview,"
|
"Metascore,AirTime,DateCreated,People,Overview,"
|
||||||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
||||||
"MediaSources,VoteCount,RecursiveItemCount,PrimaryImageAspectRatio"
|
"MediaSources,VoteCount,RecursiveItemCount,PrimaryImageAspectRatio"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def music_info():
|
def music_info():
|
||||||
return (
|
return (
|
||||||
"Etag,Genres,SortName,Studios,Writer,"
|
"Etag,Genres,SortName,Studios,Writer,"
|
||||||
"OfficialRating,CumulativeRunTimeTicks,Metascore,"
|
"OfficialRating,CumulativeRunTimeTicks,Metascore,"
|
||||||
"AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview,ItemCounts"
|
"AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview,ItemCounts"
|
||||||
)
|
)
|
||||||
|
|
||||||
#################################################################################################
|
|
||||||
|
|
||||||
class API(object):
|
class API(object):
|
||||||
|
|
||||||
|
@ -37,16 +36,16 @@ class API(object):
|
||||||
def _http(self, action, url, request={}):
|
def _http(self, action, url, request={}):
|
||||||
request.update({'type': action, 'handler': url})
|
request.update({'type': action, 'handler': url})
|
||||||
|
|
||||||
return self.client.request(request)
|
return self.client.request(request)
|
||||||
|
|
||||||
def _get(self, handler, params=None):
|
def _get(self, handler, params=None):
|
||||||
return self._http("GET", handler, {'params': params})
|
return self._http("GET", handler, {'params': params})
|
||||||
|
|
||||||
def _post(self, handler, json=None, params=None):
|
def _post(self, handler, json=None, params=None):
|
||||||
return self._http("POST", handler, {'params': params, 'json': json})
|
return self._http("POST", handler, {'params': params, 'json': json})
|
||||||
|
|
||||||
def _delete(self, handler, params=None):
|
def _delete(self, handler, params=None):
|
||||||
return self._http("DELETE", handler, {'params': params})
|
return self._http("DELETE", handler, {'params': params})
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
@ -55,48 +54,44 @@ class API(object):
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
def try_server(self):
|
def try_server(self):
|
||||||
return self._get("System/Info/Public")
|
return self._get("System/Info/Public")
|
||||||
|
|
||||||
def sessions(self, handler="", action="GET", params=None, json=None):
|
def sessions(self, handler="", action="GET", params=None, json=None):
|
||||||
|
|
||||||
if action == "POST":
|
if action == "POST":
|
||||||
return self._post("Sessions%s" % handler, json, params)
|
return self._post("Sessions%s" % handler, json, params)
|
||||||
elif action == "DELETE":
|
elif action == "DELETE":
|
||||||
return self._delete("Sessions%s" % handler, params)
|
return self._delete("Sessions%s" % handler, params)
|
||||||
else:
|
else:
|
||||||
return self._get("Sessions%s" % handler, params)
|
return self._get("Sessions%s" % handler, params)
|
||||||
|
|
||||||
def users(self, handler="", action="GET", params=None, json=None):
|
def users(self, handler="", action="GET", params=None, json=None):
|
||||||
|
|
||||||
if action == "POST":
|
if action == "POST":
|
||||||
return self._post("Users/{UserId}%s" % handler, json, params)
|
return self._post("Users/{UserId}%s" % handler, json, params)
|
||||||
elif action == "DELETE":
|
elif action == "DELETE":
|
||||||
return self._delete("Users/{UserId}%s" % handler, params)
|
return self._delete("Users/{UserId}%s" % handler, params)
|
||||||
else:
|
else:
|
||||||
return self._get("Users/{UserId}%s" % handler, params)
|
return self._get("Users/{UserId}%s" % handler, params)
|
||||||
|
|
||||||
def items(self, handler="", action="GET", params=None, json=None):
|
def items(self, handler="", action="GET", params=None, json=None):
|
||||||
|
|
||||||
if action == "POST":
|
if action == "POST":
|
||||||
return self._post("Items%s" % handler, json, params)
|
return self._post("Items%s" % handler, json, params)
|
||||||
elif action == "DELETE":
|
elif action == "DELETE":
|
||||||
return self._delete("Items%s" % handler, params)
|
return self._delete("Items%s" % handler, params)
|
||||||
else:
|
else:
|
||||||
return self._get("Items%s" % handler, params)
|
return self._get("Items%s" % handler, params)
|
||||||
|
|
||||||
def user_items(self, handler="", params=None):
|
def user_items(self, handler="", params=None):
|
||||||
return self.users("/Items%s" % handler, params=params)
|
return self.users("/Items%s" % handler, params=params)
|
||||||
|
|
||||||
def shows(self, handler, params):
|
def shows(self, handler, params):
|
||||||
return self._get("Shows%s" % handler, params)
|
return self._get("Shows%s" % handler, params)
|
||||||
|
|
||||||
def videos(self, handler):
|
def videos(self, handler):
|
||||||
return self._get("Videos%s" % handler)
|
return self._get("Videos%s" % handler)
|
||||||
|
|
||||||
def artwork(self, item_id, art, max_width, ext="jpg", index=None):
|
def artwork(self, item_id, art, max_width, ext="jpg", index=None):
|
||||||
|
|
||||||
if index is None:
|
if index is None:
|
||||||
return jellyfin_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 jellyfin_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))
|
||||||
|
|
||||||
|
@ -107,238 +102,238 @@ class API(object):
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
def get_users(self):
|
def get_users(self):
|
||||||
return self._get("Users")
|
return self._get("Users")
|
||||||
|
|
||||||
def get_public_users(self):
|
def get_public_users(self):
|
||||||
return self._get("Users/Public")
|
return self._get("Users/Public")
|
||||||
|
|
||||||
def get_user(self, user_id=None):
|
def get_user(self, user_id=None):
|
||||||
return self.users() if user_id is None else self._get("Users/%s" % user_id)
|
return self.users() if user_id is None else self._get("Users/%s" % user_id)
|
||||||
|
|
||||||
def get_views(self):
|
def get_views(self):
|
||||||
return self.users("/Views")
|
return self.users("/Views")
|
||||||
|
|
||||||
def get_media_folders(self):
|
def get_media_folders(self):
|
||||||
return self.users("/Items")
|
return self.users("/Items")
|
||||||
|
|
||||||
def get_item(self, item_id):
|
def get_item(self, item_id):
|
||||||
return self.users("/Items/%s" % item_id)
|
return self.users("/Items/%s" % item_id)
|
||||||
|
|
||||||
def get_items(self, item_ids):
|
def get_items(self, item_ids):
|
||||||
return self.users("/Items", params={
|
return self.users("/Items", params={
|
||||||
'Ids': ','.join(str(x) for x in item_ids),
|
'Ids': ','.join(str(x) for x in item_ids),
|
||||||
'Fields': info()
|
'Fields': info()
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_sessions(self):
|
def get_sessions(self):
|
||||||
return self.sessions(params={'ControllableByUserId': "{UserId}"})
|
return self.sessions(params={'ControllableByUserId': "{UserId}"})
|
||||||
|
|
||||||
def get_device(self, device_id):
|
def get_device(self, device_id):
|
||||||
return self.sessions(params={'DeviceId': device_id})
|
return self.sessions(params={'DeviceId': device_id})
|
||||||
|
|
||||||
def post_session(self, session_id, url, params=None, data=None):
|
def post_session(self, session_id, url, params=None, data=None):
|
||||||
return self.sessions("/%s/%s" % (session_id, url), "POST", params, data)
|
return self.sessions("/%s/%s" % (session_id, url), "POST", params, data)
|
||||||
|
|
||||||
def get_images(self, item_id):
|
def get_images(self, item_id):
|
||||||
return self.items("/%s/Images" % item_id)
|
return self.items("/%s/Images" % item_id)
|
||||||
|
|
||||||
def get_suggestion(self, media="Movie,Episode", limit=1):
|
def get_suggestion(self, media="Movie,Episode", limit=1):
|
||||||
return self.users("/Suggestions", {
|
return self.users("/Suggestions", params={
|
||||||
'Type': media,
|
'Type': media,
|
||||||
'Limit': limit
|
'Limit': limit
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_recently_added(self, media=None, parent_id=None, limit=20):
|
def get_recently_added(self, media=None, parent_id=None, limit=20):
|
||||||
return self.user_items("/Latest", {
|
return self.user_items("/Latest", {
|
||||||
'Limit': limit,
|
'Limit': limit,
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'IncludeItemTypes': media,
|
'IncludeItemTypes': media,
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'Fields': info()
|
'Fields': info()
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_next(self, index=None, limit=1):
|
def get_next(self, index=None, limit=1):
|
||||||
return self.shows("/NextUp", {
|
return self.shows("/NextUp", {
|
||||||
'Limit': limit,
|
'Limit': limit,
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'StartIndex': None if index is None else int(index)
|
'StartIndex': None if index is None else int(index)
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_adjacent_episodes(self, show_id, item_id):
|
def get_adjacent_episodes(self, show_id, item_id):
|
||||||
return self.shows("/%s/Episodes" % show_id, {
|
return self.shows("/%s/Episodes" % show_id, {
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'AdjacentTo': item_id,
|
'AdjacentTo': item_id,
|
||||||
'Fields': "Overview"
|
'Fields': "Overview"
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_genres(self, parent_id=None):
|
def get_genres(self, parent_id=None):
|
||||||
return self._get("Genres", {
|
return self._get("Genres", {
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'Fields': info()
|
'Fields': info()
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_recommendation(self, parent_id=None, limit=20):
|
def get_recommendation(self, parent_id=None, limit=20):
|
||||||
return self._get("Movies/Recommendations", {
|
return self._get("Movies/Recommendations", {
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'Fields': info(),
|
'Fields': info(),
|
||||||
'Limit': limit
|
'Limit': limit
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_items_by_letter(self, parent_id=None, media=None, letter=None):
|
def get_items_by_letter(self, parent_id=None, media=None, letter=None):
|
||||||
return self.user_items(params={
|
return self.user_items(params={
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'NameStartsWith': letter,
|
'NameStartsWith': letter,
|
||||||
'Fields': info(),
|
'Fields': info(),
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'IncludeItemTypes': media
|
'IncludeItemTypes': media
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_channels(self):
|
def get_channels(self):
|
||||||
return self._get("LiveTv/Channels", {
|
return self._get("LiveTv/Channels", {
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'EnableImages': True,
|
'EnableImages': True,
|
||||||
'EnableUserData': True
|
'EnableUserData': True
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_intros(self, item_id):
|
def get_intros(self, item_id):
|
||||||
return self.user_items("/%s/Intros" % item_id)
|
return self.user_items("/%s/Intros" % item_id)
|
||||||
|
|
||||||
def get_additional_parts(self, item_id):
|
def get_additional_parts(self, item_id):
|
||||||
return self.videos("/%s/AdditionalParts" % item_id)
|
return self.videos("/%s/AdditionalParts" % item_id)
|
||||||
|
|
||||||
def delete_item(self, item_id):
|
def delete_item(self, item_id):
|
||||||
return self.items("/%s" % item_id, "DELETE")
|
return self.items("/%s" % item_id, "DELETE")
|
||||||
|
|
||||||
def get_local_trailers(self, item_id):
|
def get_local_trailers(self, item_id):
|
||||||
return self.user_items("/%s/LocalTrailers" % item_id)
|
return self.user_items("/%s/LocalTrailers" % item_id)
|
||||||
|
|
||||||
def get_transcode_settings(self):
|
def get_transcode_settings(self):
|
||||||
return self._get('System/Configuration/encoding')
|
return self._get('System/Configuration/encoding')
|
||||||
|
|
||||||
def get_ancestors(self, item_id):
|
def get_ancestors(self, item_id):
|
||||||
return self.items("/%s/Ancestors" % item_id, params={
|
return self.items("/%s/Ancestors" % item_id, params={
|
||||||
'UserId': "{UserId}"
|
'UserId': "{UserId}"
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_items_theme_video(self, parent_id):
|
def get_items_theme_video(self, parent_id):
|
||||||
return self.users("/Items", params={
|
return self.users("/Items", params={
|
||||||
'HasThemeVideo': True,
|
'HasThemeVideo': True,
|
||||||
'ParentId': parent_id
|
'ParentId': parent_id
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_themes(self, item_id):
|
def get_themes(self, item_id):
|
||||||
return self.items("/%s/ThemeMedia" % item_id, params={
|
return self.items("/%s/ThemeMedia" % item_id, params={
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'InheritFromParent': True
|
'InheritFromParent': True
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_items_theme_song(self, parent_id):
|
def get_items_theme_song(self, parent_id):
|
||||||
return self.users("/Items", params={
|
return self.users("/Items", params={
|
||||||
'HasThemeSong': True,
|
'HasThemeSong': True,
|
||||||
'ParentId': parent_id
|
'ParentId': parent_id
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_plugins(self):
|
def get_plugins(self):
|
||||||
return self._get("Plugins")
|
return self._get("Plugins")
|
||||||
|
|
||||||
def get_seasons(self, show_id):
|
def get_seasons(self, show_id):
|
||||||
return self.shows("/%s/Seasons" % show_id, params={
|
return self.shows("/%s/Seasons" % show_id, params={
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'EnableImages': True,
|
'EnableImages': True,
|
||||||
'Fields': info()
|
'Fields': info()
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_date_modified(self, date, parent_id, media=None):
|
def get_date_modified(self, date, parent_id, media=None):
|
||||||
return self.users("/Items", params={
|
return self.users("/Items", params={
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'Recursive': False,
|
'Recursive': False,
|
||||||
'IsMissing': False,
|
'IsMissing': False,
|
||||||
'IsVirtualUnaired': False,
|
'IsVirtualUnaired': False,
|
||||||
'IncludeItemTypes': media or None,
|
'IncludeItemTypes': media or None,
|
||||||
'MinDateLastSaved': date,
|
'MinDateLastSaved': date,
|
||||||
'Fields': info()
|
'Fields': info()
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_userdata_date_modified(self, date, parent_id, media=None):
|
def get_userdata_date_modified(self, date, parent_id, media=None):
|
||||||
return self.users("/Items", params={
|
return self.users("/Items", params={
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'IsMissing': False,
|
'IsMissing': False,
|
||||||
'IsVirtualUnaired': False,
|
'IsVirtualUnaired': False,
|
||||||
'IncludeItemTypes': media or None,
|
'IncludeItemTypes': media or None,
|
||||||
'MinDateLastSavedForUser': date,
|
'MinDateLastSavedForUser': date,
|
||||||
'Fields': info()
|
'Fields': info()
|
||||||
})
|
})
|
||||||
|
|
||||||
def refresh_item(self, item_id):
|
def refresh_item(self, item_id):
|
||||||
return self.items("/%s/Refresh" % item_id, "POST", json={
|
return self.items("/%s/Refresh" % item_id, "POST", json={
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'ImageRefreshMode': "FullRefresh",
|
'ImageRefreshMode': "FullRefresh",
|
||||||
'MetadataRefreshMode': "FullRefresh",
|
'MetadataRefreshMode': "FullRefresh",
|
||||||
'ReplaceAllImages': False,
|
'ReplaceAllImages': False,
|
||||||
'ReplaceAllMetadata': True
|
'ReplaceAllMetadata': True
|
||||||
})
|
})
|
||||||
|
|
||||||
def favorite(self, item_id, option=True):
|
def favorite(self, item_id, option=True):
|
||||||
return self.users("/FavoriteItems/%s" % item_id, "POST" if option else "DELETE")
|
return self.users("/FavoriteItems/%s" % item_id, "POST" if option else "DELETE")
|
||||||
|
|
||||||
def get_system_info(self):
|
def get_system_info(self):
|
||||||
return self._get("System/Configuration")
|
return self._get("System/Configuration")
|
||||||
|
|
||||||
def post_capabilities(self, data):
|
def post_capabilities(self, data):
|
||||||
return self.sessions("/Capabilities/Full", "POST", json=data)
|
return self.sessions("/Capabilities/Full", "POST", json=data)
|
||||||
|
|
||||||
def session_add_user(self, session_id, user_id, option=True):
|
def session_add_user(self, session_id, user_id, option=True):
|
||||||
return self.sessions("/%s/Users/%s" % (session_id, user_id), "POST" if option else "DELETE")
|
return self.sessions("/%s/Users/%s" % (session_id, user_id), "POST" if option else "DELETE")
|
||||||
|
|
||||||
def session_playing(self, data):
|
def session_playing(self, data):
|
||||||
return self.sessions("/Playing", "POST", json=data)
|
return self.sessions("/Playing", "POST", json=data)
|
||||||
|
|
||||||
def session_progress(self, data):
|
def session_progress(self, data):
|
||||||
return self.sessions("/Playing/Progress", "POST", json=data)
|
return self.sessions("/Playing/Progress", "POST", json=data)
|
||||||
|
|
||||||
def session_stop(self, data):
|
def session_stop(self, data):
|
||||||
return self.sessions("/Playing/Stopped", "POST", json=data)
|
return self.sessions("/Playing/Stopped", "POST", json=data)
|
||||||
|
|
||||||
def item_played(self, item_id, watched):
|
def item_played(self, item_id, watched):
|
||||||
return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE")
|
return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE")
|
||||||
|
|
||||||
def get_sync_queue(self, date, filters=None):
|
def get_sync_queue(self, date, filters=None):
|
||||||
return self._get("Jellyfin.Plugin.KodiSyncQueue/{UserId}/GetItems", params={
|
return self._get("Jellyfin.Plugin.KodiSyncQueue/{UserId}/GetItems", params={
|
||||||
'LastUpdateDT': date,
|
'LastUpdateDT': date,
|
||||||
'filter': filters or None
|
'filter': filters or None
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_server_time(self):
|
def get_server_time(self):
|
||||||
return self._get("Jellyfin.Plugin.KodiSyncQueue/GetServerDateTime")
|
return self._get("Jellyfin.Plugin.KodiSyncQueue/GetServerDateTime")
|
||||||
|
|
||||||
def get_play_info(self, item_id, profile):
|
def get_play_info(self, item_id, profile):
|
||||||
return self.items("/%s/PlaybackInfo" % item_id, "POST", json={
|
return self.items("/%s/PlaybackInfo" % item_id, "POST", json={
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'DeviceProfile': profile,
|
'DeviceProfile': profile,
|
||||||
'AutoOpenLiveStream': True
|
'AutoOpenLiveStream': True
|
||||||
})
|
})
|
||||||
|
|
||||||
def get_live_stream(self, item_id, play_id, token, profile):
|
def get_live_stream(self, item_id, play_id, token, profile):
|
||||||
return self._post("LiveStreams/Open", json={
|
return self._post("LiveStreams/Open", json={
|
||||||
'UserId': "{UserId}",
|
'UserId': "{UserId}",
|
||||||
'DeviceProfile': profile,
|
'DeviceProfile': profile,
|
||||||
'OpenToken': token,
|
'OpenToken': token,
|
||||||
'PlaySessionId': play_id,
|
'PlaySessionId': play_id,
|
||||||
'ItemId': item_id
|
'ItemId': item_id
|
||||||
})
|
})
|
||||||
|
|
||||||
def close_live_stream(self, live_id):
|
def close_live_stream(self, live_id):
|
||||||
return self._post("LiveStreams/Close", json={
|
return self._post("LiveStreams/Close", json={
|
||||||
'LiveStreamId': live_id
|
'LiveStreamId': live_id
|
||||||
})
|
})
|
||||||
|
|
||||||
def close_transcode(self, device_id):
|
def close_transcode(self, device_id):
|
||||||
return self._delete("Videos/ActiveEncodings", params={
|
return self._delete("Videos/ActiveEncodings", params={
|
||||||
'DeviceId': device_id
|
'DeviceId': device_id
|
||||||
})
|
})
|
||||||
|
|
||||||
def delete_item(self, item_id):
|
def delete_item(self, item_id):
|
||||||
return self.items("/%s" % item_id, "DELETE")
|
return self.items("/%s" % item_id, "DELETE")
|
||||||
|
|
|
@ -123,9 +123,8 @@ class Library(threading.Thread):
|
||||||
|
|
||||||
''' Open the databases to test if the file exists.
|
''' Open the databases to test if the file exists.
|
||||||
'''
|
'''
|
||||||
with Database('video') as kodidb:
|
with Database('video'), Database('music'):
|
||||||
with Database('music') as musicdb:
|
pass
|
||||||
pass
|
|
||||||
|
|
||||||
@stop()
|
@stop()
|
||||||
def service(self):
|
def service(self):
|
||||||
|
@ -611,33 +610,29 @@ class UpdatedWorker(threading.Thread):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb:
|
||||||
|
while True:
|
||||||
|
|
||||||
with self.lock:
|
try:
|
||||||
with self.database as kodidb:
|
item = self.queue.get(timeout=1)
|
||||||
with Database('jellyfin') as jellyfindb:
|
except Queue.Empty:
|
||||||
|
break
|
||||||
|
|
||||||
while True:
|
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])[item['Type']]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
item = self.queue.get(timeout=1)
|
if obj(item) and self.notify:
|
||||||
except Queue.Empty:
|
self.notify_output.put((item['Type'], api.API(item).get_naming()))
|
||||||
break
|
except LibraryException as error:
|
||||||
|
if error.status == 'StopCalled':
|
||||||
|
break
|
||||||
|
except Exception as error:
|
||||||
|
LOG.exception(error)
|
||||||
|
|
||||||
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])[item['Type']]
|
self.queue.task_done()
|
||||||
|
|
||||||
try:
|
if window('jellyfin_should_stop.bool'):
|
||||||
if obj(item) and self.notify:
|
break
|
||||||
self.notify_output.put((item['Type'], api.API(item).get_naming()))
|
|
||||||
except LibraryException as error:
|
|
||||||
if error.status == 'StopCalled':
|
|
||||||
break
|
|
||||||
except Exception as error:
|
|
||||||
LOG.exception(error)
|
|
||||||
|
|
||||||
self.queue.task_done()
|
|
||||||
|
|
||||||
if window('jellyfin_should_stop.bool'):
|
|
||||||
break
|
|
||||||
|
|
||||||
LOG.info("--<[ q:updated/%s ]", id(self))
|
LOG.info("--<[ q:updated/%s ]", id(self))
|
||||||
self.is_done = True
|
self.is_done = True
|
||||||
|
@ -656,31 +651,28 @@ class UserDataWorker(threading.Thread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
with self.lock:
|
with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb:
|
||||||
with self.database as kodidb:
|
while True:
|
||||||
with Database('jellyfin') as jellyfindb:
|
|
||||||
|
|
||||||
while True:
|
try:
|
||||||
|
item = self.queue.get(timeout=1)
|
||||||
|
except Queue.Empty:
|
||||||
|
break
|
||||||
|
|
||||||
try:
|
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['UserData']
|
||||||
item = self.queue.get(timeout=1)
|
|
||||||
except Queue.Empty:
|
|
||||||
break
|
|
||||||
|
|
||||||
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['UserData']
|
try:
|
||||||
|
obj(item)
|
||||||
|
except LibraryException as error:
|
||||||
|
if error.status == 'StopCalled':
|
||||||
|
break
|
||||||
|
except Exception as error:
|
||||||
|
LOG.exception(error)
|
||||||
|
|
||||||
try:
|
self.queue.task_done()
|
||||||
obj(item)
|
|
||||||
except LibraryException as error:
|
|
||||||
if error.status == 'StopCalled':
|
|
||||||
break
|
|
||||||
except Exception as error:
|
|
||||||
LOG.exception(error)
|
|
||||||
|
|
||||||
self.queue.task_done()
|
if window('jellyfin_should_stop.bool'):
|
||||||
|
break
|
||||||
if window('jellyfin_should_stop.bool'):
|
|
||||||
break
|
|
||||||
|
|
||||||
LOG.info("--<[ q:userdata/%s ]", id(self))
|
LOG.info("--<[ q:userdata/%s ]", id(self))
|
||||||
self.is_done = True
|
self.is_done = True
|
||||||
|
@ -742,31 +734,28 @@ class RemovedWorker(threading.Thread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
with self.lock:
|
with self.lock, self.database as kodidb, Database('jellyfin') as jellyfindb:
|
||||||
with self.database as kodidb:
|
while True:
|
||||||
with Database('jellyfin') as jellyfindb:
|
|
||||||
|
|
||||||
while True:
|
try:
|
||||||
|
item = self.queue.get(timeout=1)
|
||||||
|
except Queue.Empty:
|
||||||
|
break
|
||||||
|
|
||||||
try:
|
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['Remove']
|
||||||
item = self.queue.get(timeout=1)
|
|
||||||
except Queue.Empty:
|
|
||||||
break
|
|
||||||
|
|
||||||
obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['Remove']
|
try:
|
||||||
|
obj(item['Id'])
|
||||||
|
except LibraryException as error:
|
||||||
|
if error.status == 'StopCalled':
|
||||||
|
break
|
||||||
|
except Exception as error:
|
||||||
|
LOG.exception(error)
|
||||||
|
|
||||||
try:
|
self.queue.task_done()
|
||||||
obj(item['Id'])
|
|
||||||
except LibraryException as error:
|
|
||||||
if error.status == 'StopCalled':
|
|
||||||
break
|
|
||||||
except Exception as error:
|
|
||||||
LOG.exception(error)
|
|
||||||
|
|
||||||
self.queue.task_done()
|
if window('jellyfin_should_stop.bool'):
|
||||||
|
break
|
||||||
if window('jellyfin_should_stop.bool'):
|
|
||||||
break
|
|
||||||
|
|
||||||
LOG.info("--<[ q:removed/%s ]", id(self))
|
LOG.info("--<[ q:removed/%s ]", id(self))
|
||||||
self.is_done = True
|
self.is_done = True
|
||||||
|
|
|
@ -165,7 +165,6 @@ class Artwork(object):
|
||||||
from database import Database
|
from database import Database
|
||||||
|
|
||||||
with Database('texture') as texturedb:
|
with Database('texture') as texturedb:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
texturedb.cursor.execute(QUTEX.get_cache, (url,))
|
texturedb.cursor.execute(QUTEX.get_cache, (url,))
|
||||||
cached = texturedb.cursor.fetchone()[0]
|
cached = texturedb.cursor.fetchone()[0]
|
||||||
|
@ -195,7 +194,6 @@ class GetArtworkWorker(threading.Thread):
|
||||||
'''
|
'''
|
||||||
with requests.Session() as s:
|
with requests.Session() as s:
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
url = self.queue.get(timeout=2)
|
url = self.queue.get(timeout=2)
|
||||||
except Queue.Empty:
|
except Queue.Empty:
|
||||||
|
|
Loading…
Reference in a new issue