101 lines
3.9 KiB
Python
101 lines
3.9 KiB
Python
#!/usr/bin/env python
|
|
from __future__ import print_function
|
|
from __future__ import absolute_import
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
import zulip_bots
|
|
|
|
from six.moves import configparser
|
|
|
|
from mock import MagicMock, patch
|
|
from zulip_bots.lib import StateHandler
|
|
from zulip_bots.lib import ExternalBotHandler
|
|
from zulip_bots.provision import provision_bot
|
|
from zulip_bots.run import import_module_from_source
|
|
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
def parse_args():
|
|
usage = '''
|
|
zulip-bot-output <bot_name> <message>
|
|
Example: zulip-bot-output xkcd "1"
|
|
The message need only be enclosed in quotes if empty or containing spaces.
|
|
This tool can be used for testing bots by sending simple messages
|
|
and capturing the response.
|
|
(Internally, this program loads bot-related code from the
|
|
library code and then feeds the message provided
|
|
in the command to the library code to handle.)
|
|
'''
|
|
|
|
parser = argparse.ArgumentParser(usage=usage)
|
|
parser.add_argument('bot',
|
|
action='store',
|
|
help='the name or path an existing bot to run')
|
|
|
|
parser.add_argument('message',
|
|
action='store',
|
|
help='the message content to send to the bot')
|
|
|
|
parser.add_argument('--force', '-f',
|
|
action='store_true',
|
|
help='try running bot even if dependencies install fails')
|
|
|
|
parser.add_argument('--provision', '-p',
|
|
action='store_true',
|
|
help='install dependencies for the bot')
|
|
|
|
args = parser.parse_args()
|
|
return args
|
|
|
|
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': 'foo_sender@zulip.com'}
|
|
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))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|