Example #1
0
def Adult_Toggle(adult_list=[], disable=True, update_status=0):
    """
Remove/Enable a list of add-ons, these are put into a containment area until enabled again.

CODE: Adult_Toggle(adult_list, [disable, update_status])

AVAILABLE PARAMS:
            
    (*) adult_list  -  A list containing all the add-ons you want to be disabled.

    disable  -  By default this is set to true so any add-ons in the list sent
    through will be disabled. Set to False if you want to enable the hidden add-ons.

    update_status  - When running this function it needs to disable the
    auto-update of add-ons by Kodi otherwise it risks crashing. This
    update_status paramater is the state you want Kodi to revert back to
    once the toggle of add-ons has completed. By default this is set to 0
    which is auto-update. You can also choose 1 (notify of updates) or 2
    (disable auto updates).

~"""
    from filetools import End_Path, Move_Tree, Physical_Path

    adult_store  = Physical_Path("special://profile/addon_data/script.module.python.koding.aio/adult_store")
    disable_list = []
    if not xbmcvfs.exists(adult_store):
        xbmcvfs.mkdirs(adult_store)
    my_addons = Installed_Addons()
    if disable:
        for item in my_addons:
            if item != None:
                item = item["addonid"]
                if item in adult_list:
                    disable_list.append(item)

        Toggle_Addons(addon=disable_list, enable=False, safe_mode=True, refresh=True, update_status=update_status)
        for item in disable_list:
            try:
                addon_path = xbmcaddon.Addon(id=item).getAddonInfo("path")
            except:
                addon_path = Physical_Path(os.path.join(ADDONS,item))
            path_id = End_Path(addon_path)
            if os.path.exists(addon_path):
                Move_Tree(addon_path,os.path.join(adult_store,path_id))
    else:
        KODI_VER    = int(float(xbmc.getInfoLabel("System.BuildVersion")[:2]))
        addon_vault = []
        if os.path.exists(adult_store):
            for item in os.listdir(adult_store):
                store_dir = os.path.join(adult_store,item)
                addon_dir = os.path.join(ADDONS, item)
                if os.path.exists(store_dir):
                    Move_Tree(store_dir,addon_dir)
                    addon_vault.append(item)

        if KODI_VER >= 16:
            Toggle_Addons(addon=addon_vault, safe_mode=True, refresh=True, update_status=update_status)
        else:
            Refresh(['addons','repos'])
def _connect_to_db():
    """ internal command ~"""
    def dict_factory(cursor, row):
        d = {}
        for idx, col in enumerate(cursor.description):
            d[col[0]] = row[idx]
        return d

    xbmcvfs.mkdirs(profile_path)
    db_location = os.path.join(profile_path.decode('utf-8'), 'database.db')
    db_location = Physical_Path(db_location)
    dbcon = database.connect(db_location)
    dbcon.row_factory = dict_factory
    dbcur = dbcon.cursor()
    return (dbcur, dbcon)
def Download(url, dest, dp=None, timeout=5):
    """
This will download a file, currently this has to be a standard download link which doesn't require cookies/login.

CODE: Download(src,dst,[dp])
dp is optional, by default it is set to false

AVAILABLE PARAMS:

    (*) src  - This is the source file, the URL to your download. If you attempted to download an item but it's not behaving the way you think it should (e.g. a zip file not unzipping) then change the extension of the downloaded file to .txt and open up in a text editor. You'll most likely find it's just a piece of text that was returned from the URL you gave and it should have details explaining why it failed. Could be that's the wrong URL, it requires some kind of login, it only accepts certain user-agents etc.

    (*) dst  - This is the destination file, make sure it's a physical path and not "special://...". Also remember you need to add the actual filename to the end of the path, so if we were downloading something to the "downloads" folder and we wanted the file to be called "test.txt" we would use this path: dst = "downloads/test.txt". Of course the downloads folder would actually need to exist otherwise it would fail and based on this poor example the downloads folder would be at root level of your device as we've not specified a path prior to that so it just uses the first level that's accessible.

    dp - This is optional, if you pass through the dp function as a DialogProgress() then you'll get to see the progress of the download. If you choose not to add this paramater then you'll just get a busy spinning circle icon until it's completed. See the example below for a dp example.

    timeout - By default this is set to 5. This is the max. amount of time you want to allow for checking whether or
    not the url is a valid link and can be accessed via the system.

EXAMPLE CODE:
src = 'http://noobsandnerds.com/portal/Bits%20and%20bobs/Documents/user%20guide%20of%20the%20gyro%20remote.pdf'
dst = 'special://home/remote.pdf'
dp = xbmcgui.DialogProgress()
dp.create('Downloading File','Please Wait')
koding.Download(src,dst,dp)
dialog.ok('DOWNLOAD COMPLETE','Your download is complete, please check your home Kodi folder. There should be a new file called remote.pdf.')
dialog.ok('DELETE FILE','Click OK to delete the downloaded file.')
xbmcvfs.delete(dst)
~"""
    from filetools import Physical_Path
    dest = Physical_Path(dest)
    status = Validate_Link(url, timeout)
    if status >= 200 and status < 400:
        if Python_Version() < 2.7 and url.startswith('https'):
            url = url.replace('https', 'http')
        start_time = time.time()
        urllib.urlretrieve(
            url, dest,
            lambda nb, bs, fs: Download_Progress(nb, bs, fs, dp, start_time))
        return True
    else:
        return False
# You should have received a copy of the license along with this
# work. If not, see http://creativecommons.org/licenses/by-nc-nd/4.0.

# Please make sure you've read and understood the license, this code can NOT be used commercially
# and it can NOT be modified and redistributed. If you're found to be in breach of this license
# then any affected add-ons will be blacklisted and will not be able to work on the same system
# as any other add-ons which use this code. Thank you for your cooperation.

import os
import sys
import xbmc
import xbmcgui
from systemtools import Last_Error
from filetools import Physical_Path
dialog = xbmcgui.Dialog()
koding_path = Physical_Path(
    "special://home/addons/script.module.python.koding.aio")


#----------------------------------------------------------------
# TUTORIAL #
def Browse_To_Folder(header='Select the folder you want to use',
                     path='special://home'):
    """
As the title suggests this will bring up a dialog that allows the user to browse to a folder
and the path is then returned.

IMPORTANT: Do not confuse this with the Browse_To_File function

CODE: Browse_To_Folder(header, path)

AVAILABLE PARAMS:
Example #5
0
def Grab_Log(log_type='std', formatting='original', sort_order='reverse'):
    """
This will grab the log file contents, works on all systems even forked kodi.

CODE:  Grab_Log([log_type, formatting, sort_order])

AVAILABLE PARAMS:
    
    log_type    -  This is optional, if not set you will get the current log.
    If you would prefer the old log set this to 'old'

    formatting  -  By default you'll just get a default log but you can set
    this to 'warnings', 'notices', 'errors' to filter by only those error types.
    Notices will return in blue, warnings in gold and errors in red.
    You can use as many of the formatting values as you want, just separate by an
    underscore such as 'warnings_errors'. If using anything other than the
    default in here your log will returned in order of newest log activity first
    (reversed order). You can also use 'clean' as an option and that will just
    return the full log but with clean text formatting and in reverse order.

    sort_order   -  This will only work if you've sent through an argument other
    than 'original' for the formatting. By default the log will be shown in
    'reverse' order but you can set this to 'original' if you prefer ascending
    timestamp ordering like a normal log.

EXAMPLE CODE:
my_log = koding.Grab_Log()
dialog.ok('KODI LOG LOOP','Press OK to see various logging options, every 5 seconds it will show a new log style.')
koding.Text_Box('CURRENT LOG FILE (ORIGINAL)',my_log)
xbmc.sleep(5000)
my_log = koding.Grab_Log(formatting='clean', sort_order='reverse')
koding.Text_Box('CURRENT LOG FILE (clean in reverse order)',my_log)
xbmc.sleep(5000)
my_log = koding.Grab_Log(formatting='errors_warnings', sort_order='reverse')
koding.Text_Box('CURRENT LOG FILE (erros & warnings only - reversed)',my_log)
xbmc.sleep(5000)
old_log = koding.Grab_Log(log_type='old')
koding.Text_Box('OLD LOG FILE',old_log)
~"""
    from filetools import Physical_Path, Text_File
    log_path = Physical_Path('special://logpath/')
    logfilepath = os.listdir(log_path)
    finalfile = 0
    for item in logfilepath:
        cont = False
        if item.endswith('.log') and not item.endswith(
                '.old.log') and log_type == 'std':
            mylog = os.path.join(log_path, item)
            cont = True
        elif item.endswith('.old.log') and log_type == 'old':
            mylog = os.path.join(log_path, item)
            cont = True
        if cont:
            lastmodified = xbmcvfs.Stat(mylog).st_mtime()
            if lastmodified > finalfile:
                finalfile = lastmodified
                logfile = mylog

    logtext = Text_File(logfile, 'r')

    if formatting != 'original':
        logtext_final = ''

        with open(logfile) as f:
            log_array = f.readlines()
        log_array = [line.strip() for line in log_array]

        if sort_order == 'reverse':
            log_array = reversed(log_array)

        for line in log_array:
            if ('warnings' in formatting
                    or 'clean' in formatting) and 'WARNING:' in line:
                logtext_final += line.replace(
                    'WARNING:', '[COLOR=gold]WARNING:[/COLOR]') + '\n'
            if ('errors' in formatting
                    or 'clean' in formatting) and 'ERROR:' in line:
                logtext_final += line.replace(
                    'ERROR:', '[COLOR=red]ERROR:[/COLOR]') + '\n'
            if ('notices' in formatting
                    or 'clean' in formatting) and 'NOTICE:' in line:
                logtext_final += line.replace(
                    'NOTICE:', '[COLOR=dodgerblue]NOTICE:[/COLOR]') + '\n'

        logtext = logtext_final

    return logtext
def DB_Query(db_path, query, values=''):
    """
Open a database and either return an array of results with the SELECT SQL command or perform an action such as INSERT, UPDATE, CREATE.

CODE:  DB_Query(db_path, query, [values])

AVAILABLE PARAMS:

    (*) db_path -  the full path to the database file you want to access.
    
    (*) query   -  this is the actual db query you want to process, use question marks for values

    values  -  a list of values, even if there's only one value it must be sent through as a list item.

IMPORTANT: Directly accessing databases which are outside of your add-ons domain is very much frowned
upon. If you need to access a built-in kodi database (as shown in example below) you should always use
the JSON-RPC commands where possible. 

EXAMPLE CODE:
import filetools
dbpath = filetools.DB_Path_Check('addons')
db_table = 'addon'
kodi_version = int(float(xbmc.getInfoLabel("System.BuildVersion")[:2]))
if kodi_version >= 17:
    db_table = 'addons'
db_query = koding.DB_Query(db_path=dbpath, query='SELECT * FROM %s WHERE addonID LIKE ? AND addonID NOT LIKE ?'%db_table, values=['%youtube%','%script.module%'])
koding.Text_Box('DB SEARCH RESULTS',str(db_query))
~"""
    db_dict = []
    db_path = Physical_Path(db_path)
    con = database.connect(db_path)
    cur = con.cursor()

    if query.upper().startswith('SELECT'):
        if values == '':
            cur.execute(query)
        else:
            cur.execute(query, values)

        names = list(map(lambda x: x[0], cur.description))

        for rows in iter(cur.fetchmany, []):
            for row in rows:
                temp_dict = {}
                for idx, col in enumerate(cur.description):
                    temp_dict[col[0]] = row[idx]
                db_dict.append(temp_dict)
        return db_dict

    elif query.upper().startswith('CREATE'):
        cur.execute(query)
        con.commit()

# ANY NON SELECT QUERY (UPDATE, INSERT ETC.)
    else:
        try:
            if values == '':
                cur.executemany(query)
                con.commit()
            else:
                cur.executemany(query, values)
                con.commit()
        except:
            if values == '':
                cur.execute(query)
                con.commit()
            else:
                cur.execute(query, values)
                con.commit()

    cur.close()
import xbmcaddon
import xbmcgui
import xbmcvfs
from __init__ import Caller
from filetools import Physical_Path

# Put this in a try statement, when called from a service it will throw an error otherwise
try:
    try:
        ADDON_ID = xbmcaddon.Addon().getAddonInfo('id')
    except:
        ADDON_ID = Caller()

    AddonVersion = xbmcaddon.Addon(id=ADDON_ID).getAddonInfo('version')
    profile_path = xbmcaddon.Addon(id=ADDON_ID).getAddonInfo('profile')
    addon_db_path = Physical_Path(os.path.join(profile_path, 'database.db'))
except:
    pass

dbcur, dbcon = None, None
dialog = xbmcgui.Dialog()


#----------------------------------------------------------------
def _connect_to_db():
    """ internal command ~"""
    def dict_factory(cursor, row):
        d = {}
        for idx, col in enumerate(cursor.description):
            d[col[0]] = row[idx]
        return d
def Check_Repo(repo, show_busy=True, timeout=10):
    """
This will check the status of repo and return True if the repo is online or False
if it contains paths that are no longer accessible online.

IMPORTANT: If you're running an old version of Kodi which uses the old Python 2.6
(OSX and Android lower than Kodi 17 or a linux install with old Python installed on system)
you will get a return of False on https links regardless of their real status. This is due
to the fact Python 2.6 cannot access secure links. Any still using standard http links
will return the correct results.

CODE:  Check_Repo(repo, [show_busy, timeout])

AVAILABLE PARAMS:

    (*) repo  -  This is the name of the folder the repository resides in.
    You can either use the full path or just the folder name which in 99.99%
    of cases is the add-on id. If only using the folder name DOUBLE check first as
    there are a handful which have used a different folder name to the actual add-on id!

    show_busy - By default this is set to True and a busy dialog will show during the check

    timeout - By default this is set to 10 (seconds) - this is the maximum each request
    to the repo url will take before timing out and returning False.

EXAMPLE CODE:
repo_status = Check_Repo('special://xbmc',show_busy=False,timeout=10)
if repo_status:
    dialog.ok('REPO STATUS','The repository modules4all is: [COLOR=lime]ONLINE[/COLOR]')
else:
    dialog.ok('REPO STATUS','The repository modules4all is: [COLOR=red]OFFLINE[/COLOR]')
~"""
    import re

    from __init__ import dolog
    from filetools import Text_File
    from guitools import Show_Busy
    from web import Validate_Link
    xbmc.log('### CHECKING %s' % repo, 2)
    status = True
    if show_busy:
        Show_Busy()
    if not ADDONS in repo and not XBMC_PATH in repo:
        repo_path = os.path.join(ADDONS, repo)
    else:
        repo_path = repo
    repo_path = Physical_Path(repo_path)
    xbmc.log(repo_path, 2)
    repo_path = os.path.join(repo_path, 'addon.xml')
    xbmc.log(repo_path, 2)
    if os.path.exists(repo_path):
        content = Text_File(repo_path, 'r')
        md5_urls = re.findall(r'<checksum>(.+?)</checksum>', content,
                              re.DOTALL)
        for item in md5_urls:
            link_status = Validate_Link(item, timeout)
            dolog(item)
            dolog('STATUS: %s' % link_status)
            if link_status < 200 or link_status >= 400:
                status = False
                break
        if show_busy:
            Show_Busy(False)
        return status
    else:
        if show_busy:
            Show_Busy(False)
        return False
# Please make sure you've read and understood the license, this code can NOT be used commercially
# and it can NOT be modified and redistributed. If you're found to be in breach of this license
# then any affected add-ons will be blacklisted and will not be able to work on the same system
# as any other add-ons which use this code. Thank you for your cooperation.

import datetime
import os
import sys
import shutil
import xbmc
import xbmcaddon
import xbmcgui

from filetools import Physical_Path

HOME = Physical_Path('special://home')


#----------------------------------------------------------------
# TUTORIAL #
def ASCII_Check(sourcefile=HOME, dp=False):
    """
Return a list of files found containing non ASCII characters in the filename.

CODE: ASCII_Check([sourcefile, dp])

AVAILABLE PARAMS:
    
    sourcefile  -  The folder you want to scan, by default it's set to the
    Kodi home folder.