From 2a74ad11c5183af2cf323e254ed7a902c5ff66a3 Mon Sep 17 00:00:00 2001 From: derAnfaenger Date: Mon, 13 Nov 2017 11:49:23 +0100 Subject: [PATCH] zulip_bots: Make StateHandler optional. This has the convenient side-effect of making the bot_handler.storage attribute read-only. --- .../bots/incrementor/incrementor.py | 5 +++ .../zulip_bots/bots/tictactoe/tictactoe.py | 5 +++ .../zulip_bots/bots/virtual_fs/virtual_fs.py | 6 +++ zulip_bots/zulip_bots/lib.py | 38 +++++++++++++------ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/zulip_bots/zulip_bots/bots/incrementor/incrementor.py b/zulip_bots/zulip_bots/bots/incrementor/incrementor.py index 60e36c2..461379d 100644 --- a/zulip_bots/zulip_bots/bots/incrementor/incrementor.py +++ b/zulip_bots/zulip_bots/bots/incrementor/incrementor.py @@ -2,6 +2,11 @@ class IncrementorHandler(object): + META = { + 'name': 'Incrementor', + 'description': 'Example bot to test the update_message() function.', + 'uses_storage': True, + } def usage(self): return ''' diff --git a/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py b/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py index d02f988..7c58f4d 100644 --- a/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py +++ b/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py @@ -267,6 +267,11 @@ class ticTacToeHandler(object): tic-tac-toe bot! Make sure your message starts with "@mention-bot". ''' + META = { + 'name': 'TicTacToe', + 'description': 'Lets you play Tic-tac-toe against a computer.', + 'uses_storage': True, + } def usage(self): return ''' diff --git a/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py b/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py index eba85d7..b6be581 100644 --- a/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py +++ b/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py @@ -4,6 +4,12 @@ import re import os class VirtualFsHandler(object): + META = { + 'name': 'VirtualFs', + 'description': 'Provides a simple, permanent file system to store and retrieve strings.', + 'uses_storage': True, + } + def usage(self): return get_help() diff --git a/zulip_bots/zulip_bots/lib.py b/zulip_bots/zulip_bots/lib.py index b24d7cb..8c9104f 100644 --- a/zulip_bots/zulip_bots/lib.py +++ b/zulip_bots/zulip_bots/lib.py @@ -92,14 +92,15 @@ class StateHandler(object): raise StateHandlerError("Error updating state: {}".format(str(response))) class ExternalBotHandler(object): - def __init__(self, client, root_dir): - # type: (Client, str) -> None + def __init__(self, client, root_dir, bot_details={}): + # type: (Client, str, Dict[str, Any]) -> None # Only expose a subset of our Client's functionality user_profile = client.get_profile() self._rate_limit = RateLimit(20, 5) self._client = client self._root_dir = root_dir - self.storage = StateHandler(client) + self.bot_details = bot_details + self._storage = StateHandler(client) if self.bot_details.get('uses_storage', False) else None try: self.user_id = user_profile['user_id'] self.full_name = user_profile['full_name'] @@ -109,6 +110,20 @@ class ExternalBotHandler(object): ' up the zuliprc file correctly.') sys.exit(1) + @property + def storage(self): + # type: () -> StateHandler + if not self._storage: + raise AttributeError("""Bot tried to access storage, but has not enabled +storage access. To enable storage access, add + META = { + 'uses_storage': True, + } +to your bot handler class. Check out the incrementor +bot for an example on how to do this. +""") + return self._storage + def send_message(self, message): # type: (Dict[str, Any]) -> Dict[str, Any] if self._rate_limit.is_legal(): @@ -194,21 +209,20 @@ def run_message_handler_for_bot(lib_module, quiet, config_file, bot_name): # inherit from a common prototype specifying the handle_message # function. # - # Make sure you set up your ~/.zuliprc - client = Client(config_file=config_file, client="Zulip{}Bot".format(bot_name.capitalize())) - bot_dir = os.path.dirname(lib_module.__file__) - restricted_client = ExternalBotHandler(client, bot_dir) - - message_handler = lib_module.handler_class() - if hasattr(message_handler, 'initialize'): - message_handler.initialize(bot_handler=restricted_client) - # Set default bot_details, then override from class, if provided bot_details = { 'name': bot_name.capitalize(), 'description': "", } bot_details.update(getattr(lib_module.handler_class, 'META', {})) + # Make sure you set up your ~/.zuliprc + client = Client(config_file=config_file, client="Zulip{}Bot".format(bot_name.capitalize())) + bot_dir = os.path.dirname(lib_module.__file__) + restricted_client = ExternalBotHandler(client, bot_dir, bot_details) + + message_handler = lib_module.handler_class() + if hasattr(message_handler, 'initialize'): + message_handler.initialize(bot_handler=restricted_client) if not quiet: print("Running {} Bot:".format(bot_details['name']))