예제 #1
0
def import_needed_module():
    """Import needed module according to the Kodi base URL and query string

    TODO: Remove this import 'hack' when CodeQuick 0.9.11 will be released

    """

    modules_to_import = [get_module_in_url(sys.argv[0])]
    if 'codequick/search' in sys.argv[0]:
        modules_to_import.append(get_module_in_query(sys.argv[2]))
    for module_to_import in modules_to_import:
        if module_to_import == '':
            # No additionnal module to load
            continue

        # Need to load additional module
        try:
            Script.log(
                '[import_needed_module] Import module {} on the fly'.format(
                    module_to_import),
                lvl=Script.INFO)
            importlib.import_module(module_to_import)
        except Exception:
            Script.log(
                '[import_needed_module] Failed to import module {} on the fly'.
                format(module_to_import),
                lvl=Script.WARNING)
예제 #2
0
    def execute(self,
                sqlquery,
                args,
                repeat=False):  # type: (str, tuple, bool) -> None
        self.cur.execute("BEGIN")
        try:
            self.cur.execute(sqlquery, args)

        # Handle database errors
        except sqlite3.DatabaseError as e:
            # Check if database is currupted
            if not repeat and os.path.exists(self.filepath) and \
                    (str(e).find("file is encrypted") > -1 or str(e).find("not a database") > -1):
                Script.log("Deleting broken database file: %s",
                           (self.filepath, ),
                           lvl=Script.DEBUG)
                self.close()
                os.remove(self.filepath)
                self._connect()
                self.execute(sqlquery, args, repeat=True)
            else:
                raise e

        # Just roll back database on error and raise again
        except Exception as e:
            self.db.rollback()
            raise e
        else:
            self.db.commit()
예제 #3
0
    def search(cls, callback, *args, **kwargs):
        """
        Constructor to add "saved search" support to add-on.

        This will first link to a "sub" folder that lists all saved "search terms". From here,
        "search terms" can be created or removed. When a selection is made, the "callback" function
        that was given will be executed with all parameters forwarded on. Except with one extra
        parameter, ``search_query``, which is the "search term" that was selected.

        :param callback: Function that will be called when the "listitem" is activated.
        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.
        :raises ValueError: If the given "callback" function does not have a ``search_query`` parameter.
        """
        # Check that callback function has required parameter(search_query)
        if "search_query" not in callback.route.arg_names():
            raise ValueError(
                "callback function is missing required argument: 'search_query'"
            )

        if args:
            # Convert positional arguments to keyword arguments
            callback.route.args_to_kwargs(args, kwargs)

        item = cls()
        item.label = bold(Script.localize(SEARCH))
        item.art.global_thumb("search.png")
        item.info["plot"] = Script.localize(SEARCH_PLOT)
        item.set_callback(SavedSearches,
                          route=callback.route.path,
                          first_load=True,
                          **kwargs)
        return item
예제 #4
0
    def search(cls, callback, *args, **kwargs):
        """
        Constructor to add "saved search" support to add-on.

        This will first link to a "sub" folder that lists all saved "search terms". From here,
        "search terms" can be created or removed. When a selection is made, the "callback" function
        that was given will be executed with all parameters forwarded on. Except with one extra
        parameter, ``search_query``, which is the "search term" that was selected.

        :param callback: Function that will be called when the "listitem" is activated.
        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.
        :raises ValueError: If the given "callback" function does not have a ``search_query`` parameter.
        """
        # Check that callback function has required parameter(search_query)
        if "search_query" not in callback.route.arg_names():
            raise ValueError("callback function is missing required argument: 'search_query'")

        if args:
            # Convert positional arguments to keyword arguments
            callback.route.args_to_kwargs(args, kwargs)

        item = cls()
        item.label = bold(Script.localize(SEARCH))
        item.art.global_thumb("search.png")
        item.info["plot"] = Script.localize(SEARCH_PLOT)
        item.set_callback(SavedSearches, _route=callback.route.path, first_load=True, **kwargs)
        return item
예제 #5
0
    def next_page(cls, *args, **kwargs):
        """
        Constructor for adding link to "Next Page" of content.

        By default the current running "callback" will be called with all of the parameters that are given here.
        You can specify which "callback" will be called by setting a keyword only argument called 'callback'.

        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.

        :example:
            >>> item = Listitem()
            >>> item.next_page(url="http://example.com/videos?page2")
        """
        # Current running callback
        callback = kwargs.pop(
            "callback") if "callback" in kwargs else dispatcher.get_route(
            ).callback

        # Add support params to callback params
        kwargs[
            "_updatelisting_"] = True if u"_nextpagecount_" in dispatcher.params else False
        kwargs["_title_"] = dispatcher.params.get(u"_title_", u"")
        kwargs["_nextpagecount_"] = dispatcher.params.get(
            u"_nextpagecount_", 1) + 1

        # Create listitem instance
        item = cls()
        label = u"%s %i" % (Script.localize(NEXT_PAGE),
                            kwargs["_nextpagecount_"])
        item.info["plot"] = Script.localize(NEXT_PAGE_PLOT)
        item.label = bold(label)
        item.art.global_thumb("next.png")
        item.set_callback(callback, *args, **kwargs)
        return item
예제 #6
0
    def search(cls, callback, *args, **kwargs):
        """
        Constructor to add "saved search" support to add-on.

        This will first link to a "sub" folder that lists all saved "search terms". From here,
        "search terms" can be created or removed. When a selection is made, the "callback" function
        that was given will be executed with all parameters forwarded on. Except with one extra
        parameter, ``search_query``, which is the "search term" that was selected.

        :param Callback callback: Function that will be called when the "listitem" is activated.
        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.
        """
        if hasattr(callback, "route"):
            route = callback.route
        elif isinstance(callback, CallbackRef):
            route = callback
        else:
            route = dispatcher.get_route(callback)

        kwargs["first_load"] = True
        kwargs["_route"] = route.path

        item = cls()
        item.label = bold(Script.localize(SEARCH))
        item.art.global_thumb("search.png")
        item.info["plot"] = Script.localize(SEARCH_PLOT)
        item.set_callback(Route.ref("/codequick/search:saved_searches"), *args,
                          **kwargs)
        return item
예제 #7
0
    def next_page(cls, *args, **kwargs):
        """
        Constructor for adding link to "Next Page" of content.

        The current running "callback" will be called with all of the parameters that are given here.
        You can also specify which "callback" will be called by setting a keywork only argument called 'callback'.

        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.

        :example:
            >>> item = Listitem()
            >>> item.next_page(url="http://example.com/videos?page2")
        """
        # Current running callback
        callback = dispatcher.get_route().callback
        callback = kwargs.pop("callback", callback)

        # Add support params to callback params
        kwargs["_updatelisting_"] = True if u"_nextpagecount_" in dispatcher.params else False
        kwargs["_title_"] = dispatcher.params.get(u"_title_", u"")
        kwargs["_nextpagecount_"] = dispatcher.params.get(u"_nextpagecount_", 1) + 1

        # Create listitem instance
        item = cls()
        label = u"%s %i" % (Script.localize(NEXT_PAGE), kwargs["_nextpagecount_"])
        item.info["plot"] = Script.localize(NEXT_PAGE_PLOT)
        item.label = bold(label)
        item.art.global_thumb("next.png")
        item.set_callback(callback, *args, **kwargs)
        return item
예제 #8
0
파일: listing.py 프로젝트: camster1/RTOTV
    def next_page(cls, **params):
        """
        Constructor for adding Next Page.

        Add a listitem that will link to the next page of items. The current running callback will be called with
        all of the params that are given here.

        :param params: Keyword arguments of params that will be added to the current set of callback params.

        :example:
            >>> item = Listitem()
            >>> item.next_page(url="http://example.com/videos?page2")
        """
        # Add support params to callback params
        params["_updatelisting_"] = True
        params["_title_"] = dispatcher.support_params.get(u"_title_", u"")
        params["_nextpagecount_"] = dispatcher.support_params.get(
            u"_nextpagecount_", 1) + 1

        # Create listitem instance
        item = cls()
        label = u"%s %i" % (Script.localize(NEXT_PAGE),
                            params["_nextpagecount_"])
        item.info["plot"] = "Show the next page of content."
        item.label = "[B]%s[/B]" % label
        item.art.global_thumb("next.png")
        item.params.update(params)
        item.set_callback(dispatcher.callback, **params)
        return item
예제 #9
0
    def youtube(cls, content_id, label=None, enable_playlists=True):
        """
        Constructor to add a "YouTube channel" to add-on.

        This listitem will list all videos from a "YouTube", channel or playlist. All videos will have a
        "Related Videos" option via the context menu. If ``content_id`` is a channel ID and ``enable_playlists``
        is ``True``, then a link to the "channel playlists" will also be added to the list of videos.

        :param str content_id: Channel ID or playlist ID, of video content.
        :param str label: [opt] Listitem Label. (default => "All Videos").
        :param bool enable_playlists: [opt] Set to ``False`` to disable linking to channel playlists.
                                      (default => ``True``)

        :example:
            >>> item = Listitem()
            >>> item.youtube("UC4QZ_LsYcvcq7qOsOhpAX4A")
        """
        # Youtube exists, Creating listitem link
        item = cls()
        item.label = label if label else bold(Script.localize(ALLVIDEOS))
        item.art.global_thumb("videos.png")
        item.params["contentid"] = content_id
        item.params["enable_playlists"] = False if content_id.startswith("PL") else enable_playlists
        item.set_callback(YTPlaylist)
        return item
예제 #10
0
    def youtube(cls, content_id, label=None, enable_playlists=True):
        """
        Constructor to add a youtube channel to addon.

        This listitem will list all videos from a youtube channel or playlist. All videos also have a
        related videos option via context menu. If content_id is a channel id and enable_playlists
        is ``True`` then a link to the channel playlists will also be added to the list of videos.

        :param content_id: Channel id or playlist id of video content.
        :type content_id: str or unicode

        :param label: [opt] Label of listitem. (default => 'All Videos').
        :type label: str or unicode

        :param bool enable_playlists: [opt] Set to ``False`` to disable linking to channel playlists.
                                      (default => ``True``)

        :example:
            >>> item = Listitem()
            >>> item.youtube("UC4QZ_LsYcvcq7qOsOhpAX4A")
        """
        # Youtube exists, Creating listitem link
        item = cls()
        item.label = label if label else Script.localize(ALLVIDEOS)
        item.art.global_thumb("videos.png")
        item.params["contentid"] = content_id
        item.params["enable_playlists"] = False if content_id.startswith("PL") else enable_playlists
        item.set_callback(YTPlaylist)
        return item
예제 #11
0
    def youtube(cls, content_id, label=None, enable_playlists=True):
        """
        Constructor to add a "YouTube channel" to add-on.

        This listitem will list all videos from a "YouTube", channel or playlist. All videos will have a
        "Related Videos" option via the context menu. If ``content_id`` is a channel ID and ``enable_playlists``
        is ``True``, then a link to the "channel playlists" will also be added to the list of videos.

        :param str content_id: Channel ID or playlist ID, of video content.
        :param str label: [opt] Listitem Label. (default => "All Videos").
        :param bool enable_playlists: [opt] Set to ``False`` to disable linking to channel playlists.
                                      (default => ``True``)

        :example:
            >>> item = Listitem()
            >>> item.youtube("UC4QZ_LsYcvcq7qOsOhpAX4A")
        """
        # Youtube exists, Creating listitem link
        item = cls()
        item.label = label if label else bold(Script.localize(ALLVIDEOS))
        item.art.global_thumb("videos.png")
        item.params["contentid"] = content_id
        item.params["enable_playlists"] = False if content_id.startswith(
            "PL") else enable_playlists
        item.set_callback(Route.ref("/codequick/youtube:playlist"))
        return item
예제 #12
0
    def next_page(cls, *args, **kwargs):
        """
        Constructor for adding link to Next Page of content.

        The current running callback will be called with all of the params that are given here.

        :param args: Positional arguments that will be passed to current callback.
        :param kwargs: Keyword arguments that will be passed to current callback.

        :example:
            >>> item = Listitem()
            >>> item.next_page(url="http://example.com/videos?page2")
        """
        # Current running callback
        callback = dispatcher.current_route.org_callback

        if args:
            # Convert positional arguments to keyword arguments
            args_map = callback.route.args_to_kwargs(args)
            kwargs.update(args_map)

        # Add support params to callback params
        kwargs["_updatelisting_"] = True if u"_nextpagecount_" in dispatcher.support_params else False
        kwargs["_title_"] = dispatcher.support_params.get(u"_title_", u"")
        kwargs["_nextpagecount_"] = dispatcher.support_params.get(u"_nextpagecount_", 1) + 1

        # Create listitem instance
        item = cls()
        label = u"%s %i" % (Script.localize(NEXT_PAGE), kwargs["_nextpagecount_"])
        item.info["plot"] = "Show the next page of content."
        item.label = "[B]%s[/B]" % label
        item.art.global_thumb("next.png")
        item.params.update(kwargs)
        item.set_callback(callback, **kwargs)
        return item
예제 #13
0
    def search(cls, callback, *args, **kwargs):
        """
        Constructor to add saved search Support to addon.

        This will first link to a sub folder that lists all saved search terms.
        From here, search terms can be created or removed.
        When a selection is made, the callback function that was given will be executed with all params forwarded on.
        Except with one extra param, 'search_query' witch is the search term that was selected.

        :param callback: Function that will be called when the listitem is activated.
        :param args: Positional arguments that will be passed to callback.
        :param kwargs: Keyword arguments that will be passed to callback.
        :raises ValueError: If the given callback function does not have a 'search_query' parameter.
        """
        if args:
            # Convert positional arguments to keyword arguments
            args_map = callback.route.args_to_kwargs(args)
            kwargs.update(args_map)

        # Check that callback function has required parameter(search_query).
        if "search_query" not in callback.route.arg_names():
            raise ValueError("callback function is missing required argument: 'search_query'")

        item = cls()
        item.label = u"[B]%s[/B]" % Script.localize(SEARCH)
        item.art.global_thumb("search.png")
        item.info["plot"] = "Search for video content."
        item.set_callback(SavedSearches, route=callback.route.path, first_load=True, **kwargs)
        return item
예제 #14
0
    def recent(cls, callback, *args, **kwargs):
        """
        Constructor for adding "Recent Videos" folder.

        This is a convenience method that creates the listitem with "name", "thumbnail" and "plot", already preset.

        :param callback: The "callback" function.
        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.
        """
        # Create listitem instance
        item = cls()
        item.label = bold(Script.localize(RECENT_VIDEOS))
        item.info["plot"] = Script.localize(RECENT_VIDEOS_PLOT)
        item.art.global_thumb("recent.png")
        item.set_callback(callback, *args, **kwargs)
        return item
예제 #15
0
    def recent(cls, callback, *args, **kwargs):
        """
        Constructor for adding "Recent Videos" folder.

        This is a convenience method that creates the listitem with "name", "thumbnail" and "plot", already preset.

        :param Callback callback: The "callback" function.
        :param args: "Positional" arguments that will be passed to the callback.
        :param kwargs: "Keyword" arguments that will be passed to the callback.
        """
        # Create listitem instance
        item = cls()
        item.label = bold(Script.localize(RECENT_VIDEOS))
        item.info["plot"] = Script.localize(RECENT_VIDEOS_PLOT)
        item.art.global_thumb("recent.png")
        item.set_callback(callback, *args, **kwargs)
        return item
예제 #16
0
파일: listing.py 프로젝트: camster1/RTOTV
    def related(self, callback, **query):
        """
        Convenient method to add a related videos context menu item.

        All this really does is set the label of the menu item for you.
        
        :param callback: The function that will be called when menu item is activated.
        :param query: [opt] Keyword arguments that will be passed on to callback function.
        """
        self.container(Script.localize(RELATED_VIDEOS), callback, **query)
예제 #17
0
    def related(self, callback, *args, **kwargs):
        """
        Convenient method to add a related videos context menu item.

        All this really does is call context.container and sets label for you.
        
        :param callback: The function that will be called when menu item is activated.
        :param args: [opt] Positional arguments that will be passed to callback.
        :param kwargs: [opt] Keyword arguments that will be passed on to callback function.
        """
        self.container(callback, Script.localize(RELATED_VIDEOS), *args, **kwargs)
예제 #18
0
    def related(self, callback, *args, **kwargs):
        """
        Convenient method to add a "Related Videos" context menu item.

        All this really does is to call "context.container" and sets "label" for you.

        :param callback: The function that will be called when menu item is activated.
        :param args: [opt] "Positional" arguments that will be passed to the callback.
        :param kwargs: [opt] "Keyword" arguments that will be passed to the callback.
        """
        self.container(callback, Script.localize(RELATED_VIDEOS), *args,
                       **kwargs)
def get_item_media_path(item_media_path):
    full_path = ''

    # Local image in ressources/media folder
    if type(item_media_path) is list:
        full_path = os.path.join(Script.get_info("path"), "resources", "media",
                                 *(item_media_path))

    # Remote image with complete URL
    elif 'http' in item_media_path:
        full_path = item_media_path

    # Remote image on our images repo
    else:
        full_path = 'https://github.com/Catch-up-TV-and-More/images/raw/master/' + item_media_path

    return ensure_native_str(full_path)
예제 #20
0
    def related(self, callback, *args, **kwargs):
        """
        Convenient method to add a "Related Videos" context menu item.

        All this really does is to call "context.container" and sets "label" for you.

        :param callback: The function that will be called when menu item is activated.
        :param args: [opt] "Positional" arguments that will be passed to the callback.
        :param kwargs: [opt] "Keyword" arguments that will be passed to the callback.
        """
        # Add '_updatelisting_ = True' to callback params if called from the same callback as is given here
        if callback.route == dispatcher.get_route():
            kwargs["_updatelisting_"] = True

        related_videos_text = Script.localize(RELATED_VIDEOS)
        kwargs["_title_"] = related_videos_text
        self.container(callback, related_videos_text, *args, **kwargs)
예제 #21
0
    def related(self, callback, *args, **kwargs):
        """
        Convenient method to add a "Related Videos" context menu item.

        All this really does is to call "context.container" and sets "label" for you.

        :param callback: The function that will be called when menu item is activated.
        :param args: [opt] "Positional" arguments that will be passed to the callback.
        :param kwargs: [opt] "Keyword" arguments that will be passed to the callback.
        """
        # Add '_updatelisting_ = True' to callback params if called from the same callback as is given here
        if callback.route == dispatcher.get_route():
            kwargs["_updatelisting_"] = True

        related_videos_text = Script.localize(RELATED_VIDEOS)
        kwargs["_title_"] = related_videos_text
        self.container(callback, related_videos_text, *args, **kwargs)
예제 #22
0
파일: listing.py 프로젝트: camster1/RTOTV
    def recent(cls, callback, **params):
        """
        Constructor for adding Recent Folder.

        This is really more of a convenience method that creates the listitem with name, thumbnail and plot
        already preset for the user.

        :param callback: The callback function.
        :type callback: :class:`types.FunctionType`
        :param params: Keyword arguments of parameters that will be passed to the callback function.
        """
        # Create listitem instance
        item = cls()
        item.label = Script.localize(RECENT_VIDEOS)
        item.info["plot"] = "Show the most recent videos."
        item.art.global_thumb("recent.png")
        item.set_callback(callback, **params)
        return item
예제 #23
0
    def recent(cls, callback, *args, **kwargs):
        """
        Constructor for adding Recent Videos folder.

        This is a convenience method that creates the listitem with name, thumbnail and plot
        already preset.

        :param callback: The callback function.
        :param args: Positional arguments that will be passed to callback.
        :param kwargs: Keyword arguments that will be passed to callback.
        """
        if args:
            # Convert positional arguments to keyword arguments
            args_map = callback.route.args_to_kwargs(args)
            kwargs.update(args_map)

        # Create listitem instance
        item = cls()
        item.label = Script.localize(RECENT_VIDEOS)
        item.info["plot"] = "Show the most recent videos."
        item.art.global_thumb("recent.png")
        item.set_callback(callback, **kwargs)
        return item
def get_item_media_path(item_media_path):
    full_path = os.path.join(
        Script.get_info("path"), "resources", "media", *(item_media_path))
    return ensure_native_str(full_path)
예제 #25
0
# Package imports
from codequick.script import Script
from codequick.utils import ensure_unicode, PY3

if PY3:
    # noinspection PyUnresolvedReferences, PyCompatibility
    from collections.abc import MutableMapping, MutableSequence
else:
    # noinspection PyUnresolvedReferences, PyCompatibility
    from collections import MutableMapping, MutableSequence

__all__ = ["PersistentDict", "PersistentList"]

# The addon profile directory
profile_dir = Script.get_info("profile")


class _PersistentBase(object):
    """
    Base class to handle persistent file handling.

    :param str name: Filename of persistence storage file.
    """

    def __init__(self, name):
        super(_PersistentBase, self).__init__()
        self._version_string = "__codequick_storage_version__"
        self._data_string = "__codequick_storage_data__"
        self._serializer_obj = object
        self._stream = None
예제 #26
0
import sys
import os

try:
    import cPickle as pickle
except ImportError:  # pragma: no cover
    import pickle

# Package imports
from codequick.script import Script
from codequick.utils import ensure_unicode

__all__ = ["PersistentDict", "PersistentList"]

# The addon profile directory
profile_dir = Script.get_info("profile")


class _PersistentBase(object):
    """
    Base class to handle persistent file handling.

    :param str name: Filename of persistence storage file.
    """

    def __init__(self, name):
        super(_PersistentBase, self).__init__()
        self._version_string = "__codequick_storage_version__"
        self._data_string = "__codequick_storage_data__"
        self._serializer_obj = object
        self._stream = None
예제 #27
0
# Kodi imports
import xbmcplugin
import xbmcgui

# Package imports
from codequick.script import Script
from codequick.support import auto_sort, build_path, logger_id, dispatcher
from codequick.utils import safe_path, ensure_unicode, ensure_native_str, unicode_type, long_type

__all__ = ["Listitem", "Art", "Info", "Stream", "Context", "Property", "Params"]

# Logger specific to this module
logger = logging.getLogger("%s.listitem" % logger_id)

# Listitem thumbnail locations
local_image = ensure_native_str(os.path.join(Script.get_info("path"), u"resources", u"media", u"{}"))
global_image = ensure_native_str(os.path.join(Script.get_info("path_global"), u"resources", u"media", u"{}"))

# Prefetch fanart/icon for use later
_fanart = Script.get_info("fanart")
fanart = ensure_native_str(_fanart) if os.path.exists(safe_path(_fanart)) else None
icon = ensure_native_str(Script.get_info("icon"))

# Stream type map to ensure proper stream value types
stream_type_map = {"duration": int,
                   "channels": int,
                   "aspect": float,
                   "height": int,
                   "width": int}

# Listing sort methods & sort mappings.
예제 #28
0
from codequick.utils import ensure_unicode, ensure_native_str, unicode_type, PY3, bold

if PY3:
    # noinspection PyUnresolvedReferences, PyCompatibility
    from collections.abc import MutableMapping, MutableSequence
else:
    # noinspection PyUnresolvedReferences, PyCompatibility
    from collections import MutableMapping, MutableSequence

__all__ = ["Listitem"]

# Logger specific to this module
logger = logging.getLogger("%s.listitem" % logger_id)

# Listitem thumbnail locations
local_image = ensure_native_str(os.path.join(Script.get_info("path"), u"resources", u"media", u"{}"))
global_image = ensure_native_str(os.path.join(Script.get_info("path_global"), u"resources", u"media", u"{}"))

# Prefetch fanart/icon for use later
_fanart = Script.get_info("fanart")
fanart = ensure_native_str(_fanart) if os.path.exists(_fanart) else None
icon = ensure_native_str(Script.get_info("icon"))

# Stream type map to ensure proper stream value types
stream_type_map = {"duration": int,
                   "channels": int,
                   "aspect": float,
                   "height": int,
                   "width": int}

# Listing sort methods & sort mappings.