################################################################################
# Copyright (C) 2019 drinfernoo #
# #
# This Program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2, or (at your option) #
# any later version. #
# #
# This Program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with XBMC; see the file COPYING. If not, write to #
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. #
# http://www.gnu.org/copyleft/gpl.html #
################################################################################
import xbmc
import xbmcgui
import glob
import os
import re
import sys
try:
from urllib.request import urlopen
from urllib.request import Request
except ImportError:
from urllib2 import urlopen
from urllib2 import Request
from resources.libs.common.config import CONFIG
def check_paths():
from resources.libs.common import logging
dialog = xbmcgui.Dialog()
logging.log("[Path Check] Started")
path = CONFIG.ADDON_PATH
pathclean = CONFIG.ADDON_PATH.replace('\\','/')
folderpath = pathclean.split('/')[-2]
if not CONFIG.ADDON_ID == folderpath:
dialog.ok(CONFIG.ADDONTITLE,
'[COLOR {0}]Please make sure that the plugin folder is the same as the add-on id.[/COLOR]'.format(CONFIG.COLOR2) + '\n' + '[COLOR {0}]Plugin ID:[/COLOR] [COLOR {1}]{2}[/COLOR]'.format(CONFIG.COLOR2, CONFIG.COLOR1, CONFIG.ADDON_ID) + '\n' + '[COLOR {0}]Plugin Folder:[/COLOR] [COLOR {1}]{2}[/COLOR]'.format(CONFIG.COLOR2, CONFIG.COLOR1, path))
logging.log("[Path Check] ADDON_ID and plugin folder doesnt match. {0} / {1} ".format(CONFIG.ADDON_ID, path))
else:
logging.log("[Path Check] Good!")
def check_build(name, ret):
from resources.libs.common import tools
response = tools.open_url(CONFIG.BUILDFILE)
if not response:
return False
link = response.text.replace('\n', '').replace('\r', '').replace('\t', '')\
.replace('gui=""', 'gui="http://"').replace('theme=""', 'theme="http://"')
match = re.compile('name="%s".+?ersion="(.+?)".+?rl="(.+?)".+?inor="(.+?)".+?ui="(.+?)".+?odi="(.+?)".+?heme="(.+?)".+?con="(.+?)".+?anart="(.+?)".+?review="(.+?)".+?dult="(.+?)".+?nfo="(.+?)".+?escription="(.+?)"' % name.replace('[', '\[').replace(']', '\]')).findall(link)
if len(match) > 0:
for version, url, minor, gui, kodi, theme, icon, fanart, preview, adult, info, description in match:
if ret == 'version':
return version
elif ret == 'url':
return url
elif ret == 'minor':
return minor
elif ret == 'gui':
return gui
elif ret == 'kodi':
return kodi
elif ret == 'theme':
return theme
elif ret == 'icon':
return icon
elif ret == 'fanart':
return fanart
elif ret == 'preview':
return preview
elif ret == 'adult':
return adult
elif ret == 'description':
return description
elif ret == 'info':
return info
elif ret == 'all':
return name, version, url, minor, gui, kodi, theme, icon, fanart, preview, adult, info, description
else:
return False
def check_info(name):
from resources.libs.common import tools
link = name.replace('\n', '').replace('\r', '').replace('\t', '')
match = re.compile('.+?ame="(.+?)".+?xtracted="(.+?)".+?ipsize="(.+?)".+?kin="(.+?)".+?reated="(.+?)".+?rograms="(.+?)".+?ideo="(.+?)".+?usic="(.+?)".+?icture="(.+?)".+?epos="(.+?)".+?cripts="(.+?)".+?inaries="(.+?)"').findall(link)
if len(match) > 0:
for name, extracted, zipsize, skin, created, programs, video, music, picture, repos, scripts, binaries in match:
return name, extracted, zipsize, skin, created, programs, video, music, picture, repos, scripts, binaries
else:
return False
def check_theme(name, theme, ret):
from resources.libs.common import tools
themeurl = check_build(name, 'theme')
response = tools.open_url(themeurl)
if not response:
return False
link = response.text.replace('\n', '').replace('\r', '').replace('\t', '')
match = re.compile('name="{0}".+?rl="(.+?)".+?con="(.+?)".+?anart="(.+?)".+?dult=(.+?).+?escription="(.+?)"'.format(theme.replace('[', '\[').replace(']', '\]'))).findall(link)
if len(match) > 0:
for url, icon, fanart, adult, description in match:
if ret == 'url':
return url
elif ret == 'icon':
return icon
elif ret == 'fanart':
return fanart
elif ret == 'adult':
return adult
elif ret == 'description':
return description
elif ret == 'all':
return name, theme, url, icon, fanart, adult, description
def check_wizard(ret):
from resources.libs.common import tools
response = tools.open_url(CONFIG.BUILDFILE)
if not response:
return False
link = response.text.replace('\n', '').replace('\r', '').replace('\t', '')
match = re.compile('id="{0}".+?ersion="(.+?)".+?ip="(.+?)"'.format(CONFIG.ADDON_ID)).findall(link)
if len(match) > 0:
for version, zip in match:
if ret == 'version':
return version
elif ret == 'zip':
return zip
elif ret == 'all':
return CONFIG.ADDON_ID, version, zip
else:
return False
def check_build_update():
from resources.libs.common import logging
from resources.libs.common import tools
from resources.libs.gui import window
response = tools.open_url(CONFIG.BUILDFILE)
if not response:
return
link = response.text.replace('\n', '').replace('\r', '').replace('\t', '')
match = re.compile('name="%s".+?ersion="(.+?)".+?con="(.+?)".+?anart="(.+?)"' % CONFIG.BUILDNAME.replace('[', '\[').replace(']', '\]')).findall(link)
if len(match) > 0:
version = match[0][0]
icon = match[0][1]
fanart = match[0][2]
CONFIG.set_setting('latestversion', version)
if version > CONFIG.BUILDVERSION:
if CONFIG.DISABLEUPDATE == 'false':
logging.log("[Check Updates] [Installed Version: {0}] [Current Version: {1}] Opening Update Window".format(CONFIG.BUILDVERSION, version))
window.show_update_window(CONFIG.BUILDNAME, CONFIG.BUILDVERSION, version, icon, fanart)
else:
logging.log("[Check Updates] [Installed Version: {0}] [Current Version: {1}] Update Window Disabled".format(CONFIG.BUILDVERSION, version))
else:
logging.log("[Check Updates] [Installed Version: {0}] [Current Version: {1}]".format(CONFIG.BUILDVERSION, version))
else:
logging.log("[Check Updates] ERROR: Unable to find build version in build text file", level=xbmc.LOGERROR)
def check_skin():
from resources.libs.common import logging
from resources.libs.common import tools
dialog = xbmcgui.Dialog()
logging.log("[Build Check] Invalid Skin Check Start")
gotoskin = False
if not CONFIG.DEFAULTSKIN == '':
if os.path.exists(os.path.join(CONFIG.ADDONS, CONFIG.DEFAULTSKIN)):
if dialog.yesno(CONFIG.ADDONTITLE,
"[COLOR {0}]It seems that the skin has been set back to [COLOR {1}]{2}[/COLOR]".format(CONFIG.COLOR2, CONFIG.COLOR1, CONFIG.SKIN[5:].title()) + '\n' + "Would you like to set the skin back to:[/COLOR]" + '\n' + '[COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, CONFIG.DEFAULTNAME)):
gotoskin = CONFIG.DEFAULTSKIN
gotoname = CONFIG.DEFAULTNAME
else:
logging.log("Skin was not reset")
CONFIG.set_setting('defaultskinignore', 'true')
gotoskin = False
else:
CONFIG.set_setting('defaultskin', '')
CONFIG.set_setting('defaultskinname', '')
CONFIG.DEFAULTSKIN = ''
CONFIG.DEFAULTNAME = ''
if CONFIG.DEFAULTSKIN == '':
skinname = []
skinlist = []
for folder in glob.glob(os.path.join(CONFIG.ADDONS, 'skin.*/')):
xml = "{0}/addon.xml".format(folder)
if os.path.exists(xml):
g = tools.read_from_file(xml).replace('\n', '').replace('\r', '').replace('\t', '')
match = tools.parse_dom(g, 'addon', ret='id')
match2 = tools.parse_dom(g, 'addon', ret='name')
logging.log("{0}: {1}".format(folder, str(match[0])))
if len(match) > 0:
skinlist.append(str(match[0]))
skinname.append(str(match2[0]))
else:
logging.log("ID not found for {0}".format(folder))
else:
logging.log("ID not found for {0}".format(folder))
if len(skinlist) > 0:
if len(skinlist) > 1:
if dialog.yesno(CONFIG.ADDONTITLE,
"[COLOR {0}]It seems that the skin has been set back to [COLOR {1}]{2}[/COLOR]".format(CONFIG.COLOR2, CONFIG.COLOR1, CONFIG.SKIN[5:].title()) + '\n' + "Would you like to view a list of avaliable skins?[/COLOR]"):
choice = dialog.select("Select skin to switch to!", skinname)
if choice == -1:
logging.log("Skin was not reset")
CONFIG.set_setting('defaultskinignore', 'true')
else:
gotoskin = skinlist[choice]
gotoname = skinname[choice]
else:
logging.log("Skin was not reset")
CONFIG.set_setting('defaultskinignore', 'true')
else:
if dialog.yesno(CONFIG.ADDONTITLE,
"[COLOR {0}]It seems that the skin has been set back to [COLOR {1}]{2}[/COLOR]".format(CONFIG.COLOR2, CONFIG.COLOR1, CONFIG.SKIN[5:].title()) + '\n' + "Would you like to set the skin back to:[/COLOR]" + '\n' + '[COLOR {0}]{1}[/COLOR]'.format(CONFIG.COLOR1, skinname[0])):
gotoskin = skinlist[0]
gotoname = skinname[0]
else:
logging.log("Skin was not reset")
CONFIG.set_setting('defaultskinignore', 'true')
else:
logging.log("No skins found in addons folder.")
CONFIG.set_setting('defaultskinignore', 'true')
gotoskin = False
if gotoskin:
from resources.libs import skin
if skin.switch_to_skin(gotoskin):
skin.look_and_feel_data('restore')
logging.log("[Build Check] Invalid Skin Check End")
def check_sources():
from resources.libs.common import logging
from resources.libs.common import tools
dialog = xbmcgui.Dialog()
progress_dialog = xbmcgui.DialogProgress()
if not os.path.exists(CONFIG.SOURCES):
logging.log_notify(CONFIG.ADDONTITLE,
"[COLOR {0}]No sources.xml File Found![/COLOR]".format(CONFIG.COLOR2))
return False
x = 0
bad = []
remove = []
a = tools.read_from_file(CONFIG.SOURCES)
temp = a.replace('\r', '').replace('\n', '').replace('\t', '')
match = re.compile('.+?').findall(temp)
if len(match) > 0:
match2 = re.compile('.+?(.+?).+?(.+?).+?(.+?).+?').findall(match[0])
progress_dialog.create(CONFIG.ADDONTITLE, "[COLOR {0}]Scanning Sources for Broken links[/COLOR]".format(CONFIG.COLOR2))
for name, path, sharing in match2:
x += 1
perc = int(tools.percentage(x, len(match2)))
progress_dialog.update(perc,
'' + '\n' + "[COLOR {0}]Checking [COLOR {1}]{2}[/COLOR]:[/COLOR]".format(CONFIG.COLOR2, CONFIG.COLOR1, name) + '\n' + "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, path))
working = tools.open_url(path, check=True)
if not working:
bad.append([name, path, sharing, working])
logging.log("Bad Sources: {0}".format(len(bad)))
if len(bad) > 0:
choice = dialog.yesno(CONFIG.ADDONTITLE, "[COLOR {0}]{1}[/COLOR][COLOR {2}] Source(s) have been found Broken".format(CONFIG.COLOR1, len(bad), CONFIG.COLOR2) + '\n' + "Would you like to Remove all or choose one by one?[/COLOR]",
yeslabel="[B][COLOR springgreen]Remove All[/COLOR][/B]",
nolabel="[B][COLOR red]Choose to Delete[/COLOR][/B]")
if choice == 1:
remove = bad
else:
for name, path, sharing, working in bad:
logging.log("{0} sources: {1}, {2}".format(name, path, working))
if dialog.yesno(CONFIG.ADDONTITLE,
"[COLOR {0}]{1}[/COLOR][COLOR {2}] was reported as non working".format(CONFIG.COLOR1, name, CONFIG.COLOR2) + '\n' + "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, path) + '\n' + "[COLOR {0}]{1}[/COLOR]".format(CONFIG.COLOR1, working),
yeslabel="[B][COLOR springgreen]Remove Source[/COLOR][/B]",
nolabel="[B][COLOR red]Keep Source[/COLOR][/B]"):
remove.append([name, path, sharing, working])
logging.log("Removing Source {0}".format(name))
else:
logging.log("Source {0} was not removed".format(name))
if len(remove) > 0:
for name, path, sharing, working in remove:
a = a.replace('\n\n{0}\n{1}\n{2}\n'.format(name, path, sharing), '')
logging.log("Removing Source {0}".format(name))
tools.write_to_file(CONFIG.SOURCES, str(a))
alive = len(match) - len(bad)
kept = len(bad) - len(remove)
removed = len(remove)
dialog.ok(CONFIG.ADDONTITLE,
"[COLOR {0}]Checking sources for broken paths has been completed".format(CONFIG.COLOR2) + '\n' + "Working: [COLOR {0}]{1}[/COLOR] | Kept: [COLOR {2}]{3}[/COLOR] | Removed: [COLOR {4}]{5}[/COLOR][/COLOR]".format(CONFIG.COLOR2, CONFIG.COLOR1, alive, CONFIG.COLOR1, kept, CONFIG.COLOR1, removed))
else:
logging.log("No Bad Sources to be removed.")
else:
logging.log_notify(CONFIG.ADDONTITLE,
"[COLOR {0}]All Sources Are Working[/COLOR]".format(CONFIG.COLOR2))
else:
logging.log("No Sources Found")
def check_repos():
from resources.libs.common import logging
from resources.libs.common import tools
progress_dialog = xbmcgui.DialogProgress()
progress_dialog.create(CONFIG.ADDONTITLE, '[COLOR {0}]Checking Repositories...[/COLOR]'.format(CONFIG.COLOR2))
badrepos = []
xbmc.executebuiltin('UpdateAddonRepos')
repolist = glob.glob(os.path.join(CONFIG.ADDONS, 'repo*'))
if len(repolist) == 0:
progress_dialog.close()
logging.log_notify(CONFIG.ADDONTITLE,
"[COLOR {0}]No Repositories Found![/COLOR]".format(CONFIG.COLOR2))
return
sleeptime = len(repolist)
start = 0
while start < sleeptime:
start += 1
if progress_dialog.iscanceled():
break
perc = int(tools.percentage(start, sleeptime))
progress_dialog.update(perc,
'\n' + '[COLOR {0}]Checking: [/COLOR][COLOR {1}]{2}[/COLOR]'.format(CONFIG.COLOR2, CONFIG.COLOR1, repolist[start-1].replace(CONFIG.ADDONS, '')[1:]))
xbmc.sleep(1000)
if progress_dialog.iscanceled():
progress_dialog.close()
logging.log_notify(CONFIG.ADDONTITLE,
"[COLOR {0}]Enabling Addons Cancelled[/COLOR]".format(CONFIG.COLOR2))
sys.exit()
progress_dialog.close()
logfile = logging.grab_log()
fails = re.compile('CRepositoryUpdateJob(.+?)failed').findall(logfile)
for item in fails:
logging.log("Bad Repository: {0} ".format(item))
brokenrepo = item.replace('[', '').replace(']', '').replace(' ', '').replace('/', '').replace('\\', '')
if brokenrepo not in badrepos:
badrepos.append(brokenrepo)
if len(badrepos) > 0:
msg = "[COLOR {0}]Below is a list of Repositories that did not resolve. This does not mean that they are Depreciated, sometimes hosts go down for a short period of time. Please do serveral scans of your repository list before removing a repository just to make sure it is broken.[/COLOR][CR][CR][COLOR {1}]".format(CONFIG.COLOR2, CONFIG.COLOR1)
msg += '[CR]'.join(badrepos)
msg += '[/COLOR]'
window.show_text_box("Viewing Broken Repositories", msg)
else:
logging.log_notify(CONFIG.ADDONTITLE,
"[COLOR {0}]All Repositories Working![/COLOR]".format(CONFIG.COLOR2))
def build_count():
from resources.libs import test
from resources.libs.common import tools
response = tools.open_url(CONFIG.BUILDFILE)
total = 0
count19 = 0
hidden = 0
adultcount = 0
if not response:
return total, count19, adultcount, hidden
link = response.text.replace('\n', '').replace('\r', '').replace('\t', '')
match = re.compile('name="(.+?)".+?odi="(.+?)".+?dult="(.+?)"').findall(link)
if len(match) > 0:
for name, kodi, adult in match:
if not CONFIG.SHOWADULT == 'true' and adult.lower() == 'yes':
hidden += 1
adultcount += 1
continue
if not CONFIG.DEVELOPER == 'true' and test.str_test(name):
hidden += 1
continue
kodi = int(float(kodi))
total += 1
if kodi == 19:
count19 += 1
return total, count19, adultcount, hidden