def register(search, search_movie, search_episode): try: payload = json.loads(base64.b64decode(sys.argv[1])) except: notify(ADDON.getLocalizedString(30102).encode('utf-8'), time=1000) return results = () method = { "search": search, "search_movie": search_movie, "search_episode": search_episode, }.get(payload["method"]) or (lambda *a, **kw: []) try: results = () try: objects = method(payload["search_object"]) if objects is not None: results = tuple(objects) except Exception as e: notify("%s: %s" % (ADDON.getLocalizedString(30224).encode('utf-8'), e)) map(log.error, traceback.format_exc().split("\n")) finally: try: req = urllib2.Request(payload["callback_url"], data=json.dumps(results)) with closing(urllib2.urlopen(req)) as response: log.info("%s" % repr(response)) except Exception as e: notify("%s: %s" % (ADDON.getLocalizedString(30224).encode('utf-8'), e)) map(log.error, traceback.format_exc().split("\n"))
def run(url_suffix=""): if not os.path.exists(os.path.join(xbmc.translatePath(ADDON.getAddonInfo("path")), ".firstrun")): notify(ADDON.getLocalizedString(30101).encode('utf-8')) system_information() return socket.setdefaulttimeout(300) urllib2.install_opener(urllib2.build_opener(NoRedirectHandler())) url = sys.argv[0].replace("plugin://%s" % ADDON_ID, QUASARD_HOST + url_suffix) + sys.argv[2] log.info("Requesting %s" % url) try: data = _json(url) except Exception as e: map(log.error, traceback.format_exc().split("\n")) notify("%s: %s" % (ADDON.getLocalizedString(30225).encode('utf-8'), e)) return if not data: return if data["content_type"]: xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_UNSORTED) xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE) xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_DATE) xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_GENRE) xbmcplugin.setContent(HANDLE, data["content_type"]) listitems = range(len(data["items"])) for i, item in enumerate(data["items"]): # Translate labels if item["label"][0:8] == "LOCALIZE": item["label"] = GetLocalizedString(item["label"]) if item["label2"][0:8] == "LOCALIZE": item["label2"] = GetLocalizedString(item["label2"]) listItem = xbmcgui.ListItem(label=item["label"], label2=item["label2"], iconImage=item["icon"], thumbnailImage=item["thumbnail"]) if item.get("info"): listItem.setInfo("video", item["info"]) if item.get("stream_info"): for type_, values in item["stream_info"].items(): listItem.addStreamInfo(type_, values) if item.get("art"): listItem.setArt(item["art"]) if item.get("context_menu"): # Translate context menus for m, menu in enumerate(item["context_menu"]): if menu[0][0:8] == "LOCALIZE": menu[0] = GetLocalizedString(menu[0]) listItem.addContextMenuItems(item["context_menu"]) listItem.setProperty("isPlayable", item["is_playable"] and "true" or "false") if item.get("properties"): for k, v in item["properties"].items(): listItem.setProperty(k, v) listitems[i] = (item["path"], listItem, not item["is_playable"]) xbmcplugin.addDirectoryItems(HANDLE, listitems, totalItems=len(listitems)) xbmcplugin.endOfDirectory(HANDLE, succeeded=True, updateListing=False, cacheToDisc=True)
def getLocalizedString(stringId): try: if not PY3: return ADDON.getLocalizedString(stringId).encode('utf-8', 'ignore') else: return ADDON.getLocalizedString(stringId) except: return stringId
def quasard_thread(monitor): crash_count = 0 try: while not xbmc.abortRequested: log.info("quasard: starting quasard") proc = start_quasard(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if not proc: break threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start() if PLATFORM["os"] == "windows": while proc.poll() is None: log.info(proc.stdout.readline()) else: # Kodi hangs on some Android (sigh...) systems when doing a blocking # read. We count on the fact that Quasar daemon flushes its log # output on \n, creating a pretty clean output import fcntl import select fd = proc.stdout.fileno() fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) while proc.poll() is None: try: to_read, _, _ = select.select([proc.stdout], [], []) for ro in to_read: line = ro.readline() if line == "": # write end is closed break log.info(line) except IOError: time.sleep(1) # nothing to read, sleep if proc.returncode == 0 or xbmc.abortRequested: break crash_count += 1 notify(ADDON.getLocalizedString(30100).encode('utf-8'), time=3000) xbmc.executebuiltin("Dialog.Close(all, true)") system_information() time.sleep(3) if crash_count >= 3: notify(ADDON.getLocalizedString(30110).encode('utf-8'), time=3000) break except Exception as e: notify("%s: %s" % (ADDON.getLocalizedString(30226).encode('utf-8'), e)) map(log.error, traceback.format_exc().split("\n")) raise
def request(url, params={}, headers={}, data=None, method=None): if params: url = "".join([url, "?", urlencode(params)]) req = urllib2.Request(url) if method: req.get_method = lambda: method req.add_header("User-Agent", USER_AGENT) req.add_header("Accept-Encoding", "gzip") for k, v in headers.items(): req.add_header(k, v) if data: req.add_data(data) try: with closing(urllib2.urlopen(req)) as response: data = response.read() if response.headers.get("Content-Encoding", "") == "gzip": import zlib data = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(data) response.data = data response.json = lambda: parse_json(data) response.xml = lambda: parse_xml(data) return response except Exception as e: notify("%s: %s" % (ADDON.getLocalizedString(30224).encode('utf-8'), e)) map(log.error, traceback.format_exc().split("\n")) return None, None
def register(search, search_movie, search_episode): import base64 import json import sys try: payload = json.loads(base64.b64decode(sys.argv[1])) except: notify(ADDON.getLocalizedString(30102).encode('utf-8'), time=1000) return results = () method = { "search": search, "search_movie": search_movie, "search_episode": search_episode, }.get(payload["method"]) or (lambda *a, **kw: []) try: results = () objects = method(payload["search_object"]) if objects is not None: results = tuple(objects) finally: urllib2.urlopen( payload["callback_url"], data=json.dumps(results) )
def request(url, params={}, headers={}, data=None, method=None): if params: url = "".join([url, "?", urlencode(params)]) req = urllib2.Request(url) if method: req.get_method = lambda: method req.add_header("User-Agent", USER_AGENT) req.add_header("Accept-Encoding", "gzip") for k, v in headers.items(): req.add_header(k, v) if data: req.add_data(data) try: with closing(urllib2.urlopen(req)) as response: data = response.read() if response.headers.get("Content-Encoding", "") == "gzip": import zlib data = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(data) response.data = data response.json = lambda: parse_json(data) response.xml = lambda: parse_xml(data) return response except Exception as e: notify("%s: %s" % (ADDON.getLocalizedString(30224).encode('utf-8'), e)) map(log.error, traceback.format_exc().split("\n")) return None, None
def quasard_thread(monitor): try: while not xbmc.abortRequested: log.info("quasard: starting quasard") proc = start_quasard(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if not proc: break threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start() if PLATFORM["os"] == "windows": while proc.poll() is None: log.info(proc.stdout.readline()) else: # Kodi hangs on some Android (sigh...) systems when doing a blocking # read. We count on the fact that Quasar daemon flushes its log # output on \n, creating a pretty clean output import fcntl import select fd = proc.stdout.fileno() fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) while proc.poll() is None: try: to_read, _, _ = select.select([proc.stdout], [], []) for ro in to_read: line = ro.readline() if line == "": # write end is closed break log.info(line) except IOError: time.sleep(1) # nothing to read, sleep if proc.returncode == 0 or xbmc.abortRequested: break notify(ADDON.getLocalizedString(30100).encode('utf-8'), time=3000) xbmc.executebuiltin("Dialog.Close(all, true)") system_information() time.sleep(3) except Exception as e: notify("%s: %s" % (ADDON.getLocalizedString(30226).encode('utf-8'), e)) map(log.error, traceback.format_exc().split("\n")) raise
def AddonFailure(self, addonId): if ADDON.getSetting("provider_disable_failing") == u"false": return 0 if addonId in self._failures: self._failures[addonId] += 1 else: self._failures[addonId] = 1 log.warning("Recorded failure %d for %s" % (self._failures[addonId], addonId)) if self._failures[addonId] > int(ADDON.getSetting("provider_allowed_failures")): try: time.sleep(10) notify(ADDON.getLocalizedString(30111).encode('utf-8')) urllib2.urlopen("%s/provider/%s/disable" % (QUASARD_HOST, addonId)) except: notify(ADDON.getLocalizedString(30112).encode('utf-8')) return 0 return self._failures[addonId]
def quasard_thread(monitor): try: import xbmc while not xbmc.abortRequested: log.info("quasard: starting quasard") proc = start_quasard(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start() if PLATFORM["os"] == "windows": while proc.poll() is None: log.info(proc.stdout.readline()) else: # Kodi hangs on some Android (sigh...) systems when doing a blocking # read. We count on the fact that Quasar daemon flushes its log # output on \n, creating a pretty clean output import fcntl fd = proc.stdout.fileno() fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) while proc.poll() is None: try: log.info(proc.stdout.readline()) continue except IOError: time.sleep(1) # nothing to read, sleep if proc.returncode == 0 or xbmc.abortRequested: break notify(ADDON.getLocalizedString(30100).encode('utf-8'), time=1000) reset_rpc() time.sleep(3) except Exception: import xbmc import traceback map(xbmc.log, traceback.format_exc().split("\n")) raise
def GetLocalizedString(self, *args, **kwargs): return ADDON.getLocalizedString(*args, **kwargs).encode('utf-8')
def get_quasar_binary(): binary = "quasar" + (PLATFORM["os"] == "windows" and ".exe" or "") binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % PLATFORM) if PLATFORM["os"] == "android": log.info("Detected binary folder: %s" % binary_dir) binary_dir_legacy = binary_dir.replace("/storage/emulated/0", "/storage/emulated/legacy") if os.path.exists(binary_dir_legacy): binary_dir = binary_dir_legacy log.info("Using binary folder: %s" % binary_dir) app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID, "bin", "%(os)s_%(arch)s" % PLATFORM) else: dest_binary_dir = os.path.join( xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % PLATFORM) try: binary_dir = binary_dir.decode("latin1") dest_binary_dir = dest_binary_dir.decode("latin1") except UnicodeEncodeError: log.info("Unable to decode: binary_dir=%s dest_binary_dir=%s" % (repr(binary_dir), repr(dest_binary_dir))) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) if not os.path.exists(binary_path): notify(ADDON.getLocalizedString(30103).encode('utf-8')) system_information() return False, False if not os.path.exists(dest_binary_path) or get_quasard_checksum( dest_binary_path) != get_quasard_checksum(binary_path): log.info("Updating quasar daemon...") try: os.makedirs(dest_binary_dir) except OSError: pass try: shutil.rmtree(dest_binary_dir) except OSError as e: log.error("Unable to remove destination path for update: %s" % e) system_information() pass try: shutil.copytree(binary_dir, dest_binary_dir) except OSError as e: log.error("Unable to copy to destination path for update: %s" % e) notify(ADDON.getLocalizedString(30227).encode('utf-8')) system_information() pass # Clean stale files in the directory, as this can cause headaches on # Android when they are unreachable dest_files = set(os.listdir(dest_binary_dir)) orig_files = set(os.listdir(binary_dir)) log.info("Deleting stale files %s" % (dest_files - orig_files)) for file_ in (dest_files - orig_files): path = os.path.join(dest_binary_dir, file_) if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def get_quasar_binary(): binary = "quasar" + (PLATFORM["os"] == "windows" and ".exe" or "") binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % PLATFORM) if PLATFORM["os"] == "android": log.info("Detected binary folder: %s" % binary_dir) binary_dir_legacy = binary_dir.replace("/storage/emulated/0", "/storage/emulated/legacy") if os.path.exists(binary_dir_legacy): binary_dir = binary_dir_legacy log.info("Using binary folder: %s" % binary_dir) app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID, "bin", "%(os)s_%(arch)s" % PLATFORM) else: dest_binary_dir = os.path.join(xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % PLATFORM) try: binary_dir = binary_dir.decode("latin1") dest_binary_dir = dest_binary_dir.decode("latin1") except UnicodeEncodeError: log.info("Unable to decode: binary_dir=%s dest_binary_dir=%s" % (repr(binary_dir), repr(dest_binary_dir))) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) if not os.path.exists(binary_path): notify(ADDON.getLocalizedString(30103).encode('utf-8')) system_information() return False, False if not os.path.exists(dest_binary_path) or get_quasard_checksum(dest_binary_path) != get_quasard_checksum(binary_path): log.info("Updating quasar daemon...") try: os.makedirs(dest_binary_dir) except OSError: pass try: shutil.rmtree(dest_binary_dir) except OSError as e: log.error("Unable to remove destination path for update: %s" % e) system_information() pass try: shutil.copytree(binary_dir, dest_binary_dir) except OSError as e: log.error("Unable to copy to destination path for update: %s" % e) notify(ADDON.getLocalizedString(30227).encode('utf-8')) system_information() pass # Clean stale files in the directory, as this can cause headaches on # Android when they are unreachable dest_files = set(os.listdir(dest_binary_dir)) orig_files = set(os.listdir(binary_dir)) log.info("Deleting stale files %s" % (dest_files - orig_files)) for file_ in (dest_files - orig_files): path = os.path.join(dest_binary_dir, file_) if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def GetLocalizedString(label): try: return ADDON.getLocalizedString(int(label[9:-1])).encode('utf-8') except: return label
def getLocalizedLabel(label): try: return ADDON.getLocalizedString(int(label[9:-1])).encode( 'utf-8', 'ignore') except: return label
def getLocalizedLabel(label): try: return ADDON.getLocalizedString(int(label[9:-1])).encode('utf-8', 'ignore') except: return label
def getLocalizedString(stringId): try: return ADDON.getLocalizedString(stringId).encode('utf-8', 'ignore') except: return stringId
def GetLocalizedString(self, *args, **kwargs): return ADDON.getLocalizedString(*args, **kwargs).encode('utf-8', 'ignore')