starlight_help/src/content/docs/interactive-bots-api.mdx
This page documents functions available to the bot, and the structure of the bot's config file.
With this API, you can:
With this API, you cannot:
usage(self): Retrieve information about the bot.
self: The instance the method is called onFrom zulip_bots/bots/followup/followup.py:
def usage(self):
return '''
This plugin will allow users to flag messages
as being follow-up items. Users should preface
messages with "@followup".
Before running this, make sure to create a channel
called "followup" that your API user can send to.
'''
handle_message(self, message, bot_handler): Handle a Zulip message.
self: The instance the method is called on
message: A dictionary describing a Zulip message
bot_handler: Used to interact with the server, e.g., to send a message
def handle_message(self, message, bot_handler):
original_content = message['content']
original_sender = message['sender_email']
new_content = original_content.replace('@followup',
'from %s:' % (original_sender,))
bot_handler.send_message(dict(
type='stream',
to='followup',
subject=message['sender_email'],
content=new_content,
))
bot_handler.send_message(message): Send a message as the bot user.
Generally, this is less convenient than send_reply, but it offers
additional flexibility about where the message is sent to.
message: A dictionary describing the message to be sent by the botbot_handler.send_message(dict(
type='stream', # can be 'stream' or 'private'
to=channel_name, # either the channel name or user's email
subject=subject, # message subject
content=message, # content of the sent message
))
bot_handler.send_reply(message, response): Reply to a Zulip message,
i.e., the response will be sent to the same place that the original
Zulip message was sent to.
message: A dictionary containing information on the Zulip message
to respond to (provided by handle_message)response: A string with the response message from the botbot_handler.react(message, emoji_name): Add an emoji reaction to a
Zulip message.
message: A dictionary containing information on the Zulip message
that the bot is reacting to (provided by handle_message)emoji_name: A string with the name of the emoji reaction to addbot_handler.update_message(message): Edit the content of a message
previously sent by the bot.
message: A dictionary defining what message to edit and the new contentFrom zulip_bots/bots/incrementor/incrementor.py:
bot_handler.update_message(dict(
message_id=self.message_id, # id of message to be updated
content=str(self.number), # string with which to update message with
))
A common problem when writing an interactive bot is that you want to be able to store a bit of persistent state for the bot (e.g., for an RSVP bot, the RSVPs). For a sufficiently complex bot, you want need your own database, but for simpler bots, we offer a convenient way for bot code to persistently store data.
The interface for doing this is bot_handler.storage.
The data is stored in the Zulip Server's database. Each bot user has an independent storage quota available to it.
You can use bot_handler.storage in one of two ways:
get, put, and
contains call.use_storage
context manager to minimize the number of round-trips to the server. We
recommend writing bots with the context manager such that they
automatically fetch data at the start of handle_message and submit the
state to the server at the end.use_storage(storage: BotStorage, keys: List[str]) : Fetch the data for
the specified keys via the context manager and store them in a
CachedStorage object with a bot_handler.storage.get call for each key,
at the start. This object will not communicate with the server until
manually calling flush or getting some values that were not previously
fetched. After the context manager block is exited, it will automatically
flush any changes made to the CachedStorage object to the server.
storage: A BotStorage object, i.e., bot_handler.storagekeys: A list of keys to fetchwith use_storage(bot_handler.storage, ["foo", "bar"]) as cache:
print(cache.get("foo")) # print the value of "foo"
cache.put("foo", "new value") # update the value of "foo"
# changes are automatically flushed to the server on exiting the block
When using the use_storage context manager, the bot_handler.storage
methods on the yielded object will only operate on a cached version of the
storage.
bot_handler.storage.put(key, value): Store the value value in the
entry key.
Arguments
key: A UTF-8 stringvalue: A UTF-8 stringExample
bot_handler.storage.put("foo", "bar") # set entry "foo" to "bar"
bot_handler.storage.get(key): Retrieve the value for the entry
key.
Arguments
key: A UTF-8 stringExample
bot_handler.storage.put("foo", "bar")
print(bot_handler.storage.get("foo")) # print "bar"
bot_handler.storage.contains(key): Check if the entry key exists.
Note that this will only check the cache, so it would return False if no
previous call to bot_handler.storage.get() or bot_handler.storage.put()
was made for key, since the bot was restarted.
Arguments
key: A UTF-8 stringExample
bot_handler.storage.contains("foo") # False
bot_handler.storage.put("foo", "bar")
bot_handler.storage.contains("foo") # True
By default, bot_handler.storage accepts any object for keys and
values, as long as it is JSON-able. Internally, the object then gets
converted to an UTF-8 string. You can specify custom data marshaling
by setting the functions bot_handler.storage.marshal and
bot_handler.storage.demarshal. These functions parse your data on
every call to put and get, respectively.
When using the use_storage context manager, you can manually flush
changes made to the cache to the server, using the below methods.
cache.flush(): Flush all changes to the cache to the server.
Example
with use_storage(bot_handler.storage, ["foo", "bar"]) as cache:
cache.put("foo", "foo_value") # update the value of "foo"
cache.put("bar", "bar_value") # update the value of "bar"
cache.flush() # manually flush both the changes to the server
cache.flush_one(key): Flush the changes for the specified key
to the server.
Arguments
key: A UTF-8 stringExample
with use_storage(bot_handler.storage, ["foo", "bar"]) as cache:
cache.put("foo", "baz") # update the value of "foo"
cache.put("bar", "bar_value") # update the value of "bar"
cache.flush_one("foo") # flush the changes to "foo" to the server
[api]
key=<api-key>
email=<email>
site=<dev-url>
[email protected].localhost:9991.