Пример #1
0
class ResponseBot(object):
    """
    The entry point of ResponseBot. :func:`~responsebot.responsebot.ResponseBot.__init__` inits & configures the bot.
    :func:`~responsebot.responsebot.ResponseBot.start` tries to init the main sub-components (handler discoverer,
    authenticator, tweet streamer, etc.) and handle errors if necessary
    """
    def __init__(self, *args, **kwargs):
        """
        Try to init & configure the bot from configurations read from ``.responsebot`` file, from CLI arguments or from
        direct call in code

        :param kwargs: Options for :class:`~responsebot.utils.config_utils.ResponseBotConfig`
        """
        configure_logging()
        try:
            self.config = ResponseBotConfig(*args, **kwargs)
        except MissingConfigException as e:
            logging.error(str(e))
            sys.exit()

    def start(self):
        """
        Try to init the main sub-components (:func:`~responsebot.utils.handler_utils.discover_handler_classes`, \
        :func:`~responsebot.utils.auth_utils.auth`, :class:`~responsebot.responsebot_stream.ResponseBotStream`, etc.)
        """
        logging.info('ResponseBot started')

        try:
            handler_classes = handler_utils.discover_handler_classes(self.config.get('handlers_package'))
            if len(handler_classes) == 0:
                logging.warning('No handler found. Did you forget to extend BaseTweethandler? Check --handlers-module')
        except ImportError as e:
            logging.error(str(e))
            sys.exit()

        try:
            client = auth_utils.auth(
                consumer_key=self.config.get('consumer_key'),
                consumer_secret=self.config.get('consumer_secret'),
                token_key=self.config.get('token_key'),
                token_secret=self.config.get('token_secret'),
            )
        except (APIQuotaError, AuthenticationError) as e:
            logging.error(str(e))
            sys.exit()

        try:
            listener = ResponseBotListener(client=client, handler_classes=handler_classes)

            stream = ResponseBotStream(client=client, listener=listener)
            stream.start()
        except UserHandlerException as e:
            # TODO: print only stack trace from user exception
            logging.exception(e)
            sys.exit()
        except APIError as e:
            logging.error(str(e))
            sys.exit()
    def test_load_config_from_terminal(self, mock_1, mock_2):
        params = {
            'handlers_package': 'handlers_package',
            'auth': ('consumer_key', 'consumer_secret', 'token_key', 'token_secret'),
        }

        config = ResponseBotConfig(**params)

        for config_key in ResponseBotConfig.REQUIRED_CONFIGS:
            self.assertEqual(config.get(config_key), config_key)
Пример #3
0
    def __init__(self, *args, **kwargs):
        """
        Try to init & configure the bot from configurations read from ``.responsebot`` file, from CLI arguments or from
        direct call in code

        :param kwargs: Options for :class:`~responsebot.utils.config_utils.ResponseBotConfig`
        """
        configure_logging()
        try:
            self.config = ResponseBotConfig(*args, **kwargs)
        except MissingConfigError as e:
            logging.error(str(e))
            sys.exit()

        self.error_time_log = {}
        self.error_sleep_log = {}
 def test_validate_config(self):
     params = {
         'handlers_package': 'handlers_package',
         'auth': ('consumer_key', 'consumer_secret', 'token_key', 'token_secret'),
     }
     try:
         ResponseBotConfig(**params)
     except MissingConfigError:
         self.fail('Should not raise missing exception')
Пример #5
0
    def __init__(self, *args, **kwargs):
        """
        Try to init & configure the bot from configurations read from ``.responsebot`` file, from CLI arguments or from
        direct call in code

        :param kwargs: Options for :class:`~responsebot.utils.config_utils.ResponseBotConfig`
        """
        configure_logging()
        try:
            self.config = ResponseBotConfig(*args, **kwargs)
        except MissingConfigException as e:
            logging.error(str(e))
            sys.exit()
Пример #6
0
class ResponseBot(object):
    """
    The entry point of ResponseBot. :func:`~responsebot.responsebot.ResponseBot.__init__` inits & configures the bot.
    :func:`~responsebot.responsebot.ResponseBot.start` tries to init the main sub-components (handler discoverer,
    authenticator, tweet streamer, etc.) and handle errors if necessary
    """
    def __init__(self, *args, **kwargs):
        """
        Try to init & configure the bot from configurations read from ``.responsebot`` file, from CLI arguments or from
        direct call in code

        :param kwargs: Options for :class:`~responsebot.utils.config_utils.ResponseBotConfig`
        """
        configure_logging()
        try:
            self.config = ResponseBotConfig(*args, **kwargs)
        except MissingConfigError as e:
            logging.error(str(e))
            sys.exit()

        self.error_time_log = {}
        self.error_sleep_log = {}

    def start(self):
        """
        Try to init the main sub-components (:func:`~responsebot.utils.handler_utils.discover_handler_classes`, \
        :func:`~responsebot.utils.auth_utils.auth`, :class:`~responsebot.responsebot_stream.ResponseBotStream`, etc.)
        """
        logging.info('ResponseBot started')

        handler_classes = handler_utils.discover_handler_classes(self.config.get('handlers_package'))
        if len(handler_classes) == 0:
            logging.warning('No handler found. Did you forget to extend BaseTweethandler? Check --handlers-module')

        while True:
            try:
                client = auth_utils.auth(self.config)

                listener = ResponseBotListener(client=client, handler_classes=handler_classes)

                stream = ResponseBotStream(client=client, listener=listener)
                stream.start()
            except (APIQuotaError, AuthenticationError, TweepError) as e:
                self.handle_error(e)
            else:
                break

    def handle_error(self, error):
        """
        Try to detect repetitive errors and sleep for a while to avoid being marked as spam
        """
        logging.exception("try to sleep if there are repeating errors.")
        error_desc = str(error)
        now = datetime.datetime.now()
        if error_desc not in self.error_time_log:
            self.error_time_log[error_desc] = now
            return

        time_of_last_encounter = self.error_time_log[str(error)]
        time_since_last_encounter = now - time_of_last_encounter
        if time_since_last_encounter.total_seconds() > self.config.get('min_seconds_between_errors'):
            self.error_time_log[error_desc] = now
            return

        if error_desc not in self.error_sleep_log:
            time.sleep(self.config.get('sleep_seconds_on_consecutive_errors'))
            self.error_sleep_log[error_desc] = 1
        else:
            sys.exit()
Пример #7
0
    def test_load_config_from_file(self, mock_1, mock_2):
        config = ResponseBotConfig()

        for config_key in ResponseBotConfig.REQUIRED_CONFIGS:
            self.assertEqual(config.get(config_key), 'some_config')
Пример #8
0
class ResponseBot(object):
    """
    The entry point of ResponseBot. :func:`~responsebot.responsebot.ResponseBot.__init__` inits & configures the bot.
    :func:`~responsebot.responsebot.ResponseBot.start` tries to init the main sub-components (handler discoverer,
    authenticator, tweet streamer, etc.) and handle errors if necessary
    """
    def __init__(self, *args, **kwargs):
        """
        Try to init & configure the bot from configurations read from ``.responsebot`` file, from CLI arguments or from
        direct call in code

        :param kwargs: Options for :class:`~responsebot.utils.config_utils.ResponseBotConfig`
        """
        configure_logging()
        try:
            self.config = ResponseBotConfig(*args, **kwargs)
        except MissingConfigError as e:
            logging.error(str(e))
            sys.exit()

        self.error_time_log = {}
        self.error_sleep_log = {}

    def start(self):
        """
        Try to init the main sub-components (:func:`~responsebot.utils.handler_utils.discover_handler_classes`, \
        :func:`~responsebot.utils.auth_utils.auth`, :class:`~responsebot.responsebot_stream.ResponseBotStream`, etc.)
        """
        logging.info('ResponseBot started')

        try:
            handler_classes = handler_utils.discover_handler_classes(self.config.get('handlers_package'))
            if len(handler_classes) == 0:
                logging.warning('No handler found. Did you forget to extend BaseTweethandler? Check --handlers-module')
        except ImportError as e:
            logging.error(str(e))
            sys.exit()

        while True:
            try:
                client = auth_utils.auth(self.config)

                listener = ResponseBotListener(client=client, handler_classes=handler_classes)

                stream = ResponseBotStream(client=client, listener=listener)
                stream.start()
            except (APIQuotaError, AuthenticationError, APIError) as e:
                self.handle_error(e)
            except UserHandlerError as e:
                logging.exception(e)
                sys.exit()
            else:
                break

    def handle_error(self, error):
        """
        Try to detect repetitive errors and sleep for a while to avoid being marked as spam
        """
        error_desc = str(error)
        now = datetime.datetime.now()
        if error_desc not in self.error_time_log:
            self.error_time_log[error_desc] = now
            return

        time_of_last_encounter = self.error_time_log[str(error)]
        time_since_last_encounter = now - time_of_last_encounter
        if time_since_last_encounter.total_seconds() > self.config.get('min_seconds_between_errors'):
            self.error_time_log[error_desc] = now
            return

        if error_desc not in self.error_sleep_log:
            time.sleep(self.config.get('sleep_seconds_on_consecutive_errors'))
            self.error_sleep_log[error_desc] = 1
        else:
            logging.error(error_desc)
            sys.exit()
Пример #9
0
    def test_load_config_from_file(self, mock_1, mock_2):
        config = ResponseBotConfig()

        for config_key in ResponseBotConfig.REQUIRED_CONFIGS:
            self.assertEqual(config.get(config_key), 'some_config')