Esempio n. 1
0
    def should_defer(self, task):
        if task and task.result:
            # Ignore sync conditions on manual triggers
            if task.result.trigger == SyncResult.Trigger.Manual:
                return False

            # Ignore sync conditions if the task has been queued for over 12 hours
            started_ago = datetime.utcnow() - task.result.started_at

            if started_ago > timedelta(hours=12):
                log.debug(
                    'Task has been queued for over 12 hours, ignoring sync conditions'
                )
                return False

        if Preferences.get('sync.idle_defer'):
            # Defer sync tasks until server finishes streaming (and is idle for 30 minutes)
            if ModuleManager['sessions'].is_streaming():
                log.debug(
                    'Deferring sync task, server is currently streaming media')
                return True

            if not ModuleManager['sessions'].is_idle():
                log.debug(
                    'Deferring sync task, server has been streaming media recently (in the last %d minutes)',
                    Preferences.get('sync.idle_delay'))
                return True

        return False
Esempio n. 2
0
    def should_defer(self, task):
        if task and task.result:
            # Ignore sync conditions on manual triggers
            if task.result.trigger == SyncResult.Trigger.Manual:
                return False

            # Ignore sync conditions if the task has been queued for over 12 hours
            started_ago = datetime.utcnow() - task.result.started_at

            if started_ago > timedelta(hours=12):
                log.debug('Task has been queued for over 12 hours, ignoring sync conditions')
                return False

        if Preferences.get('sync.idle_defer'):
            # Defer sync tasks until server finishes streaming (and is idle for 30 minutes)
            if ModuleManager['sessions'].is_streaming():
                log.debug('Deferring sync task, server is currently streaming media')
                return True

            if not ModuleManager['sessions'].is_idle():
                log.debug(
                    'Deferring sync task, server has been streaming media recently (in the last %d minutes)',
                    Preferences.get('sync.idle_delay')
                )
                return True

        return False
Esempio n. 3
0
    def configure(self):
        extended = Preferences.get('matcher.mode') == MatcherMode.PlexExtended

        # Configure matchers
        matchers = [
            self._database_matcher,
            self._metadata_matcher,

            # Default matchers
            plex_database.matcher.Default,
            plex_metadata.matcher.Default
        ]

        for matcher in matchers:
            if not matcher:
                continue

            # Update cache
            if self._cache:
                matcher.cache = self._cache

            # Configure features
            if matcher.caper_enabled != extended or matcher.extend_enabled != extended:
                matcher.caper_enabled = extended
                matcher.extend_enabled = extended

                log.info('Extended matcher has been %s on %r', 'enabled' if extended else 'disabled', matcher)

        return True
Esempio n. 4
0
    def run(self):
        # Check for authentication token
        log.info('X-Plex-Token: %s', 'available' if os.environ.get('PLEXTOKEN') else 'unavailable')

        # Process server startup state
        self.process_server_state()

        # Start new-style modules
        module_start()

        # Start modules
        names = []

        for module in self.modules:
            if not hasattr(module, 'start'):
                continue

            names.append(get_class_name(module))

            module.start()

        log.info('Started %s modules: %s', len(names), ', '.join(names))

        ModuleManager.start()

        # Start plex.activity.py
        Activity.start(ACTIVITY_MODE.get(Preferences.get('activity.mode')))
    def _queue(self):
        accounts = Account.select(
            Account.id
        ).where(
            Account.id > 0
        )

        for account in accounts:
            if account.deleted:
                # Ignore library update trigger for deleted accounts
                continue

            enabled = Preferences.get('sync.library_update', account)

            log.debug('account: %r, enabled: %r', account.id, enabled)

            if not enabled:
                continue

            try:
                # Queue sync for account
                self.sync.queue(
                    account=account,
                    mode=SyncMode.Full,

                    priority=100,
                    trigger=SyncResult.Trigger.LibraryUpdate
                )
            except QueueError, ex:
                log.info('Queue error: %s', ex)
Esempio n. 6
0
    def on_added(self, data, *args, **kwargs):
        if data.get('type') not in [1, 2, 4]:
            return

        log.debug(
            'Item added: %s (id: %r, type: %r)',
            data.get('title'),
            data.get('itemID'),
            data.get('type')
        )

        # Retrieve accounts
        accounts = Account.select(
            Account.id
        ).where(
            Account.id > 0
        )

        # Update library state for accounts
        for account in accounts:
            if account.deleted:
                continue

            # Ensure account has the library update trigger enabled
            enabled = Preferences.get('sync.library_update', account)

            if not enabled:
                continue

            # Update library state for account
            self.get(account.id).on_added(data)
Esempio n. 7
0
    def is_duplicate(cls, action):
        if action.event != 'scrobble/stop':
            return False

        # Retrieve scrobble duplication period
        duplication_period = Preferences.get('scrobble.duplication_period')

        if duplication_period is None:
            return False

        # Check for duplicate scrobbles in `duplication_period`
        scrobbled = ActionHistory.has_scrobbled(
            action.account, action.rating_key,
            part=action.part,
            after=action.queued_at - timedelta(minutes=duplication_period)
        )

        if scrobbled:
            log.info(
                'Ignoring duplicate %r action, scrobble already performed in the last %d minutes',
                action.event, duplication_period
            )
            return True

        return False
Esempio n. 8
0
    def configure(self):
        extended = Preferences.get('matcher.mode') == MatcherMode.PlexExtended

        # Configure matchers
        matchers = [
            self._database_matcher,
            self._metadata_matcher,

            # Default matchers
            plex_database.matcher.Default,
            plex_metadata.matcher.Default
        ]

        for matcher in matchers:
            if not matcher:
                continue

            # Update cache
            if self._cache:
                matcher.cache = self._cache

            # Configure features
            if matcher.caper_enabled != extended or matcher.extend_enabled != extended:
                matcher.caper_enabled = extended
                matcher.extend_enabled = extended

                log.info('Extended matcher has been %s on %r',
                         'enabled' if extended else 'disabled', matcher)

        return True
Esempio n. 9
0
    def run(self):
        # Check for authentication token
        log.info('X-Plex-Token: %s',
                 'available' if os.environ.get('PLEXTOKEN') else 'unavailable')

        # Process server startup state
        self.process_server_state()

        # Start new-style modules
        module_start()

        # Start modules
        names = []

        for module in self.modules:
            if not hasattr(module, 'start'):
                continue

            names.append(get_class_name(module))

            module.start()

        log.info('Started %s modules: %s', len(names), ', '.join(names))

        ModuleManager.start()

        # Start plex.activity.py
        Activity.start(ACTIVITY_MODE.get(Preferences.get('activity.mode')))
Esempio n. 10
0
    def _is_duplicate(self, data, action, p_key):
        if data != SyncData.Watched or action != 'add':
            return False

        # Retrieve scrobble duplication period
        duplication_period = Preferences.get('scrobble.duplication_period')

        if duplication_period is None:
            return False

        # Check for duplicate scrobbles in `duplication_period`
        # TODO check `part` attribute
        scrobbled = ActionHistory.has_scrobbled(
            self.task.account, p_key,
            after=datetime.utcnow() - timedelta(minutes=duplication_period)
        )

        if scrobbled:
            log.info(
                'Ignoring duplicate history addition, scrobble already performed in the last %d minutes',
                duplication_period
            )
            return True

        return False
Esempio n. 11
0
    def is_idle(self):
        # Cleanup stale sessions
        self.cleanup()

        # Check if server has been idle for `sync.idle_delay` seconds
        return self._idle_since and datetime.utcnow(
        ) - self._idle_since > timedelta(
            minutes=Preferences.get('sync.idle_delay'))
Esempio n. 12
0
    def queue(cls, event, request, session=None, account=None):
        if event is None:
            return None

        obj = None

        if request is not None:
            request = json.dumps(request)

        # Retrieve `account_id` for action
        account_id = None

        if session:
            try:
                account_id = session.account_id
            except KeyError:
                account_id = None

        if account_id is None and account:
            account_id = account.id

        if account_id is None:
            log.debug('Unable to find valid account for event %r, session %r',
                      event, session)
            return None

        if not Preferences.get('scrobble.enabled', account_id):
            log.debug('Scrobbler not enabled for account %r', account_id)
            return None

        # Try queue the event
        try:
            obj = ActionQueue.create(account=account_id,
                                     session=session,
                                     progress=session.progress,
                                     part=session.part,
                                     rating_key=session.rating_key,
                                     event=event,
                                     request=request,
                                     queued_at=datetime.utcnow())
            log.debug('Queued %r event for %r', event, session)
        except (apsw.ConstraintError, peewee.IntegrityError) as ex:
            log.info('Event %r has already been queued for session %r: %s',
                     event,
                     session.session_key,
                     ex,
                     exc_info=True)
        except Exception as ex:
            log.warn('Unable to queue event %r for %r: %s',
                     event,
                     session,
                     ex,
                     exc_info=True)

        # Ensure process thread is started
        cls.start()

        return obj
Esempio n. 13
0
def RestartRequired(last_activity_mode):
    if Preferences.get("activity.mode") != last_activity_mode:
        return True

    for key in ["language", "proxy_host", "proxy_username", "proxy_password"]:
        if Prefs[key] != Dict[key]:
            return True

    return False
Esempio n. 14
0
def RestartRequired(last_activity_mode):
    if Preferences.get('activity.mode') != last_activity_mode:
        return True

    for key in ['language', 'proxy_host', 'proxy_username', 'proxy_password']:
        if Prefs[key] != Dict[key]:
            return True

    return False
    def run(self):
        # Migrate server preferences
        Preferences.initialize()
        Preferences.migrate()

        # Try migrate administrator preferences
        try:
            Preferences.initialize(account=1)
            Preferences.migrate(account=1)
        except Account.DoesNotExist:
            log.debug('Unable to migrate administrator preferences, no account found')
Esempio n. 16
0
    def queue(cls, event, request, session=None, account=None):
        if event is None:
            return None

        obj = None

        if request is not None:
            request = json.dumps(request)

        # Retrieve `account_id` for action
        account_id = None

        if session:
            try:
                account_id = session.account_id
            except KeyError:
                account_id = None

        if account_id is None and account:
            account_id = account.id

        if account_id is None:
            log.debug('Unable to find valid account for event %r, session %r', event, session)
            return None

        if not Preferences.get('scrobble.enabled', account_id):
            log.debug('Scrobbler not enabled for account %r', account_id)
            return None

        # Try queue the event
        try:
            obj = ActionQueue.create(
                account=account_id,
                session=session,

                progress=session.progress,

                part=session.part,
                rating_key=session.rating_key,

                event=event,
                request=request,

                queued_at=datetime.utcnow()
            )
            log.debug('Queued %r event for %r', event, session)
        except (apsw.ConstraintError, peewee.IntegrityError) as ex:
            log.info('Event %r has already been queued for session %r: %s', event, session.session_key, ex, exc_info=True)
        except Exception as ex:
            log.warn('Unable to queue event %r for %r: %s', event, session, ex, exc_info=True)

        # Ensure process thread is started
        cls.start()

        return obj
Esempio n. 17
0
    def run(self):
        # Migrate server preferences
        Preferences.initialize()
        Preferences.migrate()

        # Try migrate administrator preferences
        try:
            Preferences.initialize(account=1)
            Preferences.migrate(account=1)
        except Account.DoesNotExist:
            log.debug(
                'Unable to migrate administrator preferences, no account found'
            )
Esempio n. 18
0
    def process(cls, method, headers, body, key, *args, **kwargs):
        log.debug("Handling API %s request %r - args: %r, kwargs: %r", method, key, len(args), len(kwargs.keys()))

        if not Preferences.get("api.enabled"):
            log.debug("Unable to process request, API is currently disabled")
            return cls.build_error("disabled", "Unable to process request, API is currently disabled")

        k_service, k_method = key.rsplit(".", 1)

        # Try find matching service
        service = cls.get_service(k_service)

        if service is None:
            log.warn("Unable to find service: %r", k_service)
            return cls.build_error("unknown.service", "Unable to find service: %r" % k_service)

        func = getattr(service, k_method, None)

        if func is None:
            log.warn("Unable to find method: %r", k_method)
            return cls.build_error("unknown.method", "Unable to find method: %r" % k_method)

        # Validate
        meta = getattr(func, "__meta__", {})

        if not meta.get("exposed", False):
            log.warn("Method is not exposed: %r", k_method)
            return cls.build_error("restricted.method", "Method is not exposed: %r" % k_method)

        # Decode strings in the `args` parameter
        try:
            args = cls.decode(args)
        except Exception as ex:
            return cls.build_error("args.decode_error", "Unable to decode provided args")

        # Decode strings in the `kwargs` parameter
        try:
            kwargs = cls.decode(kwargs)
        except Exception as ex:
            return cls.build_error("kwargs.decode_error", "Unable to decode provided kwargs")

        # Execute request handler
        try:
            result = cls.call(method, headers, body, func, args, kwargs)
        except ApiError as ex:
            log.warn("Error returned while handling request %r: %r", key, ex, exc_info=True)
            return cls.build_error("error.%s" % ex.code, ex.message)
        except Exception as ex:
            log.error("Exception raised while handling request %r: %s", key, ex, exc_info=True)
            return cls.build_error("exception", "Exception raised while handling the request")

        # Build response
        return cls.build_response(result)
Esempio n. 19
0
def ValidatePrefs():
    # Retrieve plex token
    token_plex = AccountMigration.get_token(Request.Headers)

    # Retrieve current activity mode
    last_activity_mode = Preferences.get('activity.mode')

    if Request.Headers.get('X-Disable-Preference-Migration', '0') == '0':
        # Run account migration
        am = AccountMigration()
        am.run(token_plex)

        # Migrate server preferences
        Preferences.migrate()

        # Try migrate administrator preferences
        try:
            Preferences.initialize(account=1)
            Preferences.migrate(account=1)
        except Account.DoesNotExist:
            log.debug(
                'Unable to migrate administrator preferences, no account found'
            )
    else:
        log.debug('Ignoring preference migration (disabled by header)')

    # Restart if activity_mode has changed
    if Preferences.get('activity.mode') != last_activity_mode or Prefs[
            'language'] != Dict['language']:
        log.info('Restart required to apply changes, restarting plugin...')

        def restart():
            # Delay until after `ValidatePrefs` returns
            time.sleep(3)

            # Restart plugin
            Plex[':/plugins'].restart(PLUGIN_IDENTIFIER)

        spawn(restart)
        return MessageContainer(_("Success"), _("Success"))

    # Fire configuration changed callback
    spawn(Main.on_configuration_changed)

    return MessageContainer(_("Success"), _("Success"))
Esempio n. 20
0
    def process(cls, method, headers, body, key, *args, **kwargs):
        log.debug('Handling API %s request %r - args: %r, kwargs: %r', method,
                  key, args, kwargs)

        if not Preferences.get('api.enabled'):
            log.debug('Unable to process request, API is currently disabled')
            return cls.build_error(
                'disabled',
                'Unable to process request, API is currently disabled')

        k_service, k_method = key.rsplit('.', 1)

        # Try find matching service
        service = cls.get_service(k_service)

        if service is None:
            log.warn('Unable to find service: %r', k_service)
            return cls.build_error('unknown.service',
                                   'Unable to find service: %r' % k_service)

        func = getattr(service, k_method, None)

        if func is None:
            log.warn('Unable to find method: %r', k_method)
            return cls.build_error('unknown.method',
                                   'Unable to find method: %r' % k_method)

        # Validate
        meta = getattr(func, '__meta__', {})

        if not meta.get('exposed', False):
            log.warn('Method is not exposed: %r', k_method)
            return cls.build_error('restricted.method',
                                   'Method is not exposed: %r' % k_method)

        # TODO validate authentication

        # Execute request handler
        try:
            result = cls.call(method, headers, body, func, args, kwargs)
        except ApiError, ex:
            log.warn('Error returned while handling request %r: %r',
                     key,
                     ex,
                     exc_info=True)
            return cls.build_error('error.%s' % ex.code, ex.message)
Esempio n. 21
0
def ValidatePrefs():
    # Retrieve plex token
    token_plex = AccountMigration.get_token(Request.Headers)

    # Retrieve current activity mode
    last_activity_mode = Preferences.get('activity.mode')

    if Request.Headers.get('X-Disable-Preference-Migration', '0') == '0':
        # Run account migration
        am = AccountMigration()
        am.run(token_plex)

        # Migrate server preferences
        Preferences.migrate()

        # Try migrate administrator preferences
        try:
            Preferences.initialize(account=1)
            Preferences.migrate(account=1)
        except Account.DoesNotExist:
            log.debug('Unable to migrate administrator preferences, no account found')
    else:
        log.debug('Ignoring preference migration (disabled by header)')

    # Restart if activity_mode has changed
    if Preferences.get('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 MessageContainer("Success", "Success")

    # Fire configuration changed callback
    spawn(Main.on_configuration_changed)

    return MessageContainer("Success", "Success")
Esempio n. 22
0
def ValidatePrefs():
    # Retrieve plex token
    token_plex = AccountMigration.get_token(Request.Headers)

    # Retrieve current activity mode
    last_activity_mode = Preferences.get("activity.mode")

    if Request.Headers.get("X-Disable-Preference-Migration", "0") == "0":
        # Run account migration
        am = AccountMigration()
        am.run(token_plex)

        # Migrate server preferences
        Preferences.migrate()

        # Try migrate administrator preferences
        try:
            Preferences.initialize(account=1)
            Preferences.migrate(account=1)
        except Account.DoesNotExist:
            log.debug("Unable to migrate administrator preferences, no account found")
    else:
        log.debug("Ignoring preference migration (disabled by header)")

    # Restart if activity_mode has changed
    if RestartRequired(last_activity_mode):
        log.info("Restart required to apply changes, restarting plugin...")

        def restart():
            # Delay until after `ValidatePrefs` returns
            time.sleep(3)

            # Restart plugin
            Plex[":/plugins"].restart(PLUGIN_IDENTIFIER)

        spawn(restart, daemon=True)
        return MessageContainer(_("Success"), _("Success"))

    # Fire configuration changed callback
    spawn(Main.on_configuration_changed, daemon=True)

    return MessageContainer(_("Success"), _("Success"))
Esempio n. 23
0
    def _is_duplicate(self, data, action, p_key):
        if data != SyncData.Watched or action != 'add':
            return False

        # Retrieve scrobble duplication period
        duplication_period = Preferences.get('scrobble.duplication_period')

        if duplication_period is None:
            return False

        # Check for duplicate scrobbles in `duplication_period`
        scrobbled = ActionHistory.has_scrobbled(
            self.task.account,
            p_key,
            after=datetime.utcnow() - timedelta(minutes=duplication_period))

        if scrobbled:
            log.info(
                'Ignoring duplicate history addition, scrobble already performed in the last %d minutes',
                duplication_period)
            return True

        return False
    def _queue(self):
        accounts = Account.select(Account.id).where(Account.id > 0)

        for account in accounts:
            if account.deleted:
                # Ignore library update trigger for deleted accounts
                continue

            enabled = Preferences.get('sync.library_update', account)

            log.debug('account: %r, enabled: %r', account.id, enabled)

            if not enabled:
                continue

            try:
                # Queue sync for account
                self.sync.queue(account=account,
                                mode=SyncMode.Full,
                                priority=100,
                                trigger=SyncResult.Trigger.LibraryUpdate)
            except QueueError, ex:
                log.info('Queue error: %s', ex)
Esempio n. 25
0
    def process(cls, method, headers, body, key, *args, **kwargs):
        log.debug('Handling API %s request %r - args: %r, kwargs: %r', method, key, args, kwargs)

        if not Preferences.get('api.enabled'):
            log.debug('Unable to process request, API is currently disabled')
            return cls.build_error('disabled', 'Unable to process request, API is currently disabled')

        k_service, k_method = key.rsplit('.', 1)

        # Try find matching service
        service = cls.get_service(k_service)

        if service is None:
            log.warn('Unable to find service: %r', k_service)
            return cls.build_error('unknown.service', 'Unable to find service: %r' % k_service)

        func = getattr(service, k_method, None)

        if func is None:
            log.warn('Unable to find method: %r', k_method)
            return cls.build_error('unknown.method', 'Unable to find method: %r' % k_method)

        # Validate
        meta = getattr(func, '__meta__', {})

        if not meta.get('exposed', False):
            log.warn('Method is not exposed: %r', k_method)
            return cls.build_error('restricted.method', 'Method is not exposed: %r' % k_method)

        # TODO validate authentication

        # Execute request handler
        try:
            result = cls.call(method, headers, body, func, args, kwargs)
        except ApiError, ex:
            log.warn('Error returned while handling request %r: %r', key, ex, exc_info=True)
            return cls.build_error('error.%s' % ex.code, ex.message)
Esempio n. 26
0
    def is_duplicate(cls, action):
        if action.event != 'scrobble/stop':
            return False

        # Retrieve scrobble duplication period
        duplication_period = Preferences.get('scrobble.duplication_period')

        if duplication_period is None:
            return False

        # Check for duplicate scrobbles in `duplication_period`
        scrobbled = ActionHistory.has_scrobbled(
            action.account, action.rating_key,
            after=action.queued_at - timedelta(minutes=duplication_period)
        )

        if scrobbled:
            log.info(
                'Ignoring duplicate %r action, scrobble already performed in the last %d minutes',
                action.event, duplication_period
            )
            return True

        return False
Esempio n. 27
0
    def _queue(self):
        started_at = self._state.started_at

        if started_at:
            log.info('Scanner started at: %r', started_at)

        # Retrieve accounts
        accounts = Account.select(
            Account.id
        ).where(
            Account.id > 0
        )

        # Trigger sync on enabled accounts
        for account in accounts:
            if account.deleted:
                continue

            # Ensure account has the library update trigger enabled
            enabled = Preferences.get('sync.library_update', account)

            if not enabled:
                continue

            # Retrieve recently added items
            items_added = self._state.get(account.id).pop_added()

            log.info(
                'Detected %d item(s) have been added for account %r',
                account.id,
                len(items_added)
            )

            # Build pull parameters
            pull = {
                # Run pull on items we explicitly know have been created
                'ids': set(items_added)
            }

            if started_at:
                # Run pull on items created since the scanner started
                pull['created_since'] = started_at - timedelta(seconds=30)

            # Queue sync for account
            try:
                self.sync.queue(
                    account=account,
                    mode=SyncMode.Full,

                    priority=100,
                    trigger=SyncResult.Trigger.LibraryUpdate,

                    pull=pull
                )
            except QueueError as ex:
                log.info('Queue error: %s', ex)

                # Unable to queue sync, add items back to the account library state
                self._state.get(account.id).extend_added(items_added)
            finally:
                # Reset library state
                self._state.reset()
Esempio n. 28
0
    def process(cls, method, headers, body, key, *args, **kwargs):
        log.debug('Handling API %s request %r - args: %r, kwargs: %r', method,
                  key, len(args), len(kwargs.keys()))

        if not Preferences.get('api.enabled'):
            log.debug('Unable to process request, API is currently disabled')
            return cls.build_error(
                'disabled',
                'Unable to process request, API is currently disabled')

        k_service, k_method = key.rsplit('.', 1)

        # Try find matching service
        service = cls.get_service(k_service)

        if service is None:
            log.warn('Unable to find service: %r', k_service)
            return cls.build_error('unknown.service',
                                   'Unable to find service: %r' % k_service)

        func = getattr(service, k_method, None)

        if func is None:
            log.warn('Unable to find method: %r', k_method)
            return cls.build_error('unknown.method',
                                   'Unable to find method: %r' % k_method)

        # Validate
        meta = getattr(func, '__meta__', {})

        if not meta.get('exposed', False):
            log.warn('Method is not exposed: %r', k_method)
            return cls.build_error('restricted.method',
                                   'Method is not exposed: %r' % k_method)

        # Decode strings in the `args` parameter
        try:
            args = cls.decode(args)
        except Exception as ex:
            return cls.build_error('args.decode_error',
                                   'Unable to decode provided args')

        # Decode strings in the `kwargs` parameter
        try:
            kwargs = cls.decode(kwargs)
        except Exception as ex:
            return cls.build_error('kwargs.decode_error',
                                   'Unable to decode provided kwargs')

        # Execute request handler
        try:
            result = cls.call(method, headers, body, func, args, kwargs)
        except ApiError as ex:
            log.warn('Error returned while handling request %r: %r',
                     key,
                     ex,
                     exc_info=True)
            return cls.build_error('error.%s' % ex.code, ex.message)
        except Exception as ex:
            log.error('Exception raised while handling request %r: %s',
                      key,
                      ex,
                      exc_info=True)
            return cls.build_error(
                'exception', 'Exception raised while handling the request')

        # Build response
        return cls.build_response(result)
Esempio n. 29
0
    def start(cls, blocking=False):
        enabled = ACTIVITY_MODE.get(Preferences.get('activity.mode'))

        # Start methods
        cls.started = cls.methods.start(enabled)
Esempio n. 30
0
    def start(cls, blocking=False):
        enabled = ACTIVITY_MODE.get(Preferences.get('activity.mode'))

        # Start methods
        cls.started = cls.methods.start(enabled)
Esempio n. 31
0
    def is_idle(self):
        # Cleanup stale sessions
        self.cleanup()

        # Check if server has been idle for `sync.idle_delay` seconds
        return self._idle_since and datetime.utcnow() - self._idle_since > timedelta(minutes=Preferences.get('sync.idle_delay'))