bots/flock: Add flock bot.
ADD
zulip_bots/zulip_bots/bots/flock/assests/1.png
zulip_bots/zulip_bots/bots/flock/assests/1.png
Binary files /dev/null and b/zulip_bots/zulip_bots/bots/flock/assests/1.png differ

ADD
zulip_bots/zulip_bots/bots/flock/doc.md
+# Flock Bot
+
+With [Flock](https://flock.com/) bot, you can send messages to any of your
+ flock contact without having to leave Zulip.
+
+Sending messages to a user is quite easy, syntax is:
+`@botname recipient_name: hello`
+where `recipient_name` is name of recipient and `hello` is the sample message.
+
+## Configuration
+
+1. Before running Flock bot, you'll need a `token`. In order to get `token`,
+ Go to [Flock apps](https://dev.flock.com/apps) and create an app.
+ After successful installation, you'll get an `token` in response from servers.
+
+1. Once you have `token`, you should supply it in `flock.conf` file.
+
+## Usage
+
+Run this bot as described in
+ [here](https://zulipchat.com/api/running-bots#running-a-bot).
+
+You can use this bot in one easy step:
+
+`@botname recipient_firstName: message`
+
+For help, do `@botname help`.

ADD
zulip_bots/zulip_bots/bots/flock/fixtures/test_message_send_failed.json
+{
+ "request": {
+ "api_url": "https://api.flock.co/v1/chat.sendMessage",
+ "method": "GET",
+ "params": {
+ "token": "12345",
+ "text": "hi there",
+ "to": "u:invalid"
+ }
+ },
+ "response": {
+ "error": "InvalidParameter",
+ "description": "A required parameter for the method call is missing or invalid",
+ "parameter": "to"
+ },
+ "response-headers": {
+ "content-type": "application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/flock/fixtures/test_message_send_success.json
+{
+ "request": {
+ "api_url": "https://api.flock.co/v1/chat.sendMessage",
+ "method": "GET",
+ "params": {
+ "token": "12345",
+ "to": "u:userid",
+ "text": "hi there"
+ }
+ },
+ "response": {
+ "uid": "15207048523"
+ },
+ "response-headers": {
+ "content-type": "application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/flock/fixtures/test_no_recipient_found.json
+{
+ "request": {
+ "api_url": "https://api.flock.co/v1/roster.listContacts",
+ "method": "GET",
+ "params": {
+ "token": "12345"
+ }
+ },
+ "response": {
+ "error": "No user found. Make sure you typed it correctly."
+ },
+ "response-headers": {
+ "content-type": "application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/flock/flock.conf
+[flock]
+token=12345

ADD
zulip_bots/zulip_bots/bots/flock/flock.py
+import logging
+import requests
+from typing import Any, Dict
+from requests.exceptions import ConnectionError
+
+USERS_LIST_URL = 'https://api.flock.co/v1/roster.listContacts'
+SEND_MESSAGE_URL = 'https://api.flock.co/v1/chat.sendMessage'
+
+help_message = '''
+You can send messages to any Flock user associated with your account from Zulip.
+*Syntax*: **@botname to: message** where `to` is **firstName** of recipient.
+'''
+
+# Matches the recipient name provided by user with list of users in his contacts.
+# If matches, returns the matched User's ID
+def find_recipient(res: str, to: str) -> str:
+ for obj in res:
+ if to == obj['firstName']:
+ return obj['id']
+
+# Returns User's ID, if not found, returns error message.
+def get_recipient_id(content: str, config: Dict[str, str]) -> str:
+ token = config['token']
+ content_pieces = content.split(':')
+ to = content_pieces[0].strip()
+ payload = {
+ 'token': token
+ }
+
+ try:
+ res = requests.get(USERS_LIST_URL, params=payload)
+ except ConnectionError as e:
+ logging.exception(str(e))
+ return "Uh-Oh, couldn't process the request \
+right now.\nPlease try again later"
+
+ res = res.json()
+ to = find_recipient(res, to)
+ if to is None:
+ return "No user found. Make sure you typed it correctly."
+ else:
+ return to
+
+# This handles the message sending work.
+def get_flock_response(content: str, config: Dict[str, str]) -> str:
+ token = config['token']
+ content_pieces = content.split(':')
+ to = content_pieces[0].strip()
+ message = content_pieces[1].strip()
+
+ to = get_recipient_id(content, config)
+ if len(str(to)) > 30:
+ return to
+
+ payload = {
+ 'to': to,
+ 'text': message,
+ 'token': token
+ }
+ try:
+ r = requests.get(SEND_MESSAGE_URL, params=payload)
+ except ConnectionError as e:
+ logging.exception(str(e))
+ return "Uh-Oh, couldn't process the request \
+right now.\nPlease try again later"
+
+ r = r.json()
+ if "uid" in r:
+ return "Message sent."
+ else:
+ return "Message sending failed :slightly_frowning_face:. Please try again."
+
+def get_flock_bot_response(content: str, config: Dict[str, str]) -> None:
+ content = content.strip()
+ if content == '' or content == 'help':
+ return help_message
+ else:
+ result = get_flock_response(content, config)
+ return result
+
+class FlockHandler(object):
+ '''
+ This is flock bot. Now you can send messages to any of your
+ flock user without having to leave Zulip.
+ '''
+
+ def initialize(self, bot_handler: Any) -> None:
+ self.config_info = bot_handler.get_config_info('flock')
+
+ def usage(self) -> str:
+ return '''Hello from Flock Bot. You can send messages to any Flock user
+right from Zulip.'''
+
+ def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None:
+ response = get_flock_bot_response(message['content'], self.config_info)
+ bot_handler.send_reply(message, response)
+
+handler_class = FlockHandler

ADD
zulip_bots/zulip_bots/bots/flock/requirements.txt
+requests

ADD
zulip_bots/zulip_bots/bots/flock/test_flock.py
+from unittest.mock import patch
+from zulip_bots.test_lib import BotTestCase
+from requests.exceptions import ConnectionError
+
+class TestFlockBot(BotTestCase):
+ bot_name = "flock"
+ normal_config = {"token": "12345"}
+
+ message_config = {
+ "token": "12345",
+ "text": "Ricky: test message",
+ "to": "u:somekey"
+ }
+
+ help_message = '''
+You can send messages to any Flock user associated with your account from Zulip.
+*Syntax*: **@botname to: message** where `to` is **firstName** of recipient.
+'''
+
+ def test_bot_responds_to_empty_message(self) -> None:
+ self.verify_reply('', self.help_message)
+
+ def test_help_message(self) -> None:
+ self.verify_reply('', self.help_message)
+
+ def test_fetch_id_connection_error(self) -> None:
+ with self.mock_config_info(self.normal_config), \
+ patch('requests.get', side_effect=ConnectionError()), \
+ patch('logging.exception'):
+ self.verify_reply('tyler: Hey tyler', "Uh-Oh, couldn\'t process the request \
+right now.\nPlease try again later")
+
+ def test_response_connection_error(self) -> None:
+ with self.mock_config_info(self.message_config), \
+ patch('requests.get', side_effect=ConnectionError()), \
+ patch('logging.exception'):
+ self.verify_reply('Ricky: test message', "Uh-Oh, couldn\'t process the request \
+right now.\nPlease try again later")
+
+ @patch('zulip_bots.bots.flock.flock.find_recipient')
+ def test_no_recipient_found(self, find_recipient: str) -> None:
+ bot_response = "No user found. Make sure you typed it correctly."
+ find_recipient.return_value = None
+ with self.mock_config_info(self.normal_config), \
+ self.mock_http_conversation('test_no_recipient_found'):
+ self.verify_reply('david: hello', bot_response)
+
+ @patch('zulip_bots.bots.flock.flock.get_recipient_id')
+ def test_message_send_success(self, get_recipient_id: str) -> None:
+ bot_response = "Message sent."
+ get_recipient_id.return_value = "u:userid"
+ with self.mock_config_info(self.normal_config), \
+ self.mock_http_conversation('test_message_send_success'):
+ self.verify_reply('Rishabh: hi there', bot_response)
+
+ @patch('zulip_bots.bots.flock.flock.get_recipient_id')
+ def test_message_send_failed(self, get_recipient_id: str) -> None:
+ bot_response = "Message sending failed :slightly_frowning_face:. Please try again."
+ get_recipient_id.return_value = "u:invalid"
+ with self.mock_config_info(self.normal_config), \
+ self.mock_http_conversation('test_message_send_failed'):
+ self.verify_reply('Rishabh: hi there', bot_response)

bots/flock: Add flock bot.