2017-05-21 23:19:07 +02:00
|
|
|
|
# Zulip bot system
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-21 23:19:07 +02:00
|
|
|
|
Zulip's features can be extended by the means of bots and integrations.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-21 23:19:07 +02:00
|
|
|
|
* **Integrations** are used to connect Zulip with different chat, scheduling and workflow software.
|
|
|
|
|
If this is what you are looking for, please check out the [integrations guide](
|
|
|
|
|
http://zulip.readthedocs.io/en/latest/integration-guide.html?highlight=integrations).
|
|
|
|
|
* **Bots**, as a more general concept, intercept and react to messages.
|
|
|
|
|
If this is what you are looking for, read on!
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-21 23:19:07 +02:00
|
|
|
|
The purpose of this documentation is to provide you with information about Zulip's
|
|
|
|
|
bot system.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
On this page you'll find:
|
|
|
|
|
|
2017-05-21 23:19:07 +02:00
|
|
|
|
* A step-by-step [tutorial](#how-to-run-a-bot) on how to run a bot.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
* A step-by-step [tutorial](#how-to-develop-a-bot) on how to develop a bot.
|
|
|
|
|
* A [documentation](#bot-api) of the bot API.
|
2017-05-21 23:19:07 +02:00
|
|
|
|
* Common [problems](#common-problems) when developing/running bots and their solutions.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
Contributions to this guide are very welcome, so if you run into any
|
|
|
|
|
issues following these instructions or come up with any tips or tools
|
2017-02-13 01:55:54 +01:00
|
|
|
|
that help with writing bots, please visit
|
2017-08-22 16:38:36 +02:00
|
|
|
|
[#integrations](https://chat.zulip.org/#narrow/stream/integrations) on the
|
2017-02-13 01:55:54 +01:00
|
|
|
|
[Zulip development community server](https://chat.zulip.org), open an
|
|
|
|
|
issue, or submit a pull request to share your ideas!
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-06-06 15:51:29 +02:00
|
|
|
|
## The bots system
|
2017-05-21 23:19:07 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
Zulip's bot system resides in the [python-zulip-api](
|
|
|
|
|
https://github.com/zulip/python-zulip-api) repository.
|
2017-05-21 23:19:07 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
The structure of the bots ecosystem looks like the following:
|
2017-05-21 23:19:07 +02:00
|
|
|
|
|
|
|
|
|
```
|
2017-08-22 16:38:36 +02:00
|
|
|
|
zulip_bots
|
|
|
|
|
└───zulip_bots
|
|
|
|
|
├───bots
|
|
|
|
|
│ ├───bot1
|
|
|
|
|
│ └───bot2
|
|
|
|
|
│ │
|
|
|
|
|
│ ├───readme.md
|
|
|
|
|
│ ├───bot2.py
|
|
|
|
|
│ ├───bot2.config
|
|
|
|
|
│ ├───libraries
|
|
|
|
|
│ │ │
|
|
|
|
|
│ │ └───lib1.py
|
|
|
|
|
│ └───assets
|
|
|
|
|
│ │
|
|
|
|
|
│ └───pic.png
|
|
|
|
|
├─── lib.py
|
|
|
|
|
├─── test_lib.py
|
|
|
|
|
├─── run.py
|
|
|
|
|
└─── provision.py
|
2017-05-21 23:19:07 +02:00
|
|
|
|
```
|
2017-05-05 22:23:15 +02:00
|
|
|
|
|
2017-05-21 23:19:07 +02:00
|
|
|
|
Each subdirectory in `bots` contains a bot. When developing bots, try to use the structure outlined
|
|
|
|
|
above as an orientation.
|
|
|
|
|
|
|
|
|
|
## How to run a bot
|
|
|
|
|
|
|
|
|
|
This guide will show you how to run a bot on a running Zulip
|
2017-08-22 16:38:36 +02:00
|
|
|
|
server. It assumes you want to use one of the existing `zulip_bots/bots`
|
2017-05-05 22:23:15 +02:00
|
|
|
|
bots in your Zulip organization. If you want to write a new one, you
|
2017-08-22 16:38:36 +02:00
|
|
|
|
just need to write the `<my-bot>.py` script and put it into `zulip_bots/bots/<my-bot>` directory.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-05 19:54:51 +02:00
|
|
|
|
You need:
|
|
|
|
|
|
2017-05-05 22:23:15 +02:00
|
|
|
|
* An account in an organization on a Zulip server
|
|
|
|
|
(e.g. [chat.zulip.org](https://chat.zulip.org) or
|
|
|
|
|
yourSubdomain.zulipchat.com, or your own development server).
|
|
|
|
|
Within that Zulip organization, users will be able to interact with
|
|
|
|
|
your bot.
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* A computer where you're running the bot from.
|
2017-05-05 19:54:51 +02:00
|
|
|
|
|
|
|
|
|
**Note: Please be considerate when testing experimental bots on
|
|
|
|
|
public servers such as chat.zulip.org.**
|
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
1. Install all requirements. You can either
|
|
|
|
|
|
|
|
|
|
* run `pip install zulip_bots` for a stable version, or
|
|
|
|
|
* clone the [`zulip_bots`](https://github.com/zulip/python-zulip-api/tree/master/zulip_bots)
|
|
|
|
|
repository for the latest code. Install it with
|
|
|
|
|
`pip -e <path/to/zulip_bots>`; you will be able to make changes to the code.
|
|
|
|
|
|
|
|
|
|
2. Register a new bot user on the Zulip server's web interface.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-05 19:54:51 +02:00
|
|
|
|
* Log in to the Zulip server.
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* Navigate to *Settings* -> *Active bots* -> *Add a new bot*.
|
|
|
|
|
Select *Generic bot* for bot type, fill out the form and click on *Create bot*.
|
|
|
|
|
* A new bot user should appear in the *Active bots* panel.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
3. Download the bot's `zuliprc` configuration file to your computer.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* In the *Active bots* panel, click on the green icon to download
|
2017-05-23 00:28:18 +02:00
|
|
|
|
its configuration file *zuliprc* (the structure of this file is
|
2017-07-10 07:55:31 +02:00
|
|
|
|
explained [here](#configuration-file)).
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* Copy the file to a destination of your choice, e.g. to `~/zuliprc`
|
|
|
|
|
or `~/zuliprc-test`.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
4. Subscribe the bot to the streams that the bot needs to interact with.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-01-05 23:23:16 +01:00
|
|
|
|
* To subscribe your bot to streams, navigate to *Manage
|
|
|
|
|
Streams*. Select a stream and add your bot by its email address
|
2017-08-22 16:38:36 +02:00
|
|
|
|
(the address you assigned in step 2).
|
2017-05-22 21:25:23 +02:00
|
|
|
|
* Now, the bot can do its job on the streams you subscribed it to.
|
2017-05-05 22:23:15 +02:00
|
|
|
|
* (In future versions of the API, this step may not be required).
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
5. Run the bot.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-05 22:23:15 +02:00
|
|
|
|
* Run
|
|
|
|
|
```
|
2017-08-22 16:38:36 +02:00
|
|
|
|
zulip-run-bot <bot-name> --config-file ~/zuliprc`
|
2017-05-05 22:23:15 +02:00
|
|
|
|
```
|
2017-08-22 16:38:36 +02:00
|
|
|
|
(using the path to the `zuliprc` file from step 3).
|
2017-01-05 23:23:16 +01:00
|
|
|
|
* Check the output of the command. It should start with the text
|
|
|
|
|
the `usage` function returns, followed by logging output similar
|
|
|
|
|
to this:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
INFO:root:starting message handling...
|
|
|
|
|
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost
|
|
|
|
|
```
|
|
|
|
|
|
2016-12-20 03:25:35 +01:00
|
|
|
|
* Congrats! Now, your bot should be ready to test on the streams you've subscribed it to.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-05-23 22:42:27 +02:00
|
|
|
|
### Testing the helloworld bot
|
|
|
|
|
|
|
|
|
|
* The `helloworld` bot is a simple bot that responds with a 'beep boop'
|
|
|
|
|
when queried. It can be used as a template to build more complex
|
|
|
|
|
bots.
|
|
|
|
|
* Go to a stream your bot is subscribed to. Talk to the bot by
|
|
|
|
|
typing `@<your bot name>` followed by some commands. If the bot is
|
|
|
|
|
the `helloworld` bot, you should expect the bot to respond with
|
|
|
|
|
"beep boop".
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
## Zulip Botserver
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
The Zulip Botserver is for people who want to
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* run bots in production.
|
|
|
|
|
* run multiple bots at once.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:20:21 +02:00
|
|
|
|
The Zulip Botserver is a Python (Flask) server that implements Zulip's
|
|
|
|
|
Outgoing Webhooks API. You can of course write your own servers using
|
|
|
|
|
the Outgoing Webhooks API, but the Botserver is designed to make it
|
|
|
|
|
easy for a novice Python programmer to write a new bot and deploy it
|
|
|
|
|
in production.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:20:21 +02:00
|
|
|
|
### Installing the Zulip Botserver
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:20:21 +02:00
|
|
|
|
Install the `zulip_botserver` PyPI package using `pip`:
|
|
|
|
|
```
|
|
|
|
|
pip install zulip_botserver
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Running bots using the Zulip Botserver
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
1. Register new bot users on the Zulip server's web interface.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* Log in to the Zulip server.
|
|
|
|
|
* Navigate to *Settings* -> *Active bots* -> *Add a new bot*.
|
|
|
|
|
Select *Outgoing webhook* for bot type, fill out the form and click on *Create bot*.
|
|
|
|
|
* A new bot user should appear in the *Active bots* panel.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
2. Download the `flaskbotrc` from the `your-bots` settings page. It
|
|
|
|
|
contains the configuration details for all the active outgoing
|
|
|
|
|
webhook bots. It's structure is very similar to that of zuliprc.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:20:21 +02:00
|
|
|
|
3. Run the Zulip Botserver by passing the `flaskbotrc` to it. The
|
2017-08-22 16:38:36 +02:00
|
|
|
|
command format is:
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
```
|
|
|
|
|
zulip-bot-server --config-file <path_to_flaskbotrc> --hostname <address> --port <port>
|
|
|
|
|
```
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
If omitted, `hostname` defaults to `127.0.0.1` and `port` to `5002`.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:20:21 +02:00
|
|
|
|
4. Now set up the outgoing webhook service which will interact with
|
2017-08-22 16:38:36 +02:00
|
|
|
|
the server: Create an **Outgoing webhook** bot with its base url
|
|
|
|
|
of the form:
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
```
|
|
|
|
|
http://<hostname>:<port>/bots/<bot_name>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`bot_name` refers to the name in the email address you specified
|
|
|
|
|
for the bot. It can be obtained by removing `-bot@*.*` from the
|
|
|
|
|
bot email: For example, the bot name of a bot with an email
|
|
|
|
|
`followup-bot@zulip.com` is `followup`.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
In the development environment, an outgoing webhook bot and
|
|
|
|
|
corresponding service already exist, with the email
|
|
|
|
|
`outgoing-webhook@zulip.com`. This can be used for interacting
|
|
|
|
|
with flask server bots.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:20:21 +02:00
|
|
|
|
5. Congrats, everything is set up! Test your botserver like you would
|
2017-08-22 16:38:36 +02:00
|
|
|
|
test a normal bot.
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
*Please note that in order to @-mention trigger a bot on a stream,
|
|
|
|
|
the bot **and** the outgoing webhook bot need to be subscribed to
|
|
|
|
|
it.*
|
2017-06-09 20:59:18 +02:00
|
|
|
|
|
2017-08-28 15:21:19 +02:00
|
|
|
|
### Running Zulip Botserver with `supervisord`
|
|
|
|
|
|
|
|
|
|
You may feel that running the `zulip-bot-server` command manually is cumbersome
|
|
|
|
|
and brittle: It needs a separate terminal for monitoring and has to be restarted on failure.
|
|
|
|
|
If that's the case, *supervisord* gives you a helping hand: Once configured, it automatically
|
|
|
|
|
runs the botserver, telling you the current botserver status, restarting it if needed, and keeping
|
|
|
|
|
track of all logged information.
|
|
|
|
|
|
|
|
|
|
Running the Zulip Botserver with *supervisord* works almost like running it manually.
|
|
|
|
|
|
|
|
|
|
0. Install *supervisord*:
|
|
|
|
|
```
|
|
|
|
|
sudo apt-get install supervisor
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
1. Configure *supervisord*:
|
|
|
|
|
* Do **one** of the following:
|
|
|
|
|
* Download the [config file](
|
|
|
|
|
https://raw.githubusercontent.com/zulip/python-zulip-api/master/zulip_botserver/zulip-botserver-supervisord.conf)
|
|
|
|
|
and store it in `/etc/supervisor/conf.d/zulip-botserver.conf`.
|
|
|
|
|
* Copy&Paste the following section into your existing supervisord config file.
|
|
|
|
|
```
|
|
|
|
|
[program:zulip-bot-server]
|
|
|
|
|
command=zulip-bot-server --config-file=<path/to/your/flaskbotrc> --hostname <address> --port <port>
|
|
|
|
|
startsecs=3
|
|
|
|
|
stdout_logfile=<path/to/your/logfile> ; all output of your botserver will be logged here
|
|
|
|
|
redirect_stderr=true
|
|
|
|
|
```
|
|
|
|
|
* Edit the `<>` sections accordingly.
|
|
|
|
|
|
|
|
|
|
2. Update *supervisord* to read the configuration file:
|
|
|
|
|
```
|
|
|
|
|
supervisorctl reread
|
|
|
|
|
supervisorctl update
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
3. Test if your setup is successful:
|
|
|
|
|
```
|
|
|
|
|
supervisorctl status
|
|
|
|
|
```
|
|
|
|
|
The output should include a line similar to this:
|
|
|
|
|
> zulip-bot-server RUNNING pid 28154, uptime 0:00:27
|
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
## How to develop a bot
|
|
|
|
|
|
2017-05-05 22:23:15 +02:00
|
|
|
|
The tutorial below explains the structure of a bot `<my-bot>.py`,
|
2017-08-22 16:38:36 +02:00
|
|
|
|
which is the only file you need to create for a new bot. You
|
2017-01-05 23:23:16 +01:00
|
|
|
|
can use this as boilerplate code for developing your own bot.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
Every bot is built upon this structure:
|
2017-01-05 23:23:16 +01:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
```
|
|
|
|
|
class MyBotHandler(object):
|
|
|
|
|
'''
|
|
|
|
|
A docstring documenting this bot.
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
def usage(self):
|
|
|
|
|
return '''Your description of the bot'''
|
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
def handle_message(self, message, bot_handler, state_handler):
|
2016-12-18 16:11:46 +01:00
|
|
|
|
# add your code here
|
|
|
|
|
|
|
|
|
|
handler_class = MyBotHandler
|
|
|
|
|
```
|
2017-01-05 23:23:16 +01:00
|
|
|
|
|
|
|
|
|
* The class name (in this case *MyBotHandler*) can be defined by you
|
|
|
|
|
and should match the name of your bot. To register your bot's class,
|
|
|
|
|
adjust the last line `handler_class = MyBotHandler` to match your
|
|
|
|
|
class name.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
* Every bot needs to implement the functions
|
2016-12-20 03:25:35 +01:00
|
|
|
|
* `usage(self)`
|
2017-06-11 15:03:39 +02:00
|
|
|
|
* `handle_message(self, message, bot_handler)`
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
* These functions are documented in the [next section](#bot-api).
|
|
|
|
|
|
|
|
|
|
## Bot API
|
2017-01-05 23:23:16 +01:00
|
|
|
|
|
2017-05-25 04:12:34 +02:00
|
|
|
|
This section documents functions available to the bot and the structure of the bot's config file.
|
2017-05-21 23:19:07 +02:00
|
|
|
|
|
|
|
|
|
With this API, you *can*
|
|
|
|
|
|
|
|
|
|
* intercept, view, and process messages sent by users on Zulip.
|
|
|
|
|
* send out new messages as replies to the processed messages.
|
|
|
|
|
|
|
|
|
|
With this API, you *cannot*
|
|
|
|
|
|
|
|
|
|
* modify an intercepted message (you have to send a new message).
|
|
|
|
|
* send messages on behalf of or impersonate other users.
|
|
|
|
|
* intercept private messages (except for PMs with the bot as an
|
|
|
|
|
explicit recipient).
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
### usage
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
*usage(self)*
|
|
|
|
|
|
|
|
|
|
is called to retrieve information about the bot.
|
|
|
|
|
|
2017-05-21 23:19:07 +02:00
|
|
|
|
##### Arguments
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
* self - the instance the method is called on.
|
|
|
|
|
|
|
|
|
|
#### Return values
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
* A string describing the bot's functionality
|
|
|
|
|
|
|
|
|
|
#### Example implementation
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
```
|
|
|
|
|
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 stream
|
|
|
|
|
called "followup" that your API user can send to.
|
|
|
|
|
'''
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### handle_message
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
*handle_message(self, message, bot_handler)*
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-03-05 14:52:12 +01:00
|
|
|
|
handles user message.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
#### Arguments
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
* self - the instance the method is called on.
|
|
|
|
|
|
2016-12-20 04:30:25 +01:00
|
|
|
|
* message - a dictionary describing a Zulip message
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
* bot_handler - used to interact with the server, e.g. to send a message
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
* state_handler - used to save states/information of the bot **beta**
|
2016-12-20 03:25:35 +01:00
|
|
|
|
* use `state_handler.set_state(state)` to set a state (any object)
|
|
|
|
|
* use `state_handler.get_state()` to retrieve the state set; returns a `NoneType` object if no state is set
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
#### Return values
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
#### Example implementation
|
|
|
|
|
|
|
|
|
|
```
|
2017-06-11 15:03:39 +02:00
|
|
|
|
def handle_message(self, message, bot_handler, state_handler):
|
2016-12-18 16:11:46 +01:00
|
|
|
|
original_content = message['content']
|
|
|
|
|
original_sender = message['sender_email']
|
|
|
|
|
new_content = original_content.replace('@followup',
|
|
|
|
|
'from %s:' % (original_sender,))
|
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
bot_handler.send_message(dict(
|
2016-12-18 16:11:46 +01:00
|
|
|
|
type='stream',
|
|
|
|
|
to='followup',
|
|
|
|
|
subject=message['sender_email'],
|
|
|
|
|
content=new_content,
|
|
|
|
|
))
|
|
|
|
|
```
|
2017-06-11 15:03:39 +02:00
|
|
|
|
### bot_handler.send_message
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
*bot_handler.send_message(message)*
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
|
|
|
|
will 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.
|
|
|
|
|
|
|
|
|
|
### Arguments
|
|
|
|
|
|
|
|
|
|
* message - a dictionary describing the message to be sent by the bot
|
|
|
|
|
|
|
|
|
|
### Example implementation
|
|
|
|
|
|
|
|
|
|
```
|
2017-06-11 15:03:39 +02:00
|
|
|
|
bot_handler.send_message(dict(
|
2017-05-25 04:12:34 +02:00
|
|
|
|
type='stream', # can be 'stream' or 'private'
|
|
|
|
|
to=stream_name, # either the stream name or user's email
|
|
|
|
|
subject=subject, # message subject
|
|
|
|
|
content=message, # content of the sent message
|
|
|
|
|
))
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
### bot_handler.send_reply
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
*bot_handler.send_reply(message, response)*
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
|
|
|
|
will reply to the triggering message to the same place the original
|
|
|
|
|
message was sent to, with the content of the reply being *response*.
|
|
|
|
|
|
|
|
|
|
### Arguments
|
|
|
|
|
|
|
|
|
|
* message - Dictionary containing information on message to respond to
|
|
|
|
|
(provided by `handle_message`).
|
|
|
|
|
* response - Response message from the bot (string).
|
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
### bot_handler.update_message
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
2017-06-11 15:03:39 +02:00
|
|
|
|
*bot_handler.update_message(message)*
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
|
|
|
|
will edit the content of a previously sent message.
|
|
|
|
|
|
|
|
|
|
### Arguments
|
|
|
|
|
|
|
|
|
|
* message - dictionary defining what message to edit and the new content
|
|
|
|
|
|
|
|
|
|
### Example
|
|
|
|
|
|
2017-08-22 16:38:36 +02:00
|
|
|
|
From `zulip_bots/bots/incrementor/incrementor.py`:
|
2017-05-25 04:12:34 +02:00
|
|
|
|
|
|
|
|
|
```
|
2017-06-11 15:03:39 +02:00
|
|
|
|
bot_handler.update_message(dict(
|
2017-05-25 04:12:34 +02:00
|
|
|
|
message_id=self.message_id, # id of message to be updated
|
|
|
|
|
content=str(self.number), # string with which to update message with
|
|
|
|
|
))
|
|
|
|
|
```
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
### Configuration file
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
[api]
|
|
|
|
|
key=<api-key>
|
|
|
|
|
email=<email>
|
|
|
|
|
site=<dev-url>
|
|
|
|
|
```
|
|
|
|
|
|
2017-01-05 23:23:16 +01:00
|
|
|
|
* key - the API key you created for the bot; this is how Zulip knows
|
|
|
|
|
the request is from an authorized user.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
* email - the email address of the bot, e.g. `some-bot@zulip.com`
|
|
|
|
|
|
2017-01-05 23:23:16 +01:00
|
|
|
|
* site - your development environment URL; if you are working on a
|
|
|
|
|
development environment hosted on your computer, use
|
|
|
|
|
`localhost:9991`
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
## Common problems
|
2017-01-05 23:23:16 +01:00
|
|
|
|
|
2016-12-18 16:11:46 +01:00
|
|
|
|
* I modified my bot's code, yet the changes don't seem to have an effect.
|
2016-12-20 03:25:35 +01:00
|
|
|
|
* Ensure that you restarted the `run.py` script.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
* My bot won't start
|
2016-12-20 03:25:35 +01:00
|
|
|
|
* Ensure that your API config file is correct (download the config file from the server).
|
2017-08-22 16:38:36 +02:00
|
|
|
|
* Ensure that you bot script is located in zulip_bots/bots/<my-bot>/
|
2017-05-05 19:54:51 +02:00
|
|
|
|
* Are you using your own Zulip development server? Ensure that you run your bot outside
|
|
|
|
|
the Vagrant environment.
|
2017-05-23 00:28:18 +02:00
|
|
|
|
* Some bots require Python 3. Try switching to a Python 3 environment before running
|
2017-08-22 16:38:36 +02:00
|
|
|
|
your bot.
|
2016-12-18 16:11:46 +01:00
|
|
|
|
|
|
|
|
|
* My bot works only on some streams.
|
2017-05-21 23:19:07 +02:00
|
|
|
|
* Subscribe your bot to other streams, as described [here](#how-to-run-a-bot).
|
2017-05-05 22:26:57 +02:00
|
|
|
|
|
|
|
|
|
## Future direction
|
|
|
|
|
|
|
|
|
|
The long-term plan for this bot system is to allow the same
|
2017-08-22 16:38:36 +02:00
|
|
|
|
`ExternalBotHandler` code to eventually be usable in several contexts:
|
2017-05-05 22:26:57 +02:00
|
|
|
|
|
|
|
|
|
* Run directly using the Zulip `call_on_each_message` API, which is
|
|
|
|
|
how the implementation above works. This is great for quick
|
|
|
|
|
development with minimal setup.
|
|
|
|
|
* Run in a simple Python webserver server, processing messages
|
|
|
|
|
received from Zulip's outgoing webhooks integration.
|
|
|
|
|
* For bots merged into the mainline Zulip codebase, enabled via a
|
|
|
|
|
button in the Zulip web UI, with no code deployment effort required.
|