zulip-bots: Set bot_handler type to BotHandler.

- Set `bot_handler` type to `BotHandler`.
- Fix mypy issues in improperly typed variables, params and returns.

Fixes part of #639
This commit is contained in:
LoopThrough-i-j 2021-03-04 01:24:28 +05:30 committed by Anders Kaseorg
parent a994c58439
commit 1fb3d529a9
41 changed files with 156 additions and 119 deletions

View file

@ -1,10 +1,11 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Any, List, Dict from typing import Any, List, Dict
from zulip_bots.lib import BotHandler
import requests import requests
class BaremetricsHandler: class BaremetricsHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('baremetrics') self.config_info = bot_handler.get_config_info('baremetrics')
self.api_key = self.config_info['api_key'] self.api_key = self.config_info['api_key']
@ -27,7 +28,7 @@ class BaremetricsHandler:
self.check_api_key(bot_handler) self.check_api_key(bot_handler)
def check_api_key(self, bot_handler: Any) -> None: def check_api_key(self, bot_handler: BotHandler) -> None:
url = "https://api.baremetrics.com/v1/account" url = "https://api.baremetrics.com/v1/account"
test_query_response = requests.get(url, headers=self.auth_header) test_query_response = requests.get(url, headers=self.auth_header)
test_query_data = test_query_response.json() test_query_data = test_query_response.json()
@ -46,7 +47,7 @@ class BaremetricsHandler:
Version 1.0 Version 1.0
''' '''
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
content = message['content'].strip().split() content = message['content'].strip().split()
if content == []: if content == []:

View file

@ -1,6 +1,7 @@
import requests import requests
import logging import logging
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
from requests.exceptions import ConnectionError from requests.exceptions import ConnectionError
help_message = ''' help_message = '''
@ -79,7 +80,7 @@ class BeeminderHandler:
towards their beeminder goals via zulip towards their beeminder goals via zulip
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('beeminder') self.config_info = bot_handler.get_config_info('beeminder')
# Check for valid auth_token # Check for valid auth_token
auth_token = self.config_info['auth_token'] auth_token = self.config_info['auth_token']
@ -93,7 +94,7 @@ class BeeminderHandler:
def usage(self) -> str: def usage(self) -> str:
return "This plugin allows users to add datapoints towards their Beeminder goals" return "This plugin allows users to add datapoints towards their Beeminder goals"
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
response = get_beeminder_response(message['content'], self.config_info) response = get_beeminder_response(message['content'], self.config_info)
bot_handler.send_reply(message, response) bot_handler.send_reply(message, response)

View file

@ -3,6 +3,7 @@ import chess.uci
import re import re
import copy import copy
from typing import Any, Optional, Dict from typing import Any, Optional, Dict
from zulip_bots.lib import BotHandler
START_REGEX = re.compile('start with other user$') START_REGEX = re.compile('start with other user$')
START_COMPUTER_REGEX = re.compile( START_COMPUTER_REGEX = re.compile(
@ -22,7 +23,7 @@ class ChessHandler:
'Stockfish program on this computer.' 'Stockfish program on this computer.'
) )
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('chess') self.config_info = bot_handler.get_config_info('chess')
try: try:
@ -38,7 +39,7 @@ class ChessHandler:
def handle_message( def handle_message(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any bot_handler: BotHandler
) -> None: ) -> None:
content = message['content'] content = message['content']
@ -93,7 +94,7 @@ class ChessHandler:
last_fen last_fen
) )
def start(self, message: Dict[str, str], bot_handler: Any) -> None: def start(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
"""Starts a game with another user, with the current user as white. """Starts a game with another user, with the current user as white.
Replies to the bot handler. Replies to the bot handler.
@ -115,7 +116,7 @@ class ChessHandler:
def start_computer( def start_computer(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
is_white_user: bool is_white_user: bool
) -> None: ) -> None:
"""Starts a game with the computer. Replies to the bot handler. """Starts a game with the computer. Replies to the bot handler.
@ -151,7 +152,7 @@ class ChessHandler:
def validate_board( def validate_board(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
fen: str fen: str
) -> Optional[chess.Board]: ) -> Optional[chess.Board]:
"""Validates a board based on its FEN string. Replies to the bot """Validates a board based on its FEN string. Replies to the bot
@ -179,7 +180,7 @@ class ChessHandler:
def validate_move( def validate_move(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
last_board: chess.Board, last_board: chess.Board,
move_san: str, move_san: str,
is_computer: object is_computer: object
@ -223,7 +224,7 @@ class ChessHandler:
def check_game_over( def check_game_over(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
new_board: chess.Board new_board: chess.Board
) -> bool: ) -> bool:
"""Checks if a game is over due to """Checks if a game is over due to
@ -280,7 +281,7 @@ class ChessHandler:
def move( def move(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
last_fen: str, last_fen: str,
move_san: str move_san: str
) -> None: ) -> None:
@ -325,7 +326,7 @@ class ChessHandler:
def move_computer( def move_computer(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
last_fen: str, last_fen: str,
move_san: str move_san: str
) -> None: ) -> None:
@ -396,7 +397,7 @@ class ChessHandler:
def move_computer_first( def move_computer_first(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
last_fen: str last_fen: str
) -> None: ) -> None:
"""Preforms a move for the computer without having the user go first in """Preforms a move for the computer without having the user go first in
@ -447,7 +448,7 @@ class ChessHandler:
def resign( def resign(
self, self,
message: Dict[str, str], message: Dict[str, str],
bot_handler: Any, bot_handler: BotHandler,
last_fen: str last_fen: str
) -> None: ) -> None:
"""Resigns the game for the current player. """Resigns the game for the current player.

View file

@ -6,6 +6,7 @@ from math import log10, floor
from zulip_bots.bots.converter import utils from zulip_bots.bots.converter import utils
from typing import Any, Dict, List from typing import Any, Dict, List
from zulip_bots.lib import BotHandler
def is_float(value: Any) -> bool: def is_float(value: Any) -> bool:
try: try:
@ -44,11 +45,11 @@ class ConverterHandler:
all supported units. all supported units.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
bot_response = get_bot_converter_response(message, bot_handler) bot_response = get_bot_converter_response(message, bot_handler)
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
def get_bot_converter_response(message: Dict[str, str], bot_handler: Any) -> str: def get_bot_converter_response(message: Dict[str, str], bot_handler: BotHandler) -> str:
content = message['content'] content = message['content']
words = content.lower().split() words = content.lower().split()

View file

@ -4,7 +4,8 @@ import requests
import html2text import html2text
import string import string
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
class DefineHandler: class DefineHandler:
''' '''
@ -24,7 +25,7 @@ class DefineHandler:
messages with @mention-bot. messages with @mention-bot.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
original_content = message['content'].strip() original_content = message['content'].strip()
bot_response = self.get_bot_define_response(original_content) bot_response = self.get_bot_define_response(original_content)

View file

@ -4,7 +4,8 @@ import json
import apiai import apiai
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
help_message = '''DialogFlow bot help_message = '''DialogFlow bot
This bot will interact with dialogflow bots. This bot will interact with dialogflow bots.
@ -40,7 +41,7 @@ class DialogFlowHandler:
DialogFlow bots to zulip DialogFlow bots to zulip
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('dialogflow') self.config_info = bot_handler.get_config_info('dialogflow')
def usage(self) -> str: def usage(self) -> str:
@ -49,7 +50,7 @@ class DialogFlowHandler:
DialogFlow bots to zulip DialogFlow bots to zulip
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
result = get_bot_result(message['content'], self.config_info, message['sender_id']) result = get_bot_result(message['content'], self.config_info, message['sender_id'])
bot_handler.send_reply(message, result) bot_handler.send_reply(message, result)

View file

@ -1,5 +1,6 @@
from dropbox import Dropbox from dropbox import Dropbox
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List, Tuple
from zulip_bots.lib import BotHandler
import re import re
URL = "[{name}](https://www.dropbox.com/home{path})" URL = "[{name}](https://www.dropbox.com/home{path})"
@ -10,7 +11,7 @@ class DropboxHandler:
between zulip and your dropbox account. between zulip and your dropbox account.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('dropbox_share') self.config_info = bot_handler.get_config_info('dropbox_share')
self.ACCESS_TOKEN = self.config_info.get('access_token') self.ACCESS_TOKEN = self.config_info.get('access_token')
self.client = Dropbox(self.ACCESS_TOKEN) self.client = Dropbox(self.ACCESS_TOKEN)
@ -18,7 +19,7 @@ class DropboxHandler:
def usage(self) -> str: def usage(self) -> str:
return get_help() return get_help()
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
command = message['content'] command = message['content']
if command == "": if command == "":
command = "help" command = "help"

View file

@ -1,4 +1,5 @@
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
def encrypt(text: str) -> str: def encrypt(text: str) -> str:
# This is where the actual ROT13 is applied # This is where the actual ROT13 is applied
@ -30,7 +31,7 @@ class EncryptHandler:
Feeding encrypted messages into the bot decrypts them. Feeding encrypted messages into the bot decrypts them.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
bot_response = self.get_bot_encrypt_response(message) bot_response = self.get_bot_encrypt_response(message)
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)

View file

@ -1,4 +1,5 @@
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
import os import os
from pathlib import Path from pathlib import Path
@ -11,7 +12,7 @@ class FileUploaderHandler:
'\n- @uploader help : Display help message' '\n- @uploader help : Display help message'
) )
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
HELP_STR = ( HELP_STR = (
'Use this bot with any of the following commands:' 'Use this bot with any of the following commands:'
'\n* `@uploader <local_file_path>` : Upload a file, where `<local_file_path>` is the path to the file' '\n* `@uploader <local_file_path>` : Upload a file, where `<local_file_path>` is the path to the file'

View file

@ -1,6 +1,7 @@
import logging import logging
import requests import requests
from typing import Any, Dict, List, Tuple, Optional from typing import Any, Dict, List, Tuple, Optional
from zulip_bots.lib import BotHandler
from requests.exceptions import ConnectionError from requests.exceptions import ConnectionError
USERS_LIST_URL = 'https://api.flock.co/v1/roster.listContacts' USERS_LIST_URL = 'https://api.flock.co/v1/roster.listContacts'
@ -92,14 +93,14 @@ class FlockHandler:
flock user without having to leave Zulip. flock user without having to leave Zulip.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('flock') self.config_info = bot_handler.get_config_info('flock')
def usage(self) -> str: def usage(self) -> str:
return '''Hello from Flock Bot. You can send messages to any Flock user return '''Hello from Flock Bot. You can send messages to any Flock user
right from Zulip.''' right from Zulip.'''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
response = get_flock_bot_response(message['content'], self.config_info) response = get_flock_bot_response(message['content'], self.config_info)
bot_handler.send_reply(message, response) bot_handler.send_reply(message, response)

View file

@ -1,5 +1,6 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Dict, Any from typing import Dict
from zulip_bots.lib import BotHandler
class FollowupHandler: class FollowupHandler:
''' '''
@ -23,11 +24,11 @@ class FollowupHandler:
called "followup" that your API user can send to. called "followup" that your API user can send to.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('followup', optional=False) self.config_info = bot_handler.get_config_info('followup', optional=False)
self.stream = self.config_info.get("stream", 'followup') self.stream = self.config_info.get("stream", 'followup')
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
if message['content'] == '': if message['content'] == '':
bot_response = "Please specify the message you want to send to followup stream after @mention-bot" bot_response = "Please specify the message you want to send to followup stream after @mention-bot"
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)

View file

@ -1,6 +1,7 @@
import requests import requests
import re import re
from typing import Any, Dict from typing import Any, Dict
from zulip_bots.lib import BotHandler
class FrontHandler: class FrontHandler:
FRONT_API = "https://api2.frontapp.com/conversations/{}" FRONT_API = "https://api2.frontapp.com/conversations/{}"
@ -20,7 +21,7 @@ class FrontHandler:
Front Bot, `front.conf` must be set up. See `doc.md` for more details. Front Bot, `front.conf` must be set up. See `doc.md` for more details.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
config = bot_handler.get_config_info('front') config = bot_handler.get_config_info('front')
api_key = config.get('api_key') api_key = config.get('api_key')
if not api_key: if not api_key:
@ -28,14 +29,14 @@ class FrontHandler:
self.auth = "Bearer " + api_key self.auth = "Bearer " + api_key
def help(self, bot_handler: Any) -> str: def help(self, bot_handler: BotHandler) -> str:
response = "" response = ""
for command, description in self.COMMANDS: for command, description in self.COMMANDS:
response += "`{}` {}\n".format(command, description) response += "`{}` {}\n".format(command, description)
return response return response
def archive(self, bot_handler: Any) -> str: def archive(self, bot_handler: BotHandler) -> str:
response = requests.patch(self.FRONT_API.format(self.conversation_id), response = requests.patch(self.FRONT_API.format(self.conversation_id),
headers={"Authorization": self.auth}, headers={"Authorization": self.auth},
json={"status": "archived"}) json={"status": "archived"})
@ -45,7 +46,7 @@ class FrontHandler:
return "Conversation was archived." return "Conversation was archived."
def delete(self, bot_handler: Any) -> str: def delete(self, bot_handler: BotHandler) -> str:
response = requests.patch(self.FRONT_API.format(self.conversation_id), response = requests.patch(self.FRONT_API.format(self.conversation_id),
headers={"Authorization": self.auth}, headers={"Authorization": self.auth},
json={"status": "deleted"}) json={"status": "deleted"})
@ -55,7 +56,7 @@ class FrontHandler:
return "Conversation was deleted." return "Conversation was deleted."
def spam(self, bot_handler: Any) -> str: def spam(self, bot_handler: BotHandler) -> str:
response = requests.patch(self.FRONT_API.format(self.conversation_id), response = requests.patch(self.FRONT_API.format(self.conversation_id),
headers={"Authorization": self.auth}, headers={"Authorization": self.auth},
json={"status": "spam"}) json={"status": "spam"})
@ -65,7 +66,7 @@ class FrontHandler:
return "Conversation was marked as spam." return "Conversation was marked as spam."
def restore(self, bot_handler: Any) -> str: def restore(self, bot_handler: BotHandler) -> str:
response = requests.patch(self.FRONT_API.format(self.conversation_id), response = requests.patch(self.FRONT_API.format(self.conversation_id),
headers={"Authorization": self.auth}, headers={"Authorization": self.auth},
json={"status": "open"}) json={"status": "open"})
@ -75,7 +76,7 @@ class FrontHandler:
return "Conversation was restored." return "Conversation was restored."
def comment(self, bot_handler: Any, **kwargs: Any) -> str: def comment(self, bot_handler: BotHandler, **kwargs: Any) -> str:
response = requests.post(self.FRONT_API.format(self.conversation_id) + "/comments", response = requests.post(self.FRONT_API.format(self.conversation_id) + "/comments",
headers={"Authorization": self.auth}, json=kwargs) headers={"Authorization": self.auth}, json=kwargs)
@ -84,7 +85,7 @@ class FrontHandler:
return "Comment was sent." return "Comment was sent."
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
command = message['content'] command = message['content']
result = re.search(self.CNV_ID_REGEXP, message['subject']) result = re.search(self.CNV_ID_REGEXP, message['subject'])

View file

@ -1,4 +1,5 @@
from typing import Dict, Any, Union from typing import Dict, Union
from zulip_bots.lib import BotHandler
import requests import requests
import logging import logging
from requests.exceptions import HTTPError, ConnectionError from requests.exceptions import HTTPError, ConnectionError
@ -40,10 +41,10 @@ class GiphyHandler:
'Follow the instructions in doc.md for setting an API key.') 'Follow the instructions in doc.md for setting an API key.')
raise ConfigValidationError(error_message) raise ConfigValidationError(error_message)
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('giphy') self.config_info = bot_handler.get_config_info('giphy')
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
bot_response = get_bot_giphy_response( bot_response = get_bot_giphy_response(
message, message,
bot_handler, bot_handler,
@ -81,7 +82,7 @@ def get_url_gif_giphy(keyword: str, api_key: str) -> Union[int, str]:
return gif_url return gif_url
def get_bot_giphy_response(message: Dict[str, str], bot_handler: Any, config_info: Dict[str, str]) -> str: def get_bot_giphy_response(message: Dict[str, str], bot_handler: BotHandler, config_info: Dict[str, str]) -> str:
# Each exception has a specific reply should "gif_url" return a number. # Each exception has a specific reply should "gif_url" return a number.
# The bot will post the appropriate message for the error. # The bot will post the appropriate message for the error.
keyword = message['content'] keyword = message['content']

View file

@ -4,6 +4,7 @@ import logging
import requests import requests
from typing import Dict, Any, Tuple, Union from typing import Dict, Any, Tuple, Union
from zulip_bots.lib import BotHandler
class GithubHandler: class GithubHandler:
''' '''
@ -14,7 +15,7 @@ class GithubHandler:
GITHUB_ISSUE_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/issues/{id}' GITHUB_ISSUE_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/issues/{id}'
HANDLE_MESSAGE_REGEX = re.compile(r"(?:([\w-]+)\/)?([\w-]+)?#(\d+)") HANDLE_MESSAGE_REGEX = re.compile(r"(?:([\w-]+)\/)?([\w-]+)?#(\d+)")
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('github_detail', optional=True) self.config_info = bot_handler.get_config_info('github_detail', optional=True)
self.owner = self.config_info.get("owner", False) self.owner = self.config_info.get("owner", False)
self.repo = self.config_info.get("repo", False) self.repo = self.config_info.get("repo", False)
@ -64,7 +65,7 @@ class GithubHandler:
repo = self.repo repo = self.repo
return (owner, repo) return (owner, repo)
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
# Send help message # Send help message
if message['content'] == 'help': if message['content'] == 'help':
bot_handler.send_reply(message, self.usage()) bot_handler.send_reply(message, self.usage())

View file

@ -5,7 +5,8 @@ import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from typing import Any, Dict, List from typing import Dict, List
from zulip_bots.lib import BotHandler
def google_search(keywords: str) -> List[Dict[str, str]]: def google_search(keywords: str) -> List[Dict[str, str]]:
query = {'q': keywords} query = {'q': keywords}
@ -81,7 +82,7 @@ class GoogleSearchHandler:
@mentioned-bot. @mentioned-bot.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
original_content = message['content'] original_content = message['content']
result = get_google_result(original_content) result = get_google_result(original_content)
bot_handler.send_reply(message, result) bot_handler.send_reply(message, result)

View file

@ -1,6 +1,7 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Any, Dict from typing import Any, Dict
from zulip_bots.lib import BotHandler
class HelloWorldHandler: class HelloWorldHandler:
def usage(self) -> str: def usage(self) -> str:
@ -12,7 +13,7 @@ class HelloWorldHandler:
sophisticated, bots. sophisticated, bots.
''' '''
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
content = 'beep boop' # type: str content = 'beep boop' # type: str
bot_handler.send_reply(message, content) bot_handler.send_reply(message, content)

View file

@ -1,5 +1,6 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
class HelpHandler: class HelpHandler:
def usage(self) -> str: def usage(self) -> str:
@ -12,7 +13,7 @@ class HelpHandler:
your Zulip instance. your Zulip instance.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
help_content = "Info on Zulip can be found here:\nhttps://github.com/zulip/zulip" help_content = "Info on Zulip can be found here:\nhttps://github.com/zulip/zulip"
bot_handler.send_reply(message, help_content) bot_handler.send_reply(message, help_content)

View file

@ -3,6 +3,7 @@ import logging
import re import re
from typing import Any, Dict, Optional, List from typing import Any, Dict, Optional, List
from zulip_bots.lib import BotHandler
API_BASE_URL = "https://beta.idonethis.com/api/v2" API_BASE_URL = "https://beta.idonethis.com/api/v2"
@ -128,7 +129,7 @@ More information in my help""")
return "Great work :thumbs_up:. New entry `{}` created!".format(data['body_formatted']) return "Great work :thumbs_up:. New entry `{}` created!".format(data['body_formatted'])
class IDoneThisHandler: class IDoneThisHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
global api_key, default_team global api_key, default_team
self.config_info = bot_handler.get_config_info('idonethis') self.config_info = bot_handler.get_config_info('idonethis')
if 'api_key' in self.config_info: if 'api_key' in self.config_info:
@ -179,7 +180,7 @@ Below are some of the commands you can use, and what they do.
new entry `something` for the product team. new entry `something` for the product team.
''' + default_team_message ''' + default_team_message
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
bot_handler.send_reply(message, self.get_response(message)) bot_handler.send_reply(message, self.get_response(message))
def get_response(self, message: Dict[str, Any]) -> str: def get_response(self, message: Dict[str, Any]) -> str:

View file

@ -1,6 +1,7 @@
import json import json
import re import re
from typing import Any, Dict, Tuple from typing import Any, Dict, Tuple
from zulip_bots.lib import BotHandler
QUESTION = 'How should we handle this?' QUESTION = 'How should we handle this?'
@ -24,7 +25,7 @@ class IncidentHandler:
glue code here should be pretty portable. glue code here should be pretty portable.
''' '''
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
query = message['content'] query = message['content']
if query.startswith('new '): if query.startswith('new '):
start_new_incident(query, message, bot_handler) start_new_incident(query, message, bot_handler)
@ -41,7 +42,7 @@ class IncidentHandler:
bot_response = 'type "new <description>" for a new incident' bot_response = 'type "new <description>" for a new incident'
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
def start_new_incident(query: str, message: Dict[str, Any], bot_handler: Any) -> None: def start_new_incident(query: str, message: Dict[str, Any], bot_handler: BotHandler) -> None:
# Here is where we would enter the incident in some sort of backend # Here is where we would enter the incident in some sort of backend
# system. We just simulate everything by having an incident id that # system. We just simulate everything by having an incident id that
# we generate here. # we generate here.

View file

@ -1,6 +1,7 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Dict, Any from typing import Dict
from zulip_bots.lib import BotHandler
class IncrementorHandler: class IncrementorHandler:
META = { META = {
@ -16,13 +17,13 @@ class IncrementorHandler:
is @-mentioned, this number will be incremented in the same message. is @-mentioned, this number will be incremented in the same message.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
storage = bot_handler.storage storage = bot_handler.storage
if not storage.contains('number') or not storage.contains('message_id'): if not storage.contains('number') or not storage.contains('message_id'):
storage.put('number', 0) storage.put('number', 0)
storage.put('message_id', None) storage.put('message_id', None)
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
storage = bot_handler.storage storage = bot_handler.storage
num = storage.get('number') num = storage.get('number')
@ -33,7 +34,8 @@ class IncrementorHandler:
storage.put('number', num) storage.put('number', num)
if storage.get('message_id') is None: if storage.get('message_id') is None:
result = bot_handler.send_reply(message, str(num)) result = bot_handler.send_reply(message, str(num))
storage.put('message_id', result['id']) if result is not None:
storage.put('message_id', result['id'])
else: else:
bot_handler.update_message(dict( bot_handler.update_message(dict(
message_id=storage.get('message_id'), message_id=storage.get('message_id'),

View file

@ -2,6 +2,7 @@ import base64
import re import re
import requests import requests
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from zulip_bots.lib import BotHandler
GET_REGEX = re.compile('get "(?P<issue_key>.+)"$') GET_REGEX = re.compile('get "(?P<issue_key>.+)"$')
CREATE_REGEX = re.compile( CREATE_REGEX = re.compile(
@ -149,7 +150,7 @@ class JiraHandler:
Jira Bot, `jira.conf` must be set up. See `doc.md` for more details. Jira Bot, `jira.conf` must be set up. See `doc.md` for more details.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
config = bot_handler.get_config_info('jira') config = bot_handler.get_config_info('jira')
username = config.get('username') username = config.get('username')
@ -198,7 +199,7 @@ class JiraHandler:
return response return response
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
content = message.get('content') content = message.get('content')
response = '' response = ''

View file

@ -2,6 +2,7 @@ import re
import requests import requests
from typing import Any, Dict from typing import Any, Dict
from zulip_bots.lib import BotHandler
class LinkShortenerHandler: class LinkShortenerHandler:
'''A Zulip bot that will shorten URLs ("links") in a conversation using the '''A Zulip bot that will shorten URLs ("links") in a conversation using the
@ -14,11 +15,11 @@ class LinkShortenerHandler:
'any URLs you want to shorten in the body of the message. \n\n' 'any URLs you want to shorten in the body of the message. \n\n'
'`key` must be set in `link_shortener.conf`.') '`key` must be set in `link_shortener.conf`.')
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('link_shortener') self.config_info = bot_handler.get_config_info('link_shortener')
self.check_api_key(bot_handler) self.check_api_key(bot_handler)
def check_api_key(self, bot_handler: Any) -> None: def check_api_key(self, bot_handler: BotHandler) -> None:
test_request_data = self.call_link_shorten_service('www.youtube.com/watch') # type: Any test_request_data = self.call_link_shorten_service('www.youtube.com/watch') # type: Any
try: try:
if self.is_invalid_token_error(test_request_data): if self.is_invalid_token_error(test_request_data):
@ -29,7 +30,7 @@ class LinkShortenerHandler:
def is_invalid_token_error(self, response_json: Any) -> bool: def is_invalid_token_error(self, response_json: Any) -> bool:
return response_json['status_code'] == 500 and response_json['status_txt'] == 'INVALID_ARG_ACCESS_TOKEN' return response_json['status_code'] == 500 and response_json['status_txt'] == 'INVALID_ARG_ACCESS_TOKEN'
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
REGEX_STR = ( REGEX_STR = (
r'(' r'('
r'(?:http|https):\/\/' # This allows for the HTTP or HTTPS r'(?:http|https):\/\/' # This allows for the HTTP or HTTPS

View file

@ -2,16 +2,17 @@
import requests import requests
from typing import Any, List, Dict from typing import Any, List, Dict
from zulip_bots.lib import BotHandler
class MentionHandler: class MentionHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('mention') self.config_info = bot_handler.get_config_info('mention')
self.access_token = self.config_info['access_token'] self.access_token = self.config_info['access_token']
self.account_id = '' self.account_id = ''
self.check_access_token(bot_handler) self.check_access_token(bot_handler)
def check_access_token(self, bot_handler: Any) -> None: def check_access_token(self, bot_handler: BotHandler) -> None:
test_query_header = { test_query_header = {
'Authorization': 'Bearer ' + self.access_token, 'Authorization': 'Bearer ' + self.access_token,
'Accept-Version': '1.15', 'Accept-Version': '1.15',
@ -33,7 +34,7 @@ class MentionHandler:
Version 1.00 Version 1.00
''' '''
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
message['content'] = message['content'].strip() message['content'] = message['content'].strip()
if message['content'].lower() == 'help': if message['content'].lower() == 'help':

View file

@ -1,6 +1,6 @@
import logging import logging
from typing import Dict, Any from typing import Dict
from zulip_bots.lib import BotHandler
from zulip_bots.bots.monkeytestit.lib import parse from zulip_bots.bots.monkeytestit.lib import parse
from zulip_bots.lib import NoBotConfigException from zulip_bots.lib import NoBotConfigException
@ -15,7 +15,7 @@ class MonkeyTestitBot:
"that, to perform a check, mention me and add the website.\n\n" \ "that, to perform a check, mention me and add the website.\n\n" \
"Check doc.md for more options and setup instructions." "Check doc.md for more options and setup instructions."
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
try: try:
self.config = bot_handler.get_config_info('monkeytestit') self.config = bot_handler.get_config_info('monkeytestit')
except NoBotConfigException: except NoBotConfigException:
@ -41,7 +41,7 @@ class MonkeyTestitBot:
" your api_key value and try again.") " your api_key value and try again.")
def handle_message(self, message: Dict[str, str], def handle_message(self, message: Dict[str, str],
bot_handler: Any) -> None: bot_handler: BotHandler) -> None:
content = message['content'] content = message['content']
response = parse.execute(content, self.api_key) response = parse.execute(content, self.api_key)

View file

@ -2,6 +2,7 @@
import simple_salesforce import simple_salesforce
from typing import Dict, Any, List from typing import Dict, Any, List
from zulip_bots.lib import BotHandler
import re import re
import logging import logging
from zulip_bots.bots.salesforce.utils import commands, object_types, link_query, default_query from zulip_bots.bots.salesforce.utils import commands, object_types, link_query, default_query
@ -151,7 +152,7 @@ class SalesforceHandler:
return 'Usage: {} [arguments]'.format(command['template']) return 'Usage: {} [arguments]'.format(command['template'])
return get_help_text() return get_help_text()
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('salesforce') self.config_info = bot_handler.get_config_info('salesforce')
try: try:
self.sf = simple_salesforce.Salesforce( self.sf = simple_salesforce.Salesforce(
@ -162,12 +163,12 @@ class SalesforceHandler:
except simple_salesforce.exceptions.SalesforceAuthenticationFailed as err: except simple_salesforce.exceptions.SalesforceAuthenticationFailed as err:
bot_handler.quit('Failed to log in to Salesforce. {} {}'.format(err.code, err.message)) bot_handler.quit('Failed to log in to Salesforce. {} {}'.format(err.code, err.message))
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
try: try:
bot_response = self.get_salesforce_response(message['content']) bot_response = self.get_salesforce_response(message['content'])
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
except Exception as e: except Exception as e:
bot_handler.send_reply('Error. {}.'.format(e), bot_response) bot_handler.send_reply(message, 'Error. {}.'.format(e), bot_response)
handler_class = SalesforceHandler handler_class = SalesforceHandler

View file

@ -1,7 +1,8 @@
import requests import requests
import logging import logging
from typing import Optional, Any, Dict from typing import Optional, Dict
from zulip_bots.lib import BotHandler
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
@ -28,11 +29,11 @@ class StackOverflowHandler:
should preface query with "@mention-bot". should preface query with "@mention-bot".
@mention-bot <search query>''' @mention-bot <search query>'''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
bot_response = self.get_bot_stackoverflow_response(message, bot_handler) bot_response = self.get_bot_stackoverflow_response(message, bot_handler)
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
def get_bot_stackoverflow_response(self, message: Dict[str, str], bot_handler: Any) -> Optional[str]: def get_bot_stackoverflow_response(self, message: Dict[str, str], bot_handler: BotHandler) -> Optional[str]:
'''This function returns the URLs of the requested topic.''' '''This function returns the URLs of the requested topic.'''
help_text = 'Please enter your query after @mention-bot to search StackOverflow' help_text = 'Please enter your query after @mention-bot to search StackOverflow'

View file

@ -1,5 +1,6 @@
import requests import requests
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
class SusiHandler: class SusiHandler:
''' '''
@ -34,7 +35,7 @@ class SusiHandler:
``` ```
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
msg = message['content'] msg = message['content']
if msg == 'help' or msg == '': if msg == 'help' or msg == '':
bot_handler.send_reply(message, self.usage()) bot_handler.send_reply(message, self.usage())

View file

@ -53,7 +53,7 @@ class TestTrelloBot(BotTestCase, DefaultTests):
with self.mock_http_conversation('get_board_descs'): with self.mock_http_conversation('get_board_descs'):
bot_instance = TrelloHandler() bot_instance = TrelloHandler()
bot_instance.initialize(StubBotHandler) bot_instance.initialize(StubBotHandler())
self.assertEqual(bot_instance.get_board_descs(['TEST']), '1.[TEST](TEST) (`TEST`)') self.assertEqual(bot_instance.get_board_descs(['TEST']), '1.[TEST](TEST) (`TEST`)')

View file

@ -1,5 +1,5 @@
from typing import Any, List, Dict from typing import Any, List, Dict
from zulip_bots.lib import BotHandler
import requests import requests
supported_commands = [ supported_commands = [
@ -15,7 +15,7 @@ INVALID_ARGUMENTS_ERROR_MESSAGE = 'Invalid Arguments.'
RESPONSE_ERROR_MESSAGE = 'Invalid Response. Please check configuration and parameters.' RESPONSE_ERROR_MESSAGE = 'Invalid Response. Please check configuration and parameters.'
class TrelloHandler: class TrelloHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('trello') self.config_info = bot_handler.get_config_info('trello')
self.api_key = self.config_info['api_key'] self.api_key = self.config_info['api_key']
self.access_token = self.config_info['access_token'] self.access_token = self.config_info['access_token']
@ -28,7 +28,7 @@ class TrelloHandler:
self.check_access_token(bot_handler) self.check_access_token(bot_handler)
def check_access_token(self, bot_handler: Any) -> None: def check_access_token(self, bot_handler: BotHandler) -> None:
test_query_response = requests.get('https://api.trello.com/1/members/{}/'.format(self.user_name), test_query_response = requests.get('https://api.trello.com/1/members/{}/'.format(self.user_name),
params=self.auth_params) params=self.auth_params)
@ -42,7 +42,7 @@ class TrelloHandler:
Use `list-commands` to get information about the supported commands. Use `list-commands` to get information about the supported commands.
''' '''
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
content = message['content'].strip().split() content = message['content'].strip().split()
if content == []: if content == []:

View file

@ -4,6 +4,7 @@ import requests
import random import random
import re import re
from typing import Optional, Any, Dict, Tuple from typing import Optional, Any, Dict, Tuple
from zulip_bots.lib import BotHandler
class NotAvailableException(Exception): class NotAvailableException(Exception):
pass pass
@ -17,7 +18,7 @@ class TriviaQuizHandler:
This plugin will give users a trivia question from This plugin will give users a trivia question from
the open trivia database at opentdb.com.''' the open trivia database at opentdb.com.'''
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
query = message['content'] query = message['content']
if query == 'new': if query == 'new':
try: try:
@ -51,10 +52,10 @@ class TriviaQuizHandler:
bot_response = 'type "new" for a new question' bot_response = 'type "new" for a new question'
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
def get_quiz_from_id(quiz_id: str, bot_handler: Any) -> str: def get_quiz_from_id(quiz_id: str, bot_handler: BotHandler) -> str:
return bot_handler.storage.get(quiz_id) return bot_handler.storage.get(quiz_id)
def start_new_quiz(message: Dict[str, Any], bot_handler: Any) -> None: def start_new_quiz(message: Dict[str, Any], bot_handler: BotHandler) -> None:
quiz = get_trivia_quiz() quiz = get_trivia_quiz()
quiz_id = generate_quiz_id(bot_handler.storage) quiz_id = generate_quiz_id(bot_handler.storage)
bot_response = format_quiz_for_markdown(quiz_id, quiz) bot_response = format_quiz_for_markdown(quiz_id, quiz)
@ -197,7 +198,7 @@ Q: {question}
) )
return content return content
def update_quiz(quiz: Dict[str, Any], quiz_id: str, bot_handler: Any) -> None: def update_quiz(quiz: Dict[str, Any], quiz_id: str, bot_handler: BotHandler) -> None:
bot_handler.storage.put(quiz_id, json.dumps(quiz)) bot_handler.storage.put(quiz_id, json.dumps(quiz))
def build_response(is_correct: bool, num_answers: int) -> str: def build_response(is_correct: bool, num_answers: int) -> str:
@ -211,7 +212,7 @@ def build_response(is_correct: bool, num_answers: int) -> str:
return response return response
def handle_answer(quiz: Dict[str, Any], option: str, quiz_id: str, def handle_answer(quiz: Dict[str, Any], option: str, quiz_id: str,
bot_handler: Any, sender_name: str) -> Tuple[bool, str]: bot_handler: BotHandler, sender_name: str) -> Tuple[bool, str]:
answer = quiz['answers'][quiz['correct_letter']] answer = quiz['answers'][quiz['correct_letter']]
is_new_answer = (option not in quiz['answered_options']) is_new_answer = (option not in quiz['answered_options'])
if is_new_answer: if is_new_answer:

View file

@ -1,6 +1,6 @@
import tweepy import tweepy
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
class TwitpostBot: class TwitpostBot:
@ -16,7 +16,7 @@ class TwitpostBot:
"Example:\n" \ "Example:\n" \
" * @twitpost tweet hey batman\n" " * @twitpost tweet hey batman\n"
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('twitter') self.config_info = bot_handler.get_config_info('twitter')
auth = tweepy.OAuthHandler(self.config_info['consumer_key'], auth = tweepy.OAuthHandler(self.config_info['consumer_key'],
self.config_info['consumer_secret']) self.config_info['consumer_secret'])
@ -24,7 +24,7 @@ class TwitpostBot:
self.config_info['access_token_secret']) self.config_info['access_token_secret'])
self.api = tweepy.API(auth, parser=tweepy.parsers.JSONParser()) self.api = tweepy.API(auth, parser=tweepy.parsers.JSONParser())
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
content = message["content"] content = message["content"]
if content.strip() == '': if content.strip() == '':

View file

@ -4,6 +4,7 @@ import re
import os import os
from typing import Any, Dict, List, Set, Tuple, Union from typing import Any, Dict, List, Set, Tuple, Union
from zulip_bots.lib import BotHandler
class VirtualFsHandler: class VirtualFsHandler:
META = { META = {
@ -14,7 +15,7 @@ class VirtualFsHandler:
def usage(self) -> str: def usage(self) -> str:
return get_help() return get_help()
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
command = message['content'] command = message['content']
if command == "": if command == "":
command = "help" command = "help"

View file

@ -2,16 +2,17 @@
import requests import requests
from typing import Any, Dict from typing import Any, Dict
from zulip_bots.lib import BotHandler
api_url = 'http://api.openweathermap.org/data/2.5/weather' api_url = 'http://api.openweathermap.org/data/2.5/weather'
class WeatherHandler: class WeatherHandler:
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.api_key = bot_handler.get_config_info('weather')['key'] self.api_key = bot_handler.get_config_info('weather')['key']
self.response_pattern = 'Weather in {}, {}:\n{:.2f} F / {:.2f} C\n{}' self.response_pattern = 'Weather in {}, {}:\n{:.2f} F / {:.2f} C\n{}'
self.check_api_key(bot_handler) self.check_api_key(bot_handler)
def check_api_key(self, bot_handler: Any) -> None: def check_api_key(self, bot_handler: BotHandler) -> None:
api_params = dict(q='nyc', APPID=self.api_key) api_params = dict(q='nyc', APPID=self.api_key)
test_response = requests.get(api_url, params=api_params) test_response = requests.get(api_url, params=api_params)
try: try:
@ -26,7 +27,7 @@ class WeatherHandler:
This plugin will give info about weather in a specified city This plugin will give info about weather in a specified city
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
help_content = ''' help_content = '''
This bot returns weather info for specified city. This bot returns weather info for specified city.
You specify city in the following format: You specify city in the following format:

View file

@ -1,6 +1,7 @@
import requests import requests
import logging import logging
from typing import Optional, Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
@ -29,11 +30,11 @@ class WikipediaHandler:
should preface searches with "@mention-bot". should preface searches with "@mention-bot".
@mention-bot <name of article>''' @mention-bot <name of article>'''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
bot_response = self.get_bot_wiki_response(message, bot_handler) bot_response = self.get_bot_wiki_response(message, bot_handler)
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
def get_bot_wiki_response(self, message: Dict[str, str], bot_handler: Any) -> Optional[str]: def get_bot_wiki_response(self, message: Dict[str, str], bot_handler: BotHandler) -> str:
'''This function returns the URLs of the requested topic.''' '''This function returns the URLs of the requested topic.'''
help_text = 'Please enter your search term after {}' help_text = 'Please enter your search term after {}'

View file

@ -1,6 +1,7 @@
# See readme.md for instructions on running this code. # See readme.md for instructions on running this code.
from typing import Dict, Any, Optional, Callable from typing import Dict, Any, Optional, Callable
from zulip_bots.lib import BotHandler
import wit import wit
import importlib.util import importlib.util
@ -11,7 +12,7 @@ class WitaiHandler:
Wit.ai bot, `witai.conf` must be set up. See `doc.md` for more details. Wit.ai bot, `witai.conf` must be set up. See `doc.md` for more details.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
config = bot_handler.get_config_info('witai') config = bot_handler.get_config_info('witai')
token = config.get('token') token = config.get('token')
@ -36,7 +37,7 @@ class WitaiHandler:
self.client = wit.Wit(token) self.client = wit.Wit(token)
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
if message['content'] == '' or message['content'] == 'help': if message['content'] == '' or message['content'] == 'help':
bot_handler.send_reply(message, self.help_message) bot_handler.send_reply(message, self.help_message)
return return

View file

@ -3,7 +3,8 @@ import random
import logging import logging
import requests import requests
from typing import Any, Dict, Optional from typing import Dict, Optional
from zulip_bots.lib import BotHandler
XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json' XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json'
LATEST_XKCD_URL = 'https://xkcd.com/info.0.json' LATEST_XKCD_URL = 'https://xkcd.com/info.0.json'
@ -34,7 +35,7 @@ class XkcdHandler:
`<comic_id>`, e.g `@mention-bot 1234`. `<comic_id>`, e.g `@mention-bot 1234`.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
quoted_name = bot_handler.identity().mention quoted_name = bot_handler.identity().mention
xkcd_bot_response = get_xkcd_bot_response(message, quoted_name) xkcd_bot_response = get_xkcd_bot_response(message, quoted_name)
bot_handler.send_reply(message, xkcd_bot_response) bot_handler.send_reply(message, xkcd_bot_response)

View file

@ -3,7 +3,8 @@ import logging
import ssl import ssl
import requests import requests
from typing import Any, Dict from typing import Dict
from zulip_bots.lib import BotHandler
HELP_MESSAGE = ''' HELP_MESSAGE = '''
This bot allows users to translate a sentence into This bot allows users to translate a sentence into
@ -32,7 +33,7 @@ class YodaSpeakHandler:
This bot will allow users to translate a sentence into 'Yoda speak'. This bot will allow users to translate a sentence into 'Yoda speak'.
It looks for messages starting with '@mention-bot'. It looks for messages starting with '@mention-bot'.
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.api_key = bot_handler.get_config_info('yoda')['api_key'] self.api_key = bot_handler.get_config_info('yoda')['api_key']
def usage(self) -> str: def usage(self) -> str:
@ -49,7 +50,7 @@ class YodaSpeakHandler:
@mention-bot You will learn how to speak like me someday. @mention-bot You will learn how to speak like me someday.
''' '''
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
self.handle_input(message, bot_handler) self.handle_input(message, bot_handler)
def send_to_yoda_api(self, sentence: str) -> str: def send_to_yoda_api(self, sentence: str) -> str:
@ -83,7 +84,7 @@ class YodaSpeakHandler:
sentence = message_content.replace(' ', '+') sentence = message_content.replace(' ', '+')
return sentence return sentence
def handle_input(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_input(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
original_content = message['content'] original_content = message['content']
if self.is_help(original_content) or (original_content == ""): if self.is_help(original_content) or (original_content == ""):
@ -108,7 +109,7 @@ class YodaSpeakHandler:
bot_handler.send_reply(message, reply_message) bot_handler.send_reply(message, reply_message)
def send_message(self, bot_handler: Any, message: str, stream: str, subject: str) -> None: def send_message(self, bot_handler: BotHandler, message: str, stream: str, subject: str) -> None:
# function for sending a message # function for sending a message
bot_handler.send_message(dict( bot_handler.send_message(dict(
type='stream', type='stream',

View file

@ -2,7 +2,8 @@ import requests
import logging import logging
from requests.exceptions import HTTPError, ConnectionError from requests.exceptions import HTTPError, ConnectionError
from typing import Dict, Any, Union, List, Tuple, Optional from typing import Dict, Union, List, Tuple, Optional
from zulip_bots.lib import BotHandler
commands_list = ('list', 'top', 'help') commands_list = ('list', 'top', 'help')
@ -23,7 +24,7 @@ class YoutubeHandler:
" * @mention-bot funny cats\n" \ " * @mention-bot funny cats\n" \
" * @mention-bot list funny dogs" " * @mention-bot list funny dogs"
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.config_info = bot_handler.get_config_info('youtube') self.config_info = bot_handler.get_config_info('youtube')
# Check if API key is valid. If it is not valid, don't run the bot. # Check if API key is valid. If it is not valid, don't run the bot.
try: try:
@ -37,7 +38,7 @@ class YoutubeHandler:
except ConnectionError: except ConnectionError:
logging.warning('Bad connection') logging.warning('Bad connection')
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
if message['content'] == '' or message['content'] == 'help': if message['content'] == '' or message['content'] == 'help':
bot_handler.send_reply(message, self.help_content) bot_handler.send_reply(message, self.help_content)

View file

@ -2,6 +2,7 @@ import json
import re import re
import random import random
import logging import logging
from zulip_bots.lib import BotHandler
from copy import deepcopy from copy import deepcopy
from typing import Any, Dict, Tuple, List from typing import Any, Dict, Tuple, List
@ -174,13 +175,13 @@ class GameAdapter:
@bot-name help @bot-name help
''' '''
def initialize(self, bot_handler: Any) -> None: def initialize(self, bot_handler: BotHandler) -> None:
self.bot_handler = bot_handler self.bot_handler = bot_handler
self.get_user_cache() self.get_user_cache()
self.email = self.bot_handler.email self.email = self.bot_handler.email
self.full_name = self.bot_handler.full_name self.full_name = self.bot_handler.full_name
def handle_message(self, message: Dict[str, Any], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None:
try: try:
self.bot_handler = bot_handler self.bot_handler = bot_handler
content = message['content'].strip() content = message['content'].strip()

View file

@ -335,7 +335,7 @@ def display_config_file_errors(error_msg: str, config_file: str) -> None:
print('\nMore details here:\n\n{}\n'.format(error_msg)) print('\nMore details here:\n\n{}\n'.format(error_msg))
def prepare_message_handler(bot: str, bot_handler: ExternalBotHandler, bot_lib_module: Any) -> Any: def prepare_message_handler(bot: str, bot_handler: BotHandler, bot_lib_module: Any) -> Any:
message_handler = bot_lib_module.handler_class() message_handler = bot_lib_module.handler_class()
if hasattr(message_handler, 'validate_config'): if hasattr(message_handler, 'validate_config'):
config_data = bot_handler.get_config_info(bot) config_data = bot_handler.get_config_info(bot)

View file

@ -1,6 +1,7 @@
import mock import mock
import os import os
from typing import Any, Dict from typing import Any, Dict
from zulip_bots.lib import BotHandler
import unittest import unittest
from .server_test_lib import BotServerTestCase from .server_test_lib import BotServerTestCase
import json import json
@ -14,7 +15,7 @@ from zulip_botserver.input_parameters import parse_args
class BotServerTests(BotServerTestCase): class BotServerTests(BotServerTestCase):
class MockMessageHandler: class MockMessageHandler:
def handle_message(self, message: Dict[str, str], bot_handler: Any) -> None: def handle_message(self, message: Dict[str, str], bot_handler: BotHandler) -> None:
assert message == {'key': "test message"} assert message == {'key': "test message"}
class MockLibModule: class MockLibModule: