diff --git a/README.md b/README.md index 91935b6..d3a5bd4 100644 --- a/README.md +++ b/README.md @@ -1,177 +1,8 @@ -#### Dependencies +# Zulip API -The [Zulip API](https://zulipchat.com/api) Python bindings require the -following Python libraries: +This repository contains the source code for Zulip's PyPI packages: -* 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= - email= - site= - insecure= - cert_bundle= - -If omitted, these settings have the following defaults: - - insecure=false - cert_bundle= - -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= - -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=` -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. +* `zulip`: [PyPI package](https://pypi.python.org/pypi/zulip/) + for Zulip's API bindings. +* `zulip_bots`: PyPI package for Zulip's bots and bots API. +* `zulip_botserver`: PyPI package for Zulip's Flask bot server. diff --git a/tools/lint b/tools/lint index 27811e3..5ef520c 100755 --- a/tools/lint +++ b/tools/lint @@ -9,7 +9,7 @@ from typing import cast, Callable, Dict, Iterator, List EXCLUDED_FILES = [ # 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): diff --git a/MANIFEST.in b/zulip/MANIFEST.in similarity index 100% rename from MANIFEST.in rename to zulip/MANIFEST.in diff --git a/zulip/README.md b/zulip/README.md new file mode 100644 index 0000000..91935b6 --- /dev/null +++ b/zulip/README.md @@ -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= + email= + site= + insecure= + cert_bundle= + +If omitted, these settings have the following defaults: + + insecure=false + cert_bundle= + +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= + +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=` +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. diff --git a/examples/create-user b/zulip/examples/create-user similarity index 100% rename from examples/create-user rename to zulip/examples/create-user diff --git a/examples/edit-message b/zulip/examples/edit-message similarity index 100% rename from examples/edit-message rename to zulip/examples/edit-message diff --git a/examples/get-presence b/zulip/examples/get-presence similarity index 100% rename from examples/get-presence rename to zulip/examples/get-presence diff --git a/examples/get-public-streams b/zulip/examples/get-public-streams similarity index 100% rename from examples/get-public-streams rename to zulip/examples/get-public-streams diff --git a/examples/list-members b/zulip/examples/list-members similarity index 100% rename from examples/list-members rename to zulip/examples/list-members diff --git a/examples/list-subscriptions b/zulip/examples/list-subscriptions similarity index 100% rename from examples/list-subscriptions rename to zulip/examples/list-subscriptions diff --git a/examples/print-events b/zulip/examples/print-events similarity index 100% rename from examples/print-events rename to zulip/examples/print-events diff --git a/examples/print-messages b/zulip/examples/print-messages similarity index 100% rename from examples/print-messages rename to zulip/examples/print-messages diff --git a/examples/recent-messages b/zulip/examples/recent-messages similarity index 100% rename from examples/recent-messages rename to zulip/examples/recent-messages diff --git a/examples/send-message b/zulip/examples/send-message similarity index 100% rename from examples/send-message rename to zulip/examples/send-message diff --git a/examples/subscribe b/zulip/examples/subscribe similarity index 100% rename from examples/subscribe rename to zulip/examples/subscribe diff --git a/examples/unsubscribe b/zulip/examples/unsubscribe similarity index 100% rename from examples/unsubscribe rename to zulip/examples/unsubscribe diff --git a/examples/upload-file b/zulip/examples/upload-file similarity index 100% rename from examples/upload-file rename to zulip/examples/upload-file diff --git a/examples/zuliprc b/zulip/examples/zuliprc similarity index 100% rename from examples/zuliprc rename to zulip/examples/zuliprc diff --git a/integrations/codebase/zulip_codebase_config.py b/zulip/integrations/codebase/zulip_codebase_config.py similarity index 100% rename from integrations/codebase/zulip_codebase_config.py rename to zulip/integrations/codebase/zulip_codebase_config.py diff --git a/integrations/codebase/zulip_codebase_mirror b/zulip/integrations/codebase/zulip_codebase_mirror similarity index 100% rename from integrations/codebase/zulip_codebase_mirror rename to zulip/integrations/codebase/zulip_codebase_mirror diff --git a/integrations/git/post-receive b/zulip/integrations/git/post-receive similarity index 100% rename from integrations/git/post-receive rename to zulip/integrations/git/post-receive diff --git a/integrations/git/zulip_git_config.py b/zulip/integrations/git/zulip_git_config.py similarity index 100% rename from integrations/git/zulip_git_config.py rename to zulip/integrations/git/zulip_git_config.py diff --git a/integrations/google/get-google-credentials b/zulip/integrations/google/get-google-credentials similarity index 100% rename from integrations/google/get-google-credentials rename to zulip/integrations/google/get-google-credentials diff --git a/integrations/google/google-calendar b/zulip/integrations/google/google-calendar similarity index 100% rename from integrations/google/google-calendar rename to zulip/integrations/google/google-calendar diff --git a/integrations/hg/zulip-changegroup.py b/zulip/integrations/hg/zulip-changegroup.py similarity index 100% rename from integrations/hg/zulip-changegroup.py rename to zulip/integrations/hg/zulip-changegroup.py diff --git a/integrations/irc/irc-mirror.py b/zulip/integrations/irc/irc-mirror.py similarity index 100% rename from integrations/irc/irc-mirror.py rename to zulip/integrations/irc/irc-mirror.py diff --git a/integrations/jabber/jabber_mirror.py b/zulip/integrations/jabber/jabber_mirror.py similarity index 100% rename from integrations/jabber/jabber_mirror.py rename to zulip/integrations/jabber/jabber_mirror.py diff --git a/integrations/jabber/jabber_mirror_backend.py b/zulip/integrations/jabber/jabber_mirror_backend.py similarity index 100% rename from integrations/jabber/jabber_mirror_backend.py rename to zulip/integrations/jabber/jabber_mirror_backend.py diff --git a/integrations/jira/org/humbug/jira/ZulipListener.groovy b/zulip/integrations/jira/org/humbug/jira/ZulipListener.groovy similarity index 100% rename from integrations/jira/org/humbug/jira/ZulipListener.groovy rename to zulip/integrations/jira/org/humbug/jira/ZulipListener.groovy diff --git a/integrations/log2zulip/log2zulip b/zulip/integrations/log2zulip/log2zulip similarity index 100% rename from integrations/log2zulip/log2zulip rename to zulip/integrations/log2zulip/log2zulip diff --git a/integrations/nagios/nagios-notify-zulip b/zulip/integrations/nagios/nagios-notify-zulip similarity index 100% rename from integrations/nagios/nagios-notify-zulip rename to zulip/integrations/nagios/nagios-notify-zulip diff --git a/integrations/nagios/zulip_nagios.cfg b/zulip/integrations/nagios/zulip_nagios.cfg similarity index 100% rename from integrations/nagios/zulip_nagios.cfg rename to zulip/integrations/nagios/zulip_nagios.cfg diff --git a/integrations/nagios/zuliprc.example b/zulip/integrations/nagios/zuliprc.example similarity index 100% rename from integrations/nagios/zuliprc.example rename to zulip/integrations/nagios/zuliprc.example diff --git a/integrations/openshift/post_deploy b/zulip/integrations/openshift/post_deploy similarity index 100% rename from integrations/openshift/post_deploy rename to zulip/integrations/openshift/post_deploy diff --git a/integrations/openshift/zulip_openshift_config.py b/zulip/integrations/openshift/zulip_openshift_config.py similarity index 100% rename from integrations/openshift/zulip_openshift_config.py rename to zulip/integrations/openshift/zulip_openshift_config.py diff --git a/integrations/perforce/git_p4.py b/zulip/integrations/perforce/git_p4.py similarity index 100% rename from integrations/perforce/git_p4.py rename to zulip/integrations/perforce/git_p4.py diff --git a/integrations/perforce/license.txt b/zulip/integrations/perforce/license.txt similarity index 100% rename from integrations/perforce/license.txt rename to zulip/integrations/perforce/license.txt diff --git a/integrations/perforce/zulip_change-commit.py b/zulip/integrations/perforce/zulip_change-commit.py similarity index 100% rename from integrations/perforce/zulip_change-commit.py rename to zulip/integrations/perforce/zulip_change-commit.py diff --git a/integrations/perforce/zulip_perforce_config.py b/zulip/integrations/perforce/zulip_perforce_config.py similarity index 100% rename from integrations/perforce/zulip_perforce_config.py rename to zulip/integrations/perforce/zulip_perforce_config.py diff --git a/integrations/rss/rss-bot b/zulip/integrations/rss/rss-bot similarity index 100% rename from integrations/rss/rss-bot rename to zulip/integrations/rss/rss-bot diff --git a/integrations/slack/zulip_slack.py b/zulip/integrations/slack/zulip_slack.py similarity index 100% rename from integrations/slack/zulip_slack.py rename to zulip/integrations/slack/zulip_slack.py diff --git a/integrations/slack/zulip_slack_config.py b/zulip/integrations/slack/zulip_slack_config.py similarity index 100% rename from integrations/slack/zulip_slack_config.py rename to zulip/integrations/slack/zulip_slack_config.py diff --git a/integrations/svn/post-commit b/zulip/integrations/svn/post-commit similarity index 100% rename from integrations/svn/post-commit rename to zulip/integrations/svn/post-commit diff --git a/integrations/svn/zulip_svn_config.py b/zulip/integrations/svn/zulip_svn_config.py similarity index 100% rename from integrations/svn/zulip_svn_config.py rename to zulip/integrations/svn/zulip_svn_config.py diff --git a/integrations/trac/zulip_trac.py b/zulip/integrations/trac/zulip_trac.py similarity index 100% rename from integrations/trac/zulip_trac.py rename to zulip/integrations/trac/zulip_trac.py diff --git a/integrations/trac/zulip_trac_config.py b/zulip/integrations/trac/zulip_trac_config.py similarity index 100% rename from integrations/trac/zulip_trac_config.py rename to zulip/integrations/trac/zulip_trac_config.py diff --git a/integrations/twitter/twitter-bot b/zulip/integrations/twitter/twitter-bot similarity index 100% rename from integrations/twitter/twitter-bot rename to zulip/integrations/twitter/twitter-bot diff --git a/integrations/twitter/twitter-search-bot b/zulip/integrations/twitter/twitter-search-bot similarity index 100% rename from integrations/twitter/twitter-search-bot rename to zulip/integrations/twitter/twitter-search-bot diff --git a/integrations/zephyr/check-mirroring b/zulip/integrations/zephyr/check-mirroring similarity index 100% rename from integrations/zephyr/check-mirroring rename to zulip/integrations/zephyr/check-mirroring diff --git a/integrations/zephyr/process_ccache b/zulip/integrations/zephyr/process_ccache similarity index 100% rename from integrations/zephyr/process_ccache rename to zulip/integrations/zephyr/process_ccache diff --git a/integrations/zephyr/sync-public-streams b/zulip/integrations/zephyr/sync-public-streams similarity index 100% rename from integrations/zephyr/sync-public-streams rename to zulip/integrations/zephyr/sync-public-streams diff --git a/integrations/zephyr/zephyr_mirror.py b/zulip/integrations/zephyr/zephyr_mirror.py similarity index 100% rename from integrations/zephyr/zephyr_mirror.py rename to zulip/integrations/zephyr/zephyr_mirror.py diff --git a/integrations/zephyr/zephyr_mirror_backend.py b/zulip/integrations/zephyr/zephyr_mirror_backend.py similarity index 100% rename from integrations/zephyr/zephyr_mirror_backend.py rename to zulip/integrations/zephyr/zephyr_mirror_backend.py diff --git a/integrations/zephyr/zmirror-renew-kerberos b/zulip/integrations/zephyr/zmirror-renew-kerberos similarity index 100% rename from integrations/zephyr/zmirror-renew-kerberos rename to zulip/integrations/zephyr/zmirror-renew-kerberos diff --git a/integrations/zephyr/zmirror_private.conf.template b/zulip/integrations/zephyr/zmirror_private.conf.template similarity index 100% rename from integrations/zephyr/zmirror_private.conf.template rename to zulip/integrations/zephyr/zmirror_private.conf.template diff --git a/setup.cfg b/zulip/setup.cfg similarity index 100% rename from setup.cfg rename to zulip/setup.cfg diff --git a/setup.py b/zulip/setup.py similarity index 84% rename from setup.py rename to zulip/setup.py index 73a00db..0acf180 100755 --- a/setup.py +++ b/zulip/setup.py @@ -59,10 +59,8 @@ package_info = dict( entry_points={ 'console_scripts': [ 'zulip-send=zulip.send:main', - 'zulip-bot-server=zulip.bot_server:main', ], }, - test_suite='tests', ) # type: Dict[str, Any] setuptools_info = dict( @@ -70,17 +68,13 @@ setuptools_info = dict( 'simplejson', 'six', 'typing>=3.5.2.2', - 'flask>=0.12.2', - 'mock>=2.0.0', - # for pep8 linter - 'pycodestyle==2.3.1', ], ) try: from setuptools import setup, find_packages package_info.update(setuptools_info) - package_info['packages'] = find_packages(exclude=["tests"]) + package_info['packages'] = find_packages() except ImportError: from distutils.core import setup @@ -98,12 +92,7 @@ except ImportError: print("requests >=0.12.1 is not installed", file=sys.stderr) sys.exit(1) - package_list = ['zulip', 'bots_api', 'bots'] - 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 + package_info['packages'] = ['zulip'] setup(**package_info) diff --git a/zulip/__init__.py b/zulip/zulip/__init__.py similarity index 100% rename from zulip/__init__.py rename to zulip/zulip/__init__.py diff --git a/zulip/send.py b/zulip/zulip/send.py similarity index 98% rename from zulip/send.py rename to zulip/zulip/send.py index d740e92..fa60127 100755 --- a/zulip/send.py +++ b/zulip/zulip/send.py @@ -23,14 +23,11 @@ # THE SOFTWARE. import sys -import os import optparse import logging from typing import Any, Dict, List, Optional -sys.path.append(os.path.join(os.path.dirname(__file__), '..')) - import zulip logging.basicConfig()