Exemplo n.º 1
0
def device_auth():
    code_data = get_device_code()
    if not code_data:
        logger.error('Failed device auth.')
        sys.exit(1)

    logger.info(f"Verification URL: {code_data['verification_url']}")
    logger.info(f"User Code: {code_data['user_code']}")
    notify("Open {verification_url} in your browser and enter this code: "
           "{user_code}".format(**code_data),
           timeout=60,
           stdout=True)
    webbrowser.open(code_data['verification_url'])

    start = time.time()
    while time.time() - start < code_data['expires_in']:
        token_data = get_device_token(code_data['device_code'])
        if not token_data:
            logger.debug('Waiting for user to authorize the app.')
            time.sleep(int(code_data['interval']))
        else:
            notify('App authorized successfully.', stdout=True)
            logger.info('Device auth successful.')
            break
    else:
        logger.error('Timed out during auth.')
    return token_data
Exemplo n.º 2
0
def merge_categories(root: dict, user, default=True, parents=[]):
    """Merge data from user config with default categories"""
    if not isinstance(user, (dict, bool)):
        logger.error(f"Invalid value {user} for category {'.'.join(parents)}")
        return
    if isinstance(user, dict):
        # check for extra keys not present in existing categories
        extra = set(user.keys()).difference(root)
        if extra:
            msg = f"Extra categor{'ies' if len(extra) > 1 else 'y'}"
            if parents:
                msg += f" under {'.'.join(parents)}"
            msg += f": {', '.join(extra)}"
            logger.warning(msg)

    for k, v in root.items():
        value = user if isinstance(user, bool) else user.get(k, default)
        if v:  # recurse for sub-categories
            parents.append(k)
            merge_categories(v, value, default)
            parents.pop()
        elif isinstance(value, bool):
            root[k] = value
        else:
            logger.error(
                f"Expected bool(true/false) but found {value} for category "
                f"{'.'.join(parents + [k])}"
            )
Exemplo n.º 3
0
 def autoload_cfg(cls):
     template = getattr(cls, 'CONFIG_TEMPLATE', None)
     monitor_cfg = config['players'][cls.name].get(template)
     auto_keys = {k for k, v in monitor_cfg.items() if v == "auto-detect"}
     if not auto_keys:
         return monitor_cfg
     try:
         loaders = getattr(cls, "read_player_cfg")(auto_keys)
     except AttributeError:
         logger.debug(f"Auto val not found for {', '.join(auto_keys)}")
         logger.error(f"Autoload not supported for {cls.name}.")
         raise AutoloadError
     except FileNotFoundError as e:
         raise AutoloadError(src=e.filename)
     while auto_keys:
         param = auto_keys.pop()
         try:
             param_loader = loaders[param]
         except KeyError:
             logger.error(f"Autoload not supported for '{param}'.")
             raise AutoloadError(param)
         try:
             monitor_cfg[param] = param_loader()
             logger.debug(
                 f"Autoloaded {cls.name} {param} = {monitor_cfg[param]}")
         except FileNotFoundError as e:
             raise AutoloadError(src=e.filename)
     return monitor_cfg
Exemplo n.º 4
0
    def refresh_token(self):
        if self._refresh_retries == self._REFRESH_RETRIES_LIMIT:
            self.token_data = {}
            self._refresh_retries = 0

            logger.critical("Too many failed refreshes. Clearing token.")
            notify("Trakt token expired. Couldn't auto-refresh token.", stdout=True)
            self.device_auth()
            return

        exchange_params = {
            "url": API_URL + '/oauth/token',
            "headers": {"Content-Type": "application/json"},
            "json": {
                "refresh_token": self.token_data['refresh_token'],
                "client_id": self.CLIENT_ID,
                "client_secret": self.CLIENT_SECRET,
                "redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
                "grant_type": "refresh_token"
            }
        }
        self._refresh_retries += 1
        exchange_resp = safe_request('post', exchange_params)

        if exchange_resp and exchange_resp.status_code == 200:
            self.token_data = exchange_resp.json()
            self._refresh_retries = 0
            logger.info('Refreshed access token.')
        else:
            logger.error("Error refreshing token.")
Exemplo n.º 5
0
    def device_auth(self):
        code_data = self.get_device_code()
        if not code_data:
            logger.error("Could not get device code.")
            return

        logger.info(f"Verification URL: {code_data['verification_url']}")
        logger.info(f"User Code: {code_data['user_code']}")
        notify(
            "Open {verification_url} in your browser and enter this code: "
            "{user_code}".format(**code_data), timeout=30, stdout=True,
            category="trakt")

        # automatically open the url in the default browser
        # but we don't want to use terminal-based browsers - most likely not
        # what the user wants
        term_bak = os.environ.pop("TERM", None)
        webbrowser.open(code_data['verification_url'])
        if term_bak is not None:
            os.environ["TERM"] = term_bak

        start = time.time()
        while time.time() - start < code_data['expires_in']:
            if self.get_device_token(code_data['device_code']):
                notify('App authorized successfully.',
                       stdout=True, category="trakt")
                logger.info('App authorized successfully.')
                break
            logger.debug('Waiting for user to authorize the app.')
            time.sleep(int(code_data['interval']))
        else:
            logger.error('Timed out during auth.')
Exemplo n.º 6
0
    def device_auth(self):
        code_data = self.get_device_code()
        if not code_data:
            logger.error("Could not get device code.")
            return

        logger.info(f"Verification URL: {code_data['verification_url']}")
        logger.info(f"User Code: {code_data['user_code']}")
        notify("Open {verification_url} in your browser and enter this code: "
               "{user_code}".format(**code_data),
               timeout=30,
               stdout=True,
               category="trakt")
        webbrowser.open(code_data['verification_url'])

        start = time.time()
        while time.time() - start < code_data['expires_in']:
            if self.get_device_token(code_data['device_code']):
                notify('App authorized successfully.',
                       stdout=True,
                       category="trakt")
                logger.info('App authorized successfully.')
                break
            logger.debug('Waiting for user to authorize the app.')
            time.sleep(int(code_data['interval']))
        else:
            logger.error('Timed out during auth.')
Exemplo n.º 7
0
 def __new__(cls, *args, **kwargs):
     try:
         cls.config = cls.autoload_cfg()
     except AutoloadError as e:
         logger.debug(str(e))
         logger.error(f"Config value autoload failed for {cls.name}.")
     except Exception:
         logger.exception(f"Config value autoload failed for {cls.name}.")
     else:
         return super().__new__(cls)
Exemplo n.º 8
0
 def __new__(cls, *args, **kwargs):
     try:
         cls.inject_base_config()
         cls.config = cls.autoload_cfg()
     except AutoloadError as e:
         logger.debug(str(e))
         logger.error(f"Config value autoload failed for {cls.name}.")
         notify(f"Check log file. {e!s}", category="exception")
     except Exception:
         msg = f"Config value autoload failed for {cls.name}."
         logger.exception(msg)
         notify(f"{msg} Check log file.", category="exception")
     else:
         return super().__new__(cls)
Exemplo n.º 9
0
 def get_token(self):
     logger.info("Retrieving plex token")
     login = self.ask("Plex login ID:")
     pwd = self.secret("Plex password:"******"user"]["authToken"]
     elif resp is not None:
         err_msg = resp.json().get("error", resp.text)
         self.line(err_msg, "error")
         logger.error(err_msg)
         return None
     else:
         logger.error("Unable to get access token")
         return None
Exemplo n.º 10
0
 def __init__(self, scrobble_queue):
     try:
         self.token = get_token()
         self.URL = self.URL.format(**self.config)
     except KeyError:
         logger.exception("Check config for correct Plex params.")
         return
     if not self.token:
         logger.error("Unable to retrieve plex token.")
         return
     super().__init__(scrobble_queue)
     self.sess.headers["Accept"] = "application/json"
     self.sess.headers["X-Plex-Token"] = self.token
     self.session_url = self.URL + "/status/sessions"
     self.media_info_cache = {}
Exemplo n.º 11
0
 def handle_cmd_response(self, resp):
     command = self.sent_commands.pop(resp['request_id'])
     if resp['error'] != 'success':
         logger.error(f'Error with command {command!s}. Response: {resp!s}')
         return
     elif command[0] != 'get_property':
         return
     param = command[1]
     data = resp['data']
     if param == 'pause':
         self.vars['state'] = 1 if data else 2
     if param in self.WATCHED_PROPS:
         self.vars[param] = data
         self.updated_props_count += 1
     if self.updated_props_count == len(self.WATCHED_PROPS):
         self.update_status()
Exemplo n.º 12
0
def get_access_token():
    global token_data
    if not token_data:
        logger.info("Access token not found in config. "
                    "Initiating device authentication.")
        token_data = device_auth()
        write_json(token_data, TRAKT_TOKEN_PATH)
    elif token_data['created_at'] + token_data['expires_in'] - \
            time.time() < 86400:
        logger.info("Access token about to expire. Refreshing.")
        token_data = refresh_token(token_data)
        write_json(token_data, TRAKT_TOKEN_PATH)
    if not token_data:
        logger.error("Unable to get access token. "
                     f"Try deleting {TRAKT_TOKEN_PATH!s} and retry.")
        notify("Failed to authorize application.", stdout=True)
        sys.exit(1)
    return token_data['access_token']
Exemplo n.º 13
0
    def run(self):
        while True:
            try:
                self.update_status()
            except requests.ConnectionError:
                logger.info(f'Unable to connect to {self.name}. Ensure that '
                            'the web interface is running.')
                self.status = {}
            except requests.HTTPError as e:
                logger.error(f"Error while getting data from {self.name}: {e}")
                break
            if not self.status.get("filepath") and not self.status.get(
                    "media_info"):
                self.status = {}
            self.handle_status_update()
            time.sleep(self.poll_interval)

        logger.warning(f"{self.name} monitor stopped")
Exemplo n.º 14
0
def get_token():
    global token_data
    if not token_data:
        logger.info("Retrieving plex token")
        login = input("Plex login ID: ")
        pwd = getpass()
        resp = plex_token_auth(login, pwd)
        if resp.ok:
            token_data = {"token": resp.json()["user"]["authToken"]}
            write_json(token_data, PLEX_TOKEN_PATH)
            logger.info(f"Saved plex token to {PLEX_TOKEN_PATH}")
        elif resp is not None:
            print(resp.json().get("error", resp.text))
            return None
        else:
            logger.error("Unable to get access token. "
                         f"Try deleting {PLEX_TOKEN_PATH!s} and retry.")
            return None
    return token_data['token']
Exemplo n.º 15
0
def get_device_token(device_code):
    token_request_params = {
        "url": API_URL + "/oauth/device/token",
        "headers": {"Content-Type": "application/json"},
        "json": {
            "code": device_code,
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET
        }
    }
    token_resp = safe_request('post', token_request_params)
    if not token_resp:
        return
    elif token_resp.status_code == 400:
        return
    elif token_resp.status_code == 200:
        return token_resp.json()
    else:
        logger.error('Invalid status code of token response.')
        sys.exit(1)