Пример #1
0
def download_github_folder(repo, folder, destination):
    contents_url = "https://api.github.com/repos/%s/contents/%s" % (repo, folder)
    log.info("Downloading repo content for folder: %s, to folder: %s" % (contents_url, destination))
    try:
        with requests.get(contents_url) as r:
            lists = json.loads(r.content, parse_int=str)

            downloaded = 0
            for i in lists:
                if 'download_url' not in i:
                    continue

                dest = os.path.join(destination, urllib_parse.unquote(i['download_url'].rsplit('/', 1)[1]))
                log.info("Downloading file '%s' to '%s'" % (i['download_url'], dest))

                with requests.get(i['download_url'], stream=True) as rd:
                    rd.raise_for_status()
                    with open(dest, 'wb') as f:
                        for chunk in rd.iter_content(chunk_size=8192):
                            f.write(chunk)
                downloaded += 1
            return downloaded > 0
    except Exception as e:
        log.error("Could not get list of files from github: %s" % e)
        raise
Пример #2
0
 def _dispatch_delete(self, objectname):
     try:
         self._objects[objectname]._shutdown()
     except Exception:
         _log.error("Error when shutting down the object %s:",
                    type(self._objects[objectname]))
         _log.debug(traceback.format_exc())
     del self._objects[objectname]
Пример #3
0
def doTraktAction(action):
    dbid = getDbId()
    mediatype = getMediaType()

    if action == "watched":
        heading = ADDON.getLocalizedString(32018)
    elif action == "unwatched":
        heading = ADDON.getLocalizedString(32019)
    else:
        heading = "Unsupported action"

    if not dbid.isdigit():
        showtmdbid = xbmc.getInfoLabel('ListItem.Property(ShowTMDBId)')
        try:
            tmdbID = sys.listitem.getUniqueID('tmdb')
        except AttributeError:
            tmdbID = ""
        if tmdbID == "" or ((mediatype == 'season' or mediatype == 'episode')
                            and showtmdbid == ""):
            log.error("Could not find TMDB id for %s" % dbid)
            xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                          ADDON.getLocalizedString(32014),
                                          xbmcgui.NOTIFICATION_WARNING, 3000)
            return

    xbmcgui.Dialog().notification(heading, sys.listitem.getLabel(),
                                  xbmcgui.NOTIFICATION_INFO, 3000)
    if not dbid.isdigit():
        log.info("Make %s non-library item: tmdbID=%s, MediaType=%s" %
                 (action, tmdbID, mediatype))
    else:
        log.info("Make %s library item: DBID=%s, MediaType=%s" %
                 (action, dbid, mediatype))

    if not dbid.isdigit():
        if mediatype == 'movie':
            url = "plugin://plugin.video.elementum/movie/%s/%s" % (tmdbID,
                                                                   action)
        if mediatype == 'tvshow':
            url = "plugin://plugin.video.elementum/show/%s/%s" % (tmdbID,
                                                                  action)
        elif mediatype == 'season':
            season = xbmc.getInfoLabel('ListItem.Season')
            url = "plugin://plugin.video.elementum/show/%s/season/%s/%s" % (
                showtmdbid, season, action)
        elif mediatype == 'episode':
            season = xbmc.getInfoLabel('ListItem.Season')
            episode = xbmc.getInfoLabel('ListItem.Episode')
            url = "plugin://plugin.video.elementum/show/%s/season/%s/episode/%s/%s" % (
                showtmdbid, season, episode, action)
    else:
        url = "plugin://plugin.video.elementum/context/media/%s/%s/%s" % (
            mediatype, dbid, action)
    log.info("Starting Elementum with: %s" % url)
    xbmc.Player().play(url)
Пример #4
0
    def Wait_Window_Loaded(self):
        tries = 9
        while self.Window_Is_Loading():
            if tries == 0:
                log.error("Failed to wait till window has finished loading")
                return int(False)

            tries = tries - 1
            time.sleep(0.3)

        log.debug("Finished waiting till window has finished loading")
        return int(True)
Пример #5
0
def getTMDBidFromElementumPath(path):
    """plugin://plugin.video.elementum/movie/628/links/Interview%20with%20the%20Vampire%20%281994%29"""
    result = re.search(r'plugin://plugin.video.elementum/[^/]+/(\d+)/.*', path)
    if result:
        tmdbID = result.group(1)
        return tmdbID
    else:
        log.error("Could not find TMDB id for %s" % path)
        xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                      ADDON.getLocalizedString(32014),
                                      xbmcgui.NOTIFICATION_WARNING, 3000)
        return ""
Пример #6
0
def jsonrpc_enabled(notify=False):
    try:
        s = socket.socket()
        s.connect(('127.0.0.1', 9090))
        s.close()
        log.info("Kodi's JSON-RPC service is available, starting up...")
        del s
        return True
    except Exception as e:
        log.error(repr(e))
        if notify:
            xbmc.executebuiltin("ActivateWindow(ServiceSettings)")
            dialog = xbmcgui.Dialog()
            dialog.ok("Elementum", getLocalizedString(30199))
    return False
Пример #7
0
def download_current_version(repo):
    contents_url = "https://api.github.com/repos/%s/git/refs/tags" % (repo)
    log.debug("Downloading repo releases: %s" % (contents_url))
    try:
        with requests.get(contents_url) as r:
            lists = json.loads(r.content, parse_int=str)

            ref = lists[-1]["ref"]
            if ref.find('/'):
                return ref.rsplit('/', 1)[1]

            return ""
    except Exception as e:
        log.error("Could not get list of tags from github: %s" % e)
        raise
Пример #8
0
def clear_fd_inherit_flags():
    # Ensure the spawned Elementum binary doesn't inherit open files from Kodi
    # which can break things like addon updates. [WINDOWS ONLY]
    try:
        from ctypes import windll

        HANDLE_RANGE = six.moves.xrange(0, 65536)
        HANDLE_FLAG_INHERIT = 1
        FILE_TYPE_DISK = 1

        for hd in HANDLE_RANGE:
            if windll.kernel32.GetFileType(hd) == FILE_TYPE_DISK:
                if not windll.kernel32.SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0):
                    log.error("Error clearing inherit flag, disk file handle %x" % hd)
    except:
        pass
Пример #9
0
def getSeasonNumberFromElementumPath(path):
    """plugin://plugin.video.elementum/show/1622/season/15/episodes"""
    season_number = xbmc.getInfoLabel('ListItem.Season')
    if season_number:
        return season_number
    else:
        result = re.search(
            r'plugin://plugin.video.elementum/[^/]+/\d+/season/(\d+)/.*', path)
        if result:
            season_number = result.group(1)
            return season_number
        else:
            log.error("Could not find season number for %s" % path)
            xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                          ADDON.getLocalizedString(32014),
                                          xbmcgui.NOTIFICATION_WARNING, 3000)
            return ""
Пример #10
0
    def _format_exception(self, obj, method, args, kw, exc):
        etype, evalue, etb = exc
        funargs = ", ".join([repr(x) for x in args] +
                            ["%s=%r" % (k, kw[k]) for k in kw])
        if len(funargs) > 40:
            funargs = funargs[:37] + "..."

        _log.error("(%s) In Handler method %s.%s(%s) ",
                   obj.__class__.__module__, obj.__class__.__name__, method,
                   funargs)
        _log.debug("\n".join([
            "%s::%s:%d %s" % (filename, fnname, lineno, srcline) for filename,
            lineno, fnname, srcline in traceback.extract_tb(etb)[1:]
        ]))
        _log.error("Unhandled error: %s: %s", etype.__name__, evalue)
        del etb
        return '%s: %s' % (etype.__name__, evalue)
Пример #11
0
    def _readn(self):
        """
            Internal function which reads from socket waiting for a newline
        """
        streambuffer = self._buffer
        pos = streambuffer.find(b'\n')
        # _log.debug("read...")
        # retry = 0
        while pos == -1:
            data = b''
            try:
                data = self._sck.recv(2048)
            except IOError as inst:
                _log.debug("Read socket error: IOError%r (timeout: %r)",
                           inst.args, self._sck.gettimeout())
                if inst.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
                    if self._sck.gettimeout() == 0:  # if it was too fast
                        self._sck.settimeout(5)
                        continue
                        # time.sleep(0.5)
                        # retry += 1
                        # if retry < 10:
                        #     _log.debug("Retry %s", retry)
                        #     continue
                # _log.debug(traceback.format_exc(0))
                if inst.errno in self._SOCKET_COMM_ERRORS:
                    raise EofError(len(streambuffer))

                return b''
            except socket.error as inst:
                _log.error("Read socket error: socket.error%r (timeout: %r)",
                           inst.args, self._sck.gettimeout())
                # _log.debug(traceback.format_exc(0))
                return b''
            except:
                raise
            if not data:
                raise EofError(len(streambuffer))
            # _log.debug("readbuf+: %r", data)
            streambuffer += data
            pos = streambuffer.find(b'\n')

        self._buffer = streambuffer[pos + 1:]
        streambuffer = streambuffer[:pos]
        # _log.debug("read: %r", buffer)
        return streambuffer
Пример #12
0
def getEpisodeNumberFromElementumPath(path):
    """plugin://plugin.video.elementum/show/1622/season/15/episode/1/links/Supernatural%20S15E01"""
    episode_number = xbmc.getInfoLabel('ListItem.Episode')
    if episode_number:
        return episode_number
    else:
        result = re.search(
            r'plugin://plugin.video.elementum/[^/]+/\d+/season/\d+/episode/(\d+)/.*',
            path)
        if result:
            episode_number = result.group(1)
            return episode_number
        else:
            log.error("Could not find episode number for %s" % path)
            xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                          ADDON.getLocalizedString(32014),
                                          xbmcgui.NOTIFICATION_WARNING, 3000)
            return ""
Пример #13
0
 def _send(self, response):
     txtResponse = None
     try:
         txtResponse = json.dumps(response, self)
     except Exception as e:
         _log.error(
             "An unexpected error ocurred when trying to create the message: %r",
             e)
         response = {
             'result': None,
             'error': "InternalServerError: " + repr(e)
         }
         txtResponse = json.dumps(response, self)
     try:
         self.write(txtResponse)
     except TypeError:
         _log.debug("response was: %r", response)
         raise
Пример #14
0
def getLocalizedLabel(label):
    try:
        if "LOCALIZE" not in label:
            return py2_encode(label)
        if ";;" not in label and label.endswith(']'):
            return py2_encode(getLocalizedString(int(label[9:-1])))
        else:
            parts = label.split(";;")
            translation = getLocalizedString(int(parts[0][9:14]))
            for i, part in enumerate(parts[1:]):
                if part[0:8] == "LOCALIZE":
                    parts[i + 1] = getLocalizedString(int(part[9:14]))
                else:
                    parts[i + 1] = py2_encode(parts[i + 1])

            return py2_encode(translation % tuple(parts[1:]), 'utf-8', 'ignore')
    except Exception as e:
        log.error("Cannot decode the label: %s, Error: %s" % (label, e))
        return label
Пример #15
0
    def setresponse(self, value):
        """
            Method used by Connection instance to tell Request that a Response
            is available to this request.

            Parameters:

            **value**
                Value (JSON decoded) received from socket.
        """
        self.responses.put(value)
        for callback in self.callbacks:
            try:
                callback(self)
            except Exception as exc:
                _log.error("Error on callback: %r", exc)
                _log.debug(traceback.format_exc())

        self.event_response.set()  # helper for threads.
        if self.auto_close:
            self.close()
Пример #16
0
 def close(self):
     """
         Close the connection and the socket.
     """
     if self.connection_status == "closed":
         return
     item = {'abort': True, 'event': threading.Event()}
     self.write_thread_queue.append(item)
     self.write_thread_semaphore.release()  # notify new item.
     item['event'].wait(1)
     if not item['event'].isSet():
         _log.warning("write thread doesn't process our abort command")
     try:
         self.handler._shutdown()
     except Exception:
         _log.error("Error when shutting down the handler: %s",
                    traceback.format_exc())
     try:
         self._sck.shutdown(socket.SHUT_RDWR)
     except socket.error:
         pass
     self._sck.close()
     self.connection_status = "closed"
Пример #17
0
def doAssign():
    mediatype = getMediaType()

    try:
        path = sys.listitem.getfilename()
    except AttributeError:
        path = sys.listitem.getPath()

    use_tmdb_id = False

    if path.startswith("plugin://plugin.video.elementum"):
        """plugin://plugin.video.elementum/show/1622/season/15/episode/1/links/Supernatural%20S15E01
        plugin://plugin.video.elementum/show/1622/season/15/episodes
        plugin://plugin.video.elementum/movie/628/links/Interview%20with%20the%20Vampire%20%281994%29"""
        use_tmdb_id = True
        result = re.search(r'plugin://plugin.video.elementum/[^/]+/(\d+)/.*',
                           path)
        if result:
            tmdbID = result.group(1)
        else:
            log.error("Could not find TMDB id for %s" % path)
            xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                          ADDON.getLocalizedString(32014),
                                          xbmcgui.NOTIFICATION_WARNING, 3000)
            return

        if mediatype == 'season':
            result = re.search(
                r'plugin://plugin.video.elementum/[^/]+/\d+/season/(\d+)/.*',
                path)
            if result:
                season_number = result.group(1)
            else:
                log.error("Could not find season number for %s" % path)
                xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                              ADDON.getLocalizedString(32014),
                                              xbmcgui.NOTIFICATION_WARNING,
                                              3000)
                return

        if mediatype == 'episode':
            result = re.search(
                r'plugin://plugin.video.elementum/[^/]+/\d+/season/(\d+)/episode/(\d+)/.*',
                path)
            if result:
                season_number = result.group(1)
                episode_number = result.group(2)
            else:
                log.error("Could not find season/episode number for %s" % path)
                xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                              ADDON.getLocalizedString(32014),
                                              xbmcgui.NOTIFICATION_WARNING,
                                              3000)
                return
    else:
        dbid = getDbId()
        if not dbid.isdigit():
            log.error("Kodi library ID is wrong %s" % dbid)
            xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                          ADDON.getLocalizedString(32016),
                                          xbmcgui.NOTIFICATION_WARNING, 3000)
            return

    # we also can use plugin://plugin.video.elementum/torrents/
    file = xbmcgui.Dialog().browseSingle(
        1, ADDON.getLocalizedString(32010), 'files', '', False, False,
        'plugin://plugin.video.elementum/history/')

    if file == '':
        return

    try:
        parsed_url = urlparse(file)
        params = parse_qs(parsed_url.query)
        if 'infohash' in params:
            torrentid = params['infohash'][0]
        else:
            torrentid = params['resume'][0]
    except Exception as e:
        log.error("Could not get torrent info for %s: %s" % (file, e))
        xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                      ADDON.getLocalizedString(32015),
                                      xbmcgui.NOTIFICATION_WARNING, 3000)
        return

    if not use_tmdb_id:
        url = "plugin://plugin.video.elementum/context/torrents/assign/%s/kodi/%s/%s" % (
            torrentid, mediatype, dbid)
        log.info("Assigning torrent %s for: DBID=%s, MediaType=%s" %
                 (torrentid, dbid, mediatype))
    else:
        if mediatype == 'movie':
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/%s/%s" % (
                torrentid, mediatype, tmdbID)
        elif mediatype == 'season':
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/%s/%s" % (
                torrentid, tmdbID, mediatype, season_number)
        elif mediatype == 'episode':
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/season/%s/%s/%s" % (
                torrentid, tmdbID, season_number, mediatype, episode_number)
        log.info("Assigning torrent %s for: TMDBID=%s, MediaType=%s" %
                 (torrentid, tmdbID, mediatype))

    xbmcgui.Dialog().notification(ADDON.getLocalizedString(32010),
                                  sys.listitem.getLabel(),
                                  xbmcgui.NOTIFICATION_INFO, 3000)

    log.info("Starting Elementum with: %s" % url)

    xbmc.Player().play(url)
Пример #18
0
def start_elementumd(**kwargs):
    jsonrpc_failures = 0
    while jsonrpc_enabled() is False:
        jsonrpc_failures += 1
        log.warning(
            "Unable to connect to Kodi's JSON-RPC service, retrying...")
        if jsonrpc_failures > 1:
            time.sleep(5)
            if not jsonrpc_enabled(notify=True):
                log.error(
                    "Unable to reach Kodi's JSON-RPC service, aborting...")
                return False
            else:
                break
        time.sleep(3)

    elementum_dir, elementum_binary = get_elementum_binary()

    log.info("Binary dir: %s, item: %s " % (elementum_dir, elementum_binary))
    if elementum_dir is False or elementum_binary is False:
        return False

    lockfile = os.path.join(ADDON_PATH, ".lockfile")
    if os.path.exists(lockfile):
        log.warning("Existing process found from lockfile, killing...")
        try:
            with open(lockfile) as lf:
                pid = int(lf.read().rstrip(" \t\r\n\0"))
            os.kill(pid, 9)
        except OSError as e:
            if e.errno != 3:
                # Ignore:   OSError: [Errno 3] No such process
                log.error(repr(e))
        except Exception as e:
            log.error(repr(e))

        if binary_platform["os"] == "windows":
            try:
                library_lockfile = os.path.join(
                    xbmc.translatePath(
                        ADDON.getAddonInfo("profile")).decode('utf-8'),
                    "library.db.lock")
                log.warning("Removing library.db.lock file at %s ..." %
                            library_lockfile)
                os.remove(library_lockfile)
            except Exception as e:
                log.error(repr(e))

    SW_HIDE = 0
    STARTF_USESHOWWINDOW = 1

    args = [elementum_binary]
    kwargs["cwd"] = elementum_dir

    if binary_platform["os"] == "windows":
        args[0] = getWindowsShortPath(elementum_binary)
        kwargs["cwd"] = getWindowsShortPath(elementum_dir)
        si = subprocess.STARTUPINFO()
        si.dwFlags = STARTF_USESHOWWINDOW
        si.wShowWindow = SW_HIDE
        clear_fd_inherit_flags()
        kwargs["startupinfo"] = si
    else:
        env = os.environ.copy()
        env["LD_LIBRARY_PATH"] = "%s:%s" % (elementum_dir,
                                            env.get("LD_LIBRARY_PATH", ""))
        kwargs["env"] = env
        kwargs["close_fds"] = True

    wait_counter = 1
    log.debug("Checking for visible")
    while xbmc.getCondVisibility(
            'Window.IsVisible(10140)') or xbmc.getCondVisibility(
                'Window.IsActive(10140)'):
        if wait_counter == 1:
            log.info(
                'Add-on settings currently opened, waiting before starting...')
        if wait_counter > 300:
            break
        time.sleep(1)
        wait_counter += 1

    log.info("elementumd: start args: %s, kw: %s" % (args, kwargs))

    if hasSubprocess:
        return subprocess.Popen(args, **kwargs)
    return False
Пример #19
0
def get_elementum_binary():
    global binary_platform
    binary_platform = get_platform()

    binary = "elementum" + (binary_platform["os"] == "windows" and ".exe"
                            or "")
    binary_dir = os.path.join(ADDON_PATH, "resources", "bin",
                              "%(os)s_%(arch)s" % binary_platform)

    if binary_platform["os"] == "android":
        log.info("Detected binary folder: %s" % binary_dir)
        binary_dir_legacy = binary_dir.replace("/storage/emulated/0",
                                               "/storage/emulated/legacy")
        if os.path.exists(binary_dir_legacy):
            binary_dir = binary_dir_legacy
            log.info("Using changed binary folder for Android: %s" %
                     binary_dir)

        app_id = android_get_current_appid()
        xbmc_data_path = os.path.join("/data", "data", app_id)
        if not os.path.exists(xbmc_data_path):
            log.info(
                "%s path does not exist, so using %s as xbmc_data_path" %
                (xbmc_data_path, xbmc.translatePath("special://xbmcbin/")))
            xbmc_data_path = xbmc.translatePath("special://xbmcbin/")

        if not os.path.exists(xbmc_data_path):
            log.info("%s path does not exist, so using %s as xbmc_data_path" %
                     (xbmc_data_path,
                      xbmc.translatePath("special://masterprofile/")))
            xbmc_data_path = xbmc.translatePath("special://masterprofile/")

        dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID,
                                       "bin",
                                       "%(os)s_%(arch)s" % binary_platform)
    else:
        dest_binary_dir = os.path.join(
            xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin",
            "%(os)s_%(arch)s" % binary_platform)

    binary_path = os.path.join(binary_dir, binary)
    dest_binary_path = os.path.join(dest_binary_dir, binary)

    log.info("Binary detection. Source: %s, Destination: %s" %
             (binary_path, dest_binary_path))

    if not os.path.exists(binary_path):
        # notify((getLocalizedString(30103) + " %(os)s_%(arch)s" % PLATFORM), time=7000)
        dialog_ok("LOCALIZE[30347];;" + "%(os)s_%(arch)s" % binary_platform)
        system_information()
        try:
            log.info("Source directory (%s):\n%s" %
                     (binary_dir, os.listdir(os.path.join(binary_dir, ".."))))
            log.info("Destination directory (%s):\n%s" %
                     (dest_binary_dir,
                      os.listdir(os.path.join(dest_binary_dir, ".."))))
        except Exception:
            pass
        return False, False

    if os.path.isdir(dest_binary_path):
        log.warning(
            "Destination path is a directory, expected previous binary file, removing..."
        )
        try:
            shutil.rmtree(dest_binary_path)
        except Exception as e:
            log.error("Unable to remove destination path for update: %s" % e)
            system_information()
            return False, False

    if not os.path.exists(dest_binary_path) or not os.path.exists(
            binary_path) or get_elementumd_checksum(
                dest_binary_path) != get_elementumd_checksum(
                    binary_path) or not filecmp.cmp(
                        dest_binary_path, binary_path, shallow=True):
        log.info("Updating elementum daemon...")
        try:
            os.makedirs(dest_binary_dir)
        except OSError:
            pass
        try:
            shutil.rmtree(dest_binary_dir)
        except Exception as e:
            log.error("Unable to remove destination path for update: %s" % e)
            system_information()
            pass
        try:
            shutil.copytree(binary_dir, dest_binary_dir)
        except Exception as e:
            log.error("Unable to copy to destination path for update: %s" % e)
            system_information()
            return False, False

    # Clean stale files in the directory, as this can cause headaches on
    # Android when they are unreachable
    dest_files = set(os.listdir(dest_binary_dir))
    orig_files = set(os.listdir(binary_dir))
    log.info("Deleting stale files %s" % (dest_files - orig_files))
    for file_ in (dest_files - orig_files):
        path = os.path.join(dest_binary_dir, file_)
        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.remove(path)

    log.info("Binary detection: [ Source: %s, Destination: %s ]" %
             (binary_path, dest_binary_path))
    return dest_binary_dir, ensure_exec_perms(dest_binary_path)
Пример #20
0
def doAssign():
    mediatype = getMediaType()

    try:
        path = sys.listitem.getfilename()
    except AttributeError:
        path = sys.listitem.getPath()

    use_elementum_path = False

    try:
        tmdbID = sys.listitem.getUniqueID('tmdb')
    except AttributeError:
        tmdbID = ""

    if tmdbID == "":
        if path.startswith("plugin://plugin.video.elementum"):
            use_elementum_path = True
            tmdbID = getTMDBidFromElementumPath(path)
            if not tmdbID:
                return

            if mediatype == 'season':
                season_number = getSeasonNumberFromElementumPath(path)
                if not season_number:
                    return

            if mediatype == 'episode':
                season_number = getSeasonNumberFromElementumPath(path)
                episode_number = getEpisodeNumberFromElementumPath(path)
                if not season_number or not episode_number:
                    return
        else:
            dbid = getDbId()
            if not dbid.isdigit():
                log.error("Kodi library ID is wrong %s" % dbid)
                xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                              ADDON.getLocalizedString(32016),
                                              xbmcgui.NOTIFICATION_WARNING,
                                              3000)
                return

    # we also can use plugin://plugin.video.elementum/torrents/
    file = xbmcgui.Dialog().browseSingle(
        1, ADDON.getLocalizedString(32010), 'files', '', False, False,
        'plugin://plugin.video.elementum/history/')

    if file == '':
        return

    try:
        parsed_url = urlparse(file)
        params = parse_qs(parsed_url.query)
        if 'infohash' in params:
            torrentid = params['infohash'][0]
        else:
            torrentid = params['resume'][0]
    except Exception as e:
        log.error("Could not get torrent info for %s: %s" % (file, e))
        xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007),
                                      ADDON.getLocalizedString(32015),
                                      xbmcgui.NOTIFICATION_WARNING, 3000)
        return

    if use_elementum_path:
        if mediatype == 'movie':
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/%s/%s" % (
                torrentid, mediatype, tmdbID)
        elif mediatype == 'season':
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/%s/%s" % (
                torrentid, tmdbID, mediatype, season_number)
        elif mediatype == 'episode':
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/season/%s/%s/%s" % (
                torrentid, tmdbID, season_number, mediatype, episode_number)
        log.info("Assigning torrent %s for: TMDBID=%s, MediaType=%s" %
                 (torrentid, tmdbID, mediatype))
    else:
        if tmdbID != "":
            url = "plugin://plugin.video.elementum/torrents/assign/%s/%s" % (
                torrentid, tmdbID)
            log.info("Assigning torrent %s for: TMDBID=%s, MediaType=%s" %
                     (torrentid, tmdbID, mediatype))
        else:
            url = "plugin://plugin.video.elementum/context/torrents/assign/%s/kodi/%s/%s" % (
                torrentid, mediatype, dbid)
            log.info("Assigning torrent %s for: DBID=%s, MediaType=%s" %
                     (torrentid, dbid, mediatype))

    xbmcgui.Dialog().notification(ADDON.getLocalizedString(32010),
                                  sys.listitem.getLabel(),
                                  xbmcgui.NOTIFICATION_INFO, 3000)

    log.info("Starting Elementum with: %s" % url)

    xbmc.Player().play(url)