示例#1
0
文件: kitana.py 项目: chopeta/Kitana
    def choose_plugin(self,
                      key=None,
                      identifier=None,
                      default_identifier=None):
        plugins = []
        try:
            plugins = self.plugins = self.server_plugins.get("Directory", [])
        except HTTPError as e:
            if e.response.status_code == 401:
                print(
                    "Access denied when accessing plugins on {}, going to server selection"
                    .format(mask_str(self.server_name)))
                message(
                    "Access denied for plugins on {}".format(self.server_name),
                    "ERROR")
                raise cherrypy.HTTPRedirect(cherrypy.url("/servers"))

        if (key and identifier) or default_identifier:
            ident = identifier or default_identifier
            for plugin in plugins:
                if plugin["identifier"] == ident:
                    self.plugin = plugin

                    print("Plugin chosen: {}".format(plugin["title"]))
                    raise cherrypy.HTTPRedirect(cherrypy.url("/"))

        template = env.get_template('plugins.jinja2')

        return template.render(plex_headers_json=json.dumps(self.plex_headers),
                               **self.default_context)
示例#2
0
文件: kitana.py 项目: chopeta/Kitana
    def get_plex_token(self, username=None, password=None, token=None):
        if username and password:
            r = self.session.post("https://plex.tv/users/sign_in.json", {
                "user[login]": username,
                "user[password]": password,
            },
                                  headers=self.plex_headers,
                                  **self.req_defaults)
            try:
                r.raise_for_status()
            except HTTPError as e:
                if e.response.status_code == 401:
                    message("Wrong username and/or password", "ERROR")
            else:
                self.plex_token = r.json()["user"]["authToken"]
                print("Token received via credentials login")
                raise cherrypy.HTTPRedirect(cherrypy.url("/"))

        if token:
            self.plex_token = token
            print("Token received via plex.tv auth")
            return json.dumps({"url": cherrypy.url(self.prefix)})

        template = env.get_template('token.jinja2')
        return template.render(plex_headers_json=json.dumps(self.plex_headers),
                               **self.default_context)
示例#3
0
    def default(self, *args, **kwargs):
        self.ensure_pms_data()

        query_params = "&".join("=".join([k, v]) for k, v in kwargs.items())
        path = "/".join(args) + ("?" + query_params if query_params else "")
        # print(args, path)
        if not path:
            path = self.plugin["key"][1:]

        try:
            return self.render_plugin(path)
        except (HTTPError, Timeout) as e:
            if isinstance(e, HTTPError):
                if e.response.status_code == 401:
                    message("Access denied on {}".format(self.server_name),
                            "ERROR")
                    print("Access denied when accessing {},"
                          " going to server selection".format(
                              mask_str(self.server_name)))
                    self.server_name = None
                    self.connection = None
                    raise cherrypy.HTTPRedirect(cherrypy.url("/servers"))
                elif e.response.status_code == 404:
                    raise cherrypy.HTTPRedirect(cherrypy.url("/plugins"))

            else:
                message("Timeout on {}".format(self.server_name), "WARNING")

            print(
                "Error when connecting to '{}', trying other connection to: {}"
                .format(mask_url(self.server_addr),
                        mask_str(self.server_name)))
            return self.discover_pms(self.server_name)
        except:
            print("Something went wrong. {}".format(traceback.format_exc()))
示例#4
0
文件: kitana.py 项目: pannal/Kitana
 def plugin_restart(self, *args, **kwargs):
     self.ensure_pms_data()
     path = ":/plugins/{}/restart".format(self.plugin["identifier"])
     r = self._dispatch(path)
     if r.status_code == 200:
         message("Plugin restart triggered", "SUCCESS")
     else:
         message("Something went wrong when trying to restart the plugin", "ERROR")
     raise cherrypy.HTTPRedirect(cherrypy.url("/"))
示例#5
0
文件: kitana.py 项目: chopeta/Kitana
    def render_plugin(self,
                      path,
                      template=template,
                      merge_item_keys=("Video", "Directory"),
                      only_return_items=False):
        content = self.plex_dispatch(path)

        try:
            has_content = int(content["size"]) > 0
        except ValueError:
            has_content = False

        if not has_content:
            redirect = content.get("title2", None)
            # this is basically meant for SZ. title2 can contain a full URL to which we will redirect
            if redirect and self.is_url(redirect):
                if self.connections:
                    f = furl(redirect)

                    # try finding the current PMS in the link
                    is_current_pms = filter(
                        lambda c: c["address"] == f.host or f.host in c["url"],
                        self.connections)
                    if is_current_pms:
                        # use current PMS connection for the link
                        con = furl(self.server_addr)
                        f.host = con.host
                        f.port = con.port
                        redirect = f
                        r = requests.get(f)

                        # special handling for data
                        if r.headers['content-type'] != 'text/html':
                            data = io.BytesIO(r.content)
                            # set headers
                            for hdr in ("Content-Type", "Content-Disposition",
                                        "Content-Length"):
                                cherrypy.response.headers[hdr] = r.headers[hdr]

                            # serve
                            return static.serve_fileobj(data)
                raise cherrypy.HTTPRedirect(redirect)

            message("No plugin data returned", "WARNING")
            print("No plugin data returned, returning to plugin selection")
            self.plugin = None
            raise cherrypy.HTTPRedirect(cherrypy.url("/"))

        items = self.merge_plugin_data(content, keys=merge_item_keys)
        if only_return_items:
            return items

        return template.render(data=content,
                               items=items,
                               **self.default_context)
示例#6
0
文件: kitana.py 项目: pannal/Kitana
def maintenance():
    if kitana.has_update:
        message("Version {} is available. Please update{}".format(kitana.has_update,
                                                                  " your docker container"
                                                                  if kitana.running_as == "docker" else ""),
                persistent=True, data={"version": kitana.VERSION, "new_version": kitana.has_update})
        kitana.has_update = False

    if not kitana.maintenance_ran:
        try:
            kitana.run_maintenance()
        except:
            pass
        kitana.maintenance_ran = True
示例#7
0
    def render_plugin(self, path):
        content = self.plex_dispatch(path)

        try:
            has_content = int(content["size"]) > 0
        except ValueError:
            has_content = False

        if not has_content:
            message("No plugin data returned", "WARNING")
            print("No plugin data returned, returning to plugin selection")
            self.plugin = None
            raise cherrypy.HTTPRedirect(cherrypy.url("/"))

        items = self.merge_plugin_data(content)
        content["Directory"] = None
        content["Video"] = None

        return template.render(data=content,
                               items=items,
                               **self.default_context)
示例#8
0
文件: kitana.py 项目: chopeta/Kitana
 def plugin_prefs(self, *args, **kwargs):
     self.ensure_pms_data()
     url = ":/plugins/{}/prefs".format(self.plugin["identifier"])
     if cherrypy.request.method == "POST":
         items = self.render_plugin(url,
                                    settings_template,
                                    merge_item_keys=("Setting", ),
                                    only_return_items=True)
         diff = {}
         for item in items:
             new_val = Kitana.normalize_post_ret_value(
                 kwargs.get(item["id"]))
             if item["value"] != new_val:
                 diff[item["id"]] = new_val
         if diff:
             path = "{}/:/prefs/set".format(self.plugin["key"][1:])
             r = self._dispatch(path, data=diff)
             if r.status_code == 200:
                 message("Settings saved", "SUCCESS")
             else:
                 message("Something went wrong", "ERROR")
             raise cherrypy.HTTPRedirect(cherrypy.url("/"))
         else:
             print("No changed settings")
             message("No settings have been changed", "SECONDARY")
             raise cherrypy.HTTPRedirect(cherrypy.url("/"))
     else:
         return self.render_plugin(url,
                                   settings_template,
                                   merge_item_keys=("Setting", ))
示例#9
0
文件: kitana.py 项目: chopeta/Kitana
    def discover_pms(self,
                     server_name=None,
                     server_addr=None,
                     blacklist_addr=None):
        try:
            r = self.session.get(
                "https://plex.tv/api/resources?includeHttps=1&includeRelay=1",
                headers=self.full_headers,
                timeout=self.plextv_timeout)
            r.raise_for_status()
        except (HTTPError, Timeout) as e:
            if isinstance(e, HTTPError):
                if e.response.status_code == 401:
                    self.plex_token = None
                    self.server_name = None
                    self.connection = None
                    print("Access denied when accessing {}, going to login".
                          format(self.server_name))
                    raise cherrypy.HTTPRedirect(cherrypy.url("/token"))
            raise

        content = xmltodict.parse(r.content,
                                  attr_prefix="",
                                  force_list=("Device", "Connection"))
        servers = OrderedDict()
        # import pprint
        # pprint.pprint(content)
        use_connection = None
        connections = []
        for device in content["MediaContainer"].get("Device", []):
            if device.get("provides") != "server" or not bool(
                    device.get("presence")):
                continue

            public_address_matches = device.get("publicAddressMatches",
                                                "0") == "1"
            https_required = device.get("httpsRequired", "0") == "1"

            for connection in device.get("Connection", []):
                connection["unavailable"] = False
                if not public_address_matches and connection.get("local",
                                                                 "0") == "1":
                    continue

                elif https_required and connection.get("protocol",
                                                       "http") != "https":
                    continue

                if device["name"] not in servers:
                    if self.only_owned and not device.get("owned", "0") == "1":
                        continue

                    servers[device["name"]] = {
                        "connections": [],
                        "owned": device.get("owned", "0") == "1",
                        "publicAddress": device.get("publicAddress", None),
                        "publicAddressMatches": public_address_matches
                    }

                if blacklist_addr and connection["uri"] in blacklist_addr:
                    print("{}: {} on blacklist, skipping".format(
                        mask_str(device["name"]), mask_url(connection["uri"])))
                    connection["unavailable"] = True
                    continue

                servers[device["name"]]["connections"].append(connection)
                if server_name and server_name == device["name"]:
                    if server_addr and connection["uri"] == server_addr:
                        use_connection = connection

                    elif server_addr and server_addr == "relay" and connection.get(
                            "relay") == "1":
                        use_connection = connection

                    elif not server_addr:
                        use_connection = connection

                    if use_connection:
                        connections = device["Connection"]
                        break

        if server_name and use_connection:
            self.server_name = server_name
            self.connection = use_connection
            self.connections = connections
            server_addr = use_connection["uri"]

            print("Server set to: {}, {}".format(mask_str(server_name),
                                                 mask_url(server_addr)))
            print("Verifying {}: {}".format(mask_str(server_name),
                                            mask_url(server_addr)))
            try:
                self.session.get(self.server_addr + "servers",
                                 headers=self.full_headers,
                                 **self.req_defaults)
            except HTTPError as e:
                if e.response.status_code == 401:
                    self.plex_token = None
                    self.server_name = None
                    self.connection = None
                    print("Access denied when accessing {}, going to login".
                          format(mask_str(self.server_name)))
                    raise cherrypy.HTTPRedirect(cherrypy.url("/token"))
            except Timeout as e:
                if not blacklist_addr:
                    blacklist_addr = []
                blacklist_addr.append(server_addr)
                print("{}: Blacklisting {} due to: {!r}".format(
                    mask_str(server_name), mask_url(server_addr), type(e)))
                return self.discover_pms(server_name=server_name,
                                         server_addr=None,
                                         blacklist_addr=blacklist_addr)

            print("Verified {}: {}".format(mask_str(server_name),
                                           mask_url(server_addr)))
            self.plugin = None
            message("Successfully connected to {}".format(self.server_name),
                    "SUCCESS")
            raise cherrypy.HTTPRedirect(cherrypy.url("/"))

        return servers
示例#10
0
文件: kitana.py 项目: sunnyd24/Kitana
    def default(self, *args, **kwargs):
        self.ensure_pms_data()

        query_params = "&".join("=".join([k, v]) for k, v in kwargs.items())
        path = "/".join(args) + ("?" + query_params if query_params else "")
        # print(args, path)
        if not path:
            path = self.plugin["key"][1:]

        try:
            return self.render_plugin(path)

        except (HTTPError, Timeout, requests.exceptions.SSLError) as e:
            urlTried = getattr(getattr(e, "request", ""), "url", None)
            if urlTried:
                urlTried = mask_url(urlTried)

            try:
                if not isinstance(e, Timeout):
                    if hasattr(e.response, "status_code"):
                        if e.response.status_code == 401:
                            message(
                                "Access denied on {}".format(self.server_name),
                                "ERROR")
                            print("Access denied when accessing {},"
                                  " going to server selection".format(
                                      mask_str(self.server_name)))
                            self.server_name = None
                            self.connection = None
                            raise cherrypy.HTTPRedirect(
                                cherrypy.url("/servers"))
                        elif e.response.status_code == 404:
                            raise cherrypy.HTTPRedirect(cherrypy.url("/"))

                else:
                    message("Timeout on {}".format(self.server_name),
                            "WARNING")

                if hasattr(e.response, "text") and e.response.text:
                    print("Plugin response: {}".format(e.response.text))

                if hasattr(e.response,
                           "status_code") and e.response.status_code != 500:
                    message(
                        "Error on {} (see log): {}".format(
                            self.server_name, e), "ERROR")
                    traceback.print_exc()
                    print(
                        "Error when connecting to '{}', trying other connection to: {}"
                        .format(mask_url(self.server_addr),
                                mask_str(self.server_name)))
                    return self.discover_pms(self.server_name)
                else:
                    message(
                        "Plugin error on {} (see log): {}".format(
                            self.server_name, e), "ERROR")
                    traceback.print_exc()
                    raise cherrypy.HTTPRedirect(cherrypy.url("/"))
            except cherrypy.HTTPRedirect:
                # intercept redirects to avoid infinite redirects
                lastUrls = cherrypy.session.get("last_urls", [])
                lastUrls.append(urlTried)

                if lastUrls.count(urlTried) > 2:
                    print("Tried to reach {} 3 times. Not retrying.".format(
                        urlTried))
                    message(
                        "Tried to reach {} 3 times. Not retrying.".format(
                            urlTried), "ERROR")
                    cherrypy.session["last_urls"] = []
                    return self.discover_pms(self.server_name)

                cherrypy.session["last_urls"] = lastUrls
                raise
        except HTTPRedirect:
            raise
        except:
            print("Something went wrong. {}".format(traceback.format_exc()))