Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
    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
Пример #7
0
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)
Пример #9
0
    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()
Пример #11
0
    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
Пример #12
0
    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
Пример #13
0
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
Пример #14
0
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
Пример #15
0
    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()
Пример #17
0
    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
Пример #18
0
    def scanner_finished(cls):
        if not get_pref('sync_run_library'):
            log.debug('"Run after library updates" not enabled, ignoring')
            return

        cls.trigger_synchronize()
Пример #19
0
    def scan_complete(cls):
        if not get_pref('sync_run_library'):
            log.info('"Run after library updates" not enabled, ignoring')
            return

        cls.trigger_synchronize()
Пример #20
0
    def scan_complete(cls):
        if not get_pref('sync_run_library'):
            log.info('"Run after library updates" not enabled, ignoring')
            return

        cls.trigger_synchronize()