Example #1
0
 def test_send_reply(self):
     client = FakeClient()
     profile = client.get_profile()
     handler = ExternalBotHandler(
         client=client, root_dir=None, bot_details=None, bot_config_file=None
     )
     to = {"id": 43}
     expected = [
         (
             {"type": "private", "display_recipient": [to]},
             {"type": "private", "to": [to["id"]]},
             None,
         ),
         (
             {"type": "private", "display_recipient": [to, profile]},
             {"type": "private", "to": [to["id"], profile["id"]]},
             "widget_content",
         ),
         (
             {"type": "stream", "display_recipient": "Stream name", "subject": "Topic"},
             {"type": "stream", "to": "Stream name", "subject": "Topic"},
             "test widget",
         ),
     ]
     response_text = "Response"
     for test in expected:
         client.send_message = MagicMock()
         handler.send_reply(test[0], response_text, test[2])
         client.send_message.assert_called_once_with(
             dict(test[1], content=response_text, widget_content=test[2])
         )
Example #2
0
    def test_basics(self):
        client = FakeClient()

        handler = ExternalBotHandler(
            client=client, root_dir=None, bot_details=None, bot_config_file=None
        )

        message = None
        handler.send_message(message)
def main():
    # type: () -> None
    args = parse_args()
    if os.path.isfile(args.bot):
        bot_path = os.path.abspath(args.bot)
        bot_name = os.path.splitext(os.path.basename(bot_path))[0]
    else:
        bot_path = os.path.abspath(
            os.path.join(current_dir, 'bots', args.bot, args.bot + '.py'))
        bot_name = args.bot
    bot_dir = os.path.dirname(bot_path)
    if args.provision:
        provision_bot(os.path.dirname(bot_path), args.force)
    lib_module = import_module_from_source(bot_path, bot_name)

    message = {'content': args.message, 'sender_email': '*****@*****.**'}
    message_handler = lib_module.handler_class()

    with patch('zulip.Client') as mock_client:
        mock_bot_handler = ExternalBotHandler(mock_client, bot_dir)
        mock_bot_handler.send_reply = MagicMock()
        mock_bot_handler.send_message = MagicMock()
        mock_bot_handler.update_message = MagicMock()
        if hasattr(message_handler, 'initialize') and callable(
                message_handler.initialize):
            message_handler.initialize(mock_bot_handler)
        message_handler.handle_message(message=message,
                                       bot_handler=mock_bot_handler,
                                       state_handler=StateHandler())
        print("On sending {} bot the message \"{}\"".format(
            bot_name, args.message))
        # send_reply and send_message have slightly arguments; the
        # following takes that into account.
        #   send_reply(original_message, response)
        #   send_message(response_message)
        if mock_bot_handler.send_reply.called:
            output_message = list(mock_bot_handler.send_reply.call_args)[0][1]
        elif mock_bot_handler.send_message.called:
            output_message = list(
                mock_bot_handler.send_message.call_args)[0][0]
        elif mock_bot_handler.update_message.called:
            output_message = list(
                mock_bot_handler.update_message.call_args)[0][0]['content']
            print(
                "the bot updates a message with the following text (in quotes):\n\"{}\""
                .format(output_message))
            sys.exit()
        else:
            print("the bot sent no reply.")
            sys.exit()
        print(
            "the bot gives the following output message (in quotes):\n\"{}\"".
            format(output_message))
Example #4
0
    def test_basics(self):
        client = FakeClient()

        handler = ExternalBotHandler(
            client=client,
            root_dir=None,
            bot_details=None,
            bot_config_file=None
        )

        message = None
        handler.send_message(message)
Example #5
0
 def test_react(self):
     client = FakeClient()
     handler = ExternalBotHandler(
         client = client,
         root_dir=None,
         bot_details=None,
         bot_config_file=None
     )
     emoji_name = 'wave'
     message = {'id': 10}
     expected = {'message_id': message['id'], 'emoji_name': 'wave', 'reaction_type': 'unicode_emoji'}
     client.add_reaction = MagicMock()
     handler.react(message, emoji_name)
     client.add_reaction.assert_called_once_with(dict(expected))
Example #6
0
 def test_react(self):
     client = FakeClient()
     handler = ExternalBotHandler(
         client=client, root_dir=None, bot_details=None, bot_config_file=None
     )
     emoji_name = "wave"
     message = {"id": 10}
     expected = {
         "message_id": message["id"],
         "emoji_name": "wave",
         "reaction_type": "unicode_emoji",
     }
     client.add_reaction = MagicMock()
     handler.react(message, emoji_name)
     client.add_reaction.assert_called_once_with(dict(expected))
Example #7
0
def load_bot_handlers():
    # type: () -> Any
    for bot in available_bots:
        client = Client(email=bots_config[bot]["email"],
                        api_key=bots_config[bot]["key"],
                        site=bots_config[bot]["site"])
        try:
            bot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   'bots', bot)
            # TODO: Figure out how to pass in third party config info.
            bot_handler = ExternalBotHandler(
                client,
                bot_dir,
                bot_details={},
                bot_config_file=None
            )
            bot_handlers[bot] = bot_handler

            lib_module = get_bot_lib_module(bot)
            message_handler = lib_module.handler_class()
            if hasattr(message_handler, 'validate_config'):
                config_data = bot_handlers[bot].get_config_info(bot)
                try:
                    lib_module.handler_class.validate_config(config_data)
                except ConfigValidationError as e:
                    print("There was a problem validating your config file:\n\n{}".format(e))
                    sys.exit(1)

            if hasattr(message_handler, 'initialize'):
                message_handler.initialize(bot_handler=bot_handler)
        except SystemExit:
            return BadRequest("Cannot fetch user profile for bot {}, make sure you have set up the flaskbotrc "
                              "file correctly.".format(bot))
Example #8
0
 def test_content_and_full_content(self):
     client = FakeClient()
     client.get_profile()
     ExternalBotHandler(client=client,
                        root_dir=None,
                        bot_details=None,
                        bot_config_file=None)
Example #9
0
def handle_bot(bot):
    # type: (str) -> Union[str, BadRequest]
    lib_module = get_bot_lib_module(bot)
    if lib_module is None:
        return BadRequest(
            "Can't find the configuration or Bot Handler code for bot {}. "
            "Make sure that the `zulip_bots` package is installed, and "
            "that your flaskbotrc is set up correctly".format(bot))

    client = Client(email=bots_config[bot]["email"],
                    api_key=bots_config[bot]["key"],
                    site=bots_config[bot]["site"])
    try:
        bot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                               'bots', bot)
        restricted_client = ExternalBotHandler(client, bot_dir)
    except SystemExit:
        return BadRequest(
            "Cannot fetch user profile for bot {}, make sure you have set up the flaskbotrc "
            "file correctly.".format(bot))

    message_handler = lib_module.handler_class()

    # TODO: Handle stateful bots properly.
    state_handler = StateHandler()

    event = request.get_json(force=True)
    message_handler.handle_message(message=event["message"],
                                   bot_handler=restricted_client,
                                   state_handler=state_handler)
    return json.dumps("")
Example #10
0
    def _create_client_and_handler_for_file_upload(self):
        client = FakeClient()
        client.upload_file = MagicMock()

        handler = ExternalBotHandler(
            client=client, root_dir=None, bot_details=None, bot_config_file=None
        )
        return client, handler
Example #11
0
 def test_content_and_full_content(self):
     client = FakeClient()
     profile = client.get_profile()
     handler = ExternalBotHandler(client=client,
                                  root_dir=None,
                                  bot_details=None,
                                  bot_config_file=None)
     to = {'email': 'Some@User'}
Example #12
0
 def test_send_reply(self):
     client = FakeClient()
     profile = client.get_profile()
     handler = ExternalBotHandler(
         client=client,
         root_dir=None,
         bot_details=None,
         bot_config_file=None
     )
     to = {'id': 43}
     expected = [({'type': 'private', 'display_recipient': [to]},
                  {'type': 'private', 'to': [to['id']]}, None),
                 ({'type': 'private', 'display_recipient': [to, profile]},
                  {'type': 'private', 'to': [to['id'], profile['id']]}, 'widget_content'),
                 ({'type': 'stream', 'display_recipient': 'Stream name', 'subject': 'Topic'},
                  {'type': 'stream', 'to': 'Stream name', 'subject': 'Topic'}, 'test widget')]
     response_text = "Response"
     for test in expected:
         client.send_message = MagicMock()
         handler.send_reply(test[0], response_text, test[2])
         client.send_message.assert_called_once_with(dict(
             test[1], content=response_text, widget_content=test[2]))
Example #13
0
 def test_send_reply(self):
     client = FakeClient()
     profile = client.get_profile()
     handler = ExternalBotHandler(
         client=client,
         root_dir=None,
         bot_details=None,
         bot_config_file=None
     )
     to = {'email': 'Some@User'}
     expected = [({'type': 'private', 'display_recipient': [to]},
                  {'type': 'private', 'to': [to['email']]}, None),
                 ({'type': 'private', 'display_recipient': [to, profile]},
                  {'type': 'private', 'to': [to['email']]}, 'widget_content'),
                 ({'type': 'stream', 'display_recipient': 'Stream name', 'subject': 'Topic'},
                  {'type': 'stream', 'to': 'Stream name', 'subject': 'Topic'}, 'test widget')]
     response_text = "Response"
     for test in expected:
         client.send_message = MagicMock()
         handler.send_reply(test[0], response_text, test[2])
         client.send_message.assert_called_once_with(dict(
             test[1], content=response_text, widget_content=test[2]))
Example #14
0
 def test_extract_query_without_mention(self):
     client = FakeClient()
     handler = ExternalBotHandler(
         client=client, root_dir=None, bot_details=None, bot_config_file=None
     )
     message = {"content": "@**Alice** Hello World"}
     self.assertEqual(extract_query_without_mention(message, handler), "Hello World")
     message = {"content": "@**Alice|alice** Hello World"}
     self.assertEqual(extract_query_without_mention(message, handler), "Hello World")
     message = {"content": "@**Alice Renamed|alice** Hello World"}
     self.assertEqual(extract_query_without_mention(message, handler), "Hello World")
     message = {"content": "Not at start @**Alice|alice** Hello World"}
     self.assertEqual(extract_query_without_mention(message, handler), None)
Example #15
0
def load_bot_handlers():
    # type: () -> Any
    for bot in available_bots:
        client = Client(email=bots_config[bot]["email"],
                        api_key=bots_config[bot]["key"],
                        site=bots_config[bot]["site"])
        try:
            bot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   'bots', bot)
            bot_handlers[bot] = ExternalBotHandler(client, bot_dir)
        except SystemExit:
            return BadRequest("Cannot fetch user profile for bot {}, make sure you have set up the flaskbotrc "
                              "file correctly.".format(bot))
Example #16
0
 def test_is_private_message_but_not_group_pm(self):
     client = FakeClient()
     handler = ExternalBotHandler(
         client=client, root_dir=None, bot_details=None, bot_config_file=None
     )
     message = {}
     message["display_recipient"] = "some stream"
     message["type"] = "stream"
     self.assertFalse(is_private_message_but_not_group_pm(message, handler))
     message["type"] = "private"
     message["display_recipient"] = [{"email": "*****@*****.**"}]
     message["sender_id"] = handler.user_id
     self.assertFalse(is_private_message_but_not_group_pm(message, handler))
     message["sender_id"] = 0  # someone else
     self.assertTrue(is_private_message_but_not_group_pm(message, handler))
     message["display_recipient"] = [{"email": "*****@*****.**"}, {"email": "*****@*****.**"}]
     self.assertFalse(is_private_message_but_not_group_pm(message, handler))
Example #17
0
def load_bot_handlers(
    available_bots: List[str],
    bots_config: Dict[str, Dict[str, str]],
    third_party_bot_conf: Optional[configparser.ConfigParser] = None,
) -> Dict[str, ExternalBotHandler]:
    bot_handlers = {}
    for bot in available_bots:
        client = Client(email=bots_config[bot]["email"],
                        api_key=bots_config[bot]["key"],
                        site=bots_config[bot]["site"])
        bot_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                               'bots', bot)
        bot_handler = ExternalBotHandler(
            client,
            bot_dir,
            bot_details={},
            bot_config_parser=third_party_bot_conf)

        bot_handlers[bot] = bot_handler
    return bot_handlers
Example #18
0
 def test_is_private_message_but_not_group_pm(self):
     client = FakeClient()
     handler = ExternalBotHandler(
         client=client,
         root_dir=None,
         bot_details=None,
         bot_config_file=None
     )
     message = {}
     message['display_recipient'] = 'some stream'
     message['type'] = 'stream'
     self.assertFalse(is_private_message_but_not_group_pm(message, handler))
     message['type'] = 'private'
     message['display_recipient'] = [{'email': '*****@*****.**'}]
     message['sender_id'] = handler.user_id
     self.assertFalse(is_private_message_but_not_group_pm(message, handler))
     message['sender_id'] = 0  # someone else
     self.assertTrue(is_private_message_but_not_group_pm(message, handler))
     message['display_recipient'] = [{'email': '*****@*****.**'}, {'email': '*****@*****.**'}]
     self.assertFalse(is_private_message_but_not_group_pm(message, handler))
Example #19
0
def handle_bot(bot):
    # type: (str) -> Union[str, BadRequest]
    if bot not in available_bots:
        return BadRequest("requested bot service {} not supported".format(bot))

    client = Client(email=bots_config[bot]["email"],
                    api_key=bots_config[bot]["key"],
                    site=bots_config[bot]["site"])
    try:
        restricted_client = ExternalBotHandler(client)
    except SystemExit:
        return BadRequest(
            "Cannot fetch user profile for bot {}, make sure you have set up the flaskbotrc "
            "file correctly.".format(bot))
    message_handler = bots_lib_module[bot].handler_class()

    # TODO: Handle stateful bots properly.
    state_handler = StateHandler()

    event = json.loads(request.data)
    message_handler.handle_message(message=event["message"],
                                   bot_handler=restricted_client,
                                   state_handler=state_handler)
    return "Success!"