Skip to content

About

Java client for the Zulip REST API

Topics

Resources

Stars

13 stars

Watchers

1 watching

Forks

Repository files navigation

badge :license Apache2 blue zulip java client endpoint?url=https%3A%2F%2Fjamesnetherton.github.io%2Fzulip java client%2Fversion

Zulip Java Client

Java client for the Zulip chat server REST API.

Refer to the compatibility matrix to see which version of the Zulip server this library is compatible with.

Quick start

Here’s how to get started with the Zulip Java client and starting making API requests.

Dependencies

Add the zulip-java-client dependency to your project.

Maven

<dependency>
    <groupId>com.github.jamesnetherton</groupId>
    <artifactId>zulip-java-client</artifactId>
    <version>0.10.1</version>
</dependency>

Gradle

dependencies {
    compile 'com.github.jamesnetherton:zulip-java-client:0.10.1'
}

Instantiate the Zulip client

Create a Zulip instance by passing the user email address, API key and the base URL of the Zulip server.

Zulip zulip = new Zulip("youremail@address.com", "your-api-key", "http://yourdomain.zulip.com")

Now you can start interacting with the Zulip APIs.

long messageId = zulip.messages()
    .sendStreamMessage("Hello World!", "Test Stream", "Test Topic")
    .execute();

When you are finished, it’s good practice to close the Zulip client.

zulip.close();

Advanced configuration

There are a few ways of customising the Zulip client configuration if you need to configure a proxy server or disable SSL certificate validation.

Configuration builder

Zulip zulip = new Zulip.Builder()
    .site(...)
    .email(...)
    .apiKey(...)
    .insecure(...)
    .build();

Zuliprc file

There is the option to use a zuliprc file as the configuration source.

Load zuliprc from the user home directory.

ZulipConfiguration configuration = ZulipConfiguration.fromZuliprc();
Zulip zulip = new Zulip(configuration);

Load zuliprc from a specified file.

ZulipConfiguration configuration = ZulipConfiguration.fromZuliprc(new File("/path/to/zuliprc"));
Zulip zulip = new Zulip(configuration);

The zuliprc file has the following format.

key=API key from the web interface
email=your email address
site=your Zulip server base URL
insecure=whether to disable SSL certificate validation (true or false)

Instantiate ZulipConfiguration

Or instantiate the ZulipConfiguration directly.

ZulipConfiguration configuration = new ZulipConfiguration("http://a.site.com", "name@email.com", "an-api-key");
Zulip zulip = new Zulip(configuration);

API Request Builders

Each API has a request builder object which is used to set the various parameter values expected by the API endpoint.

Mandatory values will always be part of the API request method signature, while optional values can be provided through the 'with' builder methods.

Here’s an example of this with the edit message API.

zulip.messages().editMessage(1) (1)
        .withContent("edited content") (2)
        .withPropagateMode(PropagateMode.CHANGE_ONE)
        .withSendNotificationToNewThread(true)
        .withSendNotificationToOldThread(true)
        .withStreamId(1)
        .withTopic("different topic")
        .execute(); (3)
  1. The zulip client object exposes methods which aggregate the REST APIs together under logical groups such as messages, streams & users. The editMessage API expects one mandatory parameter - the message id.

  2. Then follows a number of optional API parameters.

  3. The request builder is completed and sent to the Zulip server with the execute() method. This MUST be called in order for the request to be sent.

Exception handling

Zulip API error responses are thrown as ZulipClientException. The exception object contains details about the error such as the code and a descriptive message.

try {
    zulip.messages.send(..);
} catch (ZulipClientException e) {
    System.out.println(e.getMessage());
    System.out.println(e.getCode());
}

If you exceed the API request rate limit, then the exception cause will be set to ZulipRateLimitExceeded. It contains a method which enables you to get the time at which the rate limit is reset. Note that the value is a Unix epoch value.

try {
    zulip.messages.send(..);
} catch (ZulipClientException e) {
    Throwable cause = e.getCause();
    if (cause instanceof ZulipRateLimitExceededException) {
        ZulipRateLimitExceededException rle = (ZulipRateLimitExceededException) cause;
        System.out.println(rle.getReteLimitReset());
    }
}

Real time events API

There is experimental support for the Zulip real-time events API.

Capturing new messages

To consume messages posted to all streams.

EventPoller eventPoller = zulip.events().captureMessageEvents(new MessageEventListener() {
    @Override
    public void onEvent(Message event) {
        System.out.println(event.getContent());
    }
});

eventPoller.start();

// Do useful app work

eventPoller.stop();

To filter messages you may use one or more narrow expressions.

EventPoller eventPoller = zulip.events().captureMessageEvents(new MessageEventListener() {
    @Override
    public void onEvent(Message event) {
        System.out.println(event.getContent());
    }
}, Narrow.of("stream", "my-stream-name"));

eventPoller.start();

// Do useful app work

eventPoller.stop();

Capturing other event types

The captureEvents() builder registers listeners for one or more event types. The event queue is only subscribed to the event types that have a listener.

EventPoller eventPoller = zulip.events().captureEvents()
        .onMessage(event -> System.out.println(event.getMessage().getContent()))
        .onUpdateMessage(event -> System.out.println("Message " + event.getMessageId() + " edited: " + event.getContent()))
        .onDeleteMessage(event -> System.out.println("Messages deleted: " + event.getMessageIds()))
        .onReaction(event -> System.out.println(event.getOperation() + " reaction " + event.getEmojiName()))
        .build();

eventPoller.start();

// Do useful app work

eventPoller.stop();

Listeners with dedicated event classes are available for the following event types.

Builder method Event type Event class

onMessage

message

MessageEvent

onUpdateMessage

update_message

UpdateMessageEvent

onDeleteMessage

delete_message

DeleteMessageEvent

onReaction

reaction

ReactionEvent

onUpdateMessageFlags

update_message_flags

UpdateMessageFlagsEvent

onTyping

typing

TypingEvent

onTypingEditMessage

typing_edit_message

TypingEditMessageEvent

onSubmessage

submessage

SubmessageEvent

Any other event type can be consumed with the on method and the EventType enum. The event payload is available from Event.getProperties().

EventPoller eventPoller = zulip.events().captureEvents()
        .on(EventType.SUBSCRIPTION, event -> System.out.println(event.getProperties().get("op")))
        .build();

Event types introduced in newer Zulip versions that are not yet defined by EventType can be consumed by passing the event type name.

EventPoller eventPoller = zulip.events().captureEvents()
        .on("some_new_event_type", event -> System.out.println(event.getProperties()))
        .build();

The builder also supports some additional options.

EventPoller eventPoller = zulip.events().captureEvents()
        .onMessage(event -> System.out.println(event.getMessage().getContent()))
        .withNarrows(Narrow.of("channel", "my-channel-name")) (1)
        .withAllPublicStreams(true) (2)
        .withIdleQueueTimeout(3600) (3)
        .withExecutorService(Executors.newFixedThreadPool(2)) (4)
        .build();
  1. Filters which messages are captured. Note that narrows only apply to message events. Other event types, such as update_message or reaction, are received for all messages that the user has access to.

  2. Captures message events from all public channels, not only the channels that the user is subscribed to.

  3. The minimum number of seconds that the Zulip server keeps the event queue alive when it is not being polled. Requires Zulip 12 or later.

  4. A custom ExecutorService for invoking event listeners. If not specified, a cached thread pool is used and shut down when the EventPoller is stopped.

Listeners are invoked asynchronously, so events are not guaranteed to be processed in the order they were received. Keep listener implementations lightweight to avoid tying up the executor.

About

Java client for the Zulip REST API

Topics

Resources

Stars

13 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages