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:
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.