bots/flock: Add flock bot.

This commit is contained in:
Ricky 2018-03-07 20:52:01 +05:30 committed by showell
parent bb4c9c9bdb
commit b6afa030c5
9 changed files with 241 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -0,0 +1,27 @@
# 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`.

View file

@ -0,0 +1,19 @@
{
"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"
}
}

View file

@ -0,0 +1,17 @@
{
"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"
}
}

View file

@ -0,0 +1,15 @@
{
"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"
}
}

View file

@ -0,0 +1,2 @@
[flock]
token=12345

View file

@ -0,0 +1,98 @@
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

View file

@ -0,0 +1 @@
requests

View file

@ -0,0 +1,62 @@
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)