api: Move the API package to a dedicated subdirectory.
In order to keep all three packages (zulip, zulip_bots, zulip_botserver) in the same repo, all package files must now be nested one level deeper. For instance, python-zulip-api/zulip_bots/zulip_bots/bots/, instead of python-zulip-api/zulip_bots/bots/.
This commit is contained in:
parent
879f44ab3a
commit
3d0f7955b6
181
README.md
181
README.md
|
@ -1,177 +1,8 @@
|
||||||
#### Dependencies
|
# Zulip API
|
||||||
|
|
||||||
The [Zulip API](https://zulipchat.com/api) Python bindings require the
|
This repository contains the source code for Zulip's PyPI packages:
|
||||||
following Python libraries:
|
|
||||||
|
|
||||||
* requests (version >= 0.12.1)
|
* `zulip`: [PyPI package](https://pypi.python.org/pypi/zulip/)
|
||||||
* simplejson
|
for Zulip's API bindings.
|
||||||
* six
|
* `zulip_bots`: PyPI package for Zulip's bots and bots API.
|
||||||
* typing (version >= 3.5.2.2)
|
* `zulip_botserver`: PyPI package for Zulip's Flask bot server.
|
||||||
|
|
||||||
#### Installing
|
|
||||||
|
|
||||||
This package uses distutils, so you can just run:
|
|
||||||
|
|
||||||
python setup.py install
|
|
||||||
|
|
||||||
#### Using the API
|
|
||||||
|
|
||||||
For now, the only fully supported API operation is sending a message.
|
|
||||||
The other API queries work, but are under active development, so
|
|
||||||
please make sure we know you're using them so that we can notify you
|
|
||||||
as we make any changes to them.
|
|
||||||
|
|
||||||
The easiest way to use these API bindings is to base your tools off
|
|
||||||
of the example tools under examples/ in this distribution.
|
|
||||||
|
|
||||||
If you place your API key in the config file `~/.zuliprc` the Python
|
|
||||||
API bindings will automatically read it in. The format of the config
|
|
||||||
file is as follows:
|
|
||||||
|
|
||||||
[api]
|
|
||||||
key=<api key from the web interface>
|
|
||||||
email=<your email address>
|
|
||||||
site=<your Zulip server's URI>
|
|
||||||
insecure=<true or false, true means do not verify the server certificate>
|
|
||||||
cert_bundle=<path to a file containing CA or server certificates to trust>
|
|
||||||
|
|
||||||
If omitted, these settings have the following defaults:
|
|
||||||
|
|
||||||
insecure=false
|
|
||||||
cert_bundle=<the default CA bundle trusted by Python>
|
|
||||||
|
|
||||||
Alternatively, you may explicitly use "--user", "--api-key", and
|
|
||||||
`--site` in our examples, which is especially useful when testing. If
|
|
||||||
you are running several bots which share a home directory, we
|
|
||||||
recommend using `--config` to specify the path to the `zuliprc` file
|
|
||||||
for a specific bot. Finally, you can control the defaults for all of
|
|
||||||
these variables using the environment variables `ZULIP_CONFIG`,
|
|
||||||
`ZULIP_API_KEY`, `ZULIP_EMAIL`, `ZULIP_SITE`, `ZULIP_CERT`,
|
|
||||||
`ZULIP_CERT_KEY`, and `ZULIP_CERT_BUNDLE`. Command-line options take
|
|
||||||
precedence over environment variables take precedence over the config
|
|
||||||
files.
|
|
||||||
|
|
||||||
The command line equivalents for other configuration options are:
|
|
||||||
|
|
||||||
--insecure
|
|
||||||
--cert-bundle=<file>
|
|
||||||
|
|
||||||
You can obtain your Zulip API key, create bots, and manage bots all
|
|
||||||
from your Zulip settings page; with current Zulip there's also a
|
|
||||||
button to download a `zuliprc` file for your account/server pair.
|
|
||||||
|
|
||||||
A typical simple bot sending API messages will look as follows:
|
|
||||||
|
|
||||||
At the top of the file:
|
|
||||||
|
|
||||||
# Make sure the Zulip API distribution's root directory is in sys.path, then:
|
|
||||||
import zulip
|
|
||||||
zulip_client = zulip.Client(email="your-bot@example.com", client="MyTestClient/0.1")
|
|
||||||
|
|
||||||
When you want to send a message:
|
|
||||||
|
|
||||||
message = {
|
|
||||||
"type": "stream",
|
|
||||||
"to": ["support"],
|
|
||||||
"subject": "your subject",
|
|
||||||
"content": "your content",
|
|
||||||
}
|
|
||||||
zulip_client.send_message(message)
|
|
||||||
|
|
||||||
If you are parsing arguments, you may find it useful to use Zulip's
|
|
||||||
option group; see any of our API examples for details on how to do this.
|
|
||||||
|
|
||||||
Additional examples:
|
|
||||||
|
|
||||||
client.send_message({'type': 'stream', 'content': 'Zulip rules!',
|
|
||||||
'subject': 'feedback', 'to': ['support']})
|
|
||||||
client.send_message({'type': 'private', 'content': 'Zulip rules!',
|
|
||||||
'to': ['user1@example.com', 'user2@example.com']})
|
|
||||||
|
|
||||||
send_message() returns a dict guaranteed to contain the following
|
|
||||||
keys: msg, result. For successful calls, result will be "success" and
|
|
||||||
msg will be the empty string. On error, result will be "error" and
|
|
||||||
msg will describe what went wrong.
|
|
||||||
|
|
||||||
#### Examples
|
|
||||||
|
|
||||||
The API bindings package comes with several nice example scripts that
|
|
||||||
show how to use the APIs; they are installed as part of the API
|
|
||||||
bindings bundle.
|
|
||||||
|
|
||||||
#### Logging
|
|
||||||
|
|
||||||
The Zulip API comes with a ZulipStream class which can be used with the
|
|
||||||
logging module:
|
|
||||||
|
|
||||||
```
|
|
||||||
import zulip
|
|
||||||
import logging
|
|
||||||
stream = zulip.ZulipStream(type="stream", to=["support"], subject="your subject")
|
|
||||||
logger = logging.getLogger("your_logger")
|
|
||||||
logger.addHandler(logging.StreamHandler(stream))
|
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
logger.info("This is an INFO test.")
|
|
||||||
logger.debug("This is a DEBUG test.")
|
|
||||||
logger.warn("This is a WARN test.")
|
|
||||||
logger.error("This is a ERROR test.")
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Sending messages
|
|
||||||
|
|
||||||
You can use the included `zulip-send` script to send messages via the
|
|
||||||
API directly from existing scripts.
|
|
||||||
|
|
||||||
zulip-send hamlet@example.com cordelia@example.com -m \
|
|
||||||
"Conscience doth make cowards of us all."
|
|
||||||
|
|
||||||
Alternatively, if you don't want to use your ~/.zuliprc file:
|
|
||||||
|
|
||||||
zulip-send --user shakespeare-bot@example.com \
|
|
||||||
--api-key a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 \
|
|
||||||
--site https://zulip.example.com \
|
|
||||||
hamlet@example.com cordelia@example.com -m \
|
|
||||||
"Conscience doth make cowards of us all."
|
|
||||||
|
|
||||||
#### Working with an untrusted server certificate
|
|
||||||
|
|
||||||
If your server has either a self-signed certificate, or a certificate signed
|
|
||||||
by a CA that you don't wish to globally trust then by default the API will
|
|
||||||
fail with an SSL verification error.
|
|
||||||
|
|
||||||
You can add `insecure=true` to your .zuliprc file.
|
|
||||||
|
|
||||||
[api]
|
|
||||||
site=https://zulip.example.com
|
|
||||||
insecure=true
|
|
||||||
|
|
||||||
This disables verification of the server certificate, so connections are
|
|
||||||
encrypted but unauthenticated. This is not secure, but may be good enough
|
|
||||||
for a development environment.
|
|
||||||
|
|
||||||
|
|
||||||
You can explicitly trust the server certificate using `cert_bundle=<filename>`
|
|
||||||
in your .zuliprc file.
|
|
||||||
|
|
||||||
[api]
|
|
||||||
site=https://zulip.example.com
|
|
||||||
cert_bundle=/home/bots/certs/zulip.example.com.crt
|
|
||||||
|
|
||||||
You can also explicitly trust a different set of Certificate Authorities from
|
|
||||||
the default bundle that is trusted by Python. For example to trust a company
|
|
||||||
internal CA.
|
|
||||||
|
|
||||||
[api]
|
|
||||||
site=https://zulip.example.com
|
|
||||||
cert_bundle=/home/bots/certs/example.com.ca-bundle
|
|
||||||
|
|
||||||
Save the server certificate (or the CA certificate) in its own file,
|
|
||||||
converting to PEM format first if necessary.
|
|
||||||
Verify that the certificate you have saved is the same as the one on the
|
|
||||||
server.
|
|
||||||
|
|
||||||
The `cert_bundle` option trusts the server / CA certificate only for
|
|
||||||
interaction with the zulip site, and is relatively secure.
|
|
||||||
|
|
||||||
Note that a certificate bundle is merely one or more certificates combined
|
|
||||||
into a single file.
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from typing import cast, Callable, Dict, Iterator, List
|
||||||
|
|
||||||
EXCLUDED_FILES = [
|
EXCLUDED_FILES = [
|
||||||
# This is an external file that doesn't comply with our codestyle
|
# This is an external file that doesn't comply with our codestyle
|
||||||
'integrations/perforce/git_p4.py',
|
'zulip/integrations/perforce/git_p4.py',
|
||||||
]
|
]
|
||||||
|
|
||||||
def lint_all(args, options):
|
def lint_all(args, options):
|
||||||
|
|
177
zulip/README.md
Normal file
177
zulip/README.md
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
#### Dependencies
|
||||||
|
|
||||||
|
The [Zulip API](https://zulipchat.com/api) Python bindings require the
|
||||||
|
following Python libraries:
|
||||||
|
|
||||||
|
* requests (version >= 0.12.1)
|
||||||
|
* simplejson
|
||||||
|
* six
|
||||||
|
* typing (version >= 3.5.2.2)
|
||||||
|
|
||||||
|
#### Installing
|
||||||
|
|
||||||
|
This package uses distutils, so you can just run:
|
||||||
|
|
||||||
|
python setup.py install
|
||||||
|
|
||||||
|
#### Using the API
|
||||||
|
|
||||||
|
For now, the only fully supported API operation is sending a message.
|
||||||
|
The other API queries work, but are under active development, so
|
||||||
|
please make sure we know you're using them so that we can notify you
|
||||||
|
as we make any changes to them.
|
||||||
|
|
||||||
|
The easiest way to use these API bindings is to base your tools off
|
||||||
|
of the example tools under examples/ in this distribution.
|
||||||
|
|
||||||
|
If you place your API key in the config file `~/.zuliprc` the Python
|
||||||
|
API bindings will automatically read it in. The format of the config
|
||||||
|
file is as follows:
|
||||||
|
|
||||||
|
[api]
|
||||||
|
key=<api key from the web interface>
|
||||||
|
email=<your email address>
|
||||||
|
site=<your Zulip server's URI>
|
||||||
|
insecure=<true or false, true means do not verify the server certificate>
|
||||||
|
cert_bundle=<path to a file containing CA or server certificates to trust>
|
||||||
|
|
||||||
|
If omitted, these settings have the following defaults:
|
||||||
|
|
||||||
|
insecure=false
|
||||||
|
cert_bundle=<the default CA bundle trusted by Python>
|
||||||
|
|
||||||
|
Alternatively, you may explicitly use "--user", "--api-key", and
|
||||||
|
`--site` in our examples, which is especially useful when testing. If
|
||||||
|
you are running several bots which share a home directory, we
|
||||||
|
recommend using `--config` to specify the path to the `zuliprc` file
|
||||||
|
for a specific bot. Finally, you can control the defaults for all of
|
||||||
|
these variables using the environment variables `ZULIP_CONFIG`,
|
||||||
|
`ZULIP_API_KEY`, `ZULIP_EMAIL`, `ZULIP_SITE`, `ZULIP_CERT`,
|
||||||
|
`ZULIP_CERT_KEY`, and `ZULIP_CERT_BUNDLE`. Command-line options take
|
||||||
|
precedence over environment variables take precedence over the config
|
||||||
|
files.
|
||||||
|
|
||||||
|
The command line equivalents for other configuration options are:
|
||||||
|
|
||||||
|
--insecure
|
||||||
|
--cert-bundle=<file>
|
||||||
|
|
||||||
|
You can obtain your Zulip API key, create bots, and manage bots all
|
||||||
|
from your Zulip settings page; with current Zulip there's also a
|
||||||
|
button to download a `zuliprc` file for your account/server pair.
|
||||||
|
|
||||||
|
A typical simple bot sending API messages will look as follows:
|
||||||
|
|
||||||
|
At the top of the file:
|
||||||
|
|
||||||
|
# Make sure the Zulip API distribution's root directory is in sys.path, then:
|
||||||
|
import zulip
|
||||||
|
zulip_client = zulip.Client(email="your-bot@example.com", client="MyTestClient/0.1")
|
||||||
|
|
||||||
|
When you want to send a message:
|
||||||
|
|
||||||
|
message = {
|
||||||
|
"type": "stream",
|
||||||
|
"to": ["support"],
|
||||||
|
"subject": "your subject",
|
||||||
|
"content": "your content",
|
||||||
|
}
|
||||||
|
zulip_client.send_message(message)
|
||||||
|
|
||||||
|
If you are parsing arguments, you may find it useful to use Zulip's
|
||||||
|
option group; see any of our API examples for details on how to do this.
|
||||||
|
|
||||||
|
Additional examples:
|
||||||
|
|
||||||
|
client.send_message({'type': 'stream', 'content': 'Zulip rules!',
|
||||||
|
'subject': 'feedback', 'to': ['support']})
|
||||||
|
client.send_message({'type': 'private', 'content': 'Zulip rules!',
|
||||||
|
'to': ['user1@example.com', 'user2@example.com']})
|
||||||
|
|
||||||
|
send_message() returns a dict guaranteed to contain the following
|
||||||
|
keys: msg, result. For successful calls, result will be "success" and
|
||||||
|
msg will be the empty string. On error, result will be "error" and
|
||||||
|
msg will describe what went wrong.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
The API bindings package comes with several nice example scripts that
|
||||||
|
show how to use the APIs; they are installed as part of the API
|
||||||
|
bindings bundle.
|
||||||
|
|
||||||
|
#### Logging
|
||||||
|
|
||||||
|
The Zulip API comes with a ZulipStream class which can be used with the
|
||||||
|
logging module:
|
||||||
|
|
||||||
|
```
|
||||||
|
import zulip
|
||||||
|
import logging
|
||||||
|
stream = zulip.ZulipStream(type="stream", to=["support"], subject="your subject")
|
||||||
|
logger = logging.getLogger("your_logger")
|
||||||
|
logger.addHandler(logging.StreamHandler(stream))
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
logger.info("This is an INFO test.")
|
||||||
|
logger.debug("This is a DEBUG test.")
|
||||||
|
logger.warn("This is a WARN test.")
|
||||||
|
logger.error("This is a ERROR test.")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Sending messages
|
||||||
|
|
||||||
|
You can use the included `zulip-send` script to send messages via the
|
||||||
|
API directly from existing scripts.
|
||||||
|
|
||||||
|
zulip-send hamlet@example.com cordelia@example.com -m \
|
||||||
|
"Conscience doth make cowards of us all."
|
||||||
|
|
||||||
|
Alternatively, if you don't want to use your ~/.zuliprc file:
|
||||||
|
|
||||||
|
zulip-send --user shakespeare-bot@example.com \
|
||||||
|
--api-key a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 \
|
||||||
|
--site https://zulip.example.com \
|
||||||
|
hamlet@example.com cordelia@example.com -m \
|
||||||
|
"Conscience doth make cowards of us all."
|
||||||
|
|
||||||
|
#### Working with an untrusted server certificate
|
||||||
|
|
||||||
|
If your server has either a self-signed certificate, or a certificate signed
|
||||||
|
by a CA that you don't wish to globally trust then by default the API will
|
||||||
|
fail with an SSL verification error.
|
||||||
|
|
||||||
|
You can add `insecure=true` to your .zuliprc file.
|
||||||
|
|
||||||
|
[api]
|
||||||
|
site=https://zulip.example.com
|
||||||
|
insecure=true
|
||||||
|
|
||||||
|
This disables verification of the server certificate, so connections are
|
||||||
|
encrypted but unauthenticated. This is not secure, but may be good enough
|
||||||
|
for a development environment.
|
||||||
|
|
||||||
|
|
||||||
|
You can explicitly trust the server certificate using `cert_bundle=<filename>`
|
||||||
|
in your .zuliprc file.
|
||||||
|
|
||||||
|
[api]
|
||||||
|
site=https://zulip.example.com
|
||||||
|
cert_bundle=/home/bots/certs/zulip.example.com.crt
|
||||||
|
|
||||||
|
You can also explicitly trust a different set of Certificate Authorities from
|
||||||
|
the default bundle that is trusted by Python. For example to trust a company
|
||||||
|
internal CA.
|
||||||
|
|
||||||
|
[api]
|
||||||
|
site=https://zulip.example.com
|
||||||
|
cert_bundle=/home/bots/certs/example.com.ca-bundle
|
||||||
|
|
||||||
|
Save the server certificate (or the CA certificate) in its own file,
|
||||||
|
converting to PEM format first if necessary.
|
||||||
|
Verify that the certificate you have saved is the same as the one on the
|
||||||
|
server.
|
||||||
|
|
||||||
|
The `cert_bundle` option trusts the server / CA certificate only for
|
||||||
|
interaction with the zulip site, and is relatively secure.
|
||||||
|
|
||||||
|
Note that a certificate bundle is merely one or more certificates combined
|
||||||
|
into a single file.
|
|
@ -59,10 +59,8 @@ package_info = dict(
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'zulip-send=zulip.send:main',
|
'zulip-send=zulip.send:main',
|
||||||
'zulip-bot-server=zulip.bot_server:main',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
test_suite='tests',
|
|
||||||
) # type: Dict[str, Any]
|
) # type: Dict[str, Any]
|
||||||
|
|
||||||
setuptools_info = dict(
|
setuptools_info = dict(
|
||||||
|
@ -70,17 +68,13 @@ setuptools_info = dict(
|
||||||
'simplejson',
|
'simplejson',
|
||||||
'six',
|
'six',
|
||||||
'typing>=3.5.2.2',
|
'typing>=3.5.2.2',
|
||||||
'flask>=0.12.2',
|
|
||||||
'mock>=2.0.0',
|
|
||||||
# for pep8 linter
|
|
||||||
'pycodestyle==2.3.1',
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
package_info.update(setuptools_info)
|
package_info.update(setuptools_info)
|
||||||
package_info['packages'] = find_packages(exclude=["tests"])
|
package_info['packages'] = find_packages()
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
|
@ -98,12 +92,7 @@ except ImportError:
|
||||||
print("requests >=0.12.1 is not installed", file=sys.stderr)
|
print("requests >=0.12.1 is not installed", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
package_list = ['zulip', 'bots_api', 'bots']
|
package_info['packages'] = ['zulip']
|
||||||
bots_dirs = os.listdir('bots')
|
|
||||||
for bot in bots_dirs:
|
|
||||||
if os.path.isdir(os.path.join('bots', bot)):
|
|
||||||
package_list.append('bots.' + bot)
|
|
||||||
package_info['packages'] = package_list
|
|
||||||
|
|
||||||
|
|
||||||
setup(**package_info)
|
setup(**package_info)
|
|
@ -23,14 +23,11 @@
|
||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
import optparse
|
import optparse
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
|
||||||
|
|
||||||
import zulip
|
import zulip
|
||||||
|
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
Loading…
Reference in a new issue