Exemple #1
0
    def signin(cls, username=None, password=None, session=None):
        """ Returns a new :class:`~myplex.MyPlexAccount` object by connecting to MyPlex with the
            specified username and password. This is essentially logging into MyPlex and often
            the very first entry point to using this API.

            Parameters:
                username (str): Your MyPlex.tv username. If not specified, it will check the config.ini file.
                password (str): Your MyPlex.tv password. If not specified, it will check the config.ini file.

            Raises:
                :class:`~plexapi.exceptions.Unauthorized`: (401) If the username or password are invalid.
                :class:`~plexapi.exceptions.BadRequest`: If any other errors occured not allowing us to log into MyPlex.tv.
        """
        if 'X-Plex-Token' in plexapi.BASE_HEADERS:
            del plexapi.BASE_HEADERS['X-Plex-Token']
        username = username or CONFIG.get('authentication.username')
        password = password or CONFIG.get('authentication.password')
        auth = (username, password)
        log.info('POST %s', cls.SIGNIN)
        sess = session or requests.Session()
        response = sess.post(cls.SIGNIN,
                             headers=plexapi.BASE_HEADERS,
                             auth=auth,
                             timeout=TIMEOUT)
        if response.status_code != requests.codes.created:
            codename = codes.get(response.status_code)[0]
            if response.status_code == 401:
                raise Unauthorized('(%s) %s' %
                                   (response.status_code, codename))
            raise BadRequest('(%s) %s' % (response.status_code, codename))
        data = ElementTree.fromstring(response.text.encode('utf8'))
        return MyPlexAccount(data, cls.SIGNIN, session=sess)
Exemple #2
0
    def query(self, path, method=None, headers=None, **kwargs):
        """ Main method used to handle HTTPS requests to the Plex server. This method helps
            by encoding the response to utf-8 and parsing the returned XML into and
            ElementTree object. Returns None if no data exists in the response.

            Parameters:
                path (str): Relative path to query on the server api (ex: '/search?query=HELLO')
                method (func): requests.method to use for this query (request.get or
                    requests.put; defaults to get)
                headers (dict): Optionally include additional headers for this request.
                **kwargs (dict): Optionally include additional kwargs for in the specified
                    reuqest method. These kwargs are simply passed through to method().

            Raises:
                :class:`~plexapi.exceptions.BadRequest`: Raised when response is not in (200, 201).
        """
        url = self.url(path)
        method = method or self.session.get
        log.info('%s %s', method.__name__.upper(), url)
        h = self.headers().copy()
        if headers:
            h.update(headers)
        response = method(url, headers=h, timeout=TIMEOUT, **kwargs)
        #print(response.url)
        if response.status_code not in [200, 201]:  # pragma: no cover
            codename = codes.get(response.status_code)[0]
            raise BadRequest('(%s) %s %s' %
                             (response.status_code, codename, response.url))
        data = response.text.encode('utf8')
        return ElementTree.fromstring(data) if data else None
Exemple #3
0
def _listItems(url, token, cls):
    """ Builds list of classes from a XML response. """
    headers = plexapi.BASE_HEADERS
    headers['X-Plex-Token'] = token
    log.info('GET %s?X-Plex-Token=%s', url, token)
    response = requests.get(url, headers=headers, timeout=TIMEOUT)
    data = ElementTree.fromstring(response.text.encode('utf8'))
    return [cls(elem) for elem in data]
Exemple #4
0
 def query(self, url, method=None, headers=None, timeout=None, **kwargs):
     method = method or self._session.get
     timeout = timeout or TIMEOUT
     log.debug('%s %s %s', method.__name__.upper(), url, kwargs.get('json', ''))
     headers = self._headers(**headers or {})
     response = method(url, headers=headers, timeout=timeout, **kwargs)
     if response.status_code not in (200, 201, 204):  # pragma: no cover
         codename = codes.get(response.status_code)[0]
         errtext = response.text.replace('\n', ' ')
         raise BadRequest('(%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
     data = response.text.encode('utf8')
     return ElementTree.fromstring(data) if data.strip() else None
Exemple #5
0
 def query(self, url, method=None, headers=None, timeout=None, **kwargs):
     method = method or self._session.get
     timeout = timeout or TIMEOUT
     log.debug('%s %s %s', method.__name__.upper(), url, kwargs.get('json', ''))
     headers = self._headers(**headers or {})
     response = method(url, headers=headers, timeout=timeout, **kwargs)
     if response.status_code not in (200, 201, 204):  # pragma: no cover
         codename = codes.get(response.status_code)[0]
         errtext = response.text.replace('\n', ' ')
         log.warning('BadRequest (%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
         raise BadRequest('(%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
     data = response.text.encode('utf8')
     return ElementTree.fromstring(data) if data.strip() else None
Exemple #6
0
 def query(self, url, method=None, headers=None, **kwargs):
     method = method or self._session.get
     delim = '&' if '?' in url else '?'
     url = '%s%sX-Plex-Token=%s' % (url, delim, self._token)
     log.debug('%s %s', method.__name__.upper(), url)
     allheaders = BASE_HEADERS.copy()
     allheaders.update(headers or {})
     response = method(url, headers=allheaders, timeout=TIMEOUT, **kwargs)
     if response.status_code not in (200, 201):
         codename = codes.get(response.status_code)[0]
         log.warn('BadRequest (%s) %s %s' %
                  (response.status_code, codename, response.url))
         raise BadRequest('(%s) %s' % (response.status_code, codename))
     data = response.text.encode('utf8')
     return ElementTree.fromstring(data) if data.strip() else None
Exemple #7
0
 def query(self, key, method=None, headers=None, timeout=None, **kwargs):
     """ Main method used to handle HTTPS requests to the Plex server. This method helps
         by encoding the response to utf-8 and parsing the returned XML into and
         ElementTree object. Returns None if no data exists in the response.
     """
     url = self.url(key)
     method = method or self._session.get
     timeout = timeout or TIMEOUT
     log.debug('%s %s', method.__name__.upper(), url)
     headers = self._headers(**headers or {})
     response = method(url, headers=headers, timeout=timeout, **kwargs)
     if response.status_code not in (200, 201):
         codename = codes.get(response.status_code)[0]
         log.warn('BadRequest (%s) %s %s' %
                  (response.status_code, codename, response.url))
         raise BadRequest('(%s) %s' % (response.status_code, codename))
     data = response.text.encode('utf8')
     return ElementTree.fromstring(data) if data.strip() else None
Exemple #8
0
 def query(self, key, method=None, headers=None, timeout=None, **kwargs):
     """ Main method used to handle HTTPS requests to the Plex server. This method helps
         by encoding the response to utf-8 and parsing the returned XML into and
         ElementTree object. Returns None if no data exists in the response.
     """
     url = self.url(key)
     method = method or self._session.get
     timeout = timeout or TIMEOUT
     log.debug('%s %s', method.__name__.upper(), url)
     headers = self._headers(**headers or {})
     response = method(url, headers=headers, timeout=timeout, **kwargs)
     if response.status_code not in (200, 201):
         codename = codes.get(response.status_code)[0]
         errtext = response.text.replace('\n', ' ')
         log.warning('BadRequest (%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
         raise BadRequest('(%s) %s; %s %s' % (response.status_code, codename, response.url, errtext))
     data = response.text.encode('utf8')
     return ElementTree.fromstring(data) if data.strip() else None
Exemple #9
0
 def query(self, path, method=None, headers=None, timeout=None, **kwargs):
     """ Main method used to handle HTTPS requests to the Plex client. This method helps
         by encoding the response to utf-8 and parsing the returned XML into and
         ElementTree object. Returns None if no data exists in the response.
     """
     url = self.url(path)
     method = method or self._session.get
     timeout = timeout or TIMEOUT
     log.debug('%s %s', method.__name__.upper(), url)
     headers = self._headers(**headers or {})
     response = method(url, headers=headers, timeout=timeout, **kwargs)
     if response.status_code not in (200, 201, 204):
         codename = codes.get(response.status_code)[0]
         errtext = response.text.replace('\n', ' ')
         message = '(%s) %s; %s %s' % (response.status_code, codename, response.url, errtext)
         if response.status_code == 401:
             raise Unauthorized(message)
         elif response.status_code == 404:
             raise NotFound(message)
         else:
             raise BadRequest(message)
     data = response.text.encode('utf8')
     return ElementTree.fromstring(data) if data.strip() else None
Exemple #10
0
def cli(username, password, server, library):
    """Set Plex music album covers to the corresponding front covers embedded in the contained MP3 files.

    USERNAME is the Plex account username to use.\n
    SERVER is the Plex server to connect to.\n
    LIBRARY is the Plex music library to work on.

    Password can be specified via the --password option or provided in the PLEX_PASSWORD environment variable.
    """

    try:
        plex = get_plex(username, password, server)

        music = None
        try:
            music = plex.library.section(library)
            logger.info("Retrieved Plex music library.")
        except:
            logger.exception("Couldn't get Plex music library. Is the specified music library correct?")
            raise

        try:
            albums = music.albums()
        except:
            logger.exception("Couldn't retrieve albums from library.")
            raise

        if not albums:
            logger.info("No albums found.")

        for album in albums:
            logger.info("Working on: {artist} - {album}".format(artist=album.parentTitle, album=album.title))

            posters_url = "{url}/posters".format(url=plex.url(album.key))
            container = None
            try:
                response = plex._session.get(posters_url, headers=plex._headers())
                response.raise_for_status()
                data = response.text.encode('utf8')
                container = ElementTree.fromstring(data) if data.strip() else None
            except:
                logger.exception("Couldn't fetch album convers from Plex.")
                raise

            if container and len(container) > 1:
                logger.info("Found multiple covers. Looking for embedded front cover...")

                # If we have different covers across multiple tracks in the same album
                # we have no good way to select one of them, therefore we'd choose a
                # one indiscriminately. If we are to choose a cover indiscriminately
                # we may as well pick the first one and avoid reading all files in the
                # album. So we do that.
                file_ = get_file_from_track(album.tracks()[0])
                front_cover_pic = get_front_cover_pic(file_)

                if front_cover_pic:
                    logger.info("Found an embedded cover. Updating album cover...")
                    try:
                        response = plex._session.post(posters_url, data=front_cover_pic, headers=plex._headers())
                        response.raise_for_status()
                        logger.info("Album cover updated successfully.")
                    except:
                        logger.exception("Couldn't update album cover in Plex.")
                        raise
                else:
                    logger.info("No embedded front covers found.")
            else:
                logger.info("Single or no cover found. Nothing to do.")

    except:
        exit(1)