zulip_bots: Make StateHandler optional.
This has the convenient side-effect of making the bot_handler.storage attribute read-only.
This commit is contained in:
		
							parent
							
								
									f41030b515
								
							
						
					
					
						commit
						2a74ad11c5
					
				
					 4 changed files with 42 additions and 12 deletions
				
			
		| 
						 | 
					@ -2,6 +2,11 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IncrementorHandler(object):
 | 
					class IncrementorHandler(object):
 | 
				
			||||||
 | 
					    META = {
 | 
				
			||||||
 | 
					        'name': 'Incrementor',
 | 
				
			||||||
 | 
					        'description': 'Example bot to test the update_message() function.',
 | 
				
			||||||
 | 
					        'uses_storage': True,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def usage(self):
 | 
					    def usage(self):
 | 
				
			||||||
        return '''
 | 
					        return '''
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -267,6 +267,11 @@ class ticTacToeHandler(object):
 | 
				
			||||||
    tic-tac-toe bot! Make sure your message starts with
 | 
					    tic-tac-toe bot! Make sure your message starts with
 | 
				
			||||||
    "@mention-bot".
 | 
					    "@mention-bot".
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
 | 
					    META = {
 | 
				
			||||||
 | 
					        'name': 'TicTacToe',
 | 
				
			||||||
 | 
					        'description': 'Lets you play Tic-tac-toe against a computer.',
 | 
				
			||||||
 | 
					        'uses_storage': True,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def usage(self):
 | 
					    def usage(self):
 | 
				
			||||||
        return '''
 | 
					        return '''
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,12 @@ import re
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VirtualFsHandler(object):
 | 
					class VirtualFsHandler(object):
 | 
				
			||||||
 | 
					    META = {
 | 
				
			||||||
 | 
					        'name': 'VirtualFs',
 | 
				
			||||||
 | 
					        'description': 'Provides a simple, permanent file system to store and retrieve strings.',
 | 
				
			||||||
 | 
					        'uses_storage': True,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def usage(self):
 | 
					    def usage(self):
 | 
				
			||||||
        return get_help()
 | 
					        return get_help()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,14 +92,15 @@ class StateHandler(object):
 | 
				
			||||||
                raise StateHandlerError("Error updating state: {}".format(str(response)))
 | 
					                raise StateHandlerError("Error updating state: {}".format(str(response)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExternalBotHandler(object):
 | 
					class ExternalBotHandler(object):
 | 
				
			||||||
    def __init__(self, client, root_dir):
 | 
					    def __init__(self, client, root_dir, bot_details={}):
 | 
				
			||||||
        # type: (Client, str) -> None
 | 
					        # type: (Client, str, Dict[str, Any]) -> None
 | 
				
			||||||
        # Only expose a subset of our Client's functionality
 | 
					        # Only expose a subset of our Client's functionality
 | 
				
			||||||
        user_profile = client.get_profile()
 | 
					        user_profile = client.get_profile()
 | 
				
			||||||
        self._rate_limit = RateLimit(20, 5)
 | 
					        self._rate_limit = RateLimit(20, 5)
 | 
				
			||||||
        self._client = client
 | 
					        self._client = client
 | 
				
			||||||
        self._root_dir = root_dir
 | 
					        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:
 | 
					        try:
 | 
				
			||||||
            self.user_id = user_profile['user_id']
 | 
					            self.user_id = user_profile['user_id']
 | 
				
			||||||
            self.full_name = user_profile['full_name']
 | 
					            self.full_name = user_profile['full_name']
 | 
				
			||||||
| 
						 | 
					@ -109,6 +110,20 @@ class ExternalBotHandler(object):
 | 
				
			||||||
                          ' up the zuliprc file correctly.')
 | 
					                          ' up the zuliprc file correctly.')
 | 
				
			||||||
            sys.exit(1)
 | 
					            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):
 | 
					    def send_message(self, message):
 | 
				
			||||||
        # type: (Dict[str, Any]) -> Dict[str, Any]
 | 
					        # type: (Dict[str, Any]) -> Dict[str, Any]
 | 
				
			||||||
        if self._rate_limit.is_legal():
 | 
					        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
 | 
					    # inherit from a common prototype specifying the handle_message
 | 
				
			||||||
    # function.
 | 
					    # 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
 | 
					    # Set default bot_details, then override from class, if provided
 | 
				
			||||||
    bot_details = {
 | 
					    bot_details = {
 | 
				
			||||||
        'name': bot_name.capitalize(),
 | 
					        'name': bot_name.capitalize(),
 | 
				
			||||||
        'description': "",
 | 
					        'description': "",
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    bot_details.update(getattr(lib_module.handler_class, 'META', {}))
 | 
					    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:
 | 
					    if not quiet:
 | 
				
			||||||
        print("Running {} Bot:".format(bot_details['name']))
 | 
					        print("Running {} Bot:".format(bot_details['name']))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue