def _get_influx_connection(self):
        """
        Create an InfluxDB connection and test to make sure it works.
        We test with the get all users command.  If the address is bad it fails
        with a 404.  If the user doesn't have permission it fails with 401
        :return:
        """
        # TODO - Check what permissions are actually needed to make this work
        influx = InfluxDBClient(config.influx_address,
                                config.influx_port,
                                database=config.influx_database,
                                ssl=config.influx_ssl,
                                verify_ssl=config.influx_verify_ssl,
                                username=config.influx_user,
                                password=config.influx_password,
                                timeout=5)
        try:
            log.debug(
                'Testing connection to InfluxDb using provided credentials')
            influx.get_list_users(
            )  # TODO - Find better way to test connection and permissions
            log.debug('Successful connection to InfluxDb')
        except (ConnectTimeout, InfluxDBClientError) as e:
            if isinstance(e, ConnectTimeout):
                log.critical(
                    'Unable to connect to InfluxDB at the provided address (%s)',
                    config.influx_address)
            elif e.code == 401:
                log.critical(
                    'Unable to connect to InfluxDB with provided credentials')

            sys.exit(1)

        return influx
    def get_library_data(self):

        lib_data = {}

        for server in self.plex_servers:
            libs = server.library.sections()
            log.info('We found {} libraries for server {}'.format(
                str(len(libs)), server))
            host_libs = []
            for lib in libs:
                log.info('Adding data for library %s', lib.title)
                host_lib = {'name': lib.title, 'items': len(lib.search())}

                if lib.title == 'TV Shows':
                    log.info(
                        'Processing TV Shows.  This can take awhile for large libraries'
                    )
                    seasons = 0
                    episodes = 0
                    shows = lib.search()
                    for show in shows:
                        log.debug('Checking TV Show: %s', show.title)
                        seasons += len(show.seasons())
                        episodes += len(show.episodes())
                    host_lib['episodes'] = episodes
                    host_lib['seasons'] = seasons

                host_libs.append(host_lib)

            lib_data[server._baseurl] = host_libs

        self._process_library_data(lib_data)
    def write_influx_data(self, json_data):
        """
        Writes the provided JSON to the database
        :param json_data:
        :return:
        """
        log.debug(json_data)

        try:
            self.influx_client.write_points(json_data)
        except (InfluxDBClientError, ConnectionError,
                InfluxDBServerError) as e:
            if hasattr(e, 'code') and e.code == 404:
                log.error('Database {} Does Not Exist.  Attempting To Create')
                self.influx_client.create_database(config.influx_database)
                self.influx_client.write_points(json_data)
                return
            log.error('Failed to write data to InfluxDB')

        log.debug('Written To Influx: {}'.format(json_data))
    def get_auth_token(self, username, password):
        """
        Make a reqest to plex.tv to get an authentication token for future requests
        :param username: Plex Username
        :param password: Plex Password
        :return: str
        """

        log.info('Getting Auth Token For User {}'.format(username))

        auth_string = '{}:{}'.format(username, password)
        base_auth = base64.encodebytes(bytes(auth_string, 'utf-8'))
        req = Request('https://plex.tv/users/sign_in.json')
        req = self._set_default_headers(req)
        req.add_header('Authorization',
                       'Basic {}'.format(base_auth[:-1].decode('utf-8')))

        try:
            result = urlopen(req, data=b'').read()
        except HTTPError as e:
            print('Failed To Get Authentication Token')
            if e.code == 401:
                log.error('Failed to get token due to bad username/password')
            else:
                print('Maybe this will help:')
                print(e)
                log.error('Failed to get authentication token.  No idea why')
            sys.exit(1)

        output = json.loads(result.decode('utf-8'))

        # Make sure we actually got a token back
        if 'authToken' in output['user']:
            log.debug('Successfully Retrieved Auth Token')
            return output['user']['authToken']
        else:
            print(
                'Something Broke \n We got a valid response but for some reason there\'s no auth token'
            )
            sys.exit(1)
    def _set_default_headers(self, req):
        """
        Sets the default headers need for a request
        :param req:
        :return: request
        """

        log.debug('Adding Request Headers')

        headers = {
            'X-Plex-Client-Identifier': 'Plex InfluxDB Collector',
            'X-Plex-Product': 'Plex InfluxDB Collector',
            'X-Plex-Version': '1',
            'X-Plex-Token': self.token
        }

        for k, v in headers.items():
            if k == 'X-Plex-Token' and not self.token:  # Don't add token if we don't have it yet
                continue

            req.add_header(k, v)

        return req