def Addon_List(enabled=True, inc_new=False): """ Return a list of enabled or disabled add-ons found in the database. CODE: Addon_List([enabled, inc_new]) AVAILABLE PARAMS: enabled - By default this is set to True which means you'll get a list of all the enabled add-ons found in addons*.db but if you want a list of all the disabled ones just set this to False. inc_new - This will also add any new add-on folders found on your system that aren't yet in the database (ie ones that have been recently been manually extracted but not scanned in). By default this is set to False. EXAMPLE CODE: enabled_list = Addon_List(enabled=True) disabled_list = Addon_List(enabled=False) my_return = '' for item in enabled_list: my_return += '[COLOR=lime]ENABLED:[/COLOR] %s\n' % item for item in disabled_list: my_return += '[COLOR=red]DISABLED:[/COLOR] %s\n' % item Text_Box('ADDON STATUS',my_return) ~""" from database import DB_Query from guitools import Text_Box from filetools import DB_Path_Check, Get_Contents enabled_list = [] disabled_list = [] addons_db = DB_Path_Check('addons') on_system = DB_Query(addons_db, 'SELECT addonID, enabled from installed') # Create a list of enabled and disabled add-ons already on system for item in on_system: if item["enabled"]: enabled_list.append(item["addonID"]) else: disabled_list.append(item["addonID"]) if inc_new: ADDONS = xbmc.translatePath('special://home/addons') my_addons = Get_Contents(path=ADDONS, exclude_list=['packages', 'temp']) for item in my_addons: addon_id = Get_Addon_ID(item) if not addon_id in enabled_list and not addon_id in disabled_list: disabled_list.append(addon_id) if enabled: return enabled_list else: return disabled_list
def Toggle_Addons(addon='all', enable=True, safe_mode=True, exclude_list=[], new_only=True, refresh=True, update_status=0): """ Send through either a list of add-on ids or one single add-on id. The add-ons sent through will then be added to the addons*.db and enabled or disabled (depending on state sent through). WARNING: If safe_mode is set to False this directly edits the addons*.db rather than using JSON-RPC. Although directly amending the db is a lot quicker there is no guarantee it won't cause severe problems in later versions of Kodi (this was created for v17). DO NOT set safe_mode to False unless you 100% understand the consequences! CODE: Toggle_Addons([addon, enable, safe_mode, exclude_list, new_only, refresh]) AVAILABLE PARAMS: (*) addon - This can be a list of addon ids, one single id or 'all' to enable/disable all. If enabling all you can still use the exclude_list for any you want excluded from this function. enable - By default this is set to True, if you want to disable the add-on(s) then set this to False. safe_mode - By default this is set to True which means the add-ons are enabled/disabled via JSON-RPC which is the method recommended by the XBMC foundation. Setting this to False will result in a much quicker function BUT there is no guarantee this will work on future versions of Kodi and it may even cause corruption in future versions. Setting to False is NOT recommended and you should ONLY use this if you 100% understand the risks that you could break multiple setups. exclude_list - Send through a list of any add-on id's you do not want to be included in this command. new_only - By default this is set to True so only newly extracted add-on folders will be enabled/disabled. This means that any existing add-ons which have deliberately been disabled by the end user are not affected. refresh - By default this is set to True, it will refresh the current container and also force a local update on your add-ons db. 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). EXAMPLE CODE: from systemtools import Refresh xbmc.executebuiltin('ActivateWindow(Videos, addons://sources/video/)') xbmc.sleep(2000) dialog.ok('DISABLE YOUTUBE','We will now disable YouTube (if installed)') koding.Toggle_Addons(addon='plugin.video.youtube', enable=False, safe_mode=True, exclude_list=[], new_only=False) koding.Refresh('container') xbmc.sleep(2000) dialog.ok('ENABLE YOUTUBE','When you click OK we will enable YouTube (if installed)') koding.Toggle_Addons(addon='plugin.video.youtube', enable=True, safe_mode=True, exclude_list=[], new_only=False) koding.Refresh('container') ~""" from __init__ import dolog from filetools import DB_Path_Check, Get_Contents from database import DB_Query from systemtools import Data_Type, Last_Error, Refresh, Set_Setting, Sleep_If_Function_Active, Timestamp Set_Setting('general.addonupdates', 'kodi_setting', '2') dolog('disabled auto updates for add-ons') kodi_ver = int(float(xbmc.getInfoLabel("System.BuildVersion")[:2])) addons_db = DB_Path_Check('addons') data_type = Data_Type(addon) state = int(bool(enable)) enabled_list = [] disabled_list = [] if kodi_ver >= 17: on_system = DB_Query(addons_db,'SELECT addonID, enabled from installed') # Create a list of enabled and disabled add-ons already on system enabled_list = Addon_List(enabled=True) disabled_list = Addon_List(enabled=False) # If addon has been sent through as a string we add into a list if data_type == 'unicode': addon = addon.encode('utf8') data_type = Data_Type(addon) if data_type == 'str' and addon!= 'all': addon = [addon] # Grab all the add-on ids from addons folder if addon == 'all': addon = [] ADDONS = xbmc.translatePath('special://home/addons') my_addons = Get_Contents(path=ADDONS, exclude_list=['packages','temp']) for item in my_addons: addon_id = Get_Addon_ID(item) addon.append(addon_id) # Find out what is and isn't enabled in the addons*.db temp_list = [] for addon_id in addon: if not addon_id in exclude_list and addon_id != '': dolog('CHECKING: %s'%addon_id) if addon_id in disabled_list and not new_only and enable: temp_list.append(addon_id) elif addon_id not in disabled_list and addon_id not in enabled_list: temp_list.append(addon_id) elif addon_id in enabled_list and not enable: temp_list.append(addon_id) elif addon_id in disabled_list and enable: temp_list.append(addon_id) addon = temp_list # If you want to bypass the JSON-RPC mode and directly modify the db (READ WARNING ABOVE!!!) if not safe_mode and kodi_ver >= 17: installedtime = Timestamp('date_time') insert_query = 'INSERT or IGNORE into installed (addonID , enabled, installDate) VALUES (?,?,?)' update_query = 'UPDATE installed SET enabled = ? WHERE addonID = ? ' insert_values = [addon, state, installedtime] try: for item in addon: DB_Query(addons_db, insert_query, [item, state, installedtime]) DB_Query(addons_db, update_query, [state, item]) except: dolog(Last_Error()) if refresh: Refresh() # Using the safe_mode (JSON-RPC) else: mydeps = [] final_enabled = [] if state: my_value = 'true' log_value = 'ENABLED' final_addons = [] else: my_value = 'false' log_value = 'DISABLED' final_addons = addon for my_addon in addon: # If enabling the add-on then we also check for dependencies and enable them first if state: dolog('Checking dependencies for : %s'%my_addon) dependencies = Dependency_Check(addon_id=my_addon, recursive=True) mydeps.append(dependencies) # if enable selected we traverse through the dependencies enabling addons with lowest amount of deps to highest if state: mydeps = sorted(mydeps, key=len) for dep in mydeps: counter = 0 for item in dep: enable_dep = True if counter == 0: final_addons.append(item) enable_dep = False elif item in final_enabled: enable_dep = False else: enable_dep = True if enable_dep: if not item in exclude_list and not item in final_enabled and not item in enabled_list: dolog('Attempting to enable: %s'%item) if Set_Setting(setting_type='addon_enable', setting=item, value = 'true'): dolog('%s now %s' % (item, log_value)) final_enabled.append(item) counter += 1 # Now the dependencies are enabled we need to enable the actual main add-ons for my_addon in final_addons: if not my_addon in final_enabled: dolog('Attempting to enable: %s'%my_addon) if Set_Setting(setting_type='addon_enable', setting=my_addon, value = my_value): dolog('%s now %s' % (my_addon, log_value)) final_enabled.append(addon) else: dolog('Already enabled, skipping: %s'%my_addon) if refresh: Refresh(['addons','container']) Set_Setting('general.addonupdates', 'kodi_setting', '%s'%update_status) #----------------------------------------------------------------
def Addon_Service(addons='all', mode='list', skip_service='all'): """ Send through an add-on id, list of id's or leave as the default which is "all". This will loop through the list of add-ons and return the ones which are run as services. This enable/disable feature will comment out the service lines, and does not stop a running service or start a service. This is designed more for if you've manually extracted a new add-on into your system and it isn't yet enabled. Occasionally if the add-ons have dependencies which are run as services then trying to enable them can cause Kodi to freeze. CODE: Addon_Service([addon,disable]) AVAILABLE PARAMS: addons - By default this is set to "all" but if there's a sepcific set of add-ons you want to disable the service for just send through the id's in the form of a list. mode - By default this is set to 'list' meaning you'll get a return of add-on folders which contain an instance of service in the add-on.xml. You can set this to "disable" to comment out the instances of service and similarly when you need to re-enable you can use "enable" and that will uncomment out the service item. Please note that by uncommenting the service will not automatically start - you'll need to reload the profile for that. skip_service - This function can fail if certain dependencies are run as a service, if they are causing problems you can send through the id or a list of id's which you want to disable the service for. This will comment out the service part in the addon.xml before attempting to enable the add-on. Don't forget to re-enable this if you want the service running. EXAMPLE CODE: dialog.ok('[COLOR gold]CHECKING FOR SERVICES[/COLOR]','We will now check for all add-ons installed which contain services') service_addons = Addon_Service(mode='list') my_text = 'List of add-ons running as a service:\n\n' for item in service_addons: my_text += item+'\n' koding.Text_Box('[COLOR gold]SERVICE ADDONS[/COLOR]',my_text) ~""" from filetools import Get_Contents, Text_File from systemtools import Data_Type from guitools import Text_Box service_addons = [] if addons=='all': addons = Get_Contents(path=ADDONS, exclude_list=['packages','temp'],full_path=False) else: if Data_Type(addons) == 'str': addons = [addons] if skip_service=='all': skip_service = addons else: if Data_Type(skip_service) == 'str': skip_service = [skip_service] service_line = '<extension point="xbmc.service"' for item in addons: addon_path = os.path.join(ADDONS,item,'addon.xml') if os.path.exists(addon_path) and item not in skip_service: content = Text_File(addon_path,'r') if service_line in content: xbmc.log('%s contains a service,'%item,2) for line in content.splitlines(): if service_line in line: if item not in service_addons: service_addons.append(item) if not (line.strip().startswith('<!--')) and (mode == 'disable'): replace_line = '<!--%s-->'%line Text_File(addon_path,'w',content.replace(line,replace_line)) break elif line.strip().startswith('<!--') and mode == 'enable': replace_line = line.replace(r'<!--','').replace(r'-->','') Text_File(addon_path,'w',content.replace(line,replace_line)) break return service_addons
def Toggle_Addons(addon='all', enable=True, safe_mode=True, exclude_list=[], new_only=True, refresh=True): """ Send through either a list of add-on ids or one single add-on id. The add-ons sent through will then be added to the addons*.db and enabled or disabled (depending on state sent through). WARNING: If safe_mode is set to False this directly edits the addons*.db rather than using JSON-RPC. Although directly amending the db is a lot quicker there is no guarantee it won't cause severe problems in later versions of Kodi (this was created for v17). DO NOT set safe_mode to False unless you 100% understand the consequences! CODE: Toggle_Addons([addon, enable, safe_mode, exclude_list, new_only, refresh]) AVAILABLE PARAMS: (*) addon - This can be a list of addon ids, one single id or 'all' to enable/disable all. If enabling all you can still use the exclude_list for any you want excluded from this function. enable - By default this is set to True, if you want to disable the add-on(s) then set this to False. safe_mode - By default this is set to True which means the add-ons are enabled/disabled via JSON-RPC which is the method recommended by the XBMC foundation. Setting this to False will result in a much quicker function BUT there is no guarantee this will work on future versions of Kodi and it may even cause corruption in future versions. Setting to False is NOT recommended and you should ONLY use this if you 100% understand the risks that you could break multiple setups. exclude_list - Send through a list of any add-on id's you do not want to be included in this command. new_only - By default this is set to True so only newly extracted add-on folders will be enabled/disabled. This means that any existing add-ons which have deliberately been disabled by the end user are not affected. refresh - By default this is set to True, it will refresh the current container and also force a local update on your add-ons db. EXAMPLE CODE: from systemtools import Refresh xbmc.executebuiltin('ActivateWindow(Videos, addons://sources/video/)') xbmc.sleep(2000) dialog.ok('DISABLE YOUTUBE','We will now disable YouTube (if installed)') koding.Toggle_Addons(addon='plugin.video.youtube', enable=False, safe_mode=True, exclude_list=[], new_only=False) koding.Refresh('container') xbmc.sleep(2000) dialog.ok('ENABLE YOUTUBE','When you click OK we will enable YouTube (if installed)') koding.Toggle_Addons(addon='plugin.video.youtube', enable=True, safe_mode=True, exclude_list=[], new_only=False) koding.Refresh('container') ~""" from __init__ import dolog from filetools import DB_Path_Check, Get_Contents from database import DB_Query from systemtools import Data_Type, Last_Error, Refresh, Set_Setting, Timestamp kodi_ver = int(float(xbmc.getInfoLabel("System.BuildVersion")[:2])) addons_db = DB_Path_Check('addons') data_type = Data_Type(addon) state = int(bool(enable)) enabled_list = [] disabled_list = [] if kodi_ver >= 17: on_system = DB_Query(addons_db, 'SELECT addonID, enabled from installed') # Create a list of enabled and disabled add-ons already on system enabled_list = Addon_List(enabled=True) disabled_list = Addon_List(enabled=False) # If addon has been sent through as a string we add into a list if data_type == 'unicode': addon = addon.encode('utf8') data_type = Data_Type(addon) if data_type == 'str' and addon != 'all': addon = [addon, ''] # Grab all the add-on ids from addons folder if addon == 'all': addon = [] ADDONS = xbmc.translatePath('special://home/addons') my_addons = Get_Contents(path=ADDONS, exclude_list=['packages', 'temp']) for item in my_addons: addon_id = Get_Addon_ID(item) addon.append(addon_id) # Find out what is and isn't enabled in the addons*.db temp_list = [] for addon_id in addon: if not addon_id in exclude_list and addon_id != '': dolog('CHECKING: %s' % addon_id) if addon_id in disabled_list and not new_only and enable: temp_list.append(addon_id) elif addon_id not in disabled_list and addon_id not in enabled_list: temp_list.append(addon_id) elif addon_id in enabled_list and not enable: temp_list.append(addon_id) elif addon_id in disabled_list and enable: temp_list.append(addon_id) addon = temp_list # If you want to bypass the JSON-RPC mode and directly modify the db (READ WARNING ABOVE!!!) if not safe_mode and kodi_ver >= 17: installedtime = Timestamp('date_time') insert_query = 'INSERT or IGNORE into installed (addonID , enabled, installDate) VALUES (?,?,?)' update_query = 'UPDATE installed SET enabled = ? WHERE addonID = ? ' insert_values = [addon, state, installedtime] try: for item in addon: DB_Query(addons_db, insert_query, [item, state, installedtime]) DB_Query(addons_db, update_query, [state, item]) except: dolog(Last_Error()) if refresh: Refresh() # Using the safe_mode (JSON-RPC) else: final_enabled = [] if state: my_value = 'true' log_value = 'ENABLED' else: my_value = 'false' log_value = 'DISABLED' for my_addon in addon: # If enabling the add-on then we also check for dependencies and enable them first if state: dolog('Checking dependencies for : %s' % my_addon) dependencies = Dependency_Check(addon_id=my_addon, recursive=True) # traverse through the dependencies in reverse order attempting to enable for item in reversed(dependencies): if not item in exclude_list and not item in final_enabled and not item in enabled_list: dolog('Attempting to enable: %s' % item) addon_set = Set_Setting(setting_type='addon_enable', setting=item, value='true') # If we've successfully enabled then we add to list so we can skip any other instances if addon_set: dolog('%s now %s' % (my_addon, log_value)) final_enabled.append(item) # Now the dependencies are enabled we need to enable the actual main add-on if not my_addon in final_enabled: addon_set = Set_Setting(setting_type='addon_enable', setting=my_addon, value=my_value) try: if addon_set: dolog('%s now %s' % (my_addon, log_value)) final_enabled.append(addon) except: pass if refresh: Refresh(['addons', 'container']) # NEW CODE NOT WORKING # from __init__ import dolog # from filetools import DB_Path_Check, Get_Contents # from database import DB_Query # from systemtools import Data_Type, Last_Error, Refresh, Set_Setting, Timestamp # from web import Validate_Link # addons_db = DB_Path_Check('addons') # data_type = Data_Type(addon) # state = int(bool(enable)) # enabled_list = [] # disabled_list = [] # if kodi_ver >= 17: # on_system = DB_Query(addons_db,'SELECT addonID, enabled from installed') # # Create a list of enabled and disabled add-ons already on system # enabled_list = Addon_List(enabled=True) # disabled_list = Addon_List(enabled=False) # # If addon has been sent through as a string we add into a list # if data_type == 'unicode': # addon = addon.encode('utf8') # data_type = Data_Type(addon) # if data_type == 'str' and addon!= 'all': # addon = [addon,''] # # Grab all the add-on ids from addons folder # if addon == 'all': # addon = [] # my_addons = Get_Contents(path=ADDONS, exclude_list=['packages','temp']) # for item in my_addons: # addon_id = Get_Addon_ID(item) # addon.append(addon_id) # # Find out what is and isn't enabled in the addons*.db # temp_list = [] # for addon_id in addon: # if not addon_id in exclude_list and addon_id != '': # dolog('CHECKING: %s'%addon_id) # # Check ALL addons and not just newly extracted not yet in db # if addon_id in disabled_list and not new_only and enable: # dolog('[1] Adding to temp list: %s'%addon_id) # temp_list.append(addon_id) # # Check addons not in our disabled list and also aren't in the enabled list # elif addon_id not in disabled_list and addon_id not in enabled_list: # dolog('[2] Adding to temp list: %s'%addon_id) # temp_list.append(addon_id) # # Check addons that are already enabled, get ready to disable # elif addon_id in enabled_list and not enable: # dolog('[3] Adding to temp list: %s'%addon_id) # temp_list.append(addon_id) # # Check addons which are disabled get ready to enable (same as first if function??) # elif addon_id in disabled_list and enable: # dolog('[4] Adding to temp list: %s'%addon_id) # temp_list.append(addon_id) # addon = temp_list # # If you want to bypass the JSON-RPC mode and directly modify the db (READ WARNING ABOVE!!!) # if not safe_mode and kodi_ver >= 17: # installedtime = Timestamp('date_time') # insert_query = 'INSERT or IGNORE into installed (addonID , enabled, installDate) VALUES (?,?,?)' # update_query = 'UPDATE installed SET enabled = ? WHERE addonID = ? ' # insert_values = [addon, state, installedtime] # try: # for item in addon: # DB_Query(addons_db, insert_query, [item, state, installedtime]) # DB_Query(addons_db, update_query, [state, item]) # except: # dolog(Last_Error()) # if refresh: # Refresh() # # Using the safe_mode (JSON-RPC) # else: # Refresh('addons') # xbmc.sleep(1000) # final_enabled = [] # if state: # my_value = 'true' # log_value = 'ENABLED' # else: # my_value = 'false' # log_value = 'DISABLED' # for my_addon in addon: # # If enabling the add-on then we also check for dependencies and enable them first # if state: # dolog('Checking dependencies for : %s'%my_addon) # dependencies = Dependency_Check(addon_id=my_addon, recursive=True) # dolog('Dependencies: %s'%dependencies) # # traverse through the dependencies in reverse order attempting to enable # for item in reversed(dependencies): # if not item in exclude_list and not item in final_enabled and not item in enabled_list: # dolog('Attempting to enable: %s'%item) # addon_set = Set_Setting(setting_type='addon_enable', setting=item, value = 'true') # # If we've successfully enabled then we add to list so we can skip any other instances # if addon_set: # dolog('%s now %s' % (my_addon, log_value)) # final_enabled.append(item) # # Now the dependencies are enabled we need to enable the actual main add-on # bad_repo = [] # for my_addon in addon: # if not my_addon in final_enabled: # ok = True # addon_set = True # if 'repo' in my_addon: # ok = Check_Repo(my_addon) # if not ok: # dolog('BAD REPO: %s IS NOT RESOLVING SO WE ARE NOT INSTALLING'%my_addon) # addon_set = False # if addon_set: # addon_set = Set_Setting(setting_type='addon_enable', setting=my_addon, value = my_value) # if addon_set: # dolog('%s now %s' % (my_addon, log_value)) # final_enabled.append(addon) # else: # bad_repo.append(my_addon) # if len(bad_repo) > 0: # final_list = 'The following repostitories are not resolving so have not been installed: ' # for item in bad_repo: # final_list += item+',' # final_list = final_list[:-1] # dialog.ok('[COLOR=gold]BAD REPOSITORIES FOUND[/COLOR]',final_list) # if refresh: # Refresh('container') # ----------------------------------------------------------------
def Addon_Service(addons='all', mode='list', skip_service=[]): """ Send through an add-on id, list of id's or leave as the default which is "all". This will loop through the list of add-ons and return the ones which are run as services. This enable/disable feature will comment out the service lines, and does not stop a running service or start a service. This is designed more for if you've manually extracted a new add-on into your system and it isn't yet enabled. Occasionally if the add-ons have dependencies which are run as services then trying to enable them can cause Kodi to freeze. CODE: Addon_Service([addon,disable]) AVAILABLE PARAMS: addons - By default this is set to "all" but if there's a sepcific set of add-ons you want to disable the service for just send through the id's in the form of a list. mode - By default this is set to 'list' meaning you'll get a return of add-on folders which contain an instance of service in the add-on.xml. You can set this to "disable" to comment out the instances of service and similarly when you need to re-enable you can use "enable" and that will uncomment out the service item. Please note that by uncommenting the service will not automatically start - you'll need to reload the profile for that. skip_service - When running the enable or disable mode you can choose to add a list of add-ons you'd like to skip the process for. Of course you may be thinking why would I send through a list of addons I want the service enabled/disabled for but then I also add them to the skip_service list to say DON'T enable/disable - it makes no sense?! Well you'd be correct that doesn't make any sense as presumably you've already filtered out the add-ons you don't want affected, this command is designed more for those who don't send through a list of add-ons and instead use the default "all" value for the addons paramater. This then makes it very easy to just skip a handful of add-on services and enable all others. EXAMPLE CODE: dialog.ok('CHECKING FOR SERVICES','We will now check for all add-ons installed which contain services') service_addons = Addon_Service(mode='list') my_text = 'List of add-ons running as a service:\n\n' for item in service_addons: my_text += item+'\n' koding.Text_Box('[COLOR gold]SERVICE ADDONS[/COLOR]',my_text) ~""" from filetools import Get_Contents, Physical_Path, Text_File from vartools import Data_Type from guitools import Text_Box service_addons = [] if addons == 'all': addons = Get_Contents(path=ADDONS, exclude_list=['packages', 'temp'], full_path=False) else: if Data_Type(addons) == 'str': addons = [addons] if Data_Type(skip_service) == 'str': skip_service = [skip_service] service_line = '<extension point="xbmc.service"' for item in addons: addon_path = os.path.join(ADDONS, item, 'addon.xml') content = Text_File(addon_path, 'r') if service_line in content: if item not in service_addons: service_addons.append(item) if mode != 'list': if not item in skip_service: for line in content.splitlines(): if service_line in line: if not (line.strip().startswith('<!--')) and ( mode == 'disable'): replace_line = '<!--%s-->' % line Text_File( addon_path, 'w', content.replace(line, replace_line)) break elif line.strip().startswith( '<!--') and mode == 'enable': replace_line = line.replace(r'<!--', '').replace( r'-->', '') Text_File( addon_path, 'w', content.replace(line, replace_line)) break return service_addons