def update_addons(quiet=True): from distutils.version import LooseVersion if not quiet: kodi.open_busy_dialog() sources = DB.query("SELECT addon_id, source FROM install_history") update_count = 0 for source in sources: addon_id = source[0] source = json.loads(source[1]) if kodi.get_condition_visiblity("System.HasAddon(%s)" % addon_id): if source['type'] == SOURCES.ZIP: url, filename, full_name, version = github.find_zip(source['user'], addon_id) current_version = kodi.get_addon(addon_id).getAddonInfo('version') if LooseVersion(version) > LooseVersion(current_version): GitHub_Installer(addon_id, url, full_name, kodi.vfs.join("special://home", "addons"), False, quiet) update_count += 1 elif source['type'] == SOURCES.REPO: full_name = sources['user'] + '/' + sources['repo'] xml_str = github.find_xml(full_name) xml = BeautifulSoup(xml_str) addon = xml.find('addon') current_version = kodi.get_addon(addon_id).getAddonInfo('version') if LooseVersion(addon['version']) > LooseVersion(current_version): GitHub_Installer(addon_id, source['url'], full_name, kodi.vfs.join("special://home", "addons"), True, quiet) update_count += 1 if not quiet: kodi.close_busy_dialog() if update_count > 0: kodi.notify("Update complete",'Some addons may require restarting kodi.') else: kodi.notify("Update complete",'No updates found.')
def handel_error(self, error, response, request_args, request_kwargs): if response.status_code == 401: traceback.print_stack() kodi.close_busy_dialog() raise githubException("Unauthorized: %s" % error) elif response.status_code == 403 and 'X-RateLimit-Reset' in response.headers: import time retry = int(response.headers['X-RateLimit-Reset']) - int( time.time()) for delay in range(retry, 0, -1): kodi.notify("API Rate limit exceeded", "Retry in %s seconds(s)" % delay, timeout=1000) kodi.sleep(1000) return self.request(*request_args, **request_kwargs) elif response.status_code == 422 and 'Only the first 1000' in response.text: kodi.handel_error('Result count exceeds API limit.', 'Try different search or result filter.') kodi.close_busy_dialog() traceback.print_stack() else: kodi.close_busy_dialog() traceback.print_stack() raise githubException("Status %s: %s" % (response.status_code, response.text))
def onInit(self): response = request_code() self.device_code = response['device_code'] self.user_code = response['user_code'] self.timeout = int(response['expires_in']) self.getControl(CONTROLS.CODE).setLabel(self.user_code) for tick in range(self.timeout, 0, -1): if tick == 0 or self._abort: break width = (float(tick) / self.timeout) * 596 self.getControl(CONTROLS.PROGRESS).setWidth(int(width)) if (tick % 5) == 0: r = poll_credentials(self.device_code) if r: client_id = r['client_id'] client_secret = r['client_secret'] token = request_token(client_id, client_secret, self.device_code) kodi.set_setting('realdebrid_client_id', client_id, addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_client_secret', client_secret, addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_token', token['access_token'], addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_refresh_token', token['refresh_token'], addon_id='script.module.scrapecore') kodi.notify("RealDebrid Authorization", "Success!") self._close() return kodi.sleep(1000) self.close()
def onInit(self): response = request_code() self.device_code = response['device_code'] self.user_code = response['user_code'] self.timeout = int(response['expires_in']) self.getControl(CONTROLS.CODE).setLabel(self.user_code) for tick in range(self.timeout, 0,-1): if tick == 0 or self._abort: break width = (float(tick) / self.timeout) * 596 self.getControl(CONTROLS.PROGRESS).setWidth(int(width)) if (tick % 5) == 0: r = poll_credentials(self.device_code) if r: client_id = r['client_id'] client_secret = r['client_secret'] token = request_token(client_id, client_secret, self.device_code) kodi.set_setting('realdebrid_client_id', client_id, addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_client_secret', client_secret, addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_token', token['access_token'], addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_refresh_token', token['refresh_token'], addon_id='script.module.scrapecore') kodi.notify("RealDebrid Authorization", "Success!") self._close() return kodi.sleep(1000) self.close()
def master_control(): options = [ "Send to Master Control", "Stream with Master Control", "Master Control Queue" ] c = kodi.dialog_select("Master Control Menu", options) if c is False: return if c == 2: kodi.execute_url("plugin://master.control?mode=queue") elif c == 1: from scrapecore import scrapers resolved_url = scrapers.get_scraper_by_name( kodi.args['service']).resolve_url(kodi.args['raw_url']) if not resolved_url: return from mastercontrol import api as master_control stream_url = master_control.get_streaming_url(resolved_url) kodi.play_url(stream_url) elif c == 0: ids = kodi.arg('ids', decode='json') from commoncore import trakt from mastercontrol import api as master_control if kodi.args['media'] == 'movie': media = 'movie' title = "%s (%s)" % (kodi.args['title'], kodi.args['year']) filename = kodi.vfs.clean_file_name(title) destination = '' else: media = 'tvshow' destination = kodi.vfs.join(kodi.args['title'], "Season %s" % kodi.args['season']) title = "%s - S%02dE%02d" % (kodi.args['title'], int(kodi.args['season']), int(kodi.args['episode'])) filename = kodi.vfs.clean_file_name(title) from scrapecore import scrapers resolved_url = scrapers.get_scraper_by_name( kodi.args['service']).resolve_url(kodi.args['raw_url']) if not resolved_url: return video = { "type": media, "filename": filename, "url": resolved_url, "title": title, "addon": kodi.get_id(), "destination": destination, "trakt_id": kodi.args['trakt_id'] } response = master_control.enqueue(video) kodi.log(response) message = 'Failed Adding to Queue %s.' % (title) try: if response['status'] == 200: message = 'Added to Queue %s.' % (title) except: pass kodi.notify(kodi.get_name(), message)
def execute_api(): api = kodi.arg('api', decode='json') if 'confirm' in api and api['confirm']: message = api['message'] if 'message' in api else '' if not kodi.dialog_confirm("Click Yes to proceed.", api['confirm'], message): return response = core.execute_api(globals(), api) if 'notify' in api and api['notify']: kodi.notify('API Response', response) if 'refresh' in api and api['refresh']: kodi.refresh()
def install_feed(): if not kodi.dialog_confirm('Install Feed?', "Click YES to proceed."): return from libs.database import DB from libs import github xml = github.install_feed(kodi.arg('url')) try: for f in xml.findAll('feeds'): name = f.find('name').text url = f.find('url').text DB.execute("INSERT INTO feed_subscriptions(name, url) VALUES(?,?)", [name, url]) DB.commit() count = DB.query("SELECT count(1) FROM feed_subscriptions") kodi.set_setting('installed_feeds', str(count[0][0])) kodi.notify("Install Complete",'Feed Installed') except: kodi.notify("Install failed",'Invalid Format.')
def search(media, title, season=None, episode=None, year=None, episode_title=None, trakt_id=None, imdb_id=None, tmdb_id=None, tvdb_id=None, ignore_list=[], find_torrent=False): resolved_url = '' global result_count result_count = 0 pool = ThreadPool(THREAD_POOL_SIZE) def process_results(results): name, verified = results global search_results, PB, result_count verified = {v['raw_url']:v for v in verified}.values() search_results += verified search_count = len(verified) result_count += search_count PB.next("Total Results: [COLOR green]%s[/COLOR]" % result_count, "Found [COLOR green]%s[/COLOR] links from [COLOR orange]%s[/COLOR]" % (search_count, name)) if media == 'movie': args = {"title": title, "year": year, "trakt_id": trakt_id, "imdb_id": imdb_id, "tmdb_id": tmdb_id} PB.new('Searching for Movie Sources', len(_active_scrapers)) for s in _active_scrapers: if s.service in ignore_list: continue if find_torrent: if s.torrent: s.return_cached = False else: continue if 'search_movies' in dir(s): pool.queueTask(s.search_movies, args=args, taskCallback=process_results) else: args = {"title": title, "episode_title": episode_title, "season": season, "episode": episode, "year": year, "trakt_id": trakt_id, "imdb_id": imdb_id, "tvdb_id": tvdb_id} PB.new('Searching for TV Sources', len(_active_scrapers)) for s in _active_scrapers: if s.service in ignore_list: continue if find_torrent: if s.torrent: s.return_cached = False else: continue if 'search_shows' in dir(s): pool.queueTask(s.search_shows, args=args, taskCallback=process_results) pool.joinAll() PB.close() if len(search_results) == 0: kodi.notify('Search Failed', 'No results found') return [] return format_results(search_results)
def handel_error(self, error, response, request_args, request_kwargs): if response.status_code == 401: traceback.print_stack() kodi.close_busy_dialog() raise githubException("Unauthorized: %s" % error) elif response.status_code == 403 and 'X-RateLimit-Reset' in response.headers: import time retry = int(response.headers['X-RateLimit-Reset']) - int(time.time()) for delay in range(retry, 0, -1): kodi.notify("API Rate limit exceeded", "Retry in %s seconds(s)" % delay, timeout=1000) kodi.sleep(1000) return self.request(*request_args, **request_kwargs) elif response.status_code == 422 and 'Only the first 1000' in response.text: kodi.handel_error('Result count exceeds API limit.', 'Try different search or result filter.') kodi.close_busy_dialog() traceback.print_stack() else: kodi.close_busy_dialog() traceback.print_stack() raise githubException("Status %s: %s" % (response.status_code, response.text))
def authorize(): PB = kodi.ProgressBar() PB.new("Authorize RealDebrid: https://real-debrid.com/device", 600) response = request_code() device_code = response['device_code'] user_code = response['user_code'] timeout = response['expires_in'] PB.update_subheading("Enter Code: %s" % user_code, "%s sec(s)" % 600) for tick in range(600, 0, -1): if PB.is_canceled(): return percent = int((tick / 600.0) * 100) PB.update_subheading("Enter Code: %s" % user_code, "%s sec(s) remaining" % tick, percent=percent) if (tick % 5) == 0: r = poll_credentials(device_code) if r: client_id = r['client_id'] client_secret = r['client_secret'] token = request_token(client_id, client_secret, device_code) kodi.set_setting('realdebrid_client_id', client_id, addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_client_secret', client_secret, addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_token', token['access_token'], addon_id='script.module.scrapecore') kodi.set_setting('realdebrid_refresh_token', token['refresh_token'], addon_id='script.module.scrapecore') PB.close() kodi.notify("RealDebrid Authorization", "Success!") return kodi.sleep(1000)
def install_feed(): from libs.database import DB from libs import github if kodi.mode == 'install_feed': url = kodi.arg('url') xml = github.install_feed(url) else: url = kodi.dialog_file_browser('Select a feed file', mask='.zip') if not github.re_feed.search(url): return xml = github.install_feed(url, True) if not kodi.dialog_confirm('Install Feed?', "Click YES to proceed."): return try: for f in xml.findAll('feeds'): name = f.find('name').text url = f.find('url').text DB.execute("INSERT INTO feed_subscriptions(name, url) VALUES(?,?)", [name, url]) DB.commit() count = DB.query("SELECT count(1) FROM feed_subscriptions") kodi.set_setting('installed_feeds', str(count[0][0])) kodi.notify("Install Complete",'Feed Installed') except: kodi.notify("Install failed",'Invalid Format.')
def handel_error(self, error, response, request_args, request_kwargs): traceback.print_stack() if response is None: kodi.notify("Trakt Error", "See log file") raise error elif response.status_code > 499: kodi.notify("Temporary Trakt Error", "%s: %s" % (response.status_code, ERROR_CODES[response.status_code])) raise TraktException("Temporary Trakt Error <<%s>>: %s" % (response.status_code, ERROR_CODES[response.status_code])) else: kodi.notify("Trakt Error", "%s: %s" % (response.status_code, ERROR_CODES[response.status_code])) raise TraktException("Trakt Error <<%s>>: %s" % (response.status_code, ERROR_CODES[response.status_code]))
def handel_error(self, error, response, request_args, request_kwargs): traceback.print_stack() if response is None: kodi.notify("Trakt Error", "See log file") raise error elif response.status_code > 499: kodi.notify( "Temporary Trakt Error", "%s: %s" % (response.status_code, ERROR_CODES[response.status_code])) raise TraktException( "Temporary Trakt Error <<%s>>: %s" % (response.status_code, ERROR_CODES[response.status_code])) else: kodi.notify( "Trakt Error", "%s: %s" % (response.status_code, ERROR_CODES[response.status_code])) raise TraktException( "Trakt Error <<%s>>: %s" % (response.status_code, ERROR_CODES[response.status_code]))
def __init__(self, addon_id, url, full_name, destination, master=False, quiet=False, installed_list=[], batch=False): self.installed_list = installed_list self.quiet = quiet self.batch=batch if not self.quiet: kodi.open_busy_dialog() v = kodi.get_kodi_version() # Grab a list of KNOWN addons from the database. Unfortunately Jarvis requires direct database access for the installed flag if v >= 17: response = kodi.kodi_json_request("Addons.GetAddons", { "installed": False, "properties": ["path", "dependencies"]}) for a in response['result']['addons']: self.available_addons += [a['addonid']] self.source_table[a['addonid']] = a['path'] else: from sqlite3 import dbapi2 dbf = kodi.vfs.join("special://profile/Database", "Addons20.db") with dbapi2.connect(dbf) as dbh: dbc = dbh.cursor() dbc.execute("SELECT addon.addonID, broken.addonID is Null AS enabled, addon.path FROM addon LEFT JOIN broken on addon.addonID=broken.addonID WHERE enabled=1") for a in dbc.fetchall(): self.available_addons += [a[0]] self.source_table[a[0]] = a[2] dbh.close() self._addon_id = addon_id self._url = url self._full_name = full_name self._user, self.repo = full_name.split("/") self._master = master self._destination = destination # Add the final addon target to the sources list with type of zip # Initiate install routine self.install_addon(addon_id, url, full_name, master) completed = list(reversed(self.completed)) if not quiet: pb = kodi.ProgressBar() pb.new('Enabling Addons', len(completed)+1) pb.update_subheading('Building Addon List') kodi.run_command("XBMC.UpdateLocalAddons()") kodi.sleep(500) for addon_id in completed: if not quiet: #percent = 100* (completed.index(addon_id) / len(completed)) #pb.update(percent, "Enabling Addons", addon_id, '') pb.next(addon_id) kodi.sleep(100) self.enable_addon(addon_id) if not quiet: pb.next("Looking for Updates", "") kodi.sleep(500) kodi.run_command('XBMC.UpdateAddonRepos') # Enable installed addons if not self.quiet: pb.close() kodi.close_busy_dialog() if self.install_error: kodi.notify("Install failed", self._addon_id) else: kodi.notify("Install complete", self._addon_id)
def rebuild_settings(): scrapecore.write_settings_file() kodi.notify('Success', 'Settings File Written')