def singleNode(self, indexnumber, tagname, mediatype, itemtype):
        tagname = try_encode(tagname)
        cleantagname = try_decode(normalize_nodes(tagname))
        nodepath = try_decode(
            xbmc.translatePath("special://profile/library/video/"))
        nodeXML = "%splex_%s.xml" % (nodepath, cleantagname)
        path = "library://video/plex_%s.xml" % cleantagname
        if v.KODIVERSION >= 17:
            # Krypton
            windowpath = "ActivateWindow(Videos,%s,return)" % path
        else:
            windowpath = "ActivateWindow(Video,%s,return)" % path

        # Create the video node directory
        if not exists_dir(nodepath):
            # We need to copy over the default items
            copytree(
                src=try_decode(
                    xbmc.translatePath("special://xbmc/system/library/video")),
                dst=try_decode(
                    xbmc.translatePath("special://profile/library/video")))

        labels = {
            'Favorite movies': 30180,
            'Favorite tvshows': 30181,
            'channels': 30173
        }
        label = lang(labels[tagname])
        embynode = "Plex.nodes.%s" % indexnumber
        window('%s.title' % embynode, value=label)
        window('%s.path' % embynode, value=windowpath)
        window('%s.content' % embynode, value=path)
        window('%s.type' % embynode, value=itemtype)

        if exists(try_encode(nodeXML)):
            # Don't recreate xml if already exists
            return

        if itemtype == "channels":
            root = self.commonRoot(order=1,
                                   label=label,
                                   tagname=tagname,
                                   roottype=2)
            etree.SubElement(
                root, 'path'
            ).text = "plugin://plugin.video.plexkodiconnect/?id=0&mode=channels"
        else:
            root = self.commonRoot(order=1, label=label, tagname=tagname)
            etree.SubElement(root, 'order', {
                'direction': "ascending"
            }).text = "sorttitle"

        etree.SubElement(root, 'content').text = mediatype

        try:
            indent(root)
        except:
            pass
        etree.ElementTree(root).write(nodeXML, encoding="UTF-8")
Exemple #2
0
def getVideoFiles(plexId, params):
    """
    GET VIDEO EXTRAS FOR LISTITEM

    returns the video files for the item as plugin listing, can be used for
    browsing the actual files or videoextras etc.
    """
    if plexId is None:
        filename = params.get('filename')
        if filename is not None:
            filename = filename[0]
            import re
            regex = re.compile(r'''library/metadata/(\d+)''')
            filename = regex.findall(filename)
            try:
                plexId = filename[0]
            except IndexError:
                pass

    if plexId is None:
        log.info('No Plex ID found, abort getting Extras')
        return xbmcplugin.endOfDirectory(HANDLE)

    item = GetPlexMetadata(plexId)
    try:
        path = item[0][0][0].attrib['file']
    except:
        log.error('Could not get file path for item %s' % plexId)
        return xbmcplugin.endOfDirectory(HANDLE)
    # Assign network protocol
    if path.startswith('\\\\'):
        path = path.replace('\\\\', 'smb://')
        path = path.replace('\\', '/')
    # Plex returns Windows paths as e.g. 'c:\slfkjelf\slfje\file.mkv'
    elif '\\' in path:
        path = path.replace('\\', '\\\\')
    # Directory only, get rid of filename
    path = path.replace(basename(path), '')
    if exists_dir(path):
        for root, dirs, files in walk(path):
            for directory in dirs:
                item_path = try_encode(join(root, directory))
                li = ListItem(item_path, path=item_path)
                xbmcplugin.addDirectoryItem(handle=HANDLE,
                                            url=item_path,
                                            listitem=li,
                                            isFolder=True)
            for file in files:
                item_path = try_encode(join(root, file))
                li = ListItem(item_path, path=item_path)
                xbmcplugin.addDirectoryItem(handle=HANDLE,
                                            url=file,
                                            listitem=li)
            break
    else:
        log.error('Kodi cannot access folder %s' % path)
    xbmcplugin.endOfDirectory(HANDLE)
Exemple #3
0
    def fullTextureCacheSync(self):
        """
        This method will sync all Kodi artwork to textures13.db
        and cache them locally. This takes diskspace!
        """
        if not dialog('yesno', "Image Texture Cache", lang(39250)):
            return

        LOG.info("Doing Image Cache Sync")

        # ask to rest all existing or not
        if dialog('yesno', "Image Texture Cache", lang(39251)):
            LOG.info("Resetting all cache data first")
            # Remove all existing textures first
            path = tryDecode(translatePath("special://thumbnails/"))
            if exists_dir(path):
                rmtree(path, ignore_errors=True)
                self.restoreCacheDirectories()

            # remove all existing data from texture DB
            connection = kodiSQL('texture')
            cursor = connection.cursor()
            query = 'SELECT tbl_name FROM sqlite_master WHERE type=?'
            cursor.execute(query, ('table', ))
            rows = cursor.fetchall()
            for row in rows:
                tableName = row[0]
                if tableName != "version":
                    cursor.execute("DELETE FROM %s" % tableName)
            connection.commit()
            connection.close()

        # Cache all entries in video DB
        connection = kodiSQL('video')
        cursor = connection.cursor()
        # dont include actors
        query = "SELECT url FROM art WHERE media_type != ?"
        cursor.execute(query, ('actor', ))
        result = cursor.fetchall()
        total = len(result)
        LOG.info("Image cache sync about to process %s video images" % total)
        connection.close()

        for url in result:
            self.cacheTexture(url[0])
        # Cache all entries in music DB
        connection = kodiSQL('music')
        cursor = connection.cursor()
        cursor.execute("SELECT url FROM art")
        result = cursor.fetchall()
        total = len(result)
        LOG.info("Image cache sync about to process %s music images" % total)
        connection.close()
        for url in result:
            self.cacheTexture(url[0])
def test():
    import utils
    root = '/home/daniel/work/LbnlIon7350Interface/'
    paths = [downloads, json_dir, creds, meter_file, log_file]

    for path in paths:
        p = path(root)
        if not utils.exists_dir(p) and not utils.exists_file(p):
            utils.error('Path does not exist: %s' % (p))
        else:
            print('Path exists: %s' % (p))
Exemple #5
0
def test():
    import utils
    root = '/home/daniel/work/LbnlIon7350Interface/'
    paths = [downloads, json_dir, creds, meter_file, log_file]

    for path in paths:
        p = path(root)
        if not utils.exists_dir(p) and not utils.exists_file(p):
            utils.error('Path does not exist: %s' % (p))
        else:
            print('Path exists: %s' % (p))
Exemple #6
0
def getExtraFanArt(plexid, plexPath):
    """
    Get extrafanart for listitem
    will be called by skinhelper script to get the extrafanart
    for tvshows we get the plexid just from the path
    """
    log.debug('Called with plexid: %s, plexPath: %s' % (plexid, plexPath))
    if not plexid:
        if "plugin.video.plexkodiconnect" in plexPath:
            plexid = plexPath.split("/")[-2]
    if not plexid:
        log.error('Could not get a plexid, aborting')
        return xbmcplugin.endOfDirectory(HANDLE)

    # We need to store the images locally for this to work
    # because of the caching system in xbmc
    fanartDir = try_decode(translatePath(
        "special://thumbnails/plex/%s/" % plexid))
    if not exists_dir(fanartDir):
        # Download the images to the cache directory
        makedirs(fanartDir)
        xml = GetPlexMetadata(plexid)
        if xml is None:
            log.error('Could not download metadata for %s' % plexid)
            return xbmcplugin.endOfDirectory(HANDLE)

        api = API(xml[0])
        backdrops = api.artwork()['Backdrop']
        for count, backdrop in enumerate(backdrops):
            # Same ordering as in artwork
            fanartFile = try_encode(join(fanartDir, "fanart%.3d.jpg" % count))
            li = ListItem("%.3d" % count, path=fanartFile)
            xbmcplugin.addDirectoryItem(
                handle=HANDLE,
                url=fanartFile,
                listitem=li)
            copyfile(backdrop, try_decode(fanartFile))
    else:
        log.info("Found cached backdrop.")
        # Use existing cached images
        for root, dirs, files in walk(fanartDir):
            for file in files:
                fanartFile = try_encode(join(root, file))
                li = ListItem(file, path=fanartFile)
                xbmcplugin.addDirectoryItem(handle=HANDLE,
                                            url=fanartFile,
                                            listitem=li)
    xbmcplugin.endOfDirectory(HANDLE)
Exemple #7
0
    def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False):
        # Plex: reassign mediatype due to Kodi inner workings
        # How many items do we get at most?
        limit = window('fetch_pms_item_number')
        mediatypes = {
            'movie': 'movies',
            'show': 'tvshows',
            'photo': 'photos',
            'homevideo': 'homevideos',
            'musicvideos': 'musicvideos'
        }
        mediatype = mediatypes[mediatype]

        if viewtype == "mixed":
            dirname = "%s-%s" % (viewid, mediatype)
        else:
            dirname = viewid

        # Returns strings
        path = tryDecode(xbmc.translatePath(
            "special://profile/library/video/"))
        nodepath = tryDecode(xbmc.translatePath(
            "special://profile/library/video/Plex-%s/" % dirname))

        if delete:
            if exists_dir(nodepath):
                from shutil import rmtree
                rmtree(nodepath)
                log.info("Sucessfully removed videonode: %s." % tagname)
            return

        # Verify the video directory
        if not exists_dir(path):
            copytree(
                src=tryDecode(xbmc.translatePath(
                    "special://xbmc/system/library/video")),
                dst=tryDecode(xbmc.translatePath(
                    "special://profile/library/video")))

        # Create the node directory
        if mediatype != "photos":
            if not exists_dir(nodepath):
                # folder does not exist yet
                log.debug('Creating folder %s' % nodepath)
                makedirs(nodepath)

        # Create index entry
        nodeXML = "%sindex.xml" % nodepath
        # Set windows property
        path = "library://video/Plex-%s/" % dirname
        for i in range(1, indexnumber):
            # Verify to make sure we don't create duplicates
            if window('Plex.nodes.%s.index' % i) == path:
                return

        if mediatype == "photos":
            path = "plugin://plugin.video.plexkodiconnect?mode=browseplex&key=/library/sections/%s&id=%s" % (viewid, viewid)

        window('Plex.nodes.%s.index' % indexnumber, value=path)

        # Root
        if not mediatype == "photos":
            if viewtype == "mixed":
                specialtag = "%s-%s" % (tagname, mediatype)
                root = self.commonRoot(order=0,
                                       label=specialtag,
                                       tagname=tagname,
                                       roottype=0)
            else:
                root = self.commonRoot(order=0,
                                       label=tagname,
                                       tagname=tagname,
                                       roottype=0)
            try:
                indent(root)
            except:
                pass
            etree.ElementTree(root).write(nodeXML, encoding="UTF-8")

        nodetypes = {
            '1': "all",
            '2': "recent",
            '3': "recentepisodes",
            '4': "inprogress",
            '5': "inprogressepisodes",
            '6': "unwatched",
            '7': "nextepisodes",
            '8': "sets",
            '9': "genres",
            '10': "random",
            '11': "recommended",
            '12': "ondeck",
            '13': 'browsefiles'
        }
        mediatypes = {
            # label according to nodetype per mediatype
            'movies':
                {
                    '1': tagname,
                    '2': 30174,
                    # '4': 30177,
                    # '6': 30189,
                    '8': 39501,
                    '9': 135,
                    '10': 30227,
                    '11': 30230,
                    '12': 39500,
                    '13': 39702
                },

            'tvshows':
                {
                    '1': tagname,
                    # '2': 30170,
                    '3': 30174,
                    # '4': 30171,
                    # '5': 30178,
                    # '7': 30179,
                    '9': 135,
                    '10': 30227,
                    # '11': 30230,
                    '12': 39500,
                    '13': 39702
                },

            'homevideos':
                {
                    '1': tagname,
                    '2': 30251,
                    '11': 30253,
                    '13': 39702
                },

            'photos':
                {
                    '1': tagname,
                    '2': 30252,
                    '8': 30255,
                    '11': 30254,
                    '13': 39702
                },

            'musicvideos':
                {
                    '1': tagname,
                    '2': 30256,
                    '4': 30257,
                    '6': 30258,
                    '13': 39702
                }
        }

        # Key: nodetypes, value: sort order in Kodi
        sortorder = {
            '1': '3',  # "all",
            '2': '2',  # "recent",
            '3': '2',  # "recentepisodes",
            # '4': # "inprogress",
            # '5': # "inprogressepisodes",
            # '6': # "unwatched",
            # '7': # "nextepisodes",
            '8': '7',  # "sets",
            '9': '6',  # "genres",
            '10': '8',  # "random",
            '11': '5',  # "recommended",
            '12': '1',  # "ondeck"
            '13': '9'  # browse by folder
        }

        nodes = mediatypes[mediatype]
        for node in nodes:

            nodetype = nodetypes[node]
            nodeXML = "%s%s_%s.xml" % (nodepath, viewid, nodetype)
            # Get label
            stringid = nodes[node]
            if node != "1":
                label = lang(stringid)
                if not label:
                    label = xbmc.getLocalizedString(stringid)
            else:
                label = stringid

            # Set window properties
            if (mediatype == "homevideos" or mediatype == "photos") and nodetype == "all":
                # Custom query
                path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browseplex&type=%s"
                        % (viewid, mediatype))
            elif (mediatype == "homevideos" or mediatype == "photos"):
                # Custom query
                path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browseplex&type=%s&folderid=%s"
                        % (viewid, mediatype, nodetype))
            elif nodetype == "nextepisodes":
                # Custom query
                path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=nextup&limit=%s" % (tagname, limit)
            # elif v.KODIVERSION == 14 and nodetype == "recentepisodes":
            elif nodetype == "recentepisodes":
                # Custom query
                path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=recentepisodes&type=%s&tagname=%s&limit=%s"
                    % (viewid, mediatype, tagname, limit))
            elif v.KODIVERSION == 14 and nodetype == "inprogressepisodes":
                # Custom query
                path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=%s" % (tagname, limit)
            elif nodetype == 'ondeck':
                # PLEX custom query
                if mediatype == "tvshows":
                    path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=ondeck&type=%s&tagname=%s&limit=%s"
                        % (viewid, mediatype, tagname, limit))
                elif mediatype =="movies":
                    # Reset nodetype; we got the label
                    nodetype = 'inprogress'
            elif nodetype == 'browsefiles':
                path = 'plugin://plugin.video.plexkodiconnect?mode=browseplex&key=/library/sections/%s/folder' % viewid
            else:
                path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype)

            if mediatype == "photos":
                windowpath = "ActivateWindow(Pictures,%s,return)" % path
            else:
                if v.KODIVERSION >= 17:
                    # Krypton
                    windowpath = "ActivateWindow(Videos,%s,return)" % path
                else:
                    windowpath = "ActivateWindow(Video,%s,return)" % path

            if nodetype == "all":

                if viewtype == "mixed":
                    templabel = "%s-%s" % (tagname, mediatype)
                else:
                    templabel = label

                embynode = "Plex.nodes.%s" % indexnumber
                window('%s.title' % embynode, value=templabel)
                window('%s.path' % embynode, value=windowpath)
                window('%s.content' % embynode, value=path)
                window('%s.type' % embynode, value=mediatype)
            else:
                embynode = "Plex.nodes.%s.%s" % (indexnumber, nodetype)
                window('%s.title' % embynode, value=label)
                window('%s.path' % embynode, value=windowpath)
                window('%s.content' % embynode, value=path)

            if mediatype == "photos":
                # For photos, we do not create a node in videos but we do want the window props
                # to be created.
                # To do: add our photos nodes to kodi picture sources somehow
                continue

            if exists(tryEncode(nodeXML)):
                # Don't recreate xml if already exists
                continue

            # Create the root
            if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes', 'browsefiles') or mediatype == "homevideos"):
                # Folder type with plugin path
                root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname, roottype=2)
                etree.SubElement(root, 'path').text = path
                etree.SubElement(root, 'content').text = "episodes"
            else:
                root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname)
                if nodetype in ('recentepisodes', 'inprogressepisodes'):
                    etree.SubElement(root, 'content').text = "episodes"
                else:
                    etree.SubElement(root, 'content').text = mediatype

                # Elements per nodetype
                if nodetype == "all":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                
                elif nodetype == "recent":
                    etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"
                    etree.SubElement(root, 'limit').text = limit
                    if settings('MovieShowWatched') == 'false':
                        rule = etree.SubElement(root,
                                                'rule',
                                                {'field': "playcount",
                                                 'operator': "is"})
                        etree.SubElement(rule, 'value').text = "0"
                
                elif nodetype == "inprogress":
                    etree.SubElement(root, 'rule', {'field': "inprogress", 'operator': "true"})
                    etree.SubElement(root, 'limit').text = limit
                    etree.SubElement(
                        root,
                        'order',
                        {'direction': 'descending'}
                    ).text = 'lastplayed'

                elif nodetype == "genres":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                    etree.SubElement(root, 'group').text = "genres"
                
                elif nodetype == "unwatched":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                    rule = etree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"})
                    etree.SubElement(rule, 'value').text = "0"

                elif nodetype == "sets":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"
                    etree.SubElement(root, 'group').text = "tags"

                elif nodetype == "random":
                    etree.SubElement(root, 'order', {'direction': "ascending"}).text = "random"
                    etree.SubElement(root, 'limit').text = limit

                elif nodetype == "recommended":
                    etree.SubElement(root, 'order', {'direction': "descending"}).text = "rating"
                    etree.SubElement(root, 'limit').text = limit
                    rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
                    etree.SubElement(rule, 'value').text = "0"
                    rule2 = etree.SubElement(root, 'rule',
                        attrib={'field': "rating", 'operator': "greaterthan"})
                    etree.SubElement(rule2, 'value').text = "7"

                elif nodetype == "recentepisodes":
                    # Kodi Isengard, Jarvis
                    etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"
                    etree.SubElement(root, 'limit').text = limit
                    rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
                    etree.SubElement(rule, 'value').text = "0"

                elif nodetype == "inprogressepisodes":
                    # Kodi Isengard, Jarvis
                    etree.SubElement(root, 'limit').text = limit
                    rule = etree.SubElement(root, 'rule',
                        attrib={'field': "inprogress", 'operator':"true"})

            try:
                indent(root)
            except:
                pass
            etree.ElementTree(root).write(nodeXML, encoding="UTF-8")
Exemple #8
0
def main():

    # user input
    if not g_args.type:
        g_args.type = utils.read_string_input(msg="type",
                                              init_value=DEFAULT_TEMPLATE)
    if not g_args.output:
        g_args.output = utils.read_path_input(msg="file path")
    g_args.author = utils.read_string_input(msg="author",
                                            init_value=g_args.author)
    if not g_args.description:
        g_args.description = utils.read_string_input(
            msg="description", init_value=HEADER_DESCRIPTION)
    g_args.description = format_description(g_args.description)
    if g_args.type != "bash":
        g_args.copy_utils = utils.confirm("Copy utilities?",
                                          "y" if g_args.copy_utils else "n")

    template_path = utils.join_paths_str(g_args.script_dir,
                                         TEMPLATE_OPTIONS[g_args.type])

    if utils.exists_dir(g_args.output):
        print(f"Error: target path is a directory!")
        sys.exit(0)
    elif utils.exists_file(g_args.output):
        if not utils.confirm_delete_file(g_args.output, "n"):
            utils.exit("Aborted")

    out_folder = utils.get_file_path(g_args.output)
    out_file = utils.get_file_name(g_args.output)

    if not utils.exists_dir(out_folder):
        utils.make_dir(g_args.output)

    # copy template
    utils.copy_to(template_path, g_args.output)
    print(f"Created file {g_args.output}")

    if g_args.type == "class":
        utils.replace_file_text(g_args.output, CLASS_NAME, out_file)

    if g_args.type != "bash":
        if g_args.copy_utils:
            utils_folder = PY_UTILS_DIR
            out_py_utils_dir = utils.join_paths(out_folder, utils_folder)
            utils.make_dir(out_py_utils_dir)
            utils.copy_to(PY_UTILS_FILE, out_py_utils_dir)
            print(f"Created file {out_py_utils_dir}/{PY_UTILS_FILE}")
        else:
            print("""
            Important: Please make sure that python utils are available, i.e. inside PYTHONPATH.
            Clone repository via: git clone https://github.com/amplejoe/py_utils.git
            """)

    # header information
    date = utils.get_date_str()
    utils.replace_file_text(g_args.output, HEADER_DATE, date)
    utils.replace_file_text(g_args.output, HEADER_AUTHOR, g_args.author)
    if g_args.description:
        utils.replace_file_text(g_args.output, HEADER_DESCRIPTION,
                                g_args.description)