mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-11-10 04:06:11 +00:00
168 lines
4.9 KiB
Python
168 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import division, absolute_import, print_function, unicode_literals
|
|
|
|
##################################################################################################
|
|
|
|
import json
|
|
import os
|
|
|
|
from six import ensure_text
|
|
|
|
from ..helper import LazyLogger, get_filesystem_encoding
|
|
|
|
##################################################################################################
|
|
|
|
LOG = LazyLogger(__name__)
|
|
|
|
##################################################################################################
|
|
|
|
|
|
class Objects(object):
|
|
|
|
# Borg - multiple instances, shared state
|
|
_shared_state = {}
|
|
|
|
def __init__(self):
|
|
"""Hold all persistent data here."""
|
|
|
|
self.__dict__ = self._shared_state
|
|
|
|
def mapping(self):
|
|
"""Load objects mapping."""
|
|
file_dir = os.path.dirname(ensure_text(__file__, get_filesystem_encoding()))
|
|
|
|
with open(os.path.join(file_dir, "obj_map.json")) as infile:
|
|
self.objects = json.load(infile)
|
|
|
|
def map(self, item, mapping_name):
|
|
"""Syntax to traverse the item dictionary.
|
|
This of the query almost as a url.
|
|
|
|
Item is the Jellyfin item json object structure
|
|
|
|
",": each element will be used as a fallback until a value is found.
|
|
"?": split filters and key name from the query part, i.e. MediaSources/0?$Name
|
|
"$": lead the key name with $. Only one key value can be requested per element.
|
|
":": indicates it's a list of elements [], i.e. MediaSources/0/MediaStreams:?$Name
|
|
MediaStreams is a list.
|
|
"/": indicates where to go directly
|
|
"""
|
|
self.mapped_item = {}
|
|
|
|
if not mapping_name:
|
|
raise Exception("execute mapping() first")
|
|
|
|
mapping = self.objects[mapping_name]
|
|
|
|
for key, value in mapping.items():
|
|
|
|
self.mapped_item[key] = None
|
|
params = value.split(",")
|
|
|
|
for param in params:
|
|
|
|
obj = item
|
|
obj_param = param
|
|
obj_key = ""
|
|
obj_filters = {}
|
|
|
|
if "?" in obj_param:
|
|
|
|
if "$" in obj_param:
|
|
obj_param, obj_key = obj_param.rsplit("$", 1)
|
|
|
|
obj_param, filters = obj_param.rsplit("?", 1)
|
|
|
|
if filters:
|
|
for filter in filters.split("&"):
|
|
filter_key, filter_value = filter.split("=")
|
|
obj_filters[filter_key] = filter_value
|
|
|
|
if ":" in obj_param:
|
|
result = []
|
|
|
|
for d in self.__recursiveloop__(obj, obj_param):
|
|
|
|
if not obj_filters or self.__filters__(d, obj_filters):
|
|
result.append(d)
|
|
|
|
obj = result
|
|
obj_filters = {}
|
|
|
|
elif "/" in obj_param:
|
|
obj = self.__recursive__(obj, obj_param)
|
|
|
|
elif obj is item and obj is not None:
|
|
obj = item.get(obj_param)
|
|
|
|
if obj_filters and obj and not self.__filters__(obj, obj_filters):
|
|
obj = None
|
|
|
|
if obj is None and len(params) != params.index(param):
|
|
continue
|
|
|
|
if obj_key:
|
|
obj = (
|
|
[d[obj_key] for d in obj if d.get(obj_key)]
|
|
if isinstance(obj, list)
|
|
else obj.get(obj_key)
|
|
)
|
|
|
|
self.mapped_item[key] = obj
|
|
break
|
|
|
|
if (
|
|
not mapping_name.startswith("Browse")
|
|
and not mapping_name.startswith("Artwork")
|
|
and not mapping_name.startswith("UpNext")
|
|
):
|
|
|
|
self.mapped_item["ProviderName"] = self.objects.get(
|
|
"%sProviderName" % mapping_name
|
|
)
|
|
self.mapped_item["Checksum"] = json.dumps(item["UserData"])
|
|
|
|
return self.mapped_item
|
|
|
|
def __recursiveloop__(self, obj, keys):
|
|
|
|
first, rest = keys.split(":", 1)
|
|
obj = self.__recursive__(obj, first)
|
|
|
|
if obj:
|
|
for item in obj:
|
|
if rest:
|
|
self.__recursiveloop__(item, rest)
|
|
else:
|
|
yield item
|
|
|
|
def __recursive__(self, obj, keys):
|
|
|
|
for string in keys.split("/"):
|
|
|
|
if not obj:
|
|
return
|
|
|
|
obj = obj[int(string)] if string.isdigit() else obj.get(string)
|
|
|
|
return obj
|
|
|
|
def __filters__(self, obj, filters):
|
|
|
|
result = False
|
|
|
|
for key, value in filters.items():
|
|
|
|
inverse = False
|
|
|
|
if value.startswith("!"):
|
|
|
|
inverse = True
|
|
value = value.split("!", 1)[1]
|
|
|
|
if value.lower() == "null":
|
|
value = None
|
|
|
|
result = obj.get(key) != value if inverse else obj.get(key) == value
|
|
|
|
return result
|