mirror of https://github.com/zulip/zulip.git
docs: Wrap a bunch of long lines.
This commit is contained in:
parent
c57ef13a62
commit
efb8f8c26d
|
@ -192,8 +192,10 @@ mind:
|
|||
Browsing this list can be a great way to find feature ideas to
|
||||
implement that other Zulip users are excited about.
|
||||
|
||||
* [2016 roadmap milestone](http://zulip.readthedocs.io/en/latest/roadmap.html): The
|
||||
projects that are [priorities for the Zulip project](https://zulip.readthedocs.io/en/latest/roadmap.html). These are great projects if you're looking to make an impact.
|
||||
* [2016 roadmap milestone](http://zulip.readthedocs.io/en/latest/roadmap.html):
|
||||
The projects that are
|
||||
[priorities for the Zulip project](https://zulip.readthedocs.io/en/latest/roadmap.html).
|
||||
These are great projects if you're looking to make an impact.
|
||||
|
||||
Another way to find issues in Zulip is to take advantage of our
|
||||
"area:<foo>" convention in separating out issues. We partition all of
|
||||
|
|
|
@ -42,41 +42,59 @@ It presumes that you already have a fully implemented `<my-bot>.py` bot and now
|
|||
|
||||
3. Register a new bot on your Zulip server's web interface.
|
||||
|
||||
* Navigate to *Settings* -> *Your Bots* -> *Add a New Bot*, fill out the form and click on *Create Bot*.
|
||||
* Navigate to *Settings* -> *Your Bots* -> *Add a New Bot*, fill
|
||||
out the form and click on *Create Bot*.
|
||||
* A new bot should appear in the *Your Bots* panel.
|
||||
|
||||
4. Add the bot's configuration file on your Zulip server.
|
||||
|
||||
* In the *Your Bots* panel, click on the green icon to download its configuration file *.zuliprc* (the structure of this file is explained [here](#configuration-file).
|
||||
* In the *Your Bots* panel, click on the green icon to download
|
||||
its configuration file *.zuliprc* (the structure of this file is
|
||||
explained [here](#configuration-file).
|
||||
* Copy the file to a destination of your choice on your Zulip server, e.g. to `~/.zuliprc` or `~/zuliprc-test`.
|
||||
|
||||
5. Subscribe the bot to the streams that the bot needs to read messages from or write messages to.
|
||||
|
||||
* To subscribe your bot to streams, navigate to *Manage Streams*. Select a stream and add your bot by its email address (the address you assigned in step 3).
|
||||
* To subscribe your bot to streams, navigate to *Manage
|
||||
Streams*. Select a stream and add your bot by its email address
|
||||
(the address you assigned in step 3).
|
||||
* Now, the bot will do its job on the streams you subscribed it to.
|
||||
|
||||
6. Run the bot.
|
||||
|
||||
* On your Zulip server (and outside the Vagrant environment), navigate to `~/zulip/contrib_bots/`
|
||||
* Run `python run.py ~/zulip/contrib_bots/lib/<my-bot>.py --config-file ~/.zuliprc`. The `~/` before `.zuliprc` should point to the directory containing the file (in this case, it is the home directory).
|
||||
* 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
|
||||
```
|
||||
* Run `python run.py ~/zulip/contrib_bots/lib/<my-bot>.py
|
||||
--config-file ~/.zuliprc`. The `~/` before `.zuliprc` should
|
||||
point to the directory containing the file (in this case, it is
|
||||
the home directory).
|
||||
* 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
|
||||
```
|
||||
|
||||
* Congrats! Now, your bot should be ready to test on the streams you've subscribed it to.
|
||||
|
||||
### Test the `followup.py` bot
|
||||
|
||||
1. Do the previous steps for the `followup.py` bot.
|
||||
2. Create the *followup* stream.
|
||||
3. Subscribe the bot to the newly created *followup* stream and a stream you want to use it from, e.g. *social*.
|
||||
4. Send a message to the stream you've subscribed the bot to (other than *followup*). If everything works, a copy of the message should now pop up in the *followup* stream.
|
||||
3. Subscribe the bot to the newly created *followup* stream and a
|
||||
stream you want to use it from, e.g. *social*.
|
||||
4. Send a message to the stream you've subscribed the bot to (other
|
||||
than *followup*). If everything works, a copy of the message should
|
||||
now pop up in the *followup* stream.
|
||||
|
||||
## How to develop a bot
|
||||
|
||||
The tutorial below explains the structure of a bot `<my-bot>.py`. You can use this as boilerplate code for developing your own bot.
|
||||
The tutorial below explains the structure of a bot `<my-bot>.py`. You
|
||||
can use this as boilerplate code for developing your own bot.
|
||||
|
||||
Every bot is built upon this structure:
|
||||
|
||||
```
|
||||
class MyBotHandler(object):
|
||||
'''
|
||||
|
@ -94,7 +112,11 @@ class MyBotHandler(object):
|
|||
|
||||
handler_class = MyBotHandler
|
||||
```
|
||||
* 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.
|
||||
|
||||
* 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.
|
||||
|
||||
* Every bot needs to implement the functions
|
||||
* `usage(self)`
|
||||
|
@ -104,7 +126,9 @@ handler_class = MyBotHandler
|
|||
* These functions are documented in the [next section](#bot-api).
|
||||
|
||||
## Bot API
|
||||
This section documents the functions every bot needs to implement and the structure of the bot's config file.
|
||||
|
||||
This section documents the functions every bot needs to implement and
|
||||
the structure of the bot's config file.
|
||||
|
||||
### usage
|
||||
*usage(self)*
|
||||
|
@ -212,13 +236,17 @@ None.
|
|||
site=<dev-url>
|
||||
```
|
||||
|
||||
* key - the API key you created for the bot; this is how Zulip knows the request is from an authorized user.
|
||||
* key - the API key you created for the bot; this is how Zulip knows
|
||||
the request is from an authorized user.
|
||||
|
||||
* email - the email address of the bot, e.g. `some-bot@zulip.com`
|
||||
|
||||
* site - your development environment URL; if you are working on a development environment hosted on your computer, use `localhost:9991`
|
||||
* site - your development environment URL; if you are working on a
|
||||
development environment hosted on your computer, use
|
||||
`localhost:9991`
|
||||
|
||||
## Common problems
|
||||
|
||||
* I modified my bot's code, yet the changes don't seem to have an effect.
|
||||
* Ensure that you restarted the `run.py` script.
|
||||
|
||||
|
|
|
@ -320,7 +320,11 @@ Now run these commands:
|
|||
./tools/install-mypy
|
||||
./tools/setup/emoji/build_emoji
|
||||
./scripts/setup/generate_secrets.py --development
|
||||
if [ $(uname) = "OpenBSD" ]; then sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /var/postgresql/tsearch_data/; else sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.*/tsearch_data/; fi
|
||||
if [ $(uname) = "OpenBSD" ]; then
|
||||
sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /var/postgresql/tsearch_data/
|
||||
else
|
||||
sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.*/tsearch_data/
|
||||
fi
|
||||
./scripts/setup/configure-rabbitmq
|
||||
./tools/setup/postgres-init-dev-db
|
||||
./tools/do-destroy-rebuild-database
|
||||
|
|
|
@ -13,9 +13,13 @@ Zulip uses the [Django web
|
|||
framework](https://docs.djangoproject.com/en/1.8/), so a lot of these
|
||||
paths will be familiar to Django developers.
|
||||
|
||||
* `zproject/urls.py` Main [Django routes file](https://docs.djangoproject.com/en/1.8/topics/http/urls/). Defines which URLs are handled by which view functions or templates.
|
||||
* `zproject/urls.py` Main
|
||||
[Django routes file](https://docs.djangoproject.com/en/1.8/topics/http/urls/).
|
||||
Defines which URLs are handled by which view functions or templates.
|
||||
|
||||
* `zerver/models.py` Main [Django models](https://docs.djangoproject.com/en/1.8/topics/db/models/) file. Defines Zulip's database tables.
|
||||
* `zerver/models.py` Main
|
||||
[Django models](https://docs.djangoproject.com/en/1.8/topics/db/models/)
|
||||
file. Defines Zulip's database tables.
|
||||
|
||||
* `zerver/lib/actions.py` Most code doing writes to user-facing database tables.
|
||||
|
||||
|
@ -40,7 +44,8 @@ paths will be familiar to Django developers.
|
|||
See [our translating docs](translating.html) for details on Zulip's
|
||||
templating systems.
|
||||
|
||||
* `templates/zerver/` For [Jinja2](http://jinja.pocoo.org/) templates for the backend (for zerver app).
|
||||
* `templates/zerver/` For [Jinja2](http://jinja.pocoo.org/) templates
|
||||
for the backend (for zerver app).
|
||||
|
||||
* `static/templates/` [Handlebars](http://handlebarsjs.com/) templates for the frontend.
|
||||
|
||||
|
|
|
@ -21,10 +21,14 @@ are in your git checkout under `static`, and are served unminified.
|
|||
## Nginx secures traffic with [SSL](prod-install.html)
|
||||
|
||||
If you visit your Zulip server in your browser and discover that your
|
||||
traffic isn't being properly encrypted, an [nginx misconfiguration](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/sites-available/zulip-enterprise) is the
|
||||
traffic isn't being properly encrypted, an [nginx misconfiguration][nginx-config] is the
|
||||
likely culprit.
|
||||
|
||||
## Static files are [served directly](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app) by Nginx
|
||||
[nginx-config]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/sites-available/zulip-enterprise
|
||||
|
||||
## Static files are [served directly][served-directly] by Nginx
|
||||
|
||||
[served-directly]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app
|
||||
|
||||
Static files include JavaScript, css, static assets (like emoji, avatars),
|
||||
and user uploads (if stored locally and not on S3).
|
||||
|
@ -36,7 +40,9 @@ location /static/ {
|
|||
}
|
||||
```
|
||||
|
||||
## Nginx routes other requests [between tornado and django](architecture-overview.html?highlight=tornado#tornado-and-django)
|
||||
## Nginx routes other requests [between tornado and django][tornado-django]
|
||||
|
||||
[tornado-django]: architecture-overview.html?highlight=tornado#tornado-and-django
|
||||
|
||||
All our connected clients hold open long-polling connections so that
|
||||
they can recieve events (messages, presence notifications, and so on) in
|
||||
|
@ -45,7 +51,9 @@ real-time. Events are served by Zulip's `tornado` application.
|
|||
Nearly every other kind of request is served by the `zerver` Django
|
||||
application.
|
||||
|
||||
[Here is the relevant nginx routing configuration.](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app)
|
||||
[Here is the relevant nginx routing configuration.][nginx-config-link]
|
||||
|
||||
[nginx-config-link]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app
|
||||
|
||||
## Django routes the request to a view in urls.py files
|
||||
|
||||
|
@ -101,7 +109,9 @@ show my message multiple times. PATCH is special--it can be
|
|||
idempotent, and we like to write API endpoints in an idempotent fashion,
|
||||
as much as possible.
|
||||
|
||||
This [cookbook](http://restcookbook.com/) and [tutorial](http://www.restapitutorial.com/) can be helpful if you are new to REST web applications.
|
||||
This [cookbook](http://restcookbook.com/) and
|
||||
[tutorial](http://www.restapitutorial.com/) can be helpful if you are
|
||||
new to REST web applications.
|
||||
|
||||
### PUT is only for creating new things
|
||||
|
||||
|
@ -137,7 +147,8 @@ In this way, the API is partially self-documenting.
|
|||
The endpoints from the legacy JSON API are written without REST in
|
||||
mind. They are used extensively by the web client, and use POST.
|
||||
|
||||
You can see them in [zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py).
|
||||
You can see them in
|
||||
[zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py).
|
||||
|
||||
### Webhook integrations may not be RESTful
|
||||
|
||||
|
@ -147,23 +158,29 @@ only POST.
|
|||
|
||||
## Django calls rest_dispatch for REST endpoints, and authenticates
|
||||
|
||||
For requests that correspond to a REST url pattern, Zulip configures its
|
||||
url patterns (see [zerver/lib/rest.py](https://github.com/zulip/zulip/blob/master/zerver/lib/rest.py)) so that the action called is
|
||||
`rest_dispatch`. This method will authenticate the user, either through
|
||||
a session token from a cookie, or from an `email:api-key` string given
|
||||
via HTTP Basic Auth for API clients.
|
||||
For requests that correspond to a REST url pattern, Zulip configures
|
||||
its url patterns (see
|
||||
[zerver/lib/rest.py](https://github.com/zulip/zulip/blob/master/zerver/lib/rest.py))
|
||||
so that the action called is `rest_dispatch`. This method will
|
||||
authenticate the user, either through a session token from a cookie,
|
||||
or from an `email:api-key` string given via HTTP Basic Auth for API
|
||||
clients.
|
||||
|
||||
It will then look up what HTTP verb was used (GET, POST, etc) to make
|
||||
the request, and then figure out which view to show from that.
|
||||
|
||||
In our example,
|
||||
|
||||
```
|
||||
{'GET': 'zerver.views.users.get_members_backend',
|
||||
'PUT': 'zerver.views.users.create_user_backend'}
|
||||
```
|
||||
is supplied as an argument to `rest_dispatch`, along with the [HTTPRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/).
|
||||
|
||||
is supplied as an argument to `rest_dispatch`, along with the
|
||||
[HTTPRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/).
|
||||
The request has the HTTP verb `PUT`, which `rest_dispatch` can use to
|
||||
find the correct view to show: `zerver.views.users.create_user_backend`.
|
||||
find the correct view to show:
|
||||
`zerver.views.users.create_user_backend`.
|
||||
|
||||
## The view will authorize the user, extract request variables, and validate them
|
||||
|
||||
|
@ -176,7 +193,9 @@ return `json_error` in the case of an error, which gives a JSON string:
|
|||
|
||||
`{'result': 'error', 'msg': <some error message>}`
|
||||
|
||||
in a [HTTP Response](https://docs.djangoproject.com/en/1.8/ref/request-response/) with a content type of 'application/json'.
|
||||
in a
|
||||
[HTTP Response](https://docs.djangoproject.com/en/1.8/ref/request-response/)
|
||||
with a content type of 'application/json'.
|
||||
|
||||
To pass back data from the server to the calling client, in the event of
|
||||
a successfully handled request, we use `json_success(data=<some python object which can be converted to a JSON string>`.
|
||||
|
|
|
@ -16,18 +16,29 @@ override that configuration).
|
|||
If you want to use a remote Postgresql database, you should configure
|
||||
the information about the connection with the server. You need a user
|
||||
called "zulip" in your database server. You can configure these
|
||||
options in /etc/zulip/settings.py:
|
||||
options in /etc/zulip/settings.py (the below descriptions are from the
|
||||
Postgresql documentation):
|
||||
|
||||
* REMOTE_POSTGRES_HOST: Name or IP address of the remote host
|
||||
* REMOTE_POSTGRES_SSLMODE: SSL Mode used to connect to the server, different options you can use are:
|
||||
* disable: I don't care about security, and I don't want to pay the overhead of encryption.
|
||||
* allow: I don't care about security, but I will pay the overhead of encryption if the server insists on it.
|
||||
* prefer: I don't care about encryption, but I wish to pay the overhead of encryption if the server supports it.
|
||||
* require: I want my data to be encrypted, and I accept the overhead. I trust that the network will make sure I always connect to the server I want.
|
||||
* verify-ca: I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server that I trust.
|
||||
* verify-full: I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server I trust, and that it's the one I specify.
|
||||
* REMOTE_POSTGRES_SSLMODE: SSL Mode used to connect to the server,
|
||||
different options you can use are:
|
||||
* disable: I don't care about security, and I don't want to pay the
|
||||
overhead of encryption.
|
||||
* allow: I don't care about security, but I will pay the overhead of
|
||||
encryption if the server insists on it.
|
||||
* prefer: I don't care about encryption, but I wish to pay the
|
||||
overhead of encryption if the server supports it.
|
||||
* require: I want my data to be encrypted, and I accept the
|
||||
overhead. I trust that the network will make sure I always connect
|
||||
to the server I want.
|
||||
* verify-ca: I want my data encrypted, and I accept the overhead. I
|
||||
want to be sure that I connect to a server that I trust.
|
||||
* verify-full: I want my data encrypted, and I accept the
|
||||
overhead. I want to be sure that I connect to a server I trust,
|
||||
and that it's the one I specify.
|
||||
|
||||
Then you should specify the password of the user zulip for the database in /etc/zulip/zulip-secrets.conf:
|
||||
Then you should specify the password of the user zulip for the
|
||||
database in /etc/zulip/zulip-secrets.conf:
|
||||
|
||||
```
|
||||
postgres_password = xxxx
|
||||
|
|
|
@ -194,7 +194,9 @@ REQ also helps us with request variable validation. For example:
|
|||
integer (`converter` differs from `validator` in that it does not
|
||||
automatically marshall the input from JSON).
|
||||
|
||||
See [zerver/lib/validator.py](https://github.com/zulip/zulip/blob/master/zerver/lib/validator.py) for more validators and their documentation.
|
||||
See
|
||||
[zerver/lib/validator.py](https://github.com/zulip/zulip/blob/master/zerver/lib/validator.py)
|
||||
for more validators and their documentation.
|
||||
|
||||
### Deciding which HTTP verb to use
|
||||
|
||||
|
|
Loading…
Reference in New Issue