Example #1
0
    def get_user_gravatar_image(self, user=None):
        myDB = db.DBConnection()
        user_info = None

        try:
            query = 'SELECT xml ' \
                    'FROM %s ' \
                    'WHERE user = ? ' \
                    'ORDER BY id DESC LIMIT 1' % self.get_history_table_name()
            result = myDB.select_single(query, args=[user])
        except:
            logger.warn("Unable to open PlexWatch database.")
            return None

        xml_data = helpers.latinToAscii(result)

        try:
            xml_parse = minidom.parseString(xml_data)
        except:
            logger.warn("Error parsing XML for Plexwatch Database.")
            return None

        xml_head = xml_parse.getElementsByTagName('User')
        if not xml_head:
            logger.warn("Error parsing XML for Plexwatch Database.")
            return None

        for a in xml_head:
            user_id = self.get_xml_attr(a, 'id')
            user_thumb = self.get_xml_attr(a, 'thumb')

            user_info = {'user_id': user_id, 'user_thumb': user_thumb}

        return user_info
Example #2
0
    def get_user_gravatar_image(self, user=None):
        myDB = db.DBConnection()
        user_info = None

        try:
            query = 'SELECT xml ' \
                    'FROM %s ' \
                    'WHERE user = "******" ' \
                    'ORDER BY id DESC LIMIT 1' % (self.get_history_table_name(), user)
            result = myDB.select_single(query)
        except:
            logger.warn("Unable to open PlexWatch database.")
            return None

        xml_data = helpers.latinToAscii(result)

        try:
            xml_parse = minidom.parseString(xml_data)
        except:
            logger.warn("Error parsing XML for Plexwatch Database.")
            return None

        xml_head = xml_parse.getElementsByTagName('User')
        if not xml_head:
            logger.warn("Error parsing XML for Plexwatch Database.")
            return None

        for a in xml_head:
            user_id = self.get_xml_attr(a, 'id')
            user_thumb = self.get_xml_attr(a, 'thumb')

            user_info = {'user_id': user_id,
                         'user_thumb': user_thumb}

        return user_info
Example #3
0
    def get_recently_watched(self, user=None, limit='10'):
        myDB = db.DBConnection()
        recently_watched = []

        if not limit.isdigit():
            limit = '10'

        try:
            if user:
                query = 'SELECT time, user, xml FROM %s WHERE user = ? ORDER BY time DESC LIMIT ?' % \
                        (self.get_history_table_name())
                xml = myDB.select(query, args=[user, limit])
            else:
                query = 'SELECT time, user, xml FROM %s ORDER BY time DESC LIMIT ?' % \
                        (self.get_history_table_name())
                xml = myDB.select(query, args=[limit])
        except:
            logger.warn("Unable to open PlexWatch database.")
            return None

        for row in xml:
            xml_data = helpers.latinToAscii(row[2])
            try:
                xml_parse = minidom.parseString(xml_data)
            except:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            xml_head = xml_parse.getElementsByTagName('opt')
            if not xml_head:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            for a in xml_head:
                if self.get_xml_attr(a, 'type') == 'episode':
                    thumb = self.get_xml_attr(a, 'parentThumb')
                else:
                    thumb = self.get_xml_attr(a, 'thumb')

                recent_output = {
                    'type': self.get_xml_attr(a, 'type'),
                    'rating_key': self.get_xml_attr(a, 'ratingKey'),
                    'title': self.get_xml_attr(a, 'title'),
                    'thumb': thumb,
                    'index': self.get_xml_attr(a, 'index'),
                    'parentIndex': self.get_xml_attr(a, 'parentIndex'),
                    'year': self.get_xml_attr(a, 'year'),
                    'time': row[0],
                    'user': row[1]
                }
                recently_watched.append(recent_output)

        return recently_watched
Example #4
0
    def get_recently_watched(self, user=None, limit='10'):
        myDB = db.DBConnection()
        recently_watched = []

        if not limit.isdigit():
            limit = '10'

        try:
            if user:
                query = 'SELECT time, user, xml FROM %s WHERE user = "******" ORDER BY time DESC LIMIT %s' % \
                        (self.get_history_table_name(), user, limit)
                xml = myDB.select(query)
            else:
                query = 'SELECT time, user, xml FROM %s ORDER BY time DESC LIMIT %s' % \
                        (self.get_history_table_name(), limit)
                xml = myDB.select(query)
        except:
            logger.warn("Unable to open PlexWatch database.")
            return None

        for row in xml:
            xml_data = helpers.latinToAscii(row[2])
            try:
                xml_parse = minidom.parseString(xml_data)
            except:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            xml_head = xml_parse.getElementsByTagName('opt')
            if not xml_head:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            for a in xml_head:
                if self.get_xml_attr(a, 'type') == 'episode':
                    thumb = self.get_xml_attr(a, 'parentThumb')
                else:
                    thumb = self.get_xml_attr(a, 'thumb')

                recent_output = {'type': self.get_xml_attr(a, 'type'),
                                 'rating_key': self.get_xml_attr(a, 'ratingKey'),
                                 'title': self.get_xml_attr(a, 'title'),
                                 'thumb': thumb,
                                 'index': self.get_xml_attr(a, 'index'),
                                 'parentIndex': self.get_xml_attr(a, 'parentIndex'),
                                 'year': self.get_xml_attr(a, 'year'),
                                 'time': row[0],
                                 'user': row[1]
                                 }
                recently_watched.append(recent_output)

        return recently_watched
Example #5
0
def get_log_tail(window=20, parsed=True, log_type="server"):

    if plexpy.CONFIG.PMS_LOGS_FOLDER:
        log_file = ""
        if log_type == "server":
            log_file = os.path.join(plexpy.CONFIG.PMS_LOGS_FOLDER,
                                    'Plex Media Server.log')
        elif log_type == "scanner":
            log_file = os.path.join(plexpy.CONFIG.PMS_LOGS_FOLDER,
                                    'Plex Media Scanner.log')
    else:
        return []

    try:
        logfile = open(log_file, "r")
    except IOError as e:
        logger.error('Unable to open Plex Log file. %s' % e)
        return []

    log_lines = tail(logfile, window)

    if parsed:
        line_error = False
        clean_lines = []
        for i in log_lines:
            try:
                log_time = i.split(' [')[0]
                log_level = i.split('] ', 1)[1].split(' - ', 1)[0]
                log_msg = str(i.split('] ', 1)[1].split(' - ', 1)[1], 'utf-8')
                full_line = [log_time, log_level, log_msg]
                clean_lines.append(full_line)
            except:
                line_error = True
                full_line = ['', '', 'Unable to parse log line.']
                clean_lines.append(full_line)

        if line_error:
            logger.error(
                'Tautulli was unable to parse some lines of the Plex Media Server log.'
            )

        return clean_lines
    else:
        raw_lines = []
        for i in log_lines:
            raw_lines.append(helpers.latinToAscii(i))

        return raw_lines

    return log_lines
Example #6
0
    def get_user_platform_stats(self, user=None):
        myDB = db.DBConnection()

        platform_stats = []
        result_id = 0

        try:
            query = 'SELECT platform, COUNT(platform) as platform_count, xml ' \
                    'FROM grouped ' \
                    'WHERE user = ? ' \
                    'GROUP BY platform ' \
                    'ORDER BY platform_count DESC'
            result = myDB.select(query, args=[user])
        except:
            logger.warn("Unable to open PlexWatch database.")
            return None

        for item in result:
            xml_data = helpers.latinToAscii(item[2])

            try:
                xml_parse = minidom.parseString(xml_data)
            except:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            xml_head = xml_parse.getElementsByTagName('Player')
            if not xml_head:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            for a in xml_head:
                platform_type = self.get_xml_attr(a, 'platform')

            row = {
                'platform_name': item[0],
                'platform_type': platform_type,
                'total_plays': item[1],
                'result_id': result_id
            }
            platform_stats.append(row)
            result_id += 1

        return platform_stats
Example #7
0
    def get_user_platform_stats(self, user=None):
        myDB = db.DBConnection()

        platform_stats = []
        result_id = 0

        try:
            query = 'SELECT platform, COUNT(platform) as platform_count, xml ' \
                    'FROM %s ' \
                    'WHERE user = "******" ' \
                    'GROUP BY platform ' \
                    'ORDER BY platform_count DESC' % (self.get_history_table_name(), user)
            result = myDB.select(query)
        except:
            logger.warn("Unable to open PlexWatch database.")
            return None

        for item in result:
            xml_data = helpers.latinToAscii(item[2])

            try:
                xml_parse = minidom.parseString(xml_data)
            except:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            xml_head = xml_parse.getElementsByTagName('Player')
            if not xml_head:
                logger.warn("Error parsing XML for Plex stream data.")
                return None

            for a in xml_head:
                platform_type = self.get_xml_attr(a, 'platform')

            row = {'platform_name': item[0],
                   'platform_type': platform_type,
                   'total_plays': item[1],
                   'result_id': result_id
                   }
            platform_stats.append(row)
            result_id += 1

        return platform_stats
Example #8
0
    def get_token(self):

        plextv_response = self.get_plex_auth()

        if plextv_response:
            try:
                xml_parse = minidom.parseString(helpers.latinToAscii(plextv_response))
            except IOError, e:
                logger.warn("Error parsing XML for Plex.tv token: %s" % e)
                return False

            xml_head = xml_parse.getElementsByTagName('user')
            if not xml_head:
                logger.warn("Error parsing XML for Plex.tv token: %s" % e)
                return False

            auth_token = xml_head[0].getAttribute('authenticationToken')

            return auth_token
Example #9
0
    def get_stream_details(self, row_id=None):
        myDB = db.DBConnection()

        if row_id:
            query = 'SELECT xml from %s where id = %s' % (self.get_history_table_name(), row_id)
            xml = myDB.select_single(query)
            xml_data = helpers.latinToAscii(xml)
        else:
            return None

        try:
            xml_parse = minidom.parseString(xml_data)
        except:
            logger.warn("Error parsing XML for Plex stream data.")
            return None

        xml_head = xml_parse.getElementsByTagName('opt')
        if not xml_head:
            logger.warn("Error parsing XML for Plex stream data.")
            return None

        stream_output = {}

        for a in xml_head:
            media_type = self.get_xml_attr(a, 'type')
            title = self.get_xml_attr(a, 'title')
            grandparent_title = self.get_xml_attr(a, 'grandparentTitle')

            if a.getElementsByTagName('TranscodeSession'):
                transcode_data = a.getElementsByTagName('TranscodeSession')
                for transcode_session in transcode_data:
                    transcode_video_dec = self.get_xml_attr(transcode_session, 'videoDecision')
                    transcode_video_codec = self.get_xml_attr(transcode_session, 'videoCodec')
                    transcode_height = self.get_xml_attr(transcode_session, 'height')
                    transcode_width = self.get_xml_attr(transcode_session, 'width')
                    transcode_audio_dec = self.get_xml_attr(transcode_session, 'audioDecision')
                    transcode_audio_codec = self.get_xml_attr(transcode_session, 'audioCodec')
                    transcode_audio_channels = self.get_xml_attr(transcode_session, 'audioChannels')
            else:
                transcode_data = a.getElementsByTagName('Media')
                for transcode_session in transcode_data:
                    transcode_video_dec = 'direct play'
                    transcode_video_codec = self.get_xml_attr(transcode_session, 'videoCodec')
                    transcode_height = self.get_xml_attr(transcode_session, 'height')
                    transcode_width = self.get_xml_attr(transcode_session, 'width')
                    transcode_audio_dec = 'direct play'
                    transcode_audio_codec = self.get_xml_attr(transcode_session, 'audioCodec')
                    transcode_audio_channels = self.get_xml_attr(transcode_session, 'audioChannels')

            if a.getElementsByTagName('Media'):
                stream_data = a.getElementsByTagName('Media')
                for stream_item in stream_data:
                    stream_output = {'container': self.get_xml_attr(stream_item, 'container'),
                                     'bitrate': self.get_xml_attr(stream_item, 'bitrate'),
                                     'video_resolution': self.get_xml_attr(stream_item, 'videoResolution'),
                                     'width': self.get_xml_attr(stream_item, 'width'),
                                     'height': self.get_xml_attr(stream_item, 'height'),
                                     'aspect_ratio': self.get_xml_attr(stream_item, 'aspectRatio'),
                                     'video_framerate': self.get_xml_attr(stream_item, 'videoFrameRate'),
                                     'video_codec': self.get_xml_attr(stream_item, 'videoCodec'),
                                     'audio_codec': self.get_xml_attr(stream_item, 'audioCodec'),
                                     'audio_channels': self.get_xml_attr(stream_item, 'audioChannels'),
                                     'transcode_video_dec': transcode_video_dec,
                                     'transcode_video_codec': transcode_video_codec,
                                     'transcode_height': transcode_height,
                                     'transcode_width': transcode_width,
                                     'transcode_audio_dec': transcode_audio_dec,
                                     'transcode_audio_codec': transcode_audio_codec,
                                     'transcode_audio_channels': transcode_audio_channels,
                                     'media_type': media_type,
                                     'title': title,
                                     'grandparent_title': grandparent_title
                                     }

        return stream_output
Example #10
0
    def get_stream_details(self, row_id=None):
        myDB = db.DBConnection()

        if row_id:
            query = 'SELECT xml from %s where id = ?' % (
                self.get_history_table_name())
            xml = myDB.select_single(query, args=[row_id])
            xml_data = helpers.latinToAscii(xml)
        else:
            return None

        try:
            xml_parse = minidom.parseString(xml_data)
        except:
            logger.warn("Error parsing XML for Plex stream data.")
            return None

        xml_head = xml_parse.getElementsByTagName('opt')
        if not xml_head:
            logger.warn("Error parsing XML for Plex stream data.")
            return None

        stream_output = {}

        for a in xml_head:
            media_type = self.get_xml_attr(a, 'type')
            title = self.get_xml_attr(a, 'title')
            grandparent_title = self.get_xml_attr(a, 'grandparentTitle')

            if a.getElementsByTagName('TranscodeSession'):
                transcode_data = a.getElementsByTagName('TranscodeSession')
                for transcode_session in transcode_data:
                    transcode_video_dec = self.get_xml_attr(
                        transcode_session, 'videoDecision')
                    transcode_video_codec = self.get_xml_attr(
                        transcode_session, 'videoCodec')
                    transcode_height = self.get_xml_attr(
                        transcode_session, 'height')
                    transcode_width = self.get_xml_attr(
                        transcode_session, 'width')
                    transcode_audio_dec = self.get_xml_attr(
                        transcode_session, 'audioDecision')
                    transcode_audio_codec = self.get_xml_attr(
                        transcode_session, 'audioCodec')
                    transcode_audio_channels = self.get_xml_attr(
                        transcode_session, 'audioChannels')
            else:
                transcode_data = a.getElementsByTagName('Media')
                for transcode_session in transcode_data:
                    transcode_video_dec = 'direct play'
                    transcode_video_codec = self.get_xml_attr(
                        transcode_session, 'videoCodec')
                    transcode_height = self.get_xml_attr(
                        transcode_session, 'height')
                    transcode_width = self.get_xml_attr(
                        transcode_session, 'width')
                    transcode_audio_dec = 'direct play'
                    transcode_audio_codec = self.get_xml_attr(
                        transcode_session, 'audioCodec')
                    transcode_audio_channels = self.get_xml_attr(
                        transcode_session, 'audioChannels')

            if a.getElementsByTagName('Media'):
                stream_data = a.getElementsByTagName('Media')
                for stream_item in stream_data:
                    stream_output = {
                        'container':
                        self.get_xml_attr(stream_item, 'container'),
                        'bitrate':
                        self.get_xml_attr(stream_item, 'bitrate'),
                        'video_resolution':
                        self.get_xml_attr(stream_item, 'videoResolution'),
                        'width':
                        self.get_xml_attr(stream_item, 'width'),
                        'height':
                        self.get_xml_attr(stream_item, 'height'),
                        'aspect_ratio':
                        self.get_xml_attr(stream_item, 'aspectRatio'),
                        'video_framerate':
                        self.get_xml_attr(stream_item, 'videoFrameRate'),
                        'video_codec':
                        self.get_xml_attr(stream_item, 'videoCodec'),
                        'audio_codec':
                        self.get_xml_attr(stream_item, 'audioCodec'),
                        'audio_channels':
                        self.get_xml_attr(stream_item, 'audioChannels'),
                        'transcode_video_dec':
                        transcode_video_dec,
                        'transcode_video_codec':
                        transcode_video_codec,
                        'transcode_height':
                        transcode_height,
                        'transcode_width':
                        transcode_width,
                        'transcode_audio_dec':
                        transcode_audio_dec,
                        'transcode_audio_codec':
                        transcode_audio_codec,
                        'transcode_audio_channels':
                        transcode_audio_channels,
                        'media_type':
                        media_type,
                        'title':
                        title,
                        'grandparent_title':
                        grandparent_title
                    }

        return stream_output
Example #11
0
def extract_plexwatch_xml(xml=None):
    output = {}
    clean_xml = helpers.latinToAscii(xml)
    try:
        xml_parse = minidom.parseString(clean_xml)
    except:
        logger.warn(
            u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
        return None

    xml_head = xml_parse.getElementsByTagName('opt')
    if not xml_head:
        logger.warn(
            u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
        return None

    for a in xml_head:
        added_at = helpers.get_xml_attr(a, 'addedAt')
        art = helpers.get_xml_attr(a, 'art')
        duration = helpers.get_xml_attr(a, 'duration')
        grandparent_thumb = helpers.get_xml_attr(a, 'grandparentThumb')
        grandparent_title = helpers.get_xml_attr(a, 'grandparentTitle')
        guid = helpers.get_xml_attr(a, 'guid')
        section_id = helpers.get_xml_attr(a, 'librarySectionID')
        media_index = helpers.get_xml_attr(a, 'index')
        originally_available_at = helpers.get_xml_attr(
            a, 'originallyAvailableAt')
        last_viewed_at = helpers.get_xml_attr(a, 'lastViewedAt')
        parent_media_index = helpers.get_xml_attr(a, 'parentIndex')
        parent_thumb = helpers.get_xml_attr(a, 'parentThumb')
        rating = helpers.get_xml_attr(a, 'rating')
        thumb = helpers.get_xml_attr(a, 'thumb')
        media_type = helpers.get_xml_attr(a, 'type')
        updated_at = helpers.get_xml_attr(a, 'updatedAt')
        view_offset = helpers.get_xml_attr(a, 'viewOffset')
        year = helpers.get_xml_attr(a, 'year')
        parent_title = helpers.get_xml_attr(a, 'parentTitle')
        studio = helpers.get_xml_attr(a, 'studio')
        title = helpers.get_xml_attr(a, 'title')
        tagline = helpers.get_xml_attr(a, 'tagline')

        directors = []
        if a.getElementsByTagName('Director'):
            director_elem = a.getElementsByTagName('Director')
            for b in director_elem:
                directors.append(helpers.get_xml_attr(b, 'tag'))

        aspect_ratio = ''
        audio_channels = None
        audio_codec = ''
        bitrate = None
        container = ''
        height = None
        video_codec = ''
        video_framerate = ''
        video_resolution = ''
        width = None

        if a.getElementsByTagName('Media'):
            media_elem = a.getElementsByTagName('Media')
            for c in media_elem:
                aspect_ratio = helpers.get_xml_attr(c, 'aspectRatio')
                audio_channels = helpers.get_xml_attr(c, 'audioChannels')
                audio_codec = helpers.get_xml_attr(c, 'audioCodec')
                bitrate = helpers.get_xml_attr(c, 'bitrate')
                container = helpers.get_xml_attr(c, 'container')
                height = helpers.get_xml_attr(c, 'height')
                video_codec = helpers.get_xml_attr(c, 'videoCodec')
                video_framerate = helpers.get_xml_attr(c, 'videoFrameRate')
                video_resolution = helpers.get_xml_attr(c, 'videoResolution')
                width = helpers.get_xml_attr(c, 'width')

        machine_id = ''
        platform = ''
        player = ''

        if a.getElementsByTagName('Player'):
            player_elem = a.getElementsByTagName('Player')
            for d in player_elem:
                machine_id = helpers.get_xml_attr(d, 'machineIdentifier')
                platform = helpers.get_xml_attr(d, 'platform')
                player = helpers.get_xml_attr(d, 'title')

        transcode_audio_channels = None
        transcode_audio_codec = ''
        audio_decision = 'direct play'
        transcode_container = ''
        transcode_height = None
        transcode_protocol = ''
        transcode_video_codec = ''
        video_decision = 'direct play'
        transcode_width = None

        if a.getElementsByTagName('TranscodeSession'):
            transcode_elem = a.getElementsByTagName('TranscodeSession')
            for e in transcode_elem:
                transcode_audio_channels = helpers.get_xml_attr(
                    e, 'audioChannels')
                transcode_audio_codec = helpers.get_xml_attr(e, 'audioCodec')
                audio_decision = helpers.get_xml_attr(e, 'audioDecision')
                transcode_container = helpers.get_xml_attr(e, 'container')
                transcode_height = helpers.get_xml_attr(e, 'height')
                transcode_protocol = helpers.get_xml_attr(e, 'protocol')
                transcode_video_codec = helpers.get_xml_attr(e, 'videoCodec')
                video_decision = helpers.get_xml_attr(e, 'videoDecision')
                transcode_width = helpers.get_xml_attr(e, 'width')

        user_id = None

        if a.getElementsByTagName('User'):
            user_elem = a.getElementsByTagName('User')
            for f in user_elem:
                user_id = helpers.get_xml_attr(f, 'id')

        writers = []
        if a.getElementsByTagName('Writer'):
            writer_elem = a.getElementsByTagName('Writer')
            for g in writer_elem:
                writers.append(helpers.get_xml_attr(g, 'tag'))

        actors = []
        if a.getElementsByTagName('Role'):
            actor_elem = a.getElementsByTagName('Role')
            for h in actor_elem:
                actors.append(helpers.get_xml_attr(h, 'tag'))

        genres = []
        if a.getElementsByTagName('Genre'):
            genre_elem = a.getElementsByTagName('Genre')
            for i in genre_elem:
                genres.append(helpers.get_xml_attr(i, 'tag'))

        output = {
            'added_at': added_at,
            'art': art,
            'duration': duration,
            'grandparent_thumb': grandparent_thumb,
            'grandparent_title': grandparent_title,
            'parent_title': parent_title,
            'title': title,
            'tagline': tagline,
            'guid': guid,
            'section_id': section_id,
            'media_index': media_index,
            'originally_available_at': originally_available_at,
            'last_viewed_at': last_viewed_at,
            'parent_media_index': parent_media_index,
            'parent_thumb': parent_thumb,
            'rating': rating,
            'thumb': thumb,
            'media_type': media_type,
            'updated_at': updated_at,
            'view_offset': view_offset,
            'year': year,
            'directors': directors,
            'aspect_ratio': aspect_ratio,
            'audio_channels': audio_channels,
            'audio_codec': audio_codec,
            'bitrate': bitrate,
            'container': container,
            'height': height,
            'video_codec': video_codec,
            'video_framerate': video_framerate,
            'video_resolution': video_resolution,
            'width': width,
            'machine_id': machine_id,
            'platform': platform,
            'player': player,
            'transcode_audio_channels': transcode_audio_channels,
            'transcode_audio_codec': transcode_audio_codec,
            'audio_decision': audio_decision,
            'transcode_container': transcode_container,
            'transcode_height': transcode_height,
            'transcode_protocol': transcode_protocol,
            'transcode_video_codec': transcode_video_codec,
            'video_decision': video_decision,
            'transcode_width': transcode_width,
            'user_id': user_id,
            'writers': writers,
            'actors': actors,
            'genres': genres,
            'studio': studio
        }

    return output
Example #12
0
def import_from_plexwatch(database=None, table_name=None, import_ignore_interval=0):

    try:
        connection = sqlite3.connect(database, timeout=20)
        connection.row_factory = sqlite3.Row
    except sqlite3.OperationalError:
        logger.error(u"PlexPy Importer :: Invalid filename.")
        return None
    except ValueError:
        logger.error(u"PlexPy Importer :: Invalid filename.")
        return None

    try:
        connection.execute('SELECT ratingKey from %s' % table_name)
    except sqlite3.OperationalError:
        logger.error(u"PlexPy Importer :: Database specified does not contain the required fields.")
        return None

    logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")

    logger.debug(u"PlexPy Importer :: Disabling monitoring while import in progress.")
    plexpy.schedule_job(activity_pinger.check_active_sessions, 'Check for active sessions',
                        hours=0, minutes=0, seconds=0)
    plexpy.schedule_job(activity_pinger.check_recently_added, 'Check for recently added items',
                        hours=0, minutes=0, seconds=0)
    plexpy.schedule_job(activity_pinger.check_server_response, 'Check for Plex remote access',
                        hours=0, minutes=0, seconds=0)

    ap = activity_processor.ActivityProcessor()
    user_data = users.Users()

    # Get the latest friends list so we can pull user id's
    try:
        plextv.refresh_users()
    except:
        logger.debug(u"PlexPy Importer :: Unable to refresh the users list. Aborting import.")
        return None

    query = 'SELECT time AS started, ' \
            'stopped, ' \
            'cast(ratingKey as text) AS rating_key, ' \
            'null AS user_id, ' \
            'user, ' \
            'ip_address, ' \
            'paused_counter, ' \
            'platform AS player, ' \
            'null AS platform, ' \
            'null as machine_id, ' \
            'parentRatingKey as parent_rating_key, ' \
            'grandparentRatingKey as grandparent_rating_key, ' \
            'null AS media_type, ' \
            'null AS view_offset, ' \
            'xml, ' \
            'rating as content_rating,' \
            'summary,' \
            'title AS full_title,' \
            '(case when orig_title_ep = "" then orig_title else ' \
            'orig_title_ep end) as title,' \
            '(case when orig_title_ep != "" then orig_title else ' \
            'null end) as grandparent_title ' \
            'FROM ' + table_name + ' ORDER BY id'

    result = connection.execute(query)

    for row in result:
        # Extract the xml from the Plexwatch db xml field.
        extracted_xml = extract_plexwatch_xml(row['xml'])

        # If we get back None from our xml extractor skip over the record and log error.
        if not extracted_xml:
            logger.error(u"PlexPy Importer :: Skipping record with ratingKey %s due to malformed xml."
                         % str(row['rating_key']))
            continue

        # Skip line if we don't have a ratingKey to work with
        if not row['rating_key']:
            logger.error(u"PlexPy Importer :: Skipping record due to null ratingKey.")
            continue

        # If the user_id no longer exists in the friends list, pull it from the xml.
        if user_data.get_user_id(user=row['user']):
            user_id = user_data.get_user_id(user=row['user'])
        else:
            user_id = extracted_xml['user_id']

        session_history = {'started': row['started'],
                           'stopped': row['stopped'],
                           'rating_key': row['rating_key'],
                           'title': row['title'],
                           'parent_title': extracted_xml['parent_title'],
                           'grandparent_title': row['grandparent_title'],
                           'user_id': user_id,
                           'user': row['user'],
                           'ip_address': row['ip_address'],
                           'paused_counter': row['paused_counter'],
                           'player': row['player'],
                           'platform': extracted_xml['platform'],
                           'machine_id': extracted_xml['machine_id'],
                           'parent_rating_key': row['parent_rating_key'],
                           'grandparent_rating_key': row['grandparent_rating_key'],
                           'media_type': extracted_xml['media_type'],
                           'view_offset': extracted_xml['view_offset'],
                           'video_decision': extracted_xml['video_decision'],
                           'audio_decision': extracted_xml['audio_decision'],
                           'duration': extracted_xml['duration'],
                           'width': extracted_xml['width'],
                           'height': extracted_xml['height'],
                           'container': extracted_xml['container'],
                           'video_codec': extracted_xml['video_codec'],
                           'audio_codec': extracted_xml['audio_codec'],
                           'bitrate': extracted_xml['bitrate'],
                           'video_resolution': extracted_xml['video_resolution'],
                           'video_framerate': extracted_xml['video_framerate'],
                           'aspect_ratio': extracted_xml['aspect_ratio'],
                           'audio_channels': extracted_xml['audio_channels'],
                           'transcode_protocol': extracted_xml['transcode_protocol'],
                           'transcode_container': extracted_xml['transcode_container'],
                           'transcode_video_codec': extracted_xml['transcode_video_codec'],
                           'transcode_audio_codec': extracted_xml['transcode_audio_codec'],
                           'transcode_audio_channels': extracted_xml['transcode_audio_channels'],
                           'transcode_width': extracted_xml['transcode_width'],
                           'transcode_height': extracted_xml['transcode_height']
                           }

        session_history_metadata = {'rating_key': helpers.latinToAscii(row['rating_key']),
                                    'parent_rating_key': row['parent_rating_key'],
                                    'grandparent_rating_key': row['grandparent_rating_key'],
                                    'title': row['title'],
                                    'parent_title': extracted_xml['parent_title'],
                                    'grandparent_title': row['grandparent_title'],
                                    'media_index': extracted_xml['media_index'],
                                    'parent_media_index': extracted_xml['parent_media_index'],
                                    'thumb': extracted_xml['thumb'],
                                    'parent_thumb': extracted_xml['parent_thumb'],
                                    'grandparent_thumb': extracted_xml['grandparent_thumb'],
                                    'art': extracted_xml['art'],
                                    'media_type': extracted_xml['media_type'],
                                    'year': extracted_xml['year'],
                                    'originally_available_at': extracted_xml['originally_available_at'],
                                    'added_at': extracted_xml['added_at'],
                                    'updated_at': extracted_xml['updated_at'],
                                    'last_viewed_at': extracted_xml['last_viewed_at'],
                                    'content_rating': row['content_rating'],
                                    'summary': row['summary'],
                                    'tagline': extracted_xml['tagline'],
                                    'rating': extracted_xml['rating'],
                                    'duration': extracted_xml['duration'],
                                    'guid': extracted_xml['guid'],
                                    'section_id': extracted_xml['section_id'],
                                    'directors': extracted_xml['directors'],
                                    'writers': extracted_xml['writers'],
                                    'actors': extracted_xml['actors'],
                                    'genres': extracted_xml['genres'],
                                    'studio': extracted_xml['studio'],
                                    'full_title': row['full_title']
                                    }

        # On older versions of PMS, "clip" items were still classified as "movie" and had bad ratingKey values
        # Just make sure that the ratingKey is indeed an integer
        if session_history_metadata['rating_key'].isdigit():
            ap.write_session_history(session=session_history,
                                     import_metadata=session_history_metadata,
                                     is_import=True,
                                     import_ignore_interval=import_ignore_interval)
        else:
            logger.debug(u"PlexPy Importer :: Item has bad rating_key: %s" % session_history_metadata['rating_key'])

    logger.debug(u"PlexPy Importer :: PlexWatch data import complete.")
    import_users()

    logger.debug(u"PlexPy Importer :: Re-enabling monitoring.")
    plexpy.initialize_scheduler()
Example #13
0
        return []

    try:
        logfile = open(log_file, "r")
    except IOError, e:
        logger.error('Unable to open Plex Log file. %s' % e)
        return []

    log_lines = tail(logfile, window)

    if parsed:
        line_error = False
        clean_lines = []
        for i in log_lines:
            try:
                i = helpers.latinToAscii(i)
                log_time = i.split(' [')[0]
                log_level = i.split('] ', 1)[1].split(' - ',1)[0]
                log_msg = i.split('] ', 1)[1].split(' - ',1)[1]
                full_line = [log_time, log_level, log_msg]
                clean_lines.append(full_line)
            except:
                line_error = True
                full_line = ['', '', 'Unable to parse log line.']
                clean_lines.append(full_line)

        if line_error:
            logger.error('PlexPy was unable to parse some lines of the Plex Media Server log.')

        return clean_lines
    else:
Example #14
0
        return []

    try:
        logfile = open(log_file, "r")
    except IOError, e:
        logger.error('Unable to open Plex Log file. %s' % e)
        return []

    log_lines = tail(logfile, window)

    if parsed:
        line_error = False
        clean_lines = []
        for i in log_lines:
            try:
                i = helpers.latinToAscii(i)
                log_time = i.split(' [')[0]
                log_level = i.split('] ', 1)[1].split(' - ',1)[0]
                log_msg = i.split('] ', 1)[1].split(' - ',1)[1]
                full_line = [log_time, log_level, log_msg]
                clean_lines.append(full_line)
            except:
                line_error = True
                full_line = ['', '', 'Unable to parse log line.']
                clean_lines.append(full_line)

        if line_error:
            logger.error('PlexPy was unable to parse some lines of the Plex Media Server log.')

        return clean_lines
    else:
Example #15
0
    def _getHistory(self, iDisplayStart=0, iDisplayLength=100, sSearch="", iSortCol_0='0', sSortDir_0='asc', **kwargs):
        iDisplayStart = int(iDisplayStart)
        iDisplayLength = int(iDisplayLength)
        filtered = []
        totalcount = 0
        myDB = db.DBConnection()
        db_table = db.DBConnection().get_history_table_name()

        sortcolumn = 'time'
        sortbyhavepercent = False
        if iSortCol_0 == '1':
            sortcolumn = 'user'
        if iSortCol_0 == '2':
            sortcolumn = 'platform'
        elif iSortCol_0 == '3':
            sortcolumn = 'ip_address'
        elif iSortCol_0 == '4':
            sortcolumn = 'title'
        elif iSortCol_0 == '5':
            sortcolumn = 'time'
        elif iSortCol_0 == '6':
            sortcolumn = 'paused_counter'
        elif iSortCol_0 == '7':
            sortcolumn = 'stopped'
        elif iSortCol_0 == '8':
            sortbyhavepercent = True

        if sSearch == "":
            query = 'SELECT * from %s order by %s COLLATE NOCASE %s' % (db_table, sortcolumn, sSortDir_0)
            filtered = myDB.select(query)
            totalcount = len(filtered)
        else:
            query = 'SELECT * from ' + db_table + ' WHERE user LIKE "%' + sSearch + \
                    '%" OR title LIKE "%' + sSearch + '%"' + 'ORDER BY %s COLLATE NOCASE %s' % (sortcolumn, sSortDir_0)
            filtered = myDB.select(query)
            totalcount = myDB.select('SELECT COUNT(*) from processed')[0][0]

        history = filtered[iDisplayStart:(iDisplayStart + iDisplayLength)]
        rows = []
        for item in history:
            row = {"date": item['time'],
                      "user": item["user"],
                      "platform": item["platform"],
                      "ip_address": item["ip_address"],
                      "title": item["title"],
                      "started": item["time"],
                      "paused": item["paused_counter"],
                      "stopped": item["stopped"],
                      "duration": "",
                      "percent_complete": 0,
                      }

            if item['paused_counter'] > 0:
                row['paused'] = item['paused_counter']
            else:
                row['paused'] = 0

            if item['time']:
                if item['stopped'] > 0:
                    stopped = item['stopped']
                else:
                    stopped = 0
                if item['paused_counter'] > 0:
                    paused_counter = item['paused_counter']
                else:
                    paused_counter = 0

                row['duration'] = stopped - item['time'] + paused_counter

            try:
                xml_parse = minidom.parseString(helpers.latinToAscii(item['xml']))
            except IOError, e:
                logger.warn("Error parsing XML in PlexWatch db: %s" % e)

            xml_head = xml_parse.getElementsByTagName('opt')
            if not xml_head:
                logger.warn("Error parsing XML in PlexWatch db: %s" % e)

            for s in xml_head:
                if s.getAttribute('duration') and s.getAttribute('viewOffset'):
                    view_offset = helpers.cast_to_float(s.getAttribute('viewOffset'))
                    duration = helpers.cast_to_float(s.getAttribute('duration'))
                    if duration > 0:
                        row['percent_complete'] = (view_offset / duration)*100
                    else:
                        row['percent_complete'] = 0

            rows.append(row)
Example #16
0
    def get_home_stats(self, time_range='30'):
        myDB = db.DBConnection()

        if not time_range.isdigit():
            time_range = '30'

        stats_queries = ["top_tv", "popular_tv", "top_users", "top_platforms"]
        home_stats = []

        for stat in stats_queries:
            if 'top_tv' in stat:
                top_tv = []
                try:
                    query = 'SELECT orig_title, COUNT(orig_title) as total_plays, ' \
                            'grandparentRatingKey, MAX(time) as last_watch, xml ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") ' \
                            '>= datetime("now", "-%s days", "localtime") ' \
                            'AND episode != "" ' \
                            'GROUP BY orig_title ' \
                            'ORDER BY total_plays DESC LIMIT 10' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    xml_data = helpers.latinToAscii(item[4])

                    try:
                        xml_parse = minidom.parseString(xml_data)
                    except:
                        logger.warn(
                            "Error parsing XML for Plexwatch database.")
                        return None

                    xml_head = xml_parse.getElementsByTagName('opt')
                    if not xml_head:
                        logger.warn(
                            "Error parsing XML for Plexwatch database.")
                        return None

                    for a in xml_head:
                        grandparent_thumb = self.get_xml_attr(
                            a, 'grandparentThumb')

                        row = {
                            'title': item[0],
                            'total_plays': item[1],
                            'users_watched': '',
                            'rating_key': item[2],
                            'last_play': item[3],
                            'grandparent_thumb': grandparent_thumb,
                            'thumb': '',
                            'user': '',
                            'friendly_name': '',
                            'platform_type': '',
                            'platform': ''
                        }
                        top_tv.append(row)

                home_stats.append({'stat_id': stat, 'rows': top_tv})

            elif 'popular_tv' in stat:
                popular_tv = []
                try:
                    query = 'SELECT orig_title, COUNT(DISTINCT user) as users_watched, grandparentRatingKey, ' \
                            'MAX(time) as last_watch, xml, COUNT(id) as total_plays ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") ' \
                            '>= datetime("now", "-%s days", "localtime") ' \
                            'AND episode != "" ' \
                            'GROUP BY orig_title ' \
                            'ORDER BY users_watched DESC, total_plays DESC ' \
                            'LIMIT 10' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    xml_data = helpers.latinToAscii(item[4])

                    try:
                        xml_parse = minidom.parseString(xml_data)
                    except:
                        logger.warn(
                            "Error parsing XML for Plexwatch database.")
                        return None

                    xml_head = xml_parse.getElementsByTagName('opt')
                    if not xml_head:
                        logger.warn(
                            "Error parsing XML for Plexwatch database.")
                        return None

                    for a in xml_head:
                        grandparent_thumb = self.get_xml_attr(
                            a, 'grandparentThumb')

                        row = {
                            'title': item[0],
                            'users_watched': item[1],
                            'rating_key': item[2],
                            'last_play': item[3],
                            'total_plays': item[5],
                            'grandparent_thumb': grandparent_thumb,
                            'thumb': '',
                            'user': '',
                            'friendly_name': '',
                            'platform_type': '',
                            'platform': ''
                        }
                        popular_tv.append(row)

                home_stats.append({'stat_id': stat, 'rows': popular_tv})

            elif 'top_users' in stat:
                top_users = []
                try:
                    s = self.get_history_table_name()
                    query = 'SELECT user, ' \
                            '(case when friendly_name is null then user else friendly_name end) as friendly_name,' \
                            'COUNT(' + s + '.id) as total_plays, MAX(time) as last_watch, thumb ' \
                            'FROM ' + s + ' ' \
                            'LEFT OUTER JOIN plexpy_users ON ' + s + '.user = plexpy_users.username ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
                            'datetime("now", "-' + time_range + ' days", "localtime") '\
                            'GROUP BY ' + s + '.user ' \
                            'ORDER BY total_plays DESC LIMIT 10'
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    if not item['thumb'] or item['thumb'] == '':
                        user_thumb = common.DEFAULT_USER_THUMB
                    else:
                        user_thumb = item[4]

                    thumb = self.get_user_gravatar_image(item[0])
                    row = {
                        'user': item[0],
                        'friendly_name': item[1],
                        'total_plays': item[2],
                        'last_play': item[3],
                        'thumb': user_thumb,
                        'grandparent_thumb': '',
                        'users_watched': '',
                        'rating_key': '',
                        'title': '',
                        'platform_type': '',
                        'platform': ''
                    }
                    top_users.append(row)

                home_stats.append({'stat_id': stat, 'rows': top_users})

            elif 'top_platforms' in stat:
                top_platform = []

                try:
                    query = 'SELECT platform, COUNT(id) as total_plays, MAX(time) as last_watch, xml ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") ' \
                            '>= datetime("now", "-%s days", "localtime") ' \
                            'GROUP BY platform ' \
                            'ORDER BY total_plays DESC' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    xml_data = helpers.latinToAscii(item[3])

                    try:
                        xml_parse = minidom.parseString(xml_data)
                    except:
                        logger.warn(
                            "Error parsing XML for Plexwatch database.")
                        return None

                    xml_head = xml_parse.getElementsByTagName('Player')
                    if not xml_head:
                        logger.warn(
                            "Error parsing XML for Plexwatch database.")
                        return None

                    for a in xml_head:
                        platform_type = self.get_xml_attr(a, 'platform')

                        row = {
                            'platform': item[0],
                            'total_plays': item[1],
                            'last_play': item[2],
                            'platform_type': platform_type,
                            'title': '',
                            'thumb': '',
                            'grandparent_thumb': '',
                            'users_watched': '',
                            'rating_key': '',
                            'user': '',
                            'friendly_name': ''
                        }
                        top_platform.append(row)

                top_platform_aggr = self.group_and_sum_dataset(
                    top_platform, 'platform_type', ['total_plays'],
                    'total_plays')

                home_stats.append({'stat_id': stat, 'rows': top_platform_aggr})

        return home_stats
Example #17
0
    def get_home_stats(self, time_range='30'):
        myDB = db.DBConnection()

        if not time_range.isdigit():
            time_range = '30'

        stats_queries = ["top_tv", "popular_tv", "top_users", "top_platforms"]
        home_stats = []

        for stat in stats_queries:
            if 'top_tv' in stat:
                top_tv = []
                try:
                    query = 'SELECT orig_title, COUNT(orig_title) as total_plays, grandparentRatingKey, MAX(time) as last_watch, xml ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
                            'AND episode != "" ' \
                            'GROUP BY orig_title ' \
                            'ORDER BY total_plays DESC LIMIT 10' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    xml_data = helpers.latinToAscii(item[4])

                    try:
                        xml_parse = minidom.parseString(xml_data)
                    except:
                        logger.warn("Error parsing XML for Plexwatch database.")
                        return None

                    xml_head = xml_parse.getElementsByTagName('opt')
                    if not xml_head:
                        logger.warn("Error parsing XML for Plexwatch database.")
                        return None

                    for a in xml_head:
                        grandparent_thumb = self.get_xml_attr(a, 'grandparentThumb')

                        row = {'orig_title': item[0],
                               'total_plays': item[1],
                               'rating_key': item[2],
                               'last_play': item[3],
                               'grandparent_thumb': grandparent_thumb
                               }
                        top_tv.append(row)

                home_stats.append({'stat_id': stat,
                                   'rows': top_tv})

            elif 'popular_tv' in stat:
                popular_tv = []
                try:
                    query = 'SELECT orig_title, COUNT(DISTINCT user) as users_watched, grandparentRatingKey, ' \
                            'MAX(time) as last_watch, xml, COUNT(id) as total_plays ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
                            'AND episode != "" ' \
                            'GROUP BY orig_title ' \
                            'ORDER BY users_watched DESC, total_plays DESC LIMIT 10' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    xml_data = helpers.latinToAscii(item[4])

                    try:
                        xml_parse = minidom.parseString(xml_data)
                    except:
                        logger.warn("Error parsing XML for Plexwatch database.")
                        return None

                    xml_head = xml_parse.getElementsByTagName('opt')
                    if not xml_head:
                        logger.warn("Error parsing XML for Plexwatch database.")
                        return None

                    for a in xml_head:
                        grandparent_thumb = self.get_xml_attr(a, 'grandparentThumb')

                        row = {'orig_title': item[0],
                               'users_watched': item[1],
                               'rating_key': item[2],
                               'last_play': item[3],
                               'total_plays': item[5],
                               'grandparent_thumb': grandparent_thumb
                               }
                        popular_tv.append(row)

                home_stats.append({'stat_id': stat,
                                   'rows': popular_tv})

            elif 'top_users' in stat:
                top_users = []
                try:
                    query = 'SELECT user, COUNT(id) as total_plays, MAX(time) as last_watch ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
                            'GROUP BY user ' \
                            'ORDER BY total_plays DESC LIMIT 10' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    thumb = self.get_user_gravatar_image(item[0])
                    row = {'user': item[0],
                           'total_plays': item[1],
                           'last_play': item[2],
                           'thumb': thumb['user_thumb']
                    }
                    top_users.append(row)

                home_stats.append({'stat_id': stat,
                                   'rows': top_users})

            elif 'top_platforms' in stat:
                top_platform = []

                try:
                    query = 'SELECT platform, COUNT(id) as total_plays, MAX(time) as last_watch, xml ' \
                            'FROM %s ' \
                            'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
                            'GROUP BY platform ' \
                            'ORDER BY total_plays DESC' % (self.get_history_table_name(), time_range)
                    result = myDB.select(query)
                except:
                    logger.warn("Unable to open PlexWatch database.")
                    return None

                for item in result:
                    xml_data = helpers.latinToAscii(item[3])

                    try:
                        xml_parse = minidom.parseString(xml_data)
                    except:
                        logger.warn("Error parsing XML for Plexwatch database.")
                        return None

                    xml_head = xml_parse.getElementsByTagName('Player')
                    if not xml_head:
                        logger.warn("Error parsing XML for Plexwatch database.")
                        return None

                    for a in xml_head:
                        platform_type = self.get_xml_attr(a, 'platform')

                        row = {'platform': item[0],
                               'total_plays': item[1],
                               'last_play': item[2],
                               'platform_type': platform_type
                               }
                        top_platform.append(row)

                top_platform_aggr = self.group_and_sum_dataset(
                    top_platform, 'platform_type', ['total_plays'], 'total_plays')

                home_stats.append({'stat_id': stat,
                                   'rows': top_platform_aggr})

        return home_stats
Example #18
0
def extract_plexwatch_xml(xml=None):
    output = {}
    clean_xml = helpers.latinToAscii(xml)
    try:
        xml_parse = minidom.parseString(clean_xml)
    except:
        logger.warn("Error parsing XML for Plexwatch database.")
        return None

    xml_head = xml_parse.getElementsByTagName("opt")
    if not xml_head:
        logger.warn("Error parsing XML for Plexwatch database.")
        return None

    for a in xml_head:
        added_at = helpers.get_xml_attr(a, "addedAt")
        art = helpers.get_xml_attr(a, "art")
        duration = helpers.get_xml_attr(a, "duration")
        grandparent_thumb = helpers.get_xml_attr(a, "grandparentThumb")
        grandparent_title = helpers.get_xml_attr(a, "grandparentTitle")
        guid = helpers.get_xml_attr(a, "guid")
        media_index = helpers.get_xml_attr(a, "index")
        originally_available_at = helpers.get_xml_attr(a, "originallyAvailableAt")
        last_viewed_at = helpers.get_xml_attr(a, "lastViewedAt")
        parent_media_index = helpers.get_xml_attr(a, "parentIndex")
        parent_thumb = helpers.get_xml_attr(a, "parentThumb")
        rating = helpers.get_xml_attr(a, "rating")
        thumb = helpers.get_xml_attr(a, "thumb")
        media_type = helpers.get_xml_attr(a, "type")
        updated_at = helpers.get_xml_attr(a, "updatedAt")
        view_offset = helpers.get_xml_attr(a, "viewOffset")
        year = helpers.get_xml_attr(a, "year")
        parent_title = helpers.get_xml_attr(a, "parentTitle")
        studio = helpers.get_xml_attr(a, "studio")
        title = helpers.get_xml_attr(a, "title")
        tagline = helpers.get_xml_attr(a, "tagline")

        directors = []
        if a.getElementsByTagName("Director"):
            director_elem = a.getElementsByTagName("Director")
            for b in director_elem:
                directors.append(helpers.get_xml_attr(b, "tag"))

        aspect_ratio = ""
        audio_channels = None
        audio_codec = ""
        bitrate = None
        container = ""
        height = None
        video_codec = ""
        video_framerate = ""
        video_resolution = ""
        width = None

        if a.getElementsByTagName("Media"):
            media_elem = a.getElementsByTagName("Media")
            for c in media_elem:
                aspect_ratio = helpers.get_xml_attr(c, "aspectRatio")
                audio_channels = helpers.get_xml_attr(c, "audioChannels")
                audio_codec = helpers.get_xml_attr(c, "audioCodec")
                bitrate = helpers.get_xml_attr(c, "bitrate")
                container = helpers.get_xml_attr(c, "container")
                height = helpers.get_xml_attr(c, "height")
                video_codec = helpers.get_xml_attr(c, "videoCodec")
                video_framerate = helpers.get_xml_attr(c, "videoFrameRate")
                video_resolution = helpers.get_xml_attr(c, "videoResolution")
                width = helpers.get_xml_attr(c, "width")

        machine_id = ""
        platform = ""
        player = ""

        if a.getElementsByTagName("Player"):
            player_elem = a.getElementsByTagName("Player")
            for d in player_elem:
                machine_id = helpers.get_xml_attr(d, "machineIdentifier")
                platform = helpers.get_xml_attr(d, "platform")
                player = helpers.get_xml_attr(d, "title")

        transcode_audio_channels = None
        transcode_audio_codec = ""
        audio_decision = "direct play"
        transcode_container = ""
        transcode_height = None
        transcode_protocol = ""
        transcode_video_codec = ""
        video_decision = "direct play"
        transcode_width = None

        if a.getElementsByTagName("TranscodeSession"):
            transcode_elem = a.getElementsByTagName("TranscodeSession")
            for e in transcode_elem:
                transcode_audio_channels = helpers.get_xml_attr(e, "audioChannels")
                transcode_audio_codec = helpers.get_xml_attr(e, "audioCodec")
                audio_decision = helpers.get_xml_attr(e, "audioDecision")
                transcode_container = helpers.get_xml_attr(e, "container")
                transcode_height = helpers.get_xml_attr(e, "height")
                transcode_protocol = helpers.get_xml_attr(e, "protocol")
                transcode_video_codec = helpers.get_xml_attr(e, "videoCodec")
                video_decision = helpers.get_xml_attr(e, "videoDecision")
                transcode_width = helpers.get_xml_attr(e, "width")

        user_id = None

        if a.getElementsByTagName("User"):
            user_elem = a.getElementsByTagName("User")
            for f in user_elem:
                user_id = helpers.get_xml_attr(f, "id")

        writers = []
        if a.getElementsByTagName("Writer"):
            writer_elem = a.getElementsByTagName("Writer")
            for g in writer_elem:
                writers.append(helpers.get_xml_attr(g, "tag"))

        actors = []
        if a.getElementsByTagName("Role"):
            actor_elem = a.getElementsByTagName("Role")
            for h in actor_elem:
                actors.append(helpers.get_xml_attr(h, "tag"))

        genres = []
        if a.getElementsByTagName("Genre"):
            genre_elem = a.getElementsByTagName("Genre")
            for i in genre_elem:
                genres.append(helpers.get_xml_attr(i, "tag"))

        output = {
            "added_at": added_at,
            "art": art,
            "duration": duration,
            "grandparent_thumb": grandparent_thumb,
            "grandparent_title": grandparent_title,
            "parent_title": parent_title,
            "title": title,
            "tagline": tagline,
            "guid": guid,
            "media_index": media_index,
            "originally_available_at": originally_available_at,
            "last_viewed_at": last_viewed_at,
            "parent_media_index": parent_media_index,
            "parent_thumb": parent_thumb,
            "rating": rating,
            "thumb": thumb,
            "media_type": media_type,
            "updated_at": updated_at,
            "view_offset": view_offset,
            "year": year,
            "directors": directors,
            "aspect_ratio": aspect_ratio,
            "audio_channels": audio_channels,
            "audio_codec": audio_codec,
            "bitrate": bitrate,
            "container": container,
            "height": height,
            "video_codec": video_codec,
            "video_framerate": video_framerate,
            "video_resolution": video_resolution,
            "width": width,
            "machine_id": machine_id,
            "platform": platform,
            "player": player,
            "transcode_audio_channels": transcode_audio_channels,
            "transcode_audio_codec": transcode_audio_codec,
            "audio_decision": audio_decision,
            "transcode_container": transcode_container,
            "transcode_height": transcode_height,
            "transcode_protocol": transcode_protocol,
            "transcode_video_codec": transcode_video_codec,
            "video_decision": video_decision,
            "transcode_width": transcode_width,
            "user_id": user_id,
            "writers": writers,
            "actors": actors,
            "genres": genres,
            "studio": studio,
        }

    return output
Example #19
0
def extract_plexwatch_xml(xml=None):
    output = {}
    clean_xml = helpers.latinToAscii(xml)
    try:
        xml_parse = minidom.parseString(clean_xml)
    except:
        logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
        return None

    xml_head = xml_parse.getElementsByTagName('opt')
    if not xml_head:
        logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
        return None

    for a in xml_head:
        added_at = helpers.get_xml_attr(a, 'addedAt')
        art = helpers.get_xml_attr(a, 'art')
        duration = helpers.get_xml_attr(a, 'duration')
        grandparent_thumb = helpers.get_xml_attr(a, 'grandparentThumb')
        grandparent_title = helpers.get_xml_attr(a, 'grandparentTitle')
        guid = helpers.get_xml_attr(a, 'guid')
        section_id = helpers.get_xml_attr(a, 'librarySectionID')
        media_index = helpers.get_xml_attr(a, 'index')
        originally_available_at = helpers.get_xml_attr(a, 'originallyAvailableAt')
        last_viewed_at = helpers.get_xml_attr(a, 'lastViewedAt')
        parent_media_index = helpers.get_xml_attr(a, 'parentIndex')
        parent_thumb = helpers.get_xml_attr(a, 'parentThumb')
        rating = helpers.get_xml_attr(a, 'rating')
        thumb = helpers.get_xml_attr(a, 'thumb')
        media_type = helpers.get_xml_attr(a, 'type')
        updated_at = helpers.get_xml_attr(a, 'updatedAt')
        view_offset = helpers.get_xml_attr(a, 'viewOffset')
        year = helpers.get_xml_attr(a, 'year')
        parent_title = helpers.get_xml_attr(a, 'parentTitle')
        studio = helpers.get_xml_attr(a, 'studio')
        title = helpers.get_xml_attr(a, 'title')
        tagline = helpers.get_xml_attr(a, 'tagline')

        directors = []
        if a.getElementsByTagName('Director'):
            director_elem = a.getElementsByTagName('Director')
            for b in director_elem:
                directors.append(helpers.get_xml_attr(b, 'tag'))

        aspect_ratio = ''
        audio_channels = None
        audio_codec = ''
        bitrate = None
        container = ''
        height = None
        video_codec = ''
        video_framerate = ''
        video_resolution = ''
        width = None

        if a.getElementsByTagName('Media'):
            media_elem = a.getElementsByTagName('Media')
            for c in media_elem:
                aspect_ratio = helpers.get_xml_attr(c, 'aspectRatio')
                audio_channels = helpers.get_xml_attr(c, 'audioChannels')
                audio_codec = helpers.get_xml_attr(c, 'audioCodec')
                bitrate = helpers.get_xml_attr(c, 'bitrate')
                container = helpers.get_xml_attr(c, 'container')
                height = helpers.get_xml_attr(c, 'height')
                video_codec = helpers.get_xml_attr(c, 'videoCodec')
                video_framerate = helpers.get_xml_attr(c, 'videoFrameRate')
                video_resolution = helpers.get_xml_attr(c, 'videoResolution')
                width = helpers.get_xml_attr(c, 'width')

        machine_id = ''
        platform = ''
        player = ''

        if a.getElementsByTagName('Player'):
            player_elem = a.getElementsByTagName('Player')
            for d in player_elem:
                machine_id = helpers.get_xml_attr(d, 'machineIdentifier')
                platform = helpers.get_xml_attr(d, 'platform')
                player = helpers.get_xml_attr(d, 'title')

        transcode_audio_channels = None
        transcode_audio_codec = ''
        audio_decision = 'direct play'
        transcode_container = ''
        transcode_height = None
        transcode_protocol = ''
        transcode_video_codec = ''
        video_decision = 'direct play'
        transcode_width = None

        if a.getElementsByTagName('TranscodeSession'):
            transcode_elem = a.getElementsByTagName('TranscodeSession')
            for e in transcode_elem:
                transcode_audio_channels = helpers.get_xml_attr(e, 'audioChannels')
                transcode_audio_codec = helpers.get_xml_attr(e, 'audioCodec')
                audio_decision = helpers.get_xml_attr(e, 'audioDecision')
                transcode_container = helpers.get_xml_attr(e, 'container')
                transcode_height = helpers.get_xml_attr(e, 'height')
                transcode_protocol = helpers.get_xml_attr(e, 'protocol')
                transcode_video_codec = helpers.get_xml_attr(e, 'videoCodec')
                video_decision = helpers.get_xml_attr(e, 'videoDecision')
                transcode_width = helpers.get_xml_attr(e, 'width')

        user_id = None

        if a.getElementsByTagName('User'):
            user_elem = a.getElementsByTagName('User')
            for f in user_elem:
                user_id = helpers.get_xml_attr(f, 'id')

        writers = []
        if a.getElementsByTagName('Writer'):
            writer_elem = a.getElementsByTagName('Writer')
            for g in writer_elem:
                writers.append(helpers.get_xml_attr(g, 'tag'))

        actors = []
        if a.getElementsByTagName('Role'):
            actor_elem = a.getElementsByTagName('Role')
            for h in actor_elem:
                actors.append(helpers.get_xml_attr(h, 'tag'))

        genres = []
        if a.getElementsByTagName('Genre'):
            genre_elem = a.getElementsByTagName('Genre')
            for i in genre_elem:
                genres.append(helpers.get_xml_attr(i, 'tag'))

        output = {'added_at': added_at,
                  'art': art,
                  'duration': duration,
                  'grandparent_thumb': grandparent_thumb,
                  'grandparent_title': grandparent_title,
                  'parent_title': parent_title,
                  'title': title,
                  'tagline': tagline,
                  'guid': guid,
                  'section_id': section_id,
                  'media_index': media_index,
                  'originally_available_at': originally_available_at,
                  'last_viewed_at': last_viewed_at,
                  'parent_media_index': parent_media_index,
                  'parent_thumb': parent_thumb,
                  'rating': rating,
                  'thumb': thumb,
                  'media_type': media_type,
                  'updated_at': updated_at,
                  'view_offset': view_offset,
                  'year': year,
                  'directors': directors,
                  'aspect_ratio': aspect_ratio,
                  'audio_channels': audio_channels,
                  'audio_codec': audio_codec,
                  'bitrate': bitrate,
                  'container': container,
                  'height': height,
                  'video_codec': video_codec,
                  'video_framerate': video_framerate,
                  'video_resolution': video_resolution,
                  'width': width,
                  'machine_id': machine_id,
                  'platform': platform,
                  'player': player,
                  'transcode_audio_channels': transcode_audio_channels,
                  'transcode_audio_codec': transcode_audio_codec,
                  'audio_decision': audio_decision,
                  'transcode_container': transcode_container,
                  'transcode_height': transcode_height,
                  'transcode_protocol': transcode_protocol,
                  'transcode_video_codec': transcode_video_codec,
                  'video_decision': video_decision,
                  'transcode_width': transcode_width,
                  'user_id': user_id,
                  'writers': writers,
                  'actors': actors,
                  'genres': genres,
                  'studio': studio
                  }

    return output
Example #20
0
def import_from_plexwatch(database=None, table_name=None, import_ignore_interval=0):

    try:
        connection = sqlite3.connect(database, timeout=20)
        connection.row_factory = sqlite3.Row
    except sqlite3.OperationalError:
        logger.error("PlexPy Importer :: Invalid filename.")
        return None
    except ValueError:
        logger.error("PlexPy Importer :: Invalid filename.")
        return None

    try:
        connection.execute("SELECT ratingKey from %s" % table_name)
    except sqlite3.OperationalError:
        logger.error("PlexPy Importer :: Database specified does not contain the required fields.")
        return None

    logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")

    logger.debug(u"PlexPy Importer :: Disabling monitoring while import in progress.")
    plexpy.schedule_job(
        activity_pinger.check_active_sessions, "Check for active sessions", hours=0, minutes=0, seconds=0
    )

    ap = activity_processor.ActivityProcessor()
    user_data = users.Users()

    # Get the latest friends list so we can pull user id's
    try:
        plextv.refresh_users()
    except:
        logger.debug(u"PlexPy Importer :: Unable to refresh the users list. Aborting import.")
        return None

    query = (
        "SELECT time AS started, "
        "stopped, "
        "cast(ratingKey as text) AS rating_key, "
        "null AS user_id, "
        "user, "
        "ip_address, "
        "paused_counter, "
        "platform AS player, "
        "null AS platform, "
        "null as machine_id, "
        "parentRatingKey as parent_rating_key, "
        "grandparentRatingKey as grandparent_rating_key, "
        "null AS media_type, "
        "null AS view_offset, "
        "xml, "
        "rating as content_rating,"
        "summary,"
        "title AS full_title,"
        '(case when orig_title_ep = "" then orig_title else '
        "orig_title_ep end) as title,"
        '(case when orig_title_ep != "" then orig_title else '
        "null end) as grandparent_title "
        "FROM " + table_name + " ORDER BY id"
    )

    result = connection.execute(query)

    for row in result:
        # Extract the xml from the Plexwatch db xml field.
        extracted_xml = extract_plexwatch_xml(row["xml"])

        # If we get back None from our xml extractor skip over the record and log error.
        if not extracted_xml:
            logger.error(
                u"PlexPy Importer :: Skipping line with ratingKey %s due to malformed xml." % str(row["rating_key"])
            )
            continue

        # If the user_id no longer exists in the friends list, pull it from the xml.
        if user_data.get_user_id(user=row["user"]):
            user_id = user_data.get_user_id(user=row["user"])
        else:
            user_id = extracted_xml["user_id"]

        session_history = {
            "started": row["started"],
            "stopped": row["stopped"],
            "rating_key": row["rating_key"],
            "title": row["title"],
            "parent_title": extracted_xml["parent_title"],
            "grandparent_title": row["grandparent_title"],
            "user_id": user_id,
            "user": row["user"],
            "ip_address": row["ip_address"],
            "paused_counter": row["paused_counter"],
            "player": row["player"],
            "platform": extracted_xml["platform"],
            "machine_id": extracted_xml["machine_id"],
            "parent_rating_key": row["parent_rating_key"],
            "grandparent_rating_key": row["grandparent_rating_key"],
            "media_type": extracted_xml["media_type"],
            "view_offset": extracted_xml["view_offset"],
            "video_decision": extracted_xml["video_decision"],
            "audio_decision": extracted_xml["audio_decision"],
            "duration": extracted_xml["duration"],
            "width": extracted_xml["width"],
            "height": extracted_xml["height"],
            "container": extracted_xml["container"],
            "video_codec": extracted_xml["video_codec"],
            "audio_codec": extracted_xml["audio_codec"],
            "bitrate": extracted_xml["bitrate"],
            "video_resolution": extracted_xml["video_resolution"],
            "video_framerate": extracted_xml["video_framerate"],
            "aspect_ratio": extracted_xml["aspect_ratio"],
            "audio_channels": extracted_xml["audio_channels"],
            "transcode_protocol": extracted_xml["transcode_protocol"],
            "transcode_container": extracted_xml["transcode_container"],
            "transcode_video_codec": extracted_xml["transcode_video_codec"],
            "transcode_audio_codec": extracted_xml["transcode_audio_codec"],
            "transcode_audio_channels": extracted_xml["transcode_audio_channels"],
            "transcode_width": extracted_xml["transcode_width"],
            "transcode_height": extracted_xml["transcode_height"],
        }

        session_history_metadata = {
            "rating_key": helpers.latinToAscii(row["rating_key"]),
            "parent_rating_key": row["parent_rating_key"],
            "grandparent_rating_key": row["grandparent_rating_key"],
            "title": row["title"],
            "parent_title": extracted_xml["parent_title"],
            "grandparent_title": row["grandparent_title"],
            "index": extracted_xml["media_index"],
            "parent_index": extracted_xml["parent_media_index"],
            "thumb": extracted_xml["thumb"],
            "parent_thumb": extracted_xml["parent_thumb"],
            "grandparent_thumb": extracted_xml["grandparent_thumb"],
            "art": extracted_xml["art"],
            "media_type": extracted_xml["media_type"],
            "year": extracted_xml["year"],
            "originally_available_at": extracted_xml["originally_available_at"],
            "added_at": extracted_xml["added_at"],
            "updated_at": extracted_xml["updated_at"],
            "last_viewed_at": extracted_xml["last_viewed_at"],
            "content_rating": row["content_rating"],
            "summary": row["summary"],
            "tagline": extracted_xml["tagline"],
            "rating": extracted_xml["rating"],
            "duration": extracted_xml["duration"],
            "guid": extracted_xml["guid"],
            "directors": extracted_xml["directors"],
            "writers": extracted_xml["writers"],
            "actors": extracted_xml["actors"],
            "genres": extracted_xml["genres"],
            "studio": extracted_xml["studio"],
            "full_title": row["full_title"],
        }

        # On older versions of PMS, "clip" items were still classified as "movie" and had bad ratingKey values
        # Just make sure that the ratingKey is indeed an integer
        if session_history_metadata["rating_key"].isdigit():
            ap.write_session_history(
                session=session_history,
                import_metadata=session_history_metadata,
                is_import=True,
                import_ignore_interval=import_ignore_interval,
            )
        else:
            logger.debug(u"PlexPy Importer :: Item has bad rating_key: %s" % session_history_metadata["rating_key"])

    logger.debug(u"PlexPy Importer :: PlexWatch data import complete.")
    import_users()

    logger.debug(u"PlexPy Importer :: Re-enabling monitoring.")
    plexpy.initialize_scheduler()
Example #21
0
    def _getHistory(self,
                    iDisplayStart=0,
                    iDisplayLength=100,
                    sSearch="",
                    iSortCol_0='0',
                    sSortDir_0='asc',
                    **kwargs):
        iDisplayStart = int(iDisplayStart)
        iDisplayLength = int(iDisplayLength)
        filtered = []
        totalcount = 0
        myDB = db.DBConnection()
        db_table = db.DBConnection().get_history_table_name()

        sortcolumn = 'time'
        sortbyhavepercent = False
        if iSortCol_0 == '1':
            sortcolumn = 'user'
        if iSortCol_0 == '2':
            sortcolumn = 'platform'
        elif iSortCol_0 == '3':
            sortcolumn = 'ip_address'
        elif iSortCol_0 == '4':
            sortcolumn = 'title'
        elif iSortCol_0 == '5':
            sortcolumn = 'time'
        elif iSortCol_0 == '6':
            sortcolumn = 'paused_counter'
        elif iSortCol_0 == '7':
            sortcolumn = 'stopped'
        elif iSortCol_0 == '8':
            sortbyhavepercent = True

        if sSearch == "":
            query = 'SELECT * from %s order by %s COLLATE NOCASE %s' % (
                db_table, sortcolumn, sSortDir_0)
            filtered = myDB.select(query)
            totalcount = len(filtered)
        else:
            query = 'SELECT * from ' + db_table + ' WHERE user LIKE "%' + sSearch + \
                    '%" OR title LIKE "%' + sSearch + '%"' + 'ORDER BY %s COLLATE NOCASE %s' % (sortcolumn, sSortDir_0)
            filtered = myDB.select(query)
            totalcount = myDB.select('SELECT COUNT(*) from processed')[0][0]

        history = filtered[iDisplayStart:(iDisplayStart + iDisplayLength)]
        rows = []
        for item in history:
            row = {
                "date": item['time'],
                "user": item["user"],
                "platform": item["platform"],
                "ip_address": item["ip_address"],
                "title": item["title"],
                "started": item["time"],
                "paused": item["paused_counter"],
                "stopped": item["stopped"],
                "duration": "",
                "percent_complete": 0,
            }

            if item['paused_counter'] > 0:
                row['paused'] = item['paused_counter']
            else:
                row['paused'] = 0

            if item['time']:
                if item['stopped'] > 0:
                    stopped = item['stopped']
                else:
                    stopped = 0
                if item['paused_counter'] > 0:
                    paused_counter = item['paused_counter']
                else:
                    paused_counter = 0

                row['duration'] = stopped - item['time'] + paused_counter

            try:
                xml_parse = minidom.parseString(
                    helpers.latinToAscii(item['xml']))
            except IOError, e:
                logger.warn("Error parsing XML in PlexWatch db: %s" % e)

            xml_head = xml_parse.getElementsByTagName('opt')
            if not xml_head:
                logger.warn("Error parsing XML in PlexWatch db: %s" % e)

            for s in xml_head:
                if s.getAttribute('duration') and s.getAttribute('viewOffset'):
                    view_offset = helpers.cast_to_float(
                        s.getAttribute('viewOffset'))
                    duration = helpers.cast_to_float(
                        s.getAttribute('duration'))
                    if duration > 0:
                        row['percent_complete'] = (view_offset /
                                                   duration) * 100
                    else:
                        row['percent_complete'] = 0

            rows.append(row)
Example #22
0
    def get_history(self, start='', length='', kwargs=None, custom_where=''):
        data_tables = datatables.DataTables()

        start = int(start)
        length = int(length)
        filtered = []
        totalcount = 0
        search_value = ""
        search_regex = ""
        order_column = 1
        order_dir = "desc"

        if 'order[0][dir]' in kwargs:
            order_dir = kwargs.get('order[0][dir]', "desc")

        if 'order[0][column]' in kwargs:
            order_column = kwargs.get('order[0][column]', "1")

        if 'search[value]' in kwargs:
            search_value = kwargs.get('search[value]', "")

        if 'search[regex]' in kwargs:
            search_regex = kwargs.get('search[regex]', "")

        columns = ['id',
                   'time as date',
                   'user',
                   'platform',
                   'ip_address',
                   'title',
                   'time as started',
                   'paused_counter',
                   'stopped',
                   'ratingKey as rating_key',
                   'xml',
                   'round((julianday(datetime(stopped, "unixepoch", "localtime")) - \
                    julianday(datetime(time, "unixepoch", "localtime"))) * 86400) - \
                    (case when paused_counter is null then 0 else paused_counter end) as duration',
                   'grandparentRatingKey as grandparent_rating_key'
                   ]
        try:
            query = data_tables.ssp_query(table_name=self.get_history_table_name(),
                                          columns=columns,
                                          start=start,
                                          length=length,
                                          order_column=int(order_column),
                                          order_dir=order_dir,
                                          search_value=search_value,
                                          search_regex=search_regex,
                                          custom_where=custom_where,
                                          group_by='',
                                          kwargs=kwargs)
        except:
            logger.warn("Unable to open PlexWatch database.")
            return {'recordsFiltered': 0,
                    'recordsTotal': 0,
                    'data': 'null'},

        history = query['result']

        rows = []
        # NOTE: We are adding in a blank xml field in order enable the Datatables "searchable" parameter
        for item in history:
            row = {"id": item['id'],
                   "date": item['date'],
                   "user": item["user"],
                   "platform": item["platform"],
                   "ip_address": item["ip_address"],
                   "title": item["title"],
                   "started": item["started"],
                   "paused_counter": item["paused_counter"],
                   "stopped": item["stopped"],
                   "rating_key": item["rating_key"],
                   "duration": item["duration"],
                   "percent_complete": 0,
                   "xml": ""}

            if item['paused_counter'] > 0:
                row['paused_counter'] = item['paused_counter']
            else:
                row['paused_counter'] = 0

            if item['started']:
                if item['stopped'] > 0:
                    stopped = item['stopped']
                else:
                    stopped = 0
                if item['paused_counter'] > 0:
                    paused_counter = item['paused_counter']
                else:
                    paused_counter = 0

            try:
                xml_parse = minidom.parseString(helpers.latinToAscii(item['xml']))
            except IOError, e:
                logger.warn("Error parsing XML in PlexWatch db: %s" % e)

            xml_head = xml_parse.getElementsByTagName('opt')
            if not xml_head:
                logger.warn("Error parsing XML in PlexWatch db: %s" % e)

            for s in xml_head:
                if s.getAttribute('duration') and s.getAttribute('viewOffset'):
                    view_offset = helpers.cast_to_float(s.getAttribute('viewOffset'))
                    duration = helpers.cast_to_float(s.getAttribute('duration'))
                    if duration > 0:
                        row['percent_complete'] = (view_offset / duration) * 100
                    else:
                        row['percent_complete'] = 0

            rows.append(row)
Example #23
0
def import_from_plexwatch(database=None,
                          table_name=None,
                          import_ignore_interval=0):

    try:
        connection = sqlite3.connect(database, timeout=20)
        connection.row_factory = sqlite3.Row
    except sqlite3.OperationalError:
        logger.error(u"PlexPy Importer :: Invalid filename.")
        return None
    except ValueError:
        logger.error(u"PlexPy Importer :: Invalid filename.")
        return None

    try:
        connection.execute('SELECT ratingKey from %s' % table_name)
    except sqlite3.OperationalError:
        logger.error(
            u"PlexPy Importer :: Database specified does not contain the required fields."
        )
        return None

    logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")

    logger.debug(
        u"PlexPy Importer :: Disabling monitoring while import in progress.")
    plexpy.schedule_job(activity_pinger.check_active_sessions,
                        'Check for active sessions',
                        hours=0,
                        minutes=0,
                        seconds=0)
    plexpy.schedule_job(activity_pinger.check_recently_added,
                        'Check for recently added items',
                        hours=0,
                        minutes=0,
                        seconds=0)
    plexpy.schedule_job(activity_pinger.check_server_response,
                        'Check for server response',
                        hours=0,
                        minutes=0,
                        seconds=0)

    ap = activity_processor.ActivityProcessor()
    user_data = users.Users()

    # Get the latest friends list so we can pull user id's
    try:
        plextv.refresh_users()
    except:
        logger.debug(
            u"PlexPy Importer :: Unable to refresh the users list. Aborting import."
        )
        return None

    query = 'SELECT time AS started, ' \
            'stopped, ' \
            'cast(ratingKey as text) AS rating_key, ' \
            'null AS user_id, ' \
            'user, ' \
            'ip_address, ' \
            'paused_counter, ' \
            'platform AS player, ' \
            'null AS platform, ' \
            'null as machine_id, ' \
            'parentRatingKey as parent_rating_key, ' \
            'grandparentRatingKey as grandparent_rating_key, ' \
            'null AS media_type, ' \
            'null AS view_offset, ' \
            'xml, ' \
            'rating as content_rating,' \
            'summary,' \
            'title AS full_title,' \
            '(case when orig_title_ep = "" then orig_title else ' \
            'orig_title_ep end) as title,' \
            '(case when orig_title_ep != "" then orig_title else ' \
            'null end) as grandparent_title ' \
            'FROM ' + table_name + ' ORDER BY id'

    result = connection.execute(query)

    for row in result:
        # Extract the xml from the Plexwatch db xml field.
        extracted_xml = extract_plexwatch_xml(row['xml'])

        # If we get back None from our xml extractor skip over the record and log error.
        if not extracted_xml:
            logger.error(
                u"PlexPy Importer :: Skipping record with ratingKey %s due to malformed xml."
                % str(row['rating_key']))
            continue

        # Skip line if we don't have a ratingKey to work with
        if not row['rating_key']:
            logger.error(
                u"PlexPy Importer :: Skipping record due to null ratingRey.")
            continue

        # If the user_id no longer exists in the friends list, pull it from the xml.
        if user_data.get_user_id(user=row['user']):
            user_id = user_data.get_user_id(user=row['user'])
        else:
            user_id = extracted_xml['user_id']

        session_history = {
            'started': row['started'],
            'stopped': row['stopped'],
            'rating_key': row['rating_key'],
            'title': row['title'],
            'parent_title': extracted_xml['parent_title'],
            'grandparent_title': row['grandparent_title'],
            'user_id': user_id,
            'user': row['user'],
            'ip_address': row['ip_address'],
            'paused_counter': row['paused_counter'],
            'player': row['player'],
            'platform': extracted_xml['platform'],
            'machine_id': extracted_xml['machine_id'],
            'parent_rating_key': row['parent_rating_key'],
            'grandparent_rating_key': row['grandparent_rating_key'],
            'media_type': extracted_xml['media_type'],
            'view_offset': extracted_xml['view_offset'],
            'video_decision': extracted_xml['video_decision'],
            'audio_decision': extracted_xml['audio_decision'],
            'duration': extracted_xml['duration'],
            'width': extracted_xml['width'],
            'height': extracted_xml['height'],
            'container': extracted_xml['container'],
            'video_codec': extracted_xml['video_codec'],
            'audio_codec': extracted_xml['audio_codec'],
            'bitrate': extracted_xml['bitrate'],
            'video_resolution': extracted_xml['video_resolution'],
            'video_framerate': extracted_xml['video_framerate'],
            'aspect_ratio': extracted_xml['aspect_ratio'],
            'audio_channels': extracted_xml['audio_channels'],
            'transcode_protocol': extracted_xml['transcode_protocol'],
            'transcode_container': extracted_xml['transcode_container'],
            'transcode_video_codec': extracted_xml['transcode_video_codec'],
            'transcode_audio_codec': extracted_xml['transcode_audio_codec'],
            'transcode_audio_channels':
            extracted_xml['transcode_audio_channels'],
            'transcode_width': extracted_xml['transcode_width'],
            'transcode_height': extracted_xml['transcode_height']
        }

        session_history_metadata = {
            'rating_key': helpers.latinToAscii(row['rating_key']),
            'parent_rating_key': row['parent_rating_key'],
            'grandparent_rating_key': row['grandparent_rating_key'],
            'title': row['title'],
            'parent_title': extracted_xml['parent_title'],
            'grandparent_title': row['grandparent_title'],
            'media_index': extracted_xml['media_index'],
            'parent_media_index': extracted_xml['parent_media_index'],
            'thumb': extracted_xml['thumb'],
            'parent_thumb': extracted_xml['parent_thumb'],
            'grandparent_thumb': extracted_xml['grandparent_thumb'],
            'art': extracted_xml['art'],
            'media_type': extracted_xml['media_type'],
            'year': extracted_xml['year'],
            'originally_available_at':
            extracted_xml['originally_available_at'],
            'added_at': extracted_xml['added_at'],
            'updated_at': extracted_xml['updated_at'],
            'last_viewed_at': extracted_xml['last_viewed_at'],
            'content_rating': row['content_rating'],
            'summary': row['summary'],
            'tagline': extracted_xml['tagline'],
            'rating': extracted_xml['rating'],
            'duration': extracted_xml['duration'],
            'guid': extracted_xml['guid'],
            'section_id': extracted_xml['section_id'],
            'directors': extracted_xml['directors'],
            'writers': extracted_xml['writers'],
            'actors': extracted_xml['actors'],
            'genres': extracted_xml['genres'],
            'studio': extracted_xml['studio'],
            'full_title': row['full_title']
        }

        # On older versions of PMS, "clip" items were still classified as "movie" and had bad ratingKey values
        # Just make sure that the ratingKey is indeed an integer
        if session_history_metadata['rating_key'].isdigit():
            ap.write_session_history(
                session=session_history,
                import_metadata=session_history_metadata,
                is_import=True,
                import_ignore_interval=import_ignore_interval)
        else:
            logger.debug(u"PlexPy Importer :: Item has bad rating_key: %s" %
                         session_history_metadata['rating_key'])

    logger.debug(u"PlexPy Importer :: PlexWatch data import complete.")
    import_users()

    logger.debug(u"PlexPy Importer :: Re-enabling monitoring.")
    plexpy.initialize_scheduler()
Example #24
0
    def get_history(self, start='', length='', kwargs=None, custom_where=''):
        data_tables = datatables.DataTables()

        start = int(start)
        length = int(length)
        filtered = []
        totalcount = 0
        search_value = ""
        search_regex = ""
        order_column = 1
        order_dir = "desc"

        t = self.get_history_table_name()

        if 'order[0][dir]' in kwargs:
            order_dir = kwargs.get('order[0][dir]', "desc")

        if 'order[0][column]' in kwargs:
            order_column = kwargs.get('order[0][column]', "1")

        if 'search[value]' in kwargs:
            search_value = kwargs.get('search[value]', "")

        if 'search[regex]' in kwargs:
            search_regex = kwargs.get('search[regex]', "")

        columns = [
            t + '.id', t + '.time as date',
            '(case when plexpy_users.friendly_name is null then ' + t +
            '.user else plexpy_users.friendly_name end) as friendly_name',
            t + '.platform', t + '.ip_address', t + '.title',
            t + '.time as started', t + '.paused_counter', t + '.stopped',
            'round((julianday(datetime(' + t +
            '.stopped, "unixepoch", "localtime")) - \
                    julianday(datetime(' + t +
            '.time, "unixepoch", "localtime"))) * 86400) - \
                    (case when ' + t + '.paused_counter is null then 0 else ' +
            t + '.paused_counter end) as duration',
            t + '.ratingKey as rating_key', t + '.xml', t + '.user',
            t + '.grandparentRatingKey as grandparent_rating_key'
        ]
        try:
            query = data_tables.ssp_query(
                table_name=t,
                columns=columns,
                start=start,
                length=length,
                order_column=int(order_column),
                order_dir=order_dir,
                search_value=search_value,
                search_regex=search_regex,
                custom_where=custom_where,
                group_by='',
                join_type='LEFT OUTER JOIN',
                join_table='plexpy_users',
                join_evals=[t + '.user', 'plexpy_users.username'],
                kwargs=kwargs)
        except:
            logger.warn("Unable to open PlexWatch database.")
            return {'recordsFiltered': 0, 'recordsTotal': 0, 'data': 'null'},

        history = query['result']

        rows = []
        # NOTE: We are adding in a blank xml field in order enable the Datatables "searchable" parameter
        for item in history:
            row = {
                "id": item['id'],
                "date": item['date'],
                "friendly_name": item['friendly_name'],
                "platform": item["platform"],
                "ip_address": item["ip_address"],
                "title": item["title"],
                "started": item["started"],
                "paused_counter": item["paused_counter"],
                "stopped": item["stopped"],
                "rating_key": item["rating_key"],
                "duration": item["duration"],
                "percent_complete": 0,
                "xml": "",
                "user": item["user"]
            }

            if item['paused_counter'] > 0:
                row['paused_counter'] = item['paused_counter']
            else:
                row['paused_counter'] = 0

            if item['started']:
                if item['stopped'] > 0:
                    stopped = item['stopped']
                else:
                    stopped = 0
                if item['paused_counter'] > 0:
                    paused_counter = item['paused_counter']
                else:
                    paused_counter = 0

            try:
                xml_parse = minidom.parseString(
                    helpers.latinToAscii(item['xml']))
            except:
                logger.warn("Error parsing XML in PlexWatch db")

            xml_head = xml_parse.getElementsByTagName('opt')
            if not xml_head:
                logger.warn("Error parsing XML in PlexWatch db.")

            for s in xml_head:
                if s.getAttribute('duration') and s.getAttribute('viewOffset'):
                    view_offset = helpers.cast_to_float(
                        s.getAttribute('viewOffset'))
                    duration = helpers.cast_to_float(
                        s.getAttribute('duration'))
                    if duration > 0:
                        row['percent_complete'] = (view_offset /
                                                   duration) * 100
                    else:
                        row['percent_complete'] = 0

            rows.append(row)

        dict = {
            'recordsFiltered': query['filteredCount'],
            'recordsTotal': query['totalCount'],
            'data': rows,
        }

        return dict