mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-12 00:06:07 -07:00
Separate movie/episode/track watched percent
This commit is contained in:
parent
8348424758
commit
6f0c650a72
7 changed files with 74 additions and 36 deletions
|
@ -119,14 +119,34 @@
|
||||||
<p class="help-block">Include current activity in the history tables. Statistics will not be counted until the stream has ended.</p>
|
<p class="help-block">Include current activity in the history tables. Statistics will not be counted until the stream has ended.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="notify_watched_percent">Watched Percent</label>
|
<label for="movie_watched_percent">Movie Watched Percent</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" data-parsley-errors-container="#notify_watched_percent_error" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="movie_watched_percent" name="movie_watched_percent" value="${config['movie_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" data-parsley-errors-container="#movie_watched_percent_error" required>
|
||||||
</div>
|
</div>
|
||||||
<div id="notify_watched_percent_error" class="alert alert-danger settings-alert" role="alert"></div>
|
<div id="movie_watched_percent_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Set the percentage for a media item to be considered as watched. Minimum 50, Maximum 95.</p>
|
<p class="help-block">Set the percentage for a movie to be considered as watched. Minimum 50, Maximum 95.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="tv_watched_percent">TV Episode Watched Percent</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<input type="text" class="form-control" data-parsley-type="integer" id="tv_watched_percent" name="tv_watched_percent" value="${config['tv_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" data-parsley-errors-container="#tv_watched_percent_error" required>
|
||||||
|
</div>
|
||||||
|
<div id="tv_watched_percent_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">Set the percentage for a TV episode to be considered as watched. Minimum 50, Maximum 95.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="music_watched_percent">Music Listened Percent</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<input type="text" class="form-control" data-parsley-type="integer" id="music_watched_percent" name="music_watched_percent" value="${config['music_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" data-parsley-errors-container="#music_watched_percent_error" required>
|
||||||
|
</div>
|
||||||
|
<div id="music_watched_percent_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">Set the percentage for a music track to be considered as listened. Minimum 50, Maximum 95.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="padded-header">
|
<div class="padded-header">
|
||||||
|
|
|
@ -226,7 +226,9 @@ class ActivityHandler(object):
|
||||||
if this_state != 'buffering':
|
if this_state != 'buffering':
|
||||||
progress_percent = helpers.get_percent(db_session['view_offset'], db_session['duration'])
|
progress_percent = helpers.get_percent(db_session['view_offset'], db_session['duration'])
|
||||||
notify_states = notification_handler.get_notify_state(session=db_session)
|
notify_states = notification_handler.get_notify_state(session=db_session)
|
||||||
if progress_percent >= plexpy.CONFIG.NOTIFY_WATCHED_PERCENT \
|
if (db_session['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
|
||||||
|
db_session['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
|
||||||
|
db_session['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
|
||||||
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
|
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
|
||||||
plexpy.NOTIFY_QUEUE.put({'stream_data': db_session, 'notify_action': 'on_watched'})
|
plexpy.NOTIFY_QUEUE.put({'stream_data': db_session, 'notify_action': 'on_watched'})
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,9 @@ def check_active_sessions(ws_request=False):
|
||||||
if session['state'] != 'buffering':
|
if session['state'] != 'buffering':
|
||||||
progress_percent = helpers.get_percent(session['view_offset'], session['duration'])
|
progress_percent = helpers.get_percent(session['view_offset'], session['duration'])
|
||||||
notify_states = notification_handler.get_notify_state(session=session)
|
notify_states = notification_handler.get_notify_state(session=session)
|
||||||
if progress_percent >= plexpy.CONFIG.NOTIFY_WATCHED_PERCENT \
|
if (session['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
|
||||||
|
session['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
|
||||||
|
session['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
|
||||||
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
|
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
|
||||||
plexpy.NOTIFY_QUEUE.put({'stream_data': stream, 'notify_action': 'on_watched'})
|
plexpy.NOTIFY_QUEUE.put({'stream_data': stream, 'notify_action': 'on_watched'})
|
||||||
|
|
||||||
|
@ -149,7 +151,9 @@ def check_active_sessions(ws_request=False):
|
||||||
|
|
||||||
progress_percent = helpers.get_percent(stream['view_offset'], stream['duration'])
|
progress_percent = helpers.get_percent(stream['view_offset'], stream['duration'])
|
||||||
notify_states = notification_handler.get_notify_state(session=stream)
|
notify_states = notification_handler.get_notify_state(session=stream)
|
||||||
if progress_percent >= plexpy.CONFIG.NOTIFY_WATCHED_PERCENT \
|
if (session['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
|
||||||
|
session['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
|
||||||
|
session['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
|
||||||
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
|
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
|
||||||
plexpy.NOTIFY_QUEUE.put({'stream_data': stream, 'notify_action': 'on_watched'})
|
plexpy.NOTIFY_QUEUE.put({'stream_data': stream, 'notify_action': 'on_watched'})
|
||||||
|
|
||||||
|
|
|
@ -288,11 +288,13 @@ _CONFIG_DEFINITIONS = {
|
||||||
'MOVIE_NOTIFY_ON_START': (int, 'Monitoring', 1),
|
'MOVIE_NOTIFY_ON_START': (int, 'Monitoring', 1),
|
||||||
'MOVIE_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
|
'MOVIE_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
|
||||||
'MOVIE_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
|
'MOVIE_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
|
||||||
|
'MOVIE_WATCHED_PERCENT': (int, 'Monitoring', 85),
|
||||||
'MUSIC_LOGGING_ENABLE': (int, 'Monitoring', 1),
|
'MUSIC_LOGGING_ENABLE': (int, 'Monitoring', 1),
|
||||||
'MUSIC_NOTIFY_ENABLE': (int, 'Monitoring', 0),
|
'MUSIC_NOTIFY_ENABLE': (int, 'Monitoring', 0),
|
||||||
'MUSIC_NOTIFY_ON_START': (int, 'Monitoring', 1),
|
'MUSIC_NOTIFY_ON_START': (int, 'Monitoring', 1),
|
||||||
'MUSIC_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
|
'MUSIC_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
|
||||||
'MUSIC_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
|
'MUSIC_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
|
||||||
|
'MUSIC_WATCHED_PERCENT': (int, 'Monitoring', 85),
|
||||||
'MONITOR_PMS_UPDATES': (int, 'Monitoring', 0),
|
'MONITOR_PMS_UPDATES': (int, 'Monitoring', 0),
|
||||||
'MONITOR_REMOTE_ACCESS': (int, 'Monitoring', 0),
|
'MONITOR_REMOTE_ACCESS': (int, 'Monitoring', 0),
|
||||||
'MONITORING_INTERVAL': (int, 'Monitoring', 60),
|
'MONITORING_INTERVAL': (int, 'Monitoring', 60),
|
||||||
|
@ -549,6 +551,7 @@ _CONFIG_DEFINITIONS = {
|
||||||
'TV_NOTIFY_ON_START': (int, 'Monitoring', 1),
|
'TV_NOTIFY_ON_START': (int, 'Monitoring', 1),
|
||||||
'TV_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
|
'TV_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
|
||||||
'TV_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
|
'TV_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
|
||||||
|
'TV_WATCHED_PERCENT': (int, 'Monitoring', 85),
|
||||||
'TWITTER_ENABLED': (int, 'Twitter', 0),
|
'TWITTER_ENABLED': (int, 'Twitter', 0),
|
||||||
'TWITTER_ACCESS_TOKEN': (str, 'Twitter', ''),
|
'TWITTER_ACCESS_TOKEN': (str, 'Twitter', ''),
|
||||||
'TWITTER_ACCESS_TOKEN_SECRET': (str, 'Twitter', ''),
|
'TWITTER_ACCESS_TOKEN_SECRET': (str, 'Twitter', ''),
|
||||||
|
@ -855,3 +858,10 @@ class Config(object):
|
||||||
self.HTTP_PROXY = 1
|
self.HTTP_PROXY = 1
|
||||||
|
|
||||||
self.CONFIG_VERSION = 8
|
self.CONFIG_VERSION = 8
|
||||||
|
|
||||||
|
if self.CONFIG_VERSION == 8:
|
||||||
|
self.MOVIE_WATCHED_PERCENT = self.NOTIFY_WATCHED_PERCENT
|
||||||
|
self.TV_WATCHED_PERCENT = self.NOTIFY_WATCHED_PERCENT
|
||||||
|
self.MUSIC_WATCHED_PERCENT = self.NOTIFY_WATCHED_PERCENT
|
||||||
|
|
||||||
|
self.CONFIG_VERSION == 9
|
||||||
|
|
|
@ -182,7 +182,11 @@ class DataFactory(object):
|
||||||
|
|
||||||
filter_duration = 0
|
filter_duration = 0
|
||||||
total_duration = self.get_total_duration(custom_where=custom_where)
|
total_duration = self.get_total_duration(custom_where=custom_where)
|
||||||
watched_percent = plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
|
|
||||||
|
watched_percent = {'movie': plexpy.CONFIG.MOVIE_WATCHED_PERCENT,
|
||||||
|
'episode': plexpy.CONFIG.TV_WATCHED_PERCENT,
|
||||||
|
'track': plexpy.CONFIG.MUSIC_WATCHED_PERCENT
|
||||||
|
}
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
for item in history:
|
for item in history:
|
||||||
|
@ -195,9 +199,9 @@ class DataFactory(object):
|
||||||
else:
|
else:
|
||||||
thumb = item['thumb']
|
thumb = item['thumb']
|
||||||
|
|
||||||
if item['percent_complete'] >= watched_percent:
|
if item['percent_complete'] >= watched_percent[item['media_type']]:
|
||||||
watched_status = 1
|
watched_status = 1
|
||||||
elif item['percent_complete'] >= watched_percent/2:
|
elif item['percent_complete'] >= watched_percent[item['media_type']]/2:
|
||||||
watched_status = 0.5
|
watched_status = 0.5
|
||||||
else:
|
else:
|
||||||
watched_status = 0
|
watched_status = 0
|
||||||
|
@ -251,9 +255,19 @@ class DataFactory(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
def get_home_stats(self, grouping=0, time_range='30', stats_type=0, stats_count='5', stats_cards=[], notify_watched_percent='85'):
|
def get_home_stats(self, grouping=0, time_range=0, stats_type=0, stats_count=0, stats_cards=[]):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
|
grouping = grouping or plexpy.CONFIG.GROUP_HISTORY_TABLES
|
||||||
|
time_range = time_range or plexpy.CONFIG.HOME_STATS_LENGTH
|
||||||
|
stats_type = stats_type or plexpy.CONFIG.HOME_STATS_TYPE
|
||||||
|
stats_count = stats_count or plexpy.CONFIG.HOME_STATS_COUNT
|
||||||
|
stats_cards = stats_cards or plexpy.CONFIG.HOME_STATS_CARDS
|
||||||
|
|
||||||
|
movie_watched_percent = plexpy.CONFIG.MOVIE_WATCHED_PERCENT
|
||||||
|
tv_watched_percent = plexpy.CONFIG.TV_WATCHED_PERCENT
|
||||||
|
music_watched_percent = plexpy.CONFIG.MUSIC_WATCHED_PERCENT
|
||||||
|
|
||||||
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
|
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
|
||||||
sort_type = 'total_plays' if stats_type == 0 else 'total_duration'
|
sort_type = 'total_plays' if stats_type == 0 else 'total_duration'
|
||||||
|
|
||||||
|
@ -664,10 +678,11 @@ class DataFactory(object):
|
||||||
' AND (session_history.media_type = "movie" ' \
|
' AND (session_history.media_type = "movie" ' \
|
||||||
' OR session_history_metadata.media_type = "episode") ' \
|
' OR session_history_metadata.media_type = "episode") ' \
|
||||||
' GROUP BY %s) AS t ' \
|
' GROUP BY %s) AS t ' \
|
||||||
'WHERE percent_complete >= %s ' \
|
'WHERE t.media_type == "movie" AND percent_complete >= %s ' \
|
||||||
|
' OR t.media_type == "episode" AND percent_complete >= %s ' \
|
||||||
'GROUP BY t.id ' \
|
'GROUP BY t.id ' \
|
||||||
'ORDER BY last_watch DESC ' \
|
'ORDER BY last_watch DESC ' \
|
||||||
'LIMIT %s' % (time_range, group_by, notify_watched_percent, stats_count)
|
'LIMIT %s' % (time_range, group_by, movie_watched_percent, tv_watched_percent, stats_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
|
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
|
||||||
|
|
|
@ -159,7 +159,9 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
|
||||||
progress_percent = helpers.get_percent(stream_data['view_offset'], stream_data['duration'])
|
progress_percent = helpers.get_percent(stream_data['view_offset'], stream_data['duration'])
|
||||||
|
|
||||||
if notify_action == 'on_stop':
|
if notify_action == 'on_stop':
|
||||||
return plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
|
return (plexpy.CONFIG.NOTIFY_CONSECUTIVE or
|
||||||
|
(stream_data['media_type'] == 'movie' and progress_percent < plexpy.CONFIG.MOVIE_WATCHED_PERCENT)
|
||||||
|
(stream_data['media_type'] == 'episode' and progress_percent < plexpy.CONFIG.TV_WATCHED_PERCENT))
|
||||||
|
|
||||||
elif notify_action == 'on_resume':
|
elif notify_action == 'on_resume':
|
||||||
return plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99
|
return plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99
|
||||||
|
|
|
@ -309,20 +309,8 @@ class WebInterface(object):
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@requireAuth()
|
@requireAuth()
|
||||||
def home_stats(self, **kwargs):
|
def home_stats(self, **kwargs):
|
||||||
grouping = plexpy.CONFIG.GROUP_HISTORY_TABLES
|
|
||||||
time_range = plexpy.CONFIG.HOME_STATS_LENGTH
|
|
||||||
stats_type = plexpy.CONFIG.HOME_STATS_TYPE
|
|
||||||
stats_count = plexpy.CONFIG.HOME_STATS_COUNT
|
|
||||||
stats_cards = plexpy.CONFIG.HOME_STATS_CARDS
|
|
||||||
notify_watched_percent = plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
|
|
||||||
|
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
stats_data = data_factory.get_home_stats(grouping=grouping,
|
stats_data = data_factory.get_home_stats()
|
||||||
time_range=time_range,
|
|
||||||
stats_type=stats_type,
|
|
||||||
stats_count=stats_count,
|
|
||||||
stats_cards=stats_cards,
|
|
||||||
notify_watched_percent=notify_watched_percent)
|
|
||||||
|
|
||||||
return serve_template(templatename="home_stats.html", title="Stats", data=stats_data)
|
return serve_template(templatename="home_stats.html", title="Stats", data=stats_data)
|
||||||
|
|
||||||
|
@ -2600,7 +2588,6 @@ class WebInterface(object):
|
||||||
"notify_group_recently_added_parent": checked(plexpy.CONFIG.NOTIFY_GROUP_RECENTLY_ADDED_PARENT),
|
"notify_group_recently_added_parent": checked(plexpy.CONFIG.NOTIFY_GROUP_RECENTLY_ADDED_PARENT),
|
||||||
"notify_concurrent_by_ip": checked(plexpy.CONFIG.NOTIFY_CONCURRENT_BY_IP),
|
"notify_concurrent_by_ip": checked(plexpy.CONFIG.NOTIFY_CONCURRENT_BY_IP),
|
||||||
"notify_concurrent_threshold": plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD,
|
"notify_concurrent_threshold": plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD,
|
||||||
"notify_watched_percent": plexpy.CONFIG.NOTIFY_WATCHED_PERCENT,
|
|
||||||
"home_sections": json.dumps(plexpy.CONFIG.HOME_SECTIONS),
|
"home_sections": json.dumps(plexpy.CONFIG.HOME_SECTIONS),
|
||||||
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
||||||
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
|
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
|
||||||
|
@ -2617,7 +2604,10 @@ class WebInterface(object):
|
||||||
"plexpy_auto_update": checked(plexpy.CONFIG.PLEXPY_AUTO_UPDATE),
|
"plexpy_auto_update": checked(plexpy.CONFIG.PLEXPY_AUTO_UPDATE),
|
||||||
"git_branch": plexpy.CONFIG.GIT_BRANCH,
|
"git_branch": plexpy.CONFIG.GIT_BRANCH,
|
||||||
"git_path": plexpy.CONFIG.GIT_PATH,
|
"git_path": plexpy.CONFIG.GIT_PATH,
|
||||||
"git_remote": plexpy.CONFIG.GIT_REMOTE
|
"git_remote": plexpy.CONFIG.GIT_REMOTE,
|
||||||
|
"movie_watched_percent": plexpy.CONFIG.MOVIE_WATCHED_PERCENT,
|
||||||
|
"tv_watched_percent": plexpy.CONFIG.TV_WATCHED_PERCENT,
|
||||||
|
"music_watched_percent": plexpy.CONFIG.MUSIC_WATCHED_PERCENT
|
||||||
}
|
}
|
||||||
|
|
||||||
return serve_template(templatename="settings.html", title="Settings", config=config, kwargs=kwargs)
|
return serve_template(templatename="settings.html", title="Settings", config=config, kwargs=kwargs)
|
||||||
|
@ -4581,16 +4571,11 @@ class WebInterface(object):
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
stats_cards = plexpy.CONFIG.HOME_STATS_CARDS
|
|
||||||
notify_watched_percent = plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
|
|
||||||
|
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
result = data_factory.get_home_stats(grouping=grouping,
|
result = data_factory.get_home_stats(grouping=grouping,
|
||||||
time_range=time_range,
|
time_range=time_range,
|
||||||
stats_type=stats_type,
|
stats_type=stats_type,
|
||||||
stats_count=stats_count,
|
stats_count=stats_count)
|
||||||
stats_cards=stats_cards,
|
|
||||||
notify_watched_percent=notify_watched_percent)
|
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return result
|
return result
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue