コード例 #1
0
def _lib_folders(section):
    section_dir = g.py2_decode(
        xbmc.translatePath(
            makeLegalFilename('/'.join([library_path(), section]))))
    return [
        g.py2_decode(
            makeLegalFilename('/'.join([section_dir,
                                        folder.decode('utf-8')])))
        for folder in xbmcvfs.listdir(section_dir)[0]
    ]
コード例 #2
0
def _get_status_icon():
    enabled = CACHE.get(f"{ADDONID}.service_enabled")
    daylight = CACHE.get(f"{ADDONID}.daylight")
    daylight_disable = ADDON.getSettingBool("daylightDisable")
    # xbmc.log("[script.service.hue] Current status: {}".format(daylight_disable))
    if daylight and daylight_disable:
        return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/daylight.png")  # Disabled by Daylight
    elif enabled:
        return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/enabled.png")  # Enabled
    return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/disabled.png")  # Disabled
コード例 #3
0
def make_legal_filename(filename, prefix='', suffix=''):
    """Returns a legal filename, from an arbitrary string input, as a string"""

    filename = ''.join((prefix, filename, suffix))
    try:
        filename = xbmcvfs.makeLegalFilename(filename)
    except AttributeError:
        xbmcvfs.makeLegalFilename = xbmc.makeLegalFilename
        filename = xbmcvfs.makeLegalFilename(filename)

    if filename.endswith('/'):
        filename = filename[:-1]
    return filename
コード例 #4
0
def _get_item(mediatype, filename):
    # To ensure compatibility with previously exported items,
    # make the filename legal
    fname = makeLegalFilename(filename)
    untranslated_path = os.path.dirname(g.py2_decode(fname))
    translated_path = os.path.dirname(g.py2_decode(xbmc.translatePath(fname)))
    shortname = os.path.basename(g.py2_decode(xbmc.translatePath(fname)))
    # We get the data from Kodi library using filters.
    # This is much faster than loading all episodes in memory

    # First build the path filter, we may have to search in both special and translated path
    path_filter = {'field': 'path', 'operator': 'startswith', 'value': translated_path} \
        if fname[:10] != 'special://' \
        else {'or': [
            {'field': 'path', 'operator': 'startswith', 'value': translated_path},
            {'field': 'path', 'operator': 'startswith', 'value': untranslated_path}
        ]}

    # Now build the all request and call the json-rpc function through common.get_library_items
    library_item = common.get_library_items(
        mediatype, {
            'and': [
                path_filter, {
                    'field': 'filename',
                    'operator': 'is',
                    'value': shortname
                }
            ]
        })[0]
    if not library_item:
        raise ItemNotFound
    return common.get_library_item_details(mediatype,
                                           library_item[mediatype + 'id'])
コード例 #5
0
def makeLegalFilename(filename):

    filename = xbmcvfs.makeLegalFilename(filename)
    if filename[-1:] == os.path.sep or filename[-1:] == "/":
        filename = filename[:-1]

    return filename
コード例 #6
0
def scan_library(path=''):
    """
    Start a Kodi library scanning in a specified folder to find new items
    :param path: Update only the library elements in the specified path (fast processing)
    """
    method = 'VideoLibrary.Scan'
    params = {'directory': xbmcvfs.makeLegalFilename(xbmcvfs.translatePath(path))}
    return json_rpc(method, params)
コード例 #7
0
 def start_update_kodi_library(self):
     if not self.scan_in_progress and not self.clean_in_progress:
         common.debug('Start Kodi library scan')
         self.scan_in_progress = True  # Set as in progress (avoid wait "started" callback it comes late)
         self.scan_awaiting = False
         # Update only the library elements in the add-on export folder
         # for faster processing (on Kodi 18.x) with a large library
         common.scan_library(makeLegalFilename(xbmc.translatePath(get_library_path())))
     else:
         self.scan_awaiting = True
コード例 #8
0
def export_item(item_task, library_home):
    """Create strm file for an item and add it to the library"""
    # Paths must be legal to ensure NFS compatibility
    destination_folder = g.py2_decode(
        makeLegalFilename('/'.join(
            [library_home, item_task['section'], item_task['destination']])))
    _create_destination_folder(destination_folder)
    if item_task['is_strm']:
        export_filename = g.py2_decode(
            makeLegalFilename('/'.join(
                [destination_folder, item_task['filename'] + '.strm'])))
        _add_to_library(item_task['videoid'], export_filename,
                        (item_task['nfo_data'] is not None))
        _write_strm_file(item_task, export_filename)
    if item_task['nfo_data'] is not None:
        nfo_filename = g.py2_decode(
            makeLegalFilename('/'.join(
                [destination_folder, item_task['filename'] + '.nfo'])))
        _write_nfo_file(item_task['nfo_data'], nfo_filename)
    common.debug('Exported {}', item_task['title'])
コード例 #9
0
 def update_kodi_library(self, data=None):  # pylint: disable=unused-argument
     # Update only the elements in the addon export folder for faster processing with a large library (on Kodi 18.x)
     # If a scan is already in progress, the scan is delayed until onScanFinished event
     if not self.scan_in_progress:
         common.debug(
             'Kodi library update requested from library auto-update')
         self.scan_awaiting = False
         common.scan_library(
             makeLegalFilename(
                 xbmc.translatePath(kodi_library.library_path())))
     else:
         self.scan_awaiting = True
コード例 #10
0
def clean_library(show_dialog=True, path=''):
    """
    Start a Kodi library cleaning to remove non-existing items
    :param show_dialog: True a progress dialog is shown
    :param path: Clean only the library elements in the specified path (fast processing)
    """
    method = 'VideoLibrary.Clean'
    params = {'content': 'video',
              'showdialogs': show_dialog}
    if path:
        params['directory'] = xbmcvfs.makeLegalFilename(xbmcvfs.translatePath(path))
    return json_rpc(method, params)
コード例 #11
0
def build_menu(base_url, addon_handle):
    status_item = ListItem(_("Hue Status: ") + _get_status())
    status_icon = _get_status_icon()
    if status_icon:
        status_item.setArt({"icon": status_icon})
        xbmc.log(f"[script.service.hue] status_icon: {status_icon}")

    settings_item = ListItem(_("Settings"))
    settings_item.setArt({"icon": xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/settings.png")})

    xbmcplugin.addDirectoryItem(addon_handle, base_url + "/actions?light_group_id=1&action=menu", ListItem(_("Video Actions")), True)
    xbmcplugin.addDirectoryItem(addon_handle, base_url + "/actions?light_group_id=2&action=menu", ListItem(_("Audio Actions")), True)
    xbmcplugin.addDirectoryItem(addon_handle, base_url + "?toggle", status_item)
    xbmcplugin.addDirectoryItem(addon_handle, base_url + "?settings", settings_item)

    xbmcplugin.endOfDirectory(handle=addon_handle, cacheToDisc=False)
コード例 #12
0
def _get_item_details_from_kodi(mediatype, file_path):
    """Get a Kodi library item with details (from Kodi database) by searching with the file path"""
    # To ensure compatibility with previously exported items, make the filename legal
    file_path = makeLegalFilename(file_path)
    dir_path = os.path.dirname(G.py2_decode(xbmc.translatePath(file_path)))
    filename = os.path.basename(G.py2_decode(xbmc.translatePath(file_path)))
    # We get the data from Kodi library using filters, this is much faster than loading all episodes in memory.
    if file_path[:10] == 'special://':
        # If the path is special, search with real directory path and also special path
        special_dir_path = os.path.dirname(G.py2_decode(file_path))
        path_filter = {
            'or': [{
                'field': 'path',
                'operator': 'startswith',
                'value': dir_path
            }, {
                'field': 'path',
                'operator': 'startswith',
                'value': special_dir_path
            }]
        }
    else:
        path_filter = {
            'field': 'path',
            'operator': 'startswith',
            'value': dir_path
        }
    # Now build the all request and call the json-rpc function through get_library_items
    library_items = get_library_items(
        mediatype, {
            'and': [
                path_filter, {
                    'field': 'filename',
                    'operator': 'is',
                    'value': filename
                }
            ]
        })
    if not library_items:
        raise ItemNotFound
    return get_library_item_details(mediatype,
                                    library_items[0][mediatype + 'id'])
コード例 #13
0
def clean_library(show_dialog=False, path=''):
    method = 'VideoLibrary.Clean'
    params = {'content': 'video', 'showdialogs': show_dialog}
    if path:
        params['directory'] = xbmcvfs.makeLegalFilename(
            xbmcvfs.translatePath(path))

    while xbmc.getCondVisibility(
            'Library.IsScanningVideo') or xbmc.getCondVisibility(
                'Library.IsScanningMusic'):
        xbmc.Monitor().waitForAbort(1)

    result = json_rpc(method, params)

    while xbmc.getCondVisibility(
            'Library.IsScanningVideo') or xbmc.getCondVisibility(
                'Library.IsScanningMusic'):
        xbmc.Monitor().waitForAbort(1)

    return result
コード例 #14
0
def remove_item(item_task, library_home=None):
    """Remove an item from the library and delete if from disk"""
    # pylint: disable=unused-argument, broad-except

    common.info('Removing {} from library', item_task['title'])

    exported_filename = g.py2_decode(xbmc.translatePath(item_task['filepath']))
    videoid = item_task['videoid']
    common.debug('VideoId: {}', videoid)
    try:
        parent_folder = g.py2_decode(
            xbmc.translatePath(os.path.dirname(exported_filename)))
        if xbmcvfs.exists(exported_filename):
            xbmcvfs.delete(exported_filename)
        else:
            common.warn('Cannot delete {}, file does not exist',
                        exported_filename)
        # Remove the NFO files if exists
        nfo_file = os.path.splitext(exported_filename)[0] + '.nfo'
        if xbmcvfs.exists(nfo_file):
            xbmcvfs.delete(nfo_file)
        dirs, files = xbmcvfs.listdir(parent_folder)
        tvshow_nfo_file = g.py2_decode(
            makeLegalFilename('/'.join([parent_folder, 'tvshow.nfo'])))
        # Remove tvshow_nfo_file only when is the last file
        # (users have the option of removing even single seasons)
        if xbmcvfs.exists(tvshow_nfo_file) and not dirs and len(files) == 1:
            xbmcvfs.delete(tvshow_nfo_file)
            # Delete parent folder
            xbmcvfs.rmdir(parent_folder)
        # Delete parent folder when empty
        if not dirs and not files:
            xbmcvfs.rmdir(parent_folder)

        _remove_videoid_from_db(videoid)
    except ItemNotFound:
        common.warn('The video with id {} not exists in the database', videoid)
    except Exception as exc:
        import traceback
        common.error(g.py2_decode(traceback.format_exc(), 'latin-1'))
        ui.show_addon_error_info(exc)
コード例 #15
0
def purge():
    """Purge all items exported to Kodi library and delete internal library database"""
    common.info('Purging internal database and kodi library')
    for videoid_value in g.SHARED_DB.get_movies_id_list():
        videoid = common.VideoId.from_path(
            [common.VideoId.MOVIE, videoid_value])
        execute_library_tasks(videoid, [remove_item],
                              common.get_local_string(30030))
    for videoid_value in g.SHARED_DB.get_tvshows_id_list():
        videoid = common.VideoId.from_path(
            [common.VideoId.SHOW, videoid_value])
        execute_library_tasks(videoid, [remove_item],
                              common.get_local_string(30030))
    # If for some reason such as improper use of the add-on, unexpected error or other
    # has caused inconsistencies with the contents of the database or stored files,
    # make sure that everything is removed
    g.SHARED_DB.purge_library()
    for folder_name in [FOLDER_MOVIES, FOLDER_TV]:
        section_dir = xbmc.translatePath(
            makeLegalFilename('/'.join([library_path(), folder_name])))
        common.delete_folder_contents(section_dir, delete_subfolders=True)
コード例 #16
0
def get_previously_exported_items():
    """Return a list of movie or tvshow VideoIds for items that were exported in
    the old storage format"""
    result = []
    videoid_pattern = re.compile('video_id=(\\d+)')
    for folder in _lib_folders(FOLDER_MOVIES) + _lib_folders(FOLDER_TV):
        for filename in xbmcvfs.listdir(folder)[1]:
            filepath = g.py2_decode(
                makeLegalFilename('/'.join([folder, filename])))
            if filepath.endswith('.strm'):
                common.debug('Trying to migrate {}', filepath)
                try:
                    # Only get a VideoId from the first file in each folder.
                    # For shows, all episodes will result in the same VideoId
                    # and movies only contain one file
                    result.append(_get_root_videoid(filepath, videoid_pattern))
                except MetadataNotAvailable:
                    common.warn('Metadata not available, item skipped')
                except (AttributeError, IndexError):
                    common.warn('Item does not conform to old format')
                break
    return result
コード例 #17
0
ファイル: filetools.py プロジェクト: shlibidon/addon
def makeLegalFilename(path, trans_none=''):
    """
    Kodi 19: xbmc.makeLegalFilename is deprecated and might be removed in future kodi versions. Please use xbmcvfs.makeLegalFilename instead.
    @param path: cadena a convertir platform specific
    @type path: str
    @rtype: str
    @return: devuelve la cadena con el path ajustado
    """
    if not path or not isinstance(path, (unicode, basestring, bytes)):
        if path is None: path = trans_none
        return path

    if PY3 and xbmc_vfs:
        if PY3 and isinstance(path, bytes):
            path = path.decode(fs_encoding)
        path = xbmcvfs.makeLegalFilename(path)
        if isinstance(path, bytes):
            path = path.decode(fs_encoding)

    elif KODI:
        path = xbmc.makeLegalFilename(path)

    return path
コード例 #18
0
def make_legal_filename(path):
    from resources.lib.system import SYSTEM_VERSION
    if SYSTEM_VERSION > 18:
        return xbmcvfs.makeLegalFilename(path)
    return xbmc.makeLegalFilename(path)
コード例 #19
0
def recycle(source, dest_folder):
    """Move a file to a new destination. Will create destination if it does not exist.

    Example:
        result = recycle(a, b)

    :type source: unicode
    :param source: the source path (absolute)
    :type dest_folder: unicode
    :param dest_folder: the destination path (absolute)
    :rtype: bool
    :return: True if (all stacked) files were moved, False otherwise
    """
    paths = split_stack(source)
    files_moved_successfully = 0
    dest_folder = xbmcvfs.makeLegalFilename(dest_folder)

    for p in paths:
        debug(f"Attempting to move {p} to {dest_folder}.")
        if xbmcvfs.exists(p):
            if not xbmcvfs.exists(dest_folder):
                if xbmcvfs.mkdirs(dest_folder):
                    debug(f"Created destination {dest_folder}.")
                else:
                    debug(f"Destination {dest_folder} could not be created.", xbmc.LOGERROR)
                    return False

            new_path = os.path.join(dest_folder, os.path.basename(p))

            if xbmcvfs.exists(new_path):
                debug("A file with the same name already exists in the holding folder. Checking file sizes.")
                existing_file = xbmcvfs.File(new_path)
                file_to_move = xbmcvfs.File(p)
                if file_to_move.size() > existing_file.size():
                    debug("This file is larger than the existing file. Replacing it with this one.")
                    existing_file.close()
                    file_to_move.close()
                    if bool(xbmcvfs.delete(new_path) and bool(xbmcvfs.rename(p, new_path))):
                        files_moved_successfully += 1
                    else:
                        return False
                else:
                    debug("This file isn't larger than the existing file. Deleting it instead of moving.")
                    existing_file.close()
                    file_to_move.close()
                    if bool(xbmcvfs.delete(p)):
                        files_moved_successfully += 1
                    else:
                        return False
            else:
                debug(f"Moving {p} to {new_path}.")
                move_success = bool(xbmcvfs.rename(p, new_path))
                copy_success, delete_success = False, False
                if not move_success:
                    debug("Move failed, falling back to copy and delete.", xbmc.LOGWARNING)
                    copy_success = bool(xbmcvfs.copy(p, new_path))
                    if copy_success:
                        debug("Copied successfully, attempting delete of source file.")
                        delete_success = bool(xbmcvfs.delete(p))
                        if not delete_success:
                            debug("Could not remove source file. Please remove the file manually.", xbmc.LOGWARNING)
                    else:
                        debug("Copying failed, please make sure you have appropriate permissions.", xbmc.LOGFATAL)
                        return False

                if move_success or (copy_success and delete_success):
                    files_moved_successfully += 1

        else:
            debug(f"File {p} is no longer available.", xbmc.LOGWARNING)

    return len(paths) == files_moved_successfully
コード例 #20
0
def join_folders_paths(*args):
    """Join multiple folder paths in a safe way"""
    # Avoid the use of os.path.join, in some cases with special chars like % break the path
    return G.py2_decode(makeLegalFilename('/'.join(args)))