bots/flock: Add flock bot.
This commit is contained in:
		
							parent
							
								
									bb4c9c9bdb
								
							
						
					
					
						commit
						b6afa030c5
					
				
					 9 changed files with 241 additions and 0 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								zulip_bots/zulip_bots/bots/flock/assests/1.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								zulip_bots/zulip_bots/bots/flock/assests/1.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 40 KiB  | 
							
								
								
									
										27
									
								
								zulip_bots/zulip_bots/bots/flock/doc.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								zulip_bots/zulip_bots/bots/flock/doc.md
									
										
									
									
									
										Normal 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`.
 | 
			
		||||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								zulip_bots/zulip_bots/bots/flock/flock.conf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								zulip_bots/zulip_bots/bots/flock/flock.conf
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
[flock]
 | 
			
		||||
token=12345
 | 
			
		||||
							
								
								
									
										98
									
								
								zulip_bots/zulip_bots/bots/flock/flock.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								zulip_bots/zulip_bots/bots/flock/flock.py
									
										
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										1
									
								
								zulip_bots/zulip_bots/bots/flock/requirements.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								zulip_bots/zulip_bots/bots/flock/requirements.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
requests
 | 
			
		||||
							
								
								
									
										62
									
								
								zulip_bots/zulip_bots/bots/flock/test_flock.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								zulip_bots/zulip_bots/bots/flock/test_flock.py
									
										
									
									
									
										Normal 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)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue