def install_addon(self, addon_id, url, full_name, master): self.required_addons += [addon_id] self.build_dependency_list(addon_id, url, full_name, master) self.required_addons = list(set(self.required_addons)) self.unmet_addons = list(set(self.unmet_addons)) sources = self.sources self.sources = {} for addon_id in sources: source = sources[addon_id] if source['type'] == SOURCES.DEFAULT: self.install_addon(addon_id, source['url'], self._full_name, False) elif source['type'] == SOURCES.NATIVE: kodi.xbmc.executebuiltin("XBMC.InstallAddon(%s)" % addon_id) i=0 while kodi.get_condition_visiblity('System.HasAddon(%s)' % addon_id) == 0: if i == 30: kodi.raise_error("", "Unmet Dependencies:", "Install Timed Out", addon_id) break kodi.sleep(1000) i+=1 elif source['type'] == SOURCES.ZIP: downloader.download(source['url'], addon_id + ".zip", self._destination, True) elif source['type'] == SOURCES.REPO: src = kodi.vfs.join("special://home/addons", addon_id +"-master") dest = kodi.vfs.join("special://home/addons", addon_id) if kodi.vfs.exists(dest): if kodi.dialog_confirm("Confirm overwrite", dest): shutil.rmtree(dest) else: return downloader.download(source['url'], addon_id + ".zip", self._destination, True) shutil.move(src, dest) self.save_sources(sources) self.completed.append(addon_id)
def onPlayBackStarted(self): logger.log('Service: Playback started', log_utils.LOGNOTICE) playing = self.win.getProperty('salts.playing') == 'True' self.trakt_id = self.win.getProperty('salts.playing.trakt_id') self.season = self.win.getProperty('salts.playing.season') self.episode = self.win.getProperty('salts.playing.episode') srt_path = self.win.getProperty('salts.playing.srt') trakt_resume = self.win.getProperty('salts.playing.trakt_resume') salts_resume = self.win.getProperty('salts.playing.salts_resume') self._from_library = self.win.getProperty('salts.playing.library') == 'True' if playing: # Playback is ours logger.log('Service: tracking progress...', log_utils.LOGNOTICE) self.tracked = True if srt_path: logger.log('Service: Enabling subtitles: %s' % (srt_path), log_utils.LOGDEBUG) self.setSubtitles(srt_path) else: self.showSubtitles(False) self._totalTime = 0 while self._totalTime == 0: try: self._totalTime = self.getTotalTime() except RuntimeError: self._totalTime = 0 break kodi.sleep(1000) if salts_resume: logger.log("Salts Local Resume: Resume Time: %s Total Time: %s" % (salts_resume, self._totalTime), log_utils.LOGDEBUG) self.seekTime(float(salts_resume)) elif trakt_resume: resume_time = float(trakt_resume) * self._totalTime / 100 logger.log("Salts Trakt Resume: Percent: %s, Resume Time: %s Total Time: %s" % (trakt_resume, resume_time, self._totalTime), log_utils.LOGDEBUG) self.seekTime(resume_time)
def onPlayBackStarted(self): logger.log('Service: Playback started', log_utils.LOGNOTICE) playing = self.win.getProperty('transistortv.playing') == 'True' self.trakt_id = self.win.getProperty('transistortv.playing.trakt_id') self.season = self.win.getProperty('transistortv.playing.season') self.episode = self.win.getProperty('transistortv.playing.episode') srt_path = self.win.getProperty('transistortv.playing.srt') trakt_resume = self.win.getProperty('transistortv.playing.trakt_resume') transistortv_resume = self.win.getProperty('transistortv.playing.transistortv_resume') self._from_library = self.win.getProperty('transistortv.playing.library') == 'True' if playing: # Playback is ours logger.log('Service: tracking progress...', log_utils.LOGNOTICE) self.tracked = True if srt_path: logger.log('Service: Enabling subtitles: %s' % (srt_path), log_utils.LOGDEBUG) self.setSubtitles(srt_path) else: self.showSubtitles(False) self._totalTime = 0 while self._totalTime == 0: try: self._totalTime = self.getTotalTime() except RuntimeError: self._totalTime = 0 break kodi.sleep(1000) if transistortv_resume: logger.log("transistortv Local Resume: Resume Time: %s Total Time: %s" % (transistortv_resume, self._totalTime), log_utils.LOGDEBUG) self.seekTime(float(transistortv_resume)) elif trakt_resume: resume_time = float(trakt_resume) * self._totalTime / 100 logger.log("transistortv Trakt Resume: Percent: %s, Resume Time: %s Total Time: %s" % (trakt_resume, resume_time, self._totalTime), log_utils.LOGDEBUG) self.seekTime(resume_time)
def auth_trakt(): start = time.time() use_https = kodi.get_setting('use_https') == 'true' trakt_timeout = int(kodi.get_setting('trakt_timeout')) trakt_api = Trakt_API(use_https=use_https, timeout=trakt_timeout) result = trakt_api.get_code() code, expires, interval = result['device_code'], result[ 'expires_in'], result['interval'] time_left = expires - int(time.time() - start) line1 = i18n('verification_url') % (result['verification_url']) line2 = i18n('prompt_code') % (result['user_code']) line3 = i18n('code_expires') % (time_left) with ProgressDialog(i18n('trakt_acct_auth'), line1=line1, line2=line2, line3=line3) as pd: pd.update(100) while time_left: for _ in range(INTERVALS): kodi.sleep(interval * 1000 / INTERVALS) if pd.is_canceled(): return try: result = trakt_api.get_device_token(code) break except urllib2.URLError as e: # authorization is pending; too fast if e.code in [400, 429]: pass elif e.code == 418: kodi.notify(msg=i18n('user_reject_auth'), duration=3000) return elif e.code == 410: break else: raise time_left = expires - int(time.time() - start) progress = time_left * 100 / expires pd.update(progress, line3=i18n('code_expires') % (time_left)) try: kodi.set_setting('trakt_oauth_token', result['access_token']) kodi.set_setting('trakt_refresh_token', result['refresh_token']) trakt_api = Trakt_API(result['access_token'], use_https=use_https, timeout=trakt_timeout) profile = trakt_api.get_user_profile(cached=False) kodi.set_setting('trakt_user', '%s (%s)' % (profile['username'], profile['name'])) kodi.notify(msg=i18n('trakt_auth_complete'), duration=3000) except Exception as e: log_utils.log('Trakt Authorization Failed: %s' % (e), log_utils.LOGDEBUG)
def download(url, filename, destination, unzip=False): r = requests.get(url, stream=True) kodi.log("Download: %s" % url) if r.status_code == requests.codes.ok: temp_file = kodi.vfs.join(kodi.get_profile(), "downloads") if not kodi.vfs.exists(temp_file): kodi.vfs.mkdir(temp_file, recursive=True) temp_file = kodi.vfs.join(temp_file, filename) try: total_bytes = int(r.headers["Content-Length"]) except: total_bytes = 0 block_size = 1000 cached_bytes = 0 pb = xbmcgui.DialogProgress() pb.create("Downloading", filename, ' ', ' ') kodi.sleep(150) start = time.time() with open(temp_file, 'wb') as f: for block in r.iter_content(chunk_size=block_size): if not block: break if pb.iscanceled(): return False cached_bytes += len(block) f.write(block) if total_bytes > 0: delta = int(time.time() - start) if delta: kbs = int(cached_bytes / (delta * 1000)) else: kbs = 0 percent = int(cached_bytes * 100 / total_bytes) pb.update(percent, "Downloading", filename, format_speed(kbs)) pb.close() if unzip: zip_ref = zipfile.ZipFile(temp_file, 'r') zip_ref.extractall(destination) zip_ref.close() kodi.vfs.rm(temp_file, quiet=True) else: kodi.vfs.mv(temp_file, kodi.vfs.join(destination, filename)) else: kodi.close_busy_dialog() raise downloaderException(r.status_code) return True
def auth_trakt(): start = time.time() use_https = kodi.get_setting('use_https') == 'true' trakt_timeout = int(kodi.get_setting('trakt_timeout')) trakt_api = Trakt_API(use_https=use_https, timeout=trakt_timeout) result = trakt_api.get_code() code, expires, interval = result['device_code'], result['expires_in'], result['interval'] time_left = expires - int(time.time() - start) line1 = i18n('verification_url') % (result['verification_url']) line2 = i18n('prompt_code') % (result['user_code']) line3 = i18n('code_expires') % (time_left) with ProgressDialog(i18n('trakt_acct_auth'), line1=line1, line2=line2, line3=line3) as pd: pd.update(100) while time_left: for _ in range(INTERVALS): kodi.sleep(interval * 1000 / INTERVALS) if pd.is_canceled(): return try: result = trakt_api.get_device_token(code) break except urllib2.URLError as e: # authorization is pending; too fast if e.code in [400, 429]: pass elif e.code == 418: kodi.notify(msg=i18n('user_reject_auth'), duration=3000) return elif e.code == 410: break else: raise time_left = expires - int(time.time() - start) progress = time_left * 100 / expires pd.update(progress, line3=i18n('code_expires') % (time_left)) try: kodi.set_setting('trakt_oauth_token', result['access_token']) kodi.set_setting('trakt_refresh_token', result['refresh_token']) trakt_api = Trakt_API(result['access_token'], use_https=use_https, timeout=trakt_timeout) profile = trakt_api.get_user_profile(cached=False) kodi.set_setting('trakt_user', '%s (%s)' % (profile['username'], profile['name'])) kodi.notify(msg=i18n('trakt_auth_complete'), duration=3000) except Exception as e: log_utils.log('Trakt Authorization Failed: %s' % (e), log_utils.LOGDEBUG)
def call(uri, query=None, params=False, append_base=True, web=False): if web: r = requests.get(uri) if r.status_code == requests.codes.ok: r.encoding = 'utf-8' return r.text else: raise githubException("Status %s: %s" % (r.status_code, r.text)) kodi.sleep(random.randint(50, 250)) # random delay 50-250 ms url = base_url + uri if append_base else uri if query is not None: query = urllib.urlencode(query) for r in [('%3A', ":"), ("%2B", "+")]: f, t = r query = query.replace(f, t) url = url + '?' + query if kodi.get_setting('github_key'): headers = { "Authorization": "token %s" % kodi.get_setting('github_key') } else: headers = {} if params: r = requests.get(url, params, headers=headers) else: r = requests.get(url, headers=headers) if r.status_code == requests.codes.ok: return r.json() elif r.status_code == 401: kodi.notify("Unauthorized", "Bad credentials") kodi.log(r.text) return None elif r.status_code == 403: import time retry = int(r.headers['X-RateLimit-Reset']) - int(time.time()) kodi.notify("Rate limit exceeded", "Retry in %s" % retry) kodi.log(r.text) return None elif r.status_code == 422: kodi.notify("No results found", "Review search terms") kodi.log(r.text) return None else: kodi.close_busy_dialog() raise githubException("Status %s: %s" % (r.status_code, r.text))
def do_ip_auth(scraper, visit_url, qr_code): EXPIRE_DURATION = 60 * 5 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 CANCEL_BUTTON = 200 INSTR_LABEL = 101 QR_CODE_CTRL = 102 PROGRESS_CTRL = 103 class IpAuthDialog(xbmcgui.WindowXMLDialog): def onInit(self): # log_utils.log('onInit:', log_utils.LOGDEBUG) self.cancel = False self.getControl(INSTR_LABEL).setLabel(i18n('ip_auth_line1') + visit_url + i18n('ip_auth_line2')) self.progress = self.getControl(PROGRESS_CTRL) self.progress.setPercent(100) if qr_code: img = self.getControl(QR_CODE_CTRL) img.setImage(qr_code) def onAction(self, action): # log_utils.log('Action: %s' % (action.getId()), log_utils.LOGDEBUG) if action == ACTION_PREVIOUS_MENU or action == ACTION_BACK: self.cancel = True self.close() def onControl(self, control): # log_utils.log('onControl: %s' % (control), log_utils.LOGDEBUG) pass def onFocus(self, control): # log_utils.log('onFocus: %s' % (control), log_utils.LOGDEBUG) pass def onClick(self, control): # log_utils.log('onClick: %s' % (control), log_utils.LOGDEBUG) if control == CANCEL_BUTTON: self.cancel = True self.close() def setProgress(self, progress): self.progress.setPercent(progress) dialog = IpAuthDialog('IpAuthDialog.xml', kodi.get_path()) dialog.show() interval = 5000 begin = time.time() try: while True: for _ in range(INTERVALS): kodi.sleep(interval / INTERVALS) elapsed = time.time() - begin progress = int((EXPIRE_DURATION - elapsed) * 100 / EXPIRE_DURATION) dialog.setProgress(progress) if progress <= 0 or dialog.cancel: return False authorized, result = scraper.check_auth() if authorized: return result finally: del dialog
def call(uri, query=None, params=False, append_base=True, web=False, page=1, cache_limit=0): if web: r = requests.get(uri) if r.status_code == requests.codes.ok: r.encoding = 'utf-8' return r.text else: raise githubException("Status %s: %s" % (r.status_code, r.text)) url = base_url + uri if append_base else uri if query is None: query = {'page': 1} else: query['page'] = page if query is not None: _query = urllib.urlencode(query) for r in [('%3A', ":"), ("%2B", "+")]: f, t = r _query = _query.replace(f, t) url = url + '?' + _query if kodi.get_setting('github_key'): headers = { "Authorization": "token %s" % kodi.get_setting('github_key') } else: headers = {} cached, current_page, total_pages = _get_cached_response(url, cache_limit) if cached: return cached kodi.sleep(random.randint(100, 250)) # random delay 50-250 ms if params: r = requests.get(url, params, headers=headers) else: r = requests.get(url, headers=headers) if r.status_code == requests.codes.ok: results = r.json() total_count = float(results['total_count']) results['page_count'] = int(math.ceil(total_count / page_limit)) page_count = int(results['page_count']) if page_count > 1 and page == 1: for p in range(page + 1, int(page_count + 1)): kodi.sleep(500) temp = call(uri, query=query, params=params, append_base=append_base, web=web, page=p, cache_limit=cache_limit) results['items'] += temp['items'] _cache_response(url, results, page, results['page_count']) return results elif r.status_code == 401: kodi.notify("Unauthorized", "Bad credentials") kodi.log(r.text) return None elif r.status_code == 403 and 'X-RateLimit-Reset' in r.headers: import time retry = int(r.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) kodi.log(r.text) return call(uri, query=query, params=params, append_base=append_base, web=web, page=page, cache_limit=cache_limit) elif r.status_code == 422: kodi.notify("No results found", "Review search terms") kodi.log(r.text) return None else: kodi.close_busy_dialog() raise githubException("Status %s: %s" % (r.status_code, r.text))
def do_ip_auth(scraper, visit_url, qr_code): EXPIRE_DURATION = 60 * 5 ACTION_PREVIOUS_MENU = 10 ACTION_BACK = 92 CANCEL_BUTTON = 200 INSTR_LABEL = 101 QR_CODE_CTRL = 102 PROGRESS_CTRL = 103 class IpAuthDialog(xbmcgui.WindowXMLDialog): def onInit(self): # logger.log('onInit:', log_utils.LOGDEBUG) self.cancel = False self.getControl(INSTR_LABEL).setLabel(i18n('ip_auth_line1') + visit_url + i18n('ip_auth_line2')) self.progress = self.getControl(PROGRESS_CTRL) self.progress.setPercent(100) if qr_code: img = self.getControl(QR_CODE_CTRL) img.setImage(qr_code) def onAction(self, action): # logger.log('Action: %s' % (action.getId()), log_utils.LOGDEBUG) if action == ACTION_PREVIOUS_MENU or action == ACTION_BACK: self.cancel = True self.close() def onControl(self, control): # logger.log('onControl: %s' % (control), log_utils.LOGDEBUG) pass def onFocus(self, control): # logger.log('onFocus: %s' % (control), log_utils.LOGDEBUG) pass def onClick(self, control): # logger.log('onClick: %s' % (control), log_utils.LOGDEBUG) if control == CANCEL_BUTTON: self.cancel = True self.close() def setProgress(self, progress): self.progress.setPercent(progress) dialog = IpAuthDialog('IpAuthDialog.xml', kodi.get_path()) dialog.show() interval = 5000 begin = time.time() try: while True: for _ in range(INTERVALS): kodi.sleep(interval / INTERVALS) elapsed = time.time() - begin progress = int((EXPIRE_DURATION - elapsed) * 100 / EXPIRE_DURATION) dialog.setProgress(progress) if progress <= 0 or dialog.cancel: return False authorized, result = scraper.check_auth() if authorized: return result finally: del dialog
def call(uri, query=None, params=False, append_base=True, web=False, page=1, cache_limit=0): if web: r = requests.get(uri) if r.status_code == requests.codes.ok: r.encoding = 'utf-8' return r.text else: raise githubException("Status %s: %s" % (r.status_code, r.text)) url = base_url + uri if append_base else uri if query is None: query = {'page': 1} else: query['page'] = page if query is not None: _query = urllib.urlencode(query) for r in [('%3A', ":"), ("%2B", "+")]: f,t = r _query = _query.replace(f,t) url = url + '?' + _query if kodi.get_setting('github_key'): headers = {"Authorization": "token %s" % kodi.get_setting('github_key')} else: headers = {} cached, current_page, total_pages = _get_cached_response(url, cache_limit) if cached: return cached kodi.sleep(random.randint(100, 250)) # random delay 50-250 ms if params: r = requests.get(url, params, headers=headers) else: r = requests.get(url, headers=headers) if r.status_code == requests.codes.ok: results = r.json() total_count = float(results['total_count']) results['page_count'] = int(math.ceil(total_count / page_limit)) page_count = int(results['page_count']) if page_count > 1 and page == 1: for p in range(page+1, int(page_count+1)): kodi.sleep(500) temp = call(uri, query=query, params=params, append_base=append_base, web=web, page=p, cache_limit=cache_limit) results['items'] += temp['items'] _cache_response(url, results, page, results['page_count']) return results elif r.status_code == 401: kodi.notify("Unauthorized", "Bad credentials") kodi.log(r.text) return None elif r.status_code == 403 and 'X-RateLimit-Reset' in r.headers: import time retry = int(r.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) kodi.log(r.text) return call(uri, query=query, params=params, append_base=append_base, web=web, page=page, cache_limit=cache_limit) elif r.status_code == 422: kodi.notify("No results found", "Review search terms") kodi.log(r.text) return None else: kodi.close_busy_dialog() raise githubException("Status %s: %s" % (r.status_code, r.text))
def enable_addon(self, addon_id): try: kodi.xbmc.executebuiltin("XBMC.UpdateLocalAddons()") kodi.sleep(500) kodi.kodi_json_request("Addons.SetAddonEnabled", {"addonid": addon_id, "enabled": True}) except: pass