def get_enabled_functions(cls): result = [] if cls.task in get_pref('sync_watched'): result.append('watched') if cls.task in get_pref('sync_ratings'): result.append('ratings') if cls.task in get_pref('sync_collection'): result.append('collected') return result
def rate_conflict(self, p_item, t_item): status = self.get_status() # First run, overwrite with trakt rating if status.last_success is None: return True resolution = get_pref('sync_ratings_conflict') if resolution == 'trakt': return True if resolution == 'latest': t_timestamp = datetime.utcfromtimestamp(t_item.rating.timestamp) # If trakt rating was created after the last sync, update plex rating if t_timestamp > status.last_success: return True log.info( 'Conflict when updating rating for item %s (plex: %s, trakt: %s), trakt rating will be changed on next push.', p_item.rating_key, p_item.user_rating, t_item.rating.advanced ) return False
def MainMenu(): oc = ObjectContainer(no_cache=True) if not get_pref('valid'): oc.add(DirectoryObject( key='/applications/trakttv', title=L("Error: Authentication failed"), )) oc.add(DirectoryObject( key=Callback(SyncMenu), title=L("Sync"), summary=L("Sync the Plex library with Trakt.tv") )) oc.add(DirectoryObject( key=Callback(AboutMenu), title=L("About") )) oc.add(PrefsObject( title="Preferences", summary="Configure how to connect to Trakt.tv", thumb=R("icon-preferences.png") )) return oc
def ValidatePrefs(): last_activity_mode = get_pref('activity_mode') if Main.authenticate(): message = MessageContainer( "Success", "Authentication successful" ) else: message = MessageContainer( "Error", "Authentication failed, incorrect username or password" ) # Restart if activity_mode has changed if Prefs['activity_mode'] != last_activity_mode: log.info('Activity mode has changed, restarting plugin...') def restart(): # Delay until after `ValidatePrefs` returns time.sleep(3) # Restart plugin Plex[':/plugins'].restart(PLUGIN_IDENTIFIER) spawn(restart) return message # Re-initialize modules Main.init_logging() return message
def get_extended(cls, video, p_season, p_episode): # Ensure extended matcher is enabled if get_pref('matcher') != 'plex_extended': return [] # Parse filename for extra info parts = video.find('Media').findall('Part') if not parts: log.warn('Item "%s" has no parts', video.get('ratingKey')) return [] # Get just the name of the first part (without full path and extension) file_name = os.path.splitext(os.path.basename(parts[0].get('file')))[0] # Parse file_name with caper (or get cached result) c_identifiers = cls.parse(file_name) result = [] for c_identifier in c_identifiers: if 'season' not in c_identifier: continue episodes = cls.match_identifier(p_season, p_episode, c_identifier) if episodes is None: continue # Insert any new episodes found from identifier for episode in episodes: if episode == p_episode: continue result.append(episode) return result
def MainMenu(): oc = ObjectContainer(no_cache=True) if not get_pref('valid'): oc.add(DirectoryObject( key=PLUGIN_PREFIX, title=L("Error: Authentication failed"), )) oc.add(DirectoryObject( key=Callback(SyncMenu), title=L("Sync"), summary=L("Sync the Plex library with Trakt.tv"), thumb=R("icon-sync.png") )) oc.add(DirectoryObject( key=Callback(AboutMenu), title=L("About"), thumb=R("icon-about.png") )) oc.add(PrefsObject( title="Preferences", summary="Configure how to connect to Trakt.tv", thumb=R("icon-preferences.png") )) return oc
def update(self, info): # Ignore if scrobbling is disabled if not get_pref('scrobble'): return session_key = try_convert(info.get('sessionKey'), int) state = info.get('state') view_offset = info.get('viewOffset') ws = self.get_session(session_key, state, view_offset) if not ws: log.trace('Invalid or ignored session, nothing to do') return # Ignore sessions flagged as 'skip' if ws.skip: return # Validate session (check filters) if not self.valid(ws): return # Check if we are scrobbling a known media type if not ws.type: log.info('Playing unknown item, will not be scrobbled: "%s"' % ws.title) ws.skip = True return # Check if the view_offset has jumped (#131) if self.offset_jumped(ws, view_offset): log.info('View offset jump detected, ignoring the state update') ws.save() return ws.last_view_offset = view_offset # Calculate progress if not self.update_progress(ws, view_offset): log.warn('Error while updating session progress, queued session to be updated') ws.update_required = True ws.save() return action = self.get_action(ws, state) if action: self.handle_action(ws, action) else: log.debug(self.status_message(ws, state)('Nothing to do this time for %s')) ws.save() self.handle_state(ws, state)
def update(self, session_key, state, view_offset): # Ignore if scrobbling is disabled if not get_pref('scrobble'): return session = self.get_session(session_key, state, view_offset) if not session: log.trace('Invalid or ignored session, nothing to do') return # Ignore sessions flagged as 'skip' if session.skip: return # Validate session (check filters) if not self.valid(session): return media_type = session.get_type() # Check if we are scrobbling a known media type if not media_type: log.info('Playing unknown item, will not be scrobbled: "%s"' % session.get_title()) session.skip = True return session.last_view_offset = view_offset # Calculate progress if not self.update_progress(session, view_offset): log.warn( 'Error while updating session progress, queued session to be updated' ) session.update_required = True session.save() return action = self.get_action(session, state) if action: self.handle_action(session, media_type, action, state) else: log.debug( self.status_message(session, state)('Nothing to do this time for %s')) session.save() if self.handle_state(session, state) or action: session.save() Dict.Save()
def update(self, session_key, state, view_offset): # Ignore if scrobbling is disabled if not get_pref('scrobble'): return session = self.get_session(session_key, state, view_offset) if not session: log.trace('Invalid or ignored session, nothing to do') return # Ignore sessions flagged as 'skip' if session.skip: return # Validate session (check filters) if not self.valid(session): return media_type = session.get_type() # Check if we are scrobbling a known media type if not media_type: log.info('Playing unknown item, will not be scrobbled: "%s"' % session.get_title()) session.skip = True return # Check if the view_offset has jumped (#131) if self.offset_jumped(session, view_offset): log.info('View offset jump detected, ignoring the state update') session.save() return session.last_view_offset = view_offset # Calculate progress if not self.update_progress(session, view_offset): log.warn('Error while updating session progress, queued session to be updated') session.update_required = True session.save() return action = self.get_action(session, state) if action: self.handle_action(session, media_type, action, state) else: log.debug(self.status_message(session, state)('Nothing to do this time for %s')) session.save() if self.handle_state(session, state) or action: Dict.Save()
def get_action(self, session, state): """ :type session: WatchSession :type state: str :rtype: str or None """ status_message = self.status_message(session, state) # State has changed if state not in [session.cur_state, 'buffering']: session.cur_state = state if state == 'stopped' and session.watching: log.info(status_message('%s stopped, watching status cancelled')) session.watching = False return 'cancelwatching' if state == 'paused' and not session.paused_since: log.info(status_message("%s just paused, waiting 15s before cancelling the watching status")) session.paused_since = Datetime.Now() return None if state == 'playing' and not session.watching: log.info(status_message('Sending watch status for %s')) session.watching = True return 'watching' elif state == 'playing': # scrobble item if not session.scrobbled and session.progress >= get_pref('scrobble_percentage'): log.info(status_message('Scrobbling %s')) return 'scrobble' # update every 10 min if media hasn't finished elif session.progress < 100 and (session.last_updated + Datetime.Delta(minutes=10)) < Datetime.Now(): log.info(status_message('Updating watch status for %s')) session.watching = True return 'watching' # cancel watching status on items at 100% progress elif session.progress >= 100 and session.watching: log.info(status_message('Media finished, cancelling watching status for %s')) session.watching = False return 'cancelwatching' return None
def trigger(cls, key, blocking=False, **kwargs): # Ensure sync task isn't already running if not cls.lock.acquire(blocking): return False # Ensure account details are set if not get_pref('valid'): cls.lock.release() return False cls.reset() cls.current = SyncTask(key, kwargs) cls.lock.release() return True
def ValidatePrefs(): last_activity_mode = get_pref('activity_mode') if Main.validate_auth(): message = MessageContainer( "Success", "Authentication successful" ) else: message = MessageContainer( "Error", "Authentication failed, incorrect username or password" ) # Restart if activity_mode has changed if Prefs['activity_mode'] != last_activity_mode: log.info('Activity mode has changed, restarting plugin...') spawn(PlexMediaServer.restart_plugin) return message
def trigger(cls, key, blocking=False, **kwargs): # Ensure manager is initialized if not cls.initialized: log.warn(L('not_initialized')) return False, L('not_initialized') # Ensure sync task isn't already running if not cls.lock.acquire(blocking): return False, L('already_running') # Ensure account details are set if not get_pref('valid'): cls.lock.release() return False, L('invalid_credentials') cls.reset() cls.current = SyncTask(key, kwargs) cls.lock.release() return True, ''
def update(self, info): # Ignore if scrobbling is disabled if not get_pref('scrobble'): return session = self.get_session(info) if not session: log.trace('Invalid or ignored session, nothing to do') return # Validate session (check filters) if not self.valid(session): return media_type = session.get_type() # Check if we are scrobbling a known media type if not media_type: log.info('Playing unknown item, will not be scrobbled: "%s"' % session.get_title()) session.skip = True return # Calculate progress if not self.update_progress(session, info['time']): log.warn('Error while updating session progress, queued session to be updated') session.update_required = True session.save() return action = self.get_action(session, info['state']) if action: self.handle_action(session, media_type, action, info['state']) else: log.debug(self.status_message(session, info.get('state'))('Nothing to do this time for %s')) session.save() if self.handle_state(session, info['state']) or action: session.save() Dict.Save()
def rate_conflict(self, p_item, t_item): status = self.get_status() # First run, overwrite with trakt rating if status.last_success is None: return True resolution = get_pref('sync_ratings_conflict') if resolution == 'trakt': return True if resolution == 'latest': t_timestamp = datetime.utcfromtimestamp(t_item.rating_timestamp) # If trakt rating was created after the last sync, update plex rating if t_timestamp > status.last_success: return True log.info( 'Conflict when updating rating for item %s (plex: %s, trakt: %s), trakt rating will be changed on next push.', p_item.rating_key, p_item.user_rating, t_item.rating_advanced) return False
def scanner_finished(cls): if not get_pref('sync_run_library'): log.debug('"Run after library updates" not enabled, ignoring') return cls.trigger_synchronize()
def scan_complete(cls): if not get_pref('sync_run_library'): log.info('"Run after library updates" not enabled, ignoring') return cls.trigger_synchronize()