Exemplo n.º 1
0
def check_server_response():

    with monitor_lock:
        pms_connect = pmsconnect.PmsConnect()
        server_response = pms_connect.get_server_response()

        global ext_ping_count
        
        # Check for remote access
        if server_response:
        
            mapping_state = server_response['mapping_state']
            mapping_error = server_response['mapping_error']

            # Check if the port is mapped
            if not mapping_state == 'mapped':
                ext_ping_count += 1
                logger.warn(u"Plex:CS Monitor :: Plex remote access port not mapped, ping attempt %s." \
                            % str(ext_ping_count))
            # Check if the port is open
            elif mapping_error == 'unreachable':
                ext_ping_count += 1
                logger.warn(u"Plex:CS Monitor :: Plex remote access port mapped, but mapping failed, ping attempt %s." \
                            % str(ext_ping_count))
            # Reset external ping counter
            else:
                ext_ping_count = 0

        if ext_ping_count == 3:
            # Fire off notifications
            threading.Thread(target=notification_handler.notify_timeline,
                                kwargs=dict(notify_action='extdown')).start()
Exemplo n.º 2
0
def check_recently_added():

    with monitor_lock:
        # add delay to allow for metadata processing
        delay = plexcs.CONFIG.NOTIFY_RECENTLY_ADDED_DELAY
        time_threshold = int(time.time()) - delay
        time_interval = plexcs.CONFIG.MONITORING_INTERVAL

        pms_connect = pmsconnect.PmsConnect()
        recently_added_list = pms_connect.get_recently_added_details(count='10')

        if recently_added_list:
            recently_added = recently_added_list['recently_added']

            for item in recently_added:
                metadata = []
                
                if 0 < time_threshold - int(item['added_at']) <= time_interval:
                    if item['media_type'] == 'movie':
                        metadata_list = pms_connect.get_metadata_details(item['rating_key'])
                        if metadata_list:
                            metadata = [metadata_list['metadata']]
                        else:
                            logger.error(u"Plex:CS Monitor :: Unable to retrieve metadata for rating_key %s" \
                                         % str(item['rating_key']))

                    else:
                        metadata_list = pms_connect.get_metadata_children_details(item['rating_key'])
                        if metadata_list:
                            metadata = metadata_list['metadata']
                        else:
                            logger.error(u"Plex:CS Monitor :: Unable to retrieve children metadata for rating_key %s" \
                                         % str(item['rating_key']))

                if metadata:
                    if not plexcs.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT:
                        for item in metadata:
                            if 0 < time_threshold - int(item['added_at']) <= time_interval:
                                logger.debug(u"Plex:CS Monitor :: Library item %s has been added to Plex." % str(item['rating_key']))
                                # Fire off notifications
                                threading.Thread(target=notification_handler.notify_timeline,
                                                 kwargs=dict(timeline_data=item, notify_action='created')).start()
                    
                    else:
                        item = max(metadata, key=lambda x:x['added_at'])

                        if 0 < time_threshold - int(item['added_at']) <= time_interval:
                            if item['media_type'] == 'episode' or item['media_type'] == 'track':
                                metadata_list = pms_connect.get_metadata_details(item['grandparent_rating_key'])

                                if metadata_list:
                                    item = metadata_list['metadata']
                                else:
                                    logger.error(u"Plex:CS Monitor :: Unable to retrieve grandparent metadata for grandparent_rating_key %s" \
                                                 % str(item['rating_key']))

                            logger.debug(u"Plex:CS Monitor :: Library item %s has been added to Plex." % str(item['rating_key']))
                            # Fire off notifications
                            threading.Thread(target=notification_handler.notify_timeline,
                                             kwargs=dict(timeline_data=item, notify_action='created')).start()
Exemplo n.º 3
0
    def _getMetadata(self, rating_key='', **kwargs):

        pms_connect = pmsconnect.PmsConnect()
        result = pms_connect.get_metadata(rating_key, 'dict')

        if result:
            self.data = result
            return result
        else:
            self.msg = 'Unable to retrive metadata %s' % rating_key
            logger.warn('Unable to retrieve data.')
Exemplo n.º 4
0
    def _getSync(self, machine_id=None, user_id=None, **kwargs):

        pms_connect = pmsconnect.PmsConnect()
        server_id = pms_connect.get_server_identity()

        plex_tv = plextv.PlexTV()
        if not machine_id:
            result = plex_tv.get_synced_items(
                machine_id=server_id['machine_identifier'], user_id=user_id)
        else:
            result = plex_tv.get_synced_items(machine_id=machine_id,
                                              user_id=user_id)

        if result:
            self.data = result
            return result
        else:
            self.msg = 'Unable to retrieve sync data for user'
            logger.warn('Unable to retrieve sync data for user.')
Exemplo n.º 5
0
def check_active_sessions(ws_request=False):

    with monitor_lock:
        pms_connect = pmsconnect.PmsConnect()
        session_list = pms_connect.get_current_activity()
        monitor_db = database.MonitorDatabase()
        monitor_process = activity_processor.ActivityProcessor()
        # logger.debug(u"Plex:CS Monitor :: Checking for active streams.")

        global int_ping_count

        if session_list:
            int_ping_count = 0

            media_container = session_list['sessions']

            # Check our temp table for what we must do with the new streams
            db_streams = monitor_db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
                                           'grandparent_title, user_id, user, friendly_name, ip_address, player, '
                                           'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
                                           'view_offset, duration, video_decision, audio_decision, width, height, '
                                           'container, video_codec, audio_codec, bitrate, video_resolution, '
                                           'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
                                           'transcode_container, transcode_video_codec, transcode_audio_codec, '
                                           'transcode_audio_channels, transcode_width, transcode_height, '
                                           'paused_counter, last_paused '
                                           'FROM sessions')
            for stream in db_streams:
                if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key'])
                       for d in media_container):
                    # The user's session is still active
                    for session in media_container:
                        if session['session_key'] == str(stream['session_key']) and \
                                session['rating_key'] == str(stream['rating_key']):
                            # The user is still playing the same media item
                            # Here we can check the play states
                            if session['state'] != stream['state']:
                                if session['state'] == 'paused':
                                    # Push any notifications -
                                    # Push it on it's own thread so we don't hold up our db actions
                                    threading.Thread(target=notification_handler.notify,
                                                     kwargs=dict(stream_data=stream, notify_action='pause')).start()

                                if session['state'] == 'playing' and stream['state'] == 'paused':
                                    # Push any notifications -
                                    # Push it on it's own thread so we don't hold up our db actions
                                    threading.Thread(target=notification_handler.notify,
                                                     kwargs=dict(stream_data=stream, notify_action='resume')).start()

                            if stream['state'] == 'paused' and not ws_request:
                                # The stream is still paused so we need to increment the paused_counter
                                # Using the set config parameter as the interval, probably not the most accurate but
                                # it will have to do for now. If it's a websocket request don't use this method.
                                paused_counter = int(stream['paused_counter']) + plexcs.CONFIG.MONITORING_INTERVAL
                                monitor_db.action('UPDATE sessions SET paused_counter = ? '
                                                  'WHERE session_key = ? AND rating_key = ?',
                                                  [paused_counter, stream['session_key'], stream['rating_key']])

                            if session['state'] == 'buffering' and plexcs.CONFIG.BUFFER_THRESHOLD > 0:
                                # The stream is buffering so we need to increment the buffer_count
                                # We're going just increment on every monitor ping,
                                # would be difficult to keep track otherwise
                                monitor_db.action('UPDATE sessions SET buffer_count = buffer_count + 1 '
                                                  'WHERE session_key = ? AND rating_key = ?',
                                                  [stream['session_key'], stream['rating_key']])

                                # Check the current buffer count and last buffer to determine if we should notify
                                buffer_values = monitor_db.select('SELECT buffer_count, buffer_last_triggered '
                                                                  'FROM sessions '
                                                                  'WHERE session_key = ? AND rating_key = ?',
                                                                  [stream['session_key'], stream['rating_key']])

                                if buffer_values[0]['buffer_count'] >= plexcs.CONFIG.BUFFER_THRESHOLD:
                                    # Push any notifications -
                                    # Push it on it's own thread so we don't hold up our db actions
                                    # Our first buffer notification
                                    if buffer_values[0]['buffer_count'] == plexcs.CONFIG.BUFFER_THRESHOLD:
                                        logger.info(u"Plex:CS Monitor :: User '%s' has triggered a buffer warning."
                                                    % stream['user'])
                                        # Set the buffer trigger time
                                        monitor_db.action('UPDATE sessions '
                                                          'SET buffer_last_triggered = strftime("%s","now") '
                                                          'WHERE session_key = ? AND rating_key = ?',
                                                          [stream['session_key'], stream['rating_key']])

                                        threading.Thread(target=notification_handler.notify,
                                                         kwargs=dict(stream_data=stream, notify_action='buffer')).start()
                                    else:
                                        # Subsequent buffer notifications after wait time
                                        if int(time.time()) > buffer_values[0]['buffer_last_triggered'] + \
                                                plexcs.CONFIG.BUFFER_WAIT:
                                            logger.info(u"Plex:CS Monitor :: User '%s' has triggered multiple buffer warnings."
                                                    % stream['user'])
                                            # Set the buffer trigger time
                                            monitor_db.action('UPDATE sessions '
                                                              'SET buffer_last_triggered = strftime("%s","now") '
                                                              'WHERE session_key = ? AND rating_key = ?',
                                                              [stream['session_key'], stream['rating_key']])

                                            threading.Thread(target=notification_handler.notify,
                                                             kwargs=dict(stream_data=stream, notify_action='buffer')).start()

                                logger.debug(u"Plex:CS Monitor :: Stream buffering. Count is now %s. Last triggered %s."
                                             % (buffer_values[0]['buffer_count'],
                                                buffer_values[0]['buffer_last_triggered']))

                            # Check if the user has reached the offset in the media we defined as the "watched" percent
                            # Don't trigger if state is buffer as some clients push the progress to the end when
                            # buffering on start.
                            if session['view_offset'] and session['duration'] and session['state'] != 'buffering':
                                if helpers.get_percent(session['view_offset'],
                                                       session['duration']) > plexcs.CONFIG.NOTIFY_WATCHED_PERCENT:
                                    # Push any notifications -
                                    # Push it on it's own thread so we don't hold up our db actions
                                    threading.Thread(target=notification_handler.notify,
                                                     kwargs=dict(stream_data=stream, notify_action='watched')).start()

                else:
                    # The user has stopped playing a stream
                    logger.debug(u"Plex:CS Monitor :: Removing sessionKey %s ratingKey %s from session queue"
                                 % (stream['session_key'], stream['rating_key']))
                    monitor_db.action('DELETE FROM sessions WHERE session_key = ? AND rating_key = ?',
                                      [stream['session_key'], stream['rating_key']])

                    # Check if the user has reached the offset in the media we defined as the "watched" percent
                    if stream['view_offset'] and stream['duration']:
                        if helpers.get_percent(stream['view_offset'],
                                               stream['duration']) > plexcs.CONFIG.NOTIFY_WATCHED_PERCENT:
                            # Push any notifications -
                            # Push it on it's own thread so we don't hold up our db actions
                            threading.Thread(target=notification_handler.notify,
                                             kwargs=dict(stream_data=stream, notify_action='watched')).start()

                    # Push any notifications - Push it on it's own thread so we don't hold up our db actions
                    threading.Thread(target=notification_handler.notify,
                                     kwargs=dict(stream_data=stream, notify_action='stop')).start()

                    # Write the item history on playback stop
                    monitor_process.write_session_history(session=stream)

            # Process the newly received session data
            for session in media_container:
                monitor_process.write_session(session)
        else:
            logger.debug(u"Plex:CS Monitor :: Unable to read session list.")

            int_ping_count += 1
            logger.warn(u"Plex:CS Monitor :: Unable to get an internal response from the server, ping attempt %s." \
                        % str(int_ping_count))

        if int_ping_count == 3:
            # Fire off notifications
            threading.Thread(target=notification_handler.notify_timeline,
                                kwargs=dict(notify_action='intdown')).start()
Exemplo n.º 6
0
def build_notify_text(session=None, timeline=None, state=None):
    import re

    # Get the server name
    server_name = plexcs.CONFIG.PMS_NAME

    # Get the server uptime
    plex_tv = plextv.PlexTV()
    server_times = plex_tv.get_server_times()

    if server_times:
        updated_at = server_times[0]['updated_at']
        server_uptime = helpers.human_duration(
            int(time.time() - helpers.cast_to_float(updated_at)))
    else:
        logger.error(u"Plex:CS Notifier :: Unable to retrieve server uptime.")
        server_uptime = 'N/A'

    # Get metadata feed for item
    if session:
        rating_key = session['rating_key']
    elif timeline:
        rating_key = timeline['rating_key']

    pms_connect = pmsconnect.PmsConnect()
    metadata_list = pms_connect.get_metadata_details(rating_key=rating_key)

    if metadata_list:
        metadata = metadata_list['metadata']
    else:
        logger.error(
            u"Plex:CS Notifier :: Unable to retrieve metadata for rating_key %s"
            % str(rating_key))
        return []

    # Check for exclusion tags
    if metadata['media_type'] == 'movie':
        # Regex pattern to remove the text in the tags we don't want
        pattern = re.compile(
            '\n*<tv>[^>]+.</tv>\n*|\n*<music>[^>]+.</music>\n*',
            re.IGNORECASE | re.DOTALL)
    elif metadata['media_type'] == 'show' or metadata[
            'media_type'] == 'episode':
        # Regex pattern to remove the text in the tags we don't want
        pattern = re.compile(
            '\n*<movie>[^>]+.</movie>\n*|\n*?<music>[^>]+.</music>\n*',
            re.IGNORECASE | re.DOTALL)
    elif metadata['media_type'] == 'artist' or metadata[
            'media_type'] == 'track':
        # Regex pattern to remove the text in the tags we don't want
        pattern = re.compile(
            '\n*<tv>[^>]+.</tv>\n*|\n*<movie>[^>]+.</movie>\n*',
            re.IGNORECASE | re.DOTALL)
    else:
        pattern = None

    if metadata['media_type'] == 'movie' \
        or metadata['media_type'] == 'show' or metadata['media_type'] == 'episode' \
        or metadata['media_type'] == 'artist' or metadata['media_type'] == 'track' \
        and pattern:
        # Remove the unwanted tags and strip any unmatch tags too.
        on_start_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT))
        on_start_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_START_BODY_TEXT))
        on_stop_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT))
        on_stop_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_STOP_BODY_TEXT))
        on_pause_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT))
        on_pause_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT))
        on_resume_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT))
        on_resume_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT))
        on_buffer_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT))
        on_buffer_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT))
        on_watched_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT))
        on_watched_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT))
        on_created_subject = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT))
        on_created_body = strip_tag(
            re.sub(pattern, '', plexcs.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT))
    else:
        on_start_subject = plexcs.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT
        on_start_body = plexcs.CONFIG.NOTIFY_ON_START_BODY_TEXT
        on_stop_subject = plexcs.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT
        on_stop_body = plexcs.CONFIG.NOTIFY_ON_STOP_BODY_TEXT
        on_pause_subject = plexcs.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT
        on_pause_body = plexcs.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT
        on_resume_subject = plexcs.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT
        on_resume_body = plexcs.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT
        on_buffer_subject = plexcs.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT
        on_buffer_body = plexcs.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT
        on_watched_subject = plexcs.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT
        on_watched_body = plexcs.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT
        on_created_subject = plexcs.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT
        on_created_body = plexcs.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT

    # Create a title
    if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track':
        full_title = '%s - %s' % (metadata['grandparent_title'],
                                  metadata['title'])
    else:
        full_title = metadata['title']

    duration = helpers.convert_milliseconds_to_minutes(metadata['duration'])

    # Default values
    video_decision = ''
    audio_decision = ''
    transcode_decision = ''
    stream_duration = 0
    view_offset = 0
    user = ''
    platform = ''
    player = ''
    ip_address = 'N/A'

    # Session values
    if session:
        # Generate a combined transcode decision value
        video_decision = session['video_decision'].title()
        audio_decision = session['audio_decision'].title()

        if session['video_decision'] == 'transcode' or session[
                'audio_decision'] == 'transcode':
            transcode_decision = 'Transcode'
        elif session['video_decision'] == 'copy' or session[
                'audio_decision'] == 'copy':
            transcode_decision = 'Direct Stream'
        else:
            transcode_decision = 'Direct Play'

        if state != 'play':
            if session['paused_counter']:
                stream_duration = int(
                    (time.time() - helpers.cast_to_float(session['started']) -
                     helpers.cast_to_float(session['paused_counter'])) / 60)
            else:
                stream_duration = int(
                    (time.time() - helpers.cast_to_float(session['started'])) /
                    60)

        view_offset = helpers.convert_milliseconds_to_minutes(
            session['view_offset'])
        user = session['friendly_name']
        platform = session['platform']
        player = session['player']
        ip_address = session['ip_address'] if session['ip_address'] else 'N/A'

    progress_percent = helpers.get_percent(view_offset, duration)

    available_params = {
        'server_name': server_name,
        'server_uptime': server_uptime,
        'user': user,
        'platform': platform,
        'player': player,
        'ip_address': ip_address,
        'media_type': metadata['media_type'],
        'title': full_title,
        'show_name': metadata['grandparent_title'],
        'episode_name': metadata['title'],
        'artist_name': metadata['grandparent_title'],
        'album_name': metadata['parent_title'],
        'track_name': metadata['title'],
        'season_num': metadata['parent_index'].zfill(1),
        'season_num00': metadata['parent_index'].zfill(2),
        'episode_num': metadata['index'].zfill(1),
        'episode_num00': metadata['index'].zfill(2),
        'video_decision': video_decision,
        'audio_decision': audio_decision,
        'transcode_decision': transcode_decision,
        'year': metadata['year'],
        'studio': metadata['studio'],
        'content_rating': metadata['content_rating'],
        'directors': ', '.join(metadata['directors']),
        'writers': ', '.join(metadata['writers']),
        'actors': ', '.join(metadata['actors']),
        'genres': ', '.join(metadata['genres']),
        'summary': metadata['summary'],
        'tagline': metadata['tagline'],
        'rating': metadata['rating'],
        'duration': duration,
        'stream_duration': stream_duration,
        'remaining_duration': duration - view_offset,
        'progress': view_offset,
        'progress_percent': progress_percent
    }

    # Default subject text
    subject_text = 'Plex:CS (%s)' % server_name

    if state == 'play':
        # Default body text
        body_text = '%s (%s) is watching %s' % (session['friendly_name'],
                                                session['player'], full_title)

        if on_start_subject and on_start_body:
            try:
                subject_text = unicode(on_start_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_start_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    elif state == 'stop':
        # Default body text
        body_text = '%s (%s) has stopped %s' % (session['friendly_name'],
                                                session['player'], full_title)

        if on_stop_subject and on_stop_body:
            try:
                subject_text = unicode(on_stop_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_stop_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    elif state == 'pause':
        # Default body text
        body_text = '%s (%s) has paused %s' % (session['friendly_name'],
                                               session['player'], full_title)

        if on_pause_subject and on_pause_body:
            try:
                subject_text = unicode(on_pause_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_pause_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    elif state == 'resume':
        # Default body text
        body_text = '%s (%s) has resumed %s' % (session['friendly_name'],
                                                session['player'], full_title)

        if on_resume_subject and on_resume_body:
            try:
                subject_text = unicode(on_resume_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_resume_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    elif state == 'buffer':
        # Default body text
        body_text = '%s (%s) is buffering %s' % (session['friendly_name'],
                                                 session['player'], full_title)

        if on_buffer_subject and on_buffer_body:
            try:
                subject_text = unicode(on_buffer_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_buffer_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    elif state == 'watched':
        # Default body text
        body_text = '%s (%s) has watched %s' % (session['friendly_name'],
                                                session['player'], full_title)

        if on_watched_subject and on_watched_body:
            try:
                subject_text = unicode(on_watched_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_watched_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    elif state == 'created':
        # Default body text
        body_text = '%s was recently added to Plex.' % full_title

        if on_created_subject and on_created_body:
            try:
                subject_text = unicode(on_created_subject).format(
                    **available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification subject. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification subject. Using fallback."
                )

            try:
                body_text = unicode(on_created_body).format(**available_params)
            except LookupError as e:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse field %s in notification body. Using fallback."
                    % e)
            except:
                logger.error(
                    u"Plex:CS Notifier :: Unable to parse custom notification body. Using fallback."
                )

            return [subject_text, body_text]
        else:
            return [subject_text, body_text]
    else:
        return None
Exemplo n.º 7
0
    def write_session_history(self,
                              session=None,
                              import_metadata=None,
                              is_import=False,
                              import_ignore_interval=0):
        from plexcs import users

        user_data = users.Users()
        user_details = user_data.get_user_friendly_name(user=session['user'])

        if session:
            logging_enabled = False

            if is_import:
                if str(session['stopped']).isdigit():
                    stopped = int(session['stopped'])
                else:
                    stopped = int(time.time())
            else:
                stopped = int(time.time())

            if plexcs.CONFIG.MOVIE_LOGGING_ENABLE and str(session['rating_key']).isdigit() and \
                    session['media_type'] == 'movie':
                logging_enabled = True
            elif plexcs.CONFIG.TV_LOGGING_ENABLE and str(session['rating_key']).isdigit() and \
                    session['media_type'] == 'episode':
                logging_enabled = True
            elif plexcs.CONFIG.MUSIC_LOGGING_ENABLE and str(session['rating_key']).isdigit() and \
                    session['media_type'] == 'track':
                logging_enabled = True
            else:
                logger.debug(
                    u"Plex:CS ActivityProcessor :: ratingKey %s not logged. Does not meet logging criteria. "
                    u"Media type is '%s'" %
                    (session['rating_key'], session['media_type']))

            if str(session['paused_counter']).isdigit():
                real_play_time = stopped - session['started'] - int(
                    session['paused_counter'])
            else:
                real_play_time = stopped - session['started']

            if plexcs.CONFIG.LOGGING_IGNORE_INTERVAL and not is_import:
                if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \
                        (real_play_time < int(plexcs.CONFIG.LOGGING_IGNORE_INTERVAL)):
                    logging_enabled = False
                    logger.debug(
                        u"Plex:CS ActivityProcessor :: Play duration for ratingKey %s is %s secs which is less than %s "
                        u"seconds, so we're not logging it." %
                        (session['rating_key'], str(real_play_time),
                         plexcs.CONFIG.LOGGING_IGNORE_INTERVAL))
            if session['media_type'] == 'track' and not is_import:
                if real_play_time < 15 and session['duration'] >= 30:
                    logging_enabled = False
                    logger.debug(
                        u"Plex:CS ActivityProcessor :: Play duration for ratingKey %s is %s secs, "
                        u"looks like it was skipped so we're not logging it" %
                        (session['rating_key'], str(real_play_time)))
            elif is_import and import_ignore_interval:
                if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \
                        (real_play_time < int(import_ignore_interval)):
                    logging_enabled = False
                    logger.debug(
                        u"Plex:CS ActivityProcessor :: Play duration for ratingKey %s is %s secs which is less than %s "
                        u"seconds, so we're not logging it." %
                        (session['rating_key'], str(real_play_time),
                         import_ignore_interval))

            if not user_details['keep_history'] and not is_import:
                logging_enabled = False
                logger.debug(
                    u"Plex:CS ActivityProcessor :: History logging for user '%s' is disabled."
                    % session['user'])

            if logging_enabled:
                # logger.debug(u"Plex:CS ActivityProcessor :: Attempting to write to session_history table...")
                query = 'INSERT INTO session_history (started, stopped, rating_key, parent_rating_key, ' \
                        'grandparent_rating_key, media_type, user_id, user, ip_address, paused_counter, player, ' \
                        'platform, machine_id, view_offset) VALUES ' \
                        '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'

                args = [
                    session['started'], stopped, session['rating_key'],
                    session['parent_rating_key'],
                    session['grandparent_rating_key'], session['media_type'],
                    session['user_id'], session['user'], session['ip_address'],
                    session['paused_counter'], session['player'],
                    session['platform'], session['machine_id'],
                    session['view_offset']
                ]

                # logger.debug(u"Plex:CS ActivityProcessor :: Writing session_history transaction...")
                self.db.action(query=query, args=args)

                # Check if we should group the session, select the last two rows from the user
                query = 'SELECT id, rating_key, user_id, reference_id FROM session_history \
                         WHERE user_id = ? ORDER BY id DESC LIMIT 2 '

                args = [session['user_id']]

                result = self.db.select(query=query, args=args)

                new_session = {
                    'id': result[0]['id'],
                    'rating_key': result[0]['rating_key'],
                    'user_id': result[0]['user_id'],
                    'reference_id': result[0]['reference_id']
                }

                if len(result) == 1:
                    prev_session = None
                else:
                    prev_session = {
                        'id': result[1]['id'],
                        'rating_key': result[1]['rating_key'],
                        'user_id': result[1]['user_id'],
                        'reference_id': result[1]['reference_id']
                    }

                query = 'UPDATE session_history SET reference_id = ? WHERE id = ? '
                # If rating_key is the same in the previous session, then set the reference_id to the previous row, else set the reference_id to the new id
                if (prev_session
                        is not None) and (prev_session['rating_key']
                                          == new_session['rating_key']):
                    args = [prev_session['reference_id'], new_session['id']]
                else:
                    args = [new_session['id'], new_session['id']]

                self.db.action(query=query, args=args)

                # logger.debug(u"Plex:CS ActivityProcessor :: Successfully written history item, last id for session_history is %s"
                #              % last_id)

                # Write the session_history_media_info table
                # logger.debug(u"Plex:CS ActivityProcessor :: Attempting to write to session_history_media_info table...")
                query = 'INSERT INTO session_history_media_info (id, rating_key, video_decision, audio_decision, ' \
                        'duration, width, height, container, video_codec, audio_codec, bitrate, video_resolution, ' \
                        'video_framerate, aspect_ratio, audio_channels, transcode_protocol, transcode_container, ' \
                        'transcode_video_codec, transcode_audio_codec, transcode_audio_channels, transcode_width, ' \
                        'transcode_height) VALUES ' \
                        '(last_insert_rowid(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'

                args = [
                    session['rating_key'], session['video_decision'],
                    session['audio_decision'], session['duration'],
                    session['width'], session['height'], session['container'],
                    session['video_codec'], session['audio_codec'],
                    session['bitrate'], session['video_resolution'],
                    session['video_framerate'], session['aspect_ratio'],
                    session['audio_channels'], session['transcode_protocol'],
                    session['transcode_container'],
                    session['transcode_video_codec'],
                    session['transcode_audio_codec'],
                    session['transcode_audio_channels'],
                    session['transcode_width'], session['transcode_height']
                ]

                # logger.debug(u"Plex:CS ActivityProcessor :: Writing session_history_media_info transaction...")
                self.db.action(query=query, args=args)

                if not is_import:
                    logger.debug(
                        u"Plex:CS ActivityProcessor :: Fetching metadata for item ratingKey %s"
                        % session['rating_key'])
                    pms_connect = pmsconnect.PmsConnect()
                    result = pms_connect.get_metadata_details(
                        rating_key=str(session['rating_key']))
                    metadata = result['metadata']
                else:
                    metadata = import_metadata

                # Write the session_history_metadata table
                directors = ";".join(metadata['directors'])
                writers = ";".join(metadata['writers'])
                actors = ";".join(metadata['actors'])
                genres = ";".join(metadata['genres'])

                # Build media item title
                if session['media_type'] == 'episode' or session[
                        'media_type'] == 'track':
                    full_title = '%s - %s' % (metadata['grandparent_title'],
                                              metadata['title'])
                elif session['media_type'] == 'movie':
                    full_title = metadata['title']
                else:
                    full_title = metadata['title']

                # logger.debug(u"Plex:CS ActivityProcessor :: Attempting to write to session_history_metadata table...")
                query = 'INSERT INTO session_history_metadata (id, rating_key, parent_rating_key, ' \
                        'grandparent_rating_key, title, parent_title, grandparent_title, full_title, media_index, ' \
                        'parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, year, ' \
                        'originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, ' \
                        'tagline, rating, duration, guid, directors, writers, actors, genres, studio) VALUES ' \
                        '(last_insert_rowid(), ' \
                        '?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'

                args = [
                    session['rating_key'], session['parent_rating_key'],
                    session['grandparent_rating_key'], session['title'],
                    session['parent_title'], session['grandparent_title'],
                    full_title, metadata['index'], metadata['parent_index'],
                    metadata['thumb'], metadata['parent_thumb'],
                    metadata['grandparent_thumb'], metadata['art'],
                    session['media_type'], metadata['year'],
                    metadata['originally_available_at'], metadata['added_at'],
                    metadata['updated_at'], metadata['last_viewed_at'],
                    metadata['content_rating'], metadata['summary'],
                    metadata['tagline'], metadata['rating'],
                    metadata['duration'], metadata['guid'], directors, writers,
                    actors, genres, metadata['studio']
                ]

                # logger.debug(u"Plex:CS ActivityProcessor :: Writing session_history_metadata transaction...")
                self.db.action(query=query, args=args)