diff --git a/data/interfaces/default/home_stats.html b/data/interfaces/default/home_stats.html index cb8bea64..5c54d771 100644 --- a/data/interfaces/default/home_stats.html +++ b/data/interfaces/default/home_stats.html @@ -21,10 +21,11 @@ grandparent_thumb Returns location of the item's thumbnail. Use with pms_i rating_key Returns the unique identifier for the media item. title Returns the title for the associated stat. -== Only if 'stat_id' is 'top_tv' or 'top_user' or 'top_platform' == +== Only if 'stat_id' is 'top_tv' or 'top_movies' or 'top_user' or 'top_platform' == total_plays Returns the count for the associated stat. +total_duration Returns the total duration for the associated stat. -== Only of 'stat_id' is 'popular_tv' == +== Only of 'stat_id' is 'popular_tv' or 'popular_movies' == users_watched Returns the count for the associated stat. == Only if 'stat_id' is 'top_user' == @@ -63,8 +64,13 @@ DOCUMENTATION :: END
+ % if a['stat_type'] == 'total_plays':

${a['rows'][0]['total_plays']}

plays

+ % else: +

${a['rows'][0]['total_duration']}

+

mins

+ % endif
@@ -113,8 +119,38 @@ DOCUMENTATION :: END
+ % if a['stat_type'] == 'total_plays':

${a['rows'][0]['total_plays']}

plays

+ % else: +

${a['rows'][0]['total_duration']}

+

mins

+ % endif +
+ + + % elif a['stat_id'] == 'popular_movies' and a['rows']: +
+
  • + + + % if a['rows'][0]['thumb']: + + % else: + + % endif + + +
    +

    Most Popular Movie

    +
    + ${a['rows'][0]['title']} +
    +
    +
    +

    ${a['rows'][0]['users_watched']}

    +

    users

  • @@ -149,8 +185,13 @@ DOCUMENTATION :: END
    + % if a['stat_type'] == 'total_plays':

    ${a['rows'][0]['total_plays']}

    plays

    + % else: +

    ${a['rows'][0]['total_duration']}

    +

    mins

    + % endif
    @@ -165,8 +206,13 @@ DOCUMENTATION :: END
    ${a['rows'][0]['platform_type']}
    + % if a['stat_type'] == 'total_plays':

    ${a['rows'][0]['total_plays']}

    plays

    + % else: +

    ${a['rows'][0]['total_duration']}

    +

    mins

    + % endif
    diff --git a/data/interfaces/default/index.html b/data/interfaces/default/index.html index b78bc0cb..5af438ef 100644 --- a/data/interfaces/default/index.html +++ b/data/interfaces/default/index.html @@ -45,12 +45,12 @@ diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 70e6f6a0..581bb715 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -280,8 +280,12 @@ available_notification_agents = notifiers.available_notification_agents()

    If you have media indexing enabled on your server, use these on the activity pane.

    +
    +

    Homepage Statistics

    +
    +
    - +
    @@ -289,6 +293,12 @@ available_notification_agents = notifiers.available_notification_agents()

    Specify the number of days for the statistics on the home page. Default is 30 days.

    +
    + +

    Use play duration instead of play count to generate statistics.

    +

    Plex Logs

    diff --git a/plexpy/config.py b/plexpy/config.py index 55411795..5fe59e29 100644 --- a/plexpy/config.py +++ b/plexpy/config.py @@ -83,6 +83,7 @@ _CONFIG_DEFINITIONS = { 'GROWL_ON_BUFFER': (int, 'Growl', 0), 'GROWL_ON_WATCHED': (int, 'Growl', 0), 'HOME_STATS_LENGTH': (int, 'General', 30), + 'HOME_STATS_TYPE': (int, 'General', 0), 'HTTPS_CERT': (str, 'General', ''), 'HTTPS_KEY': (str, 'General', ''), 'HTTP_HOST': (str, 'General', '0.0.0.0'), diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 3f8e89ef..005f6d07 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -110,14 +110,16 @@ class DataFactory(object): return dict - def get_home_stats(self, time_range='30'): + def get_home_stats(self, time_range='30', stat_type='0'): monitor_db = database.MonitorDatabase() if not time_range.isdigit(): time_range = '30' + sort_type = 'total_plays' if stat_type == '0' else 'total_duration' + # This actually determines the output order in the home page - stats_queries = ["top_tv", "popular_tv", "top_movies", "top_users", "top_platforms"] + stats_queries = ["top_tv", "popular_tv", "top_movies", "popular_movies", "top_users", "top_platforms"] home_stats = [] for stat in stats_queries: @@ -127,6 +129,10 @@ class DataFactory(object): query = 'SELECT session_history_metadata.id, ' \ 'session_history_metadata.grandparent_title, ' \ 'COUNT(session_history_metadata.grandparent_title) as total_plays, ' \ + 'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \ + 'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \ + '(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \ + 'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \ 'session_history_metadata.grandparent_rating_key, ' \ 'MAX(session_history.started) as last_watch,' \ 'session_history_metadata.grandparent_thumb ' \ @@ -136,7 +142,7 @@ class DataFactory(object): '>= datetime("now", "-%s days", "localtime") ' \ 'AND session_history_metadata.media_type = "episode" ' \ 'GROUP BY session_history_metadata.grandparent_title ' \ - 'ORDER BY total_plays DESC LIMIT 10' % time_range + 'ORDER BY %s DESC LIMIT 10' % (time_range, sort_type) result = monitor_db.select(query) except: logger.warn("Unable to execute database query.") @@ -145,10 +151,11 @@ class DataFactory(object): for item in result: row = {'title': item[1], 'total_plays': item[2], + 'total_duration': item[3], 'users_watched': '', - 'rating_key': item[3], - 'last_play': item[4], - 'grandparent_thumb': item[5], + 'rating_key': item[4], + 'last_play': item[5], + 'grandparent_thumb': item[6], 'thumb': '', 'user': '', 'friendly_name': '', @@ -159,6 +166,7 @@ class DataFactory(object): top_tv.append(row) home_stats.append({'stat_id': stat, + 'stat_type': sort_type, 'rows': top_tv}) elif 'top_movies' in stat: @@ -167,6 +175,10 @@ class DataFactory(object): query = 'SELECT session_history_metadata.id, ' \ 'session_history_metadata.full_title, ' \ 'COUNT(session_history_metadata.full_title) as total_plays, ' \ + 'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \ + 'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \ + '(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \ + 'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \ 'session_history_metadata.rating_key, ' \ 'MAX(session_history.started) as last_watch,' \ 'session_history_metadata.thumb ' \ @@ -176,7 +188,7 @@ class DataFactory(object): '>= datetime("now", "-%s days", "localtime") ' \ 'AND session_history_metadata.media_type = "movie" ' \ 'GROUP BY session_history_metadata.full_title ' \ - 'ORDER BY total_plays DESC LIMIT 10' % time_range + 'ORDER BY %s DESC LIMIT 10' % (time_range, sort_type) result = monitor_db.select(query) except: logger.warn("Unable to execute database query.") @@ -185,11 +197,12 @@ class DataFactory(object): for item in result: row = {'title': item[1], 'total_plays': item[2], + 'total_duration': item[3], 'users_watched': '', - 'rating_key': item[3], - 'last_play': item[4], + 'rating_key': item[4], + 'last_play': item[5], 'grandparent_thumb': '', - 'thumb': item[5], + 'thumb': item[6], 'user': '', 'friendly_name': '', 'platform_type': '', @@ -199,6 +212,7 @@ class DataFactory(object): top_movies.append(row) home_stats.append({'stat_id': stat, + 'stat_type': sort_type, 'rows': top_movies}) elif 'popular_tv' in stat: @@ -243,6 +257,48 @@ class DataFactory(object): home_stats.append({'stat_id': stat, 'rows': popular_tv}) + elif 'popular_movies' in stat: + popular_movies = [] + try: + query = 'SELECT session_history_metadata.id, ' \ + 'session_history_metadata.full_title, ' \ + 'COUNT(DISTINCT session_history.user_id) as users_watched, ' \ + 'session_history_metadata.rating_key, ' \ + 'MAX(session_history.started) as last_watch, ' \ + 'COUNT(session_history.id) as total_plays, ' \ + 'session_history_metadata.thumb ' \ + 'FROM session_history_metadata ' \ + 'JOIN session_history ON session_history_metadata.id = session_history.id ' \ + 'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \ + '>= datetime("now", "-%s days", "localtime") ' \ + 'AND session_history_metadata.media_type = "movie" ' \ + 'GROUP BY session_history_metadata.full_title ' \ + 'ORDER BY users_watched DESC, total_plays DESC ' \ + 'LIMIT 10' % time_range + result = monitor_db.select(query) + except: + logger.warn("Unable to execute database query.") + return None + + for item in result: + row = {'title': item[1], + 'users_watched': item[2], + 'rating_key': item[3], + 'last_play': item[4], + 'total_plays': item[5], + 'grandparent_thumb': '', + 'thumb': item[6], + 'user': '', + 'friendly_name': '', + 'platform_type': '', + 'platform': '', + 'row_id': item[0] + } + popular_movies.append(row) + + home_stats.append({'stat_id': stat, + 'rows': popular_movies}) + elif 'top_users' in stat: top_users = [] try: @@ -250,6 +306,10 @@ class DataFactory(object): '(case when users.friendly_name is null then session_history.user else ' \ 'users.friendly_name end) as friendly_name,' \ 'COUNT(session_history.id) as total_plays, ' \ + 'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \ + 'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \ + '(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \ + 'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \ 'MAX(session_history.started) as last_watch, ' \ 'users.custom_avatar_url as thumb, ' \ 'users.user_id ' \ @@ -259,23 +319,24 @@ class DataFactory(object): 'WHERE datetime(session_history.stopped, "unixepoch", "localtime") >= ' \ 'datetime("now", "-%s days", "localtime") '\ 'GROUP BY session_history.user_id ' \ - 'ORDER BY total_plays DESC LIMIT 10' % time_range + 'ORDER BY %s DESC LIMIT 10' % (time_range, sort_type) result = monitor_db.select(query) except: logger.warn("Unable to execute database query.") return None for item in result: - if not item[4] or item[4] == '': + if not item[5] or item[5] == '': user_thumb = common.DEFAULT_USER_THUMB else: - user_thumb = item[4] + user_thumb = item[5] row = {'user': item[0], - 'user_id': item[5], + 'user_id': item[6], 'friendly_name': item[1], 'total_plays': item[2], - 'last_play': item[3], + 'total_duration': item[3], + 'last_play': item[4], 'thumb': user_thumb, 'grandparent_thumb': '', 'users_watched': '', @@ -288,6 +349,7 @@ class DataFactory(object): top_users.append(row) home_stats.append({'stat_id': stat, + 'stat_type': sort_type, 'rows': top_users}) elif 'top_platforms' in stat: @@ -296,6 +358,10 @@ class DataFactory(object): try: query = 'SELECT session_history.platform, ' \ 'COUNT(session_history.id) as total_plays, ' \ + 'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \ + 'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \ + '(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \ + 'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \ 'MAX(session_history.started) as last_watch ' \ 'FROM session_history ' \ 'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \ @@ -310,7 +376,8 @@ class DataFactory(object): for item in result: row = {'platform': item[0], 'total_plays': item[1], - 'last_play': item[2], + 'total_duration': item[2], + 'last_play': item[3], 'platform_type': item[0], 'title': '', 'thumb': '', @@ -324,6 +391,7 @@ class DataFactory(object): top_platform.append(row) home_stats.append({'stat_id': stat, + 'stat_type': sort_type, 'rows': top_platform}) return home_stats diff --git a/plexpy/webserve.py b/plexpy/webserve.py index ef2ad933..8b7e3c6d 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -65,7 +65,8 @@ class WebInterface(object): @cherrypy.expose def home(self): config = { - "home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH + "home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH, + "home_stats_type": plexpy.CONFIG.HOME_STATS_TYPE } return serve_template(templatename="index.html", title="Home", config=config) @@ -118,9 +119,9 @@ class WebInterface(object): return json.dumps(formats) @cherrypy.expose - def home_stats(self, time_range='30', **kwargs): + def home_stats(self, time_range='30', stat_type='0', **kwargs): data_factory = datafactory.DataFactory() - stats_data = data_factory.get_home_stats(time_range=time_range) + stats_data = data_factory.get_home_stats(time_range=time_range, stat_type=stat_type) return serve_template(templatename="home_stats.html", title="Stats", data=stats_data) @@ -451,6 +452,7 @@ class WebInterface(object): "notify_on_watched_subject_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT, "notify_on_watched_body_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT, "home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH, + "home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE), "buffer_threshold": plexpy.CONFIG.BUFFER_THRESHOLD, "buffer_wait": plexpy.CONFIG.BUFFER_WAIT } @@ -473,7 +475,7 @@ class WebInterface(object): "tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start", "tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop", "tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup", - "ip_logging_enable", "video_logging_enable", "music_logging_enable", "pms_is_remote" + "ip_logging_enable", "video_logging_enable", "music_logging_enable", "pms_is_remote", "home_stats_type" ] for checked_config in checked_configs: if checked_config not in kwargs: