mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-16 02:02:58 -07:00
Trigger on_watched based on credits markers
This commit is contained in:
parent
b1dd28e39b
commit
b2b12044e3
2 changed files with 101 additions and 31 deletions
|
@ -110,11 +110,13 @@ class ActivityHandler(object):
|
||||||
self.set_session_state()
|
self.set_session_state()
|
||||||
self.get_db_session()
|
self.get_db_session()
|
||||||
|
|
||||||
def set_session_state(self):
|
def set_session_state(self, view_offset=None):
|
||||||
self.ap.set_session_state(session_key=self.session_key,
|
self.ap.set_session_state(
|
||||||
state=self.state,
|
session_key=self.session_key,
|
||||||
view_offset=self.view_offset,
|
state=self.state,
|
||||||
stopped=helpers.timestamp())
|
view_offset=view_offset or self.view_offset,
|
||||||
|
stopped=helpers.timestamp()
|
||||||
|
)
|
||||||
|
|
||||||
def put_notification(self, notify_action, **kwargs):
|
def put_notification(self, notify_action, **kwargs):
|
||||||
notification = {'stream_data': self.db_session.copy(), 'notify_action': notify_action}
|
notification = {'stream_data': self.db_session.copy(), 'notify_action': notify_action}
|
||||||
|
@ -246,26 +248,34 @@ class ActivityHandler(object):
|
||||||
self.put_notification('on_change')
|
self.put_notification('on_change')
|
||||||
|
|
||||||
def on_intro(self, marker):
|
def on_intro(self, marker):
|
||||||
if self.get_live_session():
|
logger.debug("Tautulli ActivityHandler :: Session %s reached intro marker." % str(self.session_key))
|
||||||
logger.debug("Tautulli ActivityHandler :: Session %s reached intro marker." % str(self.session_key))
|
|
||||||
|
|
||||||
self.put_notification('on_intro', marker=marker)
|
self.set_session_state(view_offset=marker['start_time_offset'])
|
||||||
|
|
||||||
|
self.put_notification('on_intro', marker=marker)
|
||||||
|
|
||||||
def on_commercial(self, marker):
|
def on_commercial(self, marker):
|
||||||
if self.get_live_session():
|
logger.debug("Tautulli ActivityHandler :: Session %s reached commercial marker." % str(self.session_key))
|
||||||
logger.debug("Tautulli ActivityHandler :: Session %s reached commercial marker." % str(self.session_key))
|
|
||||||
|
|
||||||
self.put_notification('on_commercial', marker=marker)
|
self.set_session_state(view_offset=marker['start_time_offset'])
|
||||||
|
|
||||||
|
self.put_notification('on_commercial', marker=marker)
|
||||||
|
|
||||||
def on_credits(self, marker):
|
def on_credits(self, marker):
|
||||||
if self.get_live_session():
|
logger.debug("Tautulli ActivityHandler :: Session %s reached credits marker." % str(self.session_key))
|
||||||
logger.debug("Tautulli ActivityHandler :: Session %s reached credits marker." % str(self.session_key))
|
|
||||||
|
|
||||||
self.put_notification('on_credits', marker=marker)
|
self.set_session_state(view_offset=marker['start_time_offset'])
|
||||||
|
|
||||||
def on_watched(self):
|
self.put_notification('on_credits', marker=marker)
|
||||||
|
|
||||||
|
def on_watched(self, marker=None):
|
||||||
logger.debug("Tautulli ActivityHandler :: Session %s watched." % str(self.session_key))
|
logger.debug("Tautulli ActivityHandler :: Session %s watched." % str(self.session_key))
|
||||||
|
|
||||||
|
if marker:
|
||||||
|
self.set_session_state(view_offset=marker['start_time_offset'])
|
||||||
|
else:
|
||||||
|
self.update_db_session()
|
||||||
|
|
||||||
watched_notifiers = notification_handler.get_notify_state_enabled(
|
watched_notifiers = notification_handler.get_notify_state_enabled(
|
||||||
session=self.db_session, notify_action='on_watched', notified=False)
|
session=self.db_session, notify_action='on_watched', notified=False)
|
||||||
|
|
||||||
|
@ -368,38 +378,58 @@ class ActivityHandler(object):
|
||||||
|
|
||||||
if self.db_session['marker'] != marker_idx:
|
if self.db_session['marker'] != marker_idx:
|
||||||
self.ap.set_marker(session_key=self.session_key, marker_idx=marker_idx, marker_type=marker['type'])
|
self.ap.set_marker(session_key=self.session_key, marker_idx=marker_idx, marker_type=marker['type'])
|
||||||
callback_func = getattr(self, 'on_{}'.format(marker['type']))
|
|
||||||
|
|
||||||
if self.view_offset < marker['start_time_offset']:
|
if self.view_offset < marker['start_time_offset']:
|
||||||
# Schedule a callback for the exact offset of the marker
|
# Schedule a callback for the exact offset of the marker
|
||||||
schedule_callback(
|
schedule_callback(
|
||||||
'session_key-{}-marker-{}'.format(self.session_key, marker_idx),
|
'session_key-{}-marker-{}'.format(self.session_key, marker_idx),
|
||||||
func=callback_func,
|
func=self._marker_callback,
|
||||||
args=[marker],
|
args=[marker],
|
||||||
milliseconds=marker['start_time_offset'] - self.view_offset
|
milliseconds=marker['start_time_offset'] - self.view_offset
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
callback_func(marker)
|
self._marker_callback(marker)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if not marker_flag:
|
if not marker_flag:
|
||||||
self.ap.set_marker(session_key=self.session_key, marker_idx=0)
|
self.ap.set_marker(session_key=self.session_key, marker_idx=0)
|
||||||
|
|
||||||
def check_watched(self):
|
def _marker_callback(self, marker):
|
||||||
# Monitor if the stream has reached the watch percentage for notifications
|
if self.get_live_session():
|
||||||
if not self.db_session['watched'] and self.timeline['state'] != 'buffering':
|
# Reset ActivityProcessor object for new database thread
|
||||||
progress_percent = helpers.get_percent(self.timeline['viewOffset'], self.db_session['duration'])
|
self.ap = activity_processor.ActivityProcessor()
|
||||||
watched_percent = {
|
|
||||||
'movie': plexpy.CONFIG.MOVIE_WATCHED_PERCENT,
|
|
||||||
'episode': plexpy.CONFIG.TV_WATCHED_PERCENT,
|
|
||||||
'track': plexpy.CONFIG.MUSIC_WATCHED_PERCENT,
|
|
||||||
'clip': plexpy.CONFIG.TV_WATCHED_PERCENT
|
|
||||||
}
|
|
||||||
|
|
||||||
if progress_percent >= watched_percent.get(self.db_session['media_type'], 101):
|
if marker['type'] == 'intro':
|
||||||
self.ap.set_watched(session_key=self.session_key)
|
self.on_intro(marker)
|
||||||
self.on_watched()
|
elif marker['type'] == 'commercial':
|
||||||
|
self.on_commercial(marker)
|
||||||
|
elif marker['type'] == 'credits':
|
||||||
|
self.on_credits(marker)
|
||||||
|
|
||||||
|
if not self.db_session['watched']:
|
||||||
|
if marker['final'] and plexpy.CONFIG.WATCHED_MARKER == 1:
|
||||||
|
self._marker_watched(marker)
|
||||||
|
elif marker['first'] and (plexpy.CONFIG.WATCHED_MARKER in (2, 3)):
|
||||||
|
self._marker_watched(marker)
|
||||||
|
|
||||||
|
def _marker_watched(self, marker):
|
||||||
|
if not self.db_session['watched']:
|
||||||
|
self._watched_callback(marker)
|
||||||
|
|
||||||
|
def check_watched(self):
|
||||||
|
if plexpy.CONFIG.WATCHED_MARKER == 1 or plexpy.CONFIG.WATCHED_MARKER == 2:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Monitor if the stream has reached the watch percentage for notifications
|
||||||
|
if not self.db_session['watched'] and self.state != 'buffering' and helpers.check_watched(
|
||||||
|
self.db_session['media_type'], self.view_offset, self.db_session['duration']
|
||||||
|
):
|
||||||
|
self._watched_callback()
|
||||||
|
|
||||||
|
def _watched_callback(self, marker=None):
|
||||||
|
self.ap.set_watched(session_key=self.session_key)
|
||||||
|
self.on_watched(marker)
|
||||||
|
|
||||||
|
|
||||||
class TimelineHandler(object):
|
class TimelineHandler(object):
|
||||||
|
|
|
@ -1733,3 +1733,43 @@ def short_season(title):
|
||||||
if title.startswith('Season ') and title[7:].isdigit():
|
if title.startswith('Season ') and title[7:].isdigit():
|
||||||
return 'S%s' % title[7:]
|
return 'S%s' % title[7:]
|
||||||
return title
|
return title
|
||||||
|
|
||||||
|
|
||||||
|
def get_first_final_marker(markers):
|
||||||
|
first = None
|
||||||
|
final = None
|
||||||
|
for marker in markers:
|
||||||
|
if marker['first']:
|
||||||
|
first = marker
|
||||||
|
if marker['final']:
|
||||||
|
final = marker
|
||||||
|
return first, final
|
||||||
|
|
||||||
|
|
||||||
|
def check_watched(media_type, view_offset, duration, marker_credits_first=None, marker_credits_final=None):
|
||||||
|
if isinstance(marker_credits_first, dict):
|
||||||
|
marker_credits_first = marker_credits_first['start_time_offset']
|
||||||
|
if isinstance(marker_credits_final, dict):
|
||||||
|
marker_credits_final = marker_credits_final['start_time_offset']
|
||||||
|
|
||||||
|
view_offset = cast_to_int(view_offset)
|
||||||
|
duration = cast_to_int(duration)
|
||||||
|
|
||||||
|
watched_percent = {
|
||||||
|
'movie': plexpy.CONFIG.MOVIE_WATCHED_PERCENT,
|
||||||
|
'episode': plexpy.CONFIG.TV_WATCHED_PERCENT,
|
||||||
|
'track': plexpy.CONFIG.MUSIC_WATCHED_PERCENT,
|
||||||
|
'clip': plexpy.CONFIG.TV_WATCHED_PERCENT
|
||||||
|
}
|
||||||
|
threshold = watched_percent.get(media_type, 0) / 100 * duration
|
||||||
|
if not threshold:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if plexpy.CONFIG.WATCHED_MARKER == 1 and marker_credits_final:
|
||||||
|
return view_offset >= marker_credits_final
|
||||||
|
elif plexpy.CONFIG.WATCHED_MARKER == 2 and marker_credits_first:
|
||||||
|
return view_offset >= marker_credits_first
|
||||||
|
elif plexpy.CONFIG.WATCHED_MARKER == 3 and marker_credits_first:
|
||||||
|
return view_offset >= min(threshold, marker_credits_first)
|
||||||
|
else:
|
||||||
|
return view_offset >= threshold
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue