Skip to content

Commit

Permalink
Merge pull request #18 from HubSpot/update-readme
Browse files Browse the repository at this point in the history
Update readme
  • Loading branch information
szabowexler authored Apr 5, 2018
2 parents 0b235a0 + fe0a0ea commit 152f416
Showing 1 changed file with 160 additions and 6 deletions.
166 changes: 160 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,47 @@
# slack-client
# slack-client

An asychronous HTTP client wrapping Slack's [RPC-style web api](https://api.slack.com/web). The API here is simple: you just need a `SlackClient` and you're good to go.
![license](https://img.shields.io/github/license/HubSpot/slack-client.svg?style=social)
![GitHub last commit](https://img.shields.io/github/last-commit/HubSpot/slack-client.svg?style=social)
[![Build Status](https://travis-ci.org/HubSpot/slack-client.svg?branch=master)](https://travis-ci.org/HubSpot/slack-client) ![GitHub release](https://img.shields.io/github/release/HubSpot/slack-client.svg) ![Maven metadata URI](https://img.shields.io/maven-metadata/v/http/central.maven.org/maven2/com/hubspot/slack/slack-client/maven-metadata.xml.svg)

* [Overview](overview)
* [Usage](usage)
* [Setting up Guice](setting-up-guice)
* [Using the Client](using-the-client)
* [Find a user by email, then send a message](find-a-user-by-email-then-send-a-message)
* [Filtering messages in a QA environment to specific channels](filtering-messages-in-a-qa-environment-to-specific-channels)
* [Printing requests for specific methods](printing-requests-for-specific-methods)


## Overview

An asychronous HTTP client wrapping Slack's [RPC-style web api](https://api.slack.com/web). Provides an extensible API with builder-style parameters and responses, allowing you to focus on your interactions with users, rather than your interactions with Slack. Notably, we:

* Implement most (if not all) of Slack's [web API](https://api.slack.com/web), and actively maintain this project
* Provide per-method in-memory rate limiting so you don't have to worry about overwhelming slack from a single process
* Expose highly configurable hooks to allow filtering and debugging in an extensible way

## Usage

Include the base and client modules in your POM:
To use with Maven-based projects, add the following dependencies::

```xml
<dependency>
<groupId>com.hubspot.slack</groupId>
<artifactId>slack-base</artifactId>
<version>1.0</version>
<version>{latest version}</version>
</dependency>
<dependency>
<groupId>com.hubspot.slack</groupId>
<artifactId>slack-java-client</artifactId>
<version>1.0</version>
<version>{latest version}</version>
</dependency>
```

Latest version can be seen [here, on Maven central](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.hubspot.slack%22).

### Seting up Guice

Install the `SlackClientModule` in the Guice module you want to use to talk to slack.

```java
Expand Down Expand Up @@ -52,11 +75,142 @@ public class MySlacker {
) {
this.slackClient = clientFactory.build(
SlackClientRuntimeConfig.builder()
.setTokenSupplier(() -> "your token here")
// ... all your configuration here
.build()
);
}

// then just use the client!
}
```

### Using the Client

If you're not familiar with Java 8's `CompletableFuture` API, know that you can transform this client from an asynchronous one to a synchronous one by calling `join` on any of the futures returned. To simplify getting started, here are some examples of using the client for common tasks.

#### Find a user by email, then send a message

```java
void sendMeAMessage() {
Optional<SlackUser> meMaybe = findMe();
if (!meMaybe.isPresent()) {
LOG.error("Couldn't find me in slack!");
}

slackMe(meMaybe.get());
}

Optional<SlackUser> findMe() {
/**
* Since we may have to enumerate a large set, we chunk it up into pages, and handle each page separately.
*/
Iterable<CompletableFuture<Result<List<SlackUser>, SlackError>>> userPageFutures = slackClient.listUsers();

/**
* We'll enumerate the pages so we can short-circuit and break out early if we can
*/
for (CompletableFuture<Result<List<SlackUser>, SlackError>> userPageFuture : userPageFutures) {
Result<List<SlackUser>, SlackError> pageResult = userPageFuture.join();

// If there was a problem fetching the page, it'll percolate here as a RTE
List<SlackUser> slackUsers = pageResult.unwrapOrElseThrow();
Optional<SlackUser> matchingUser = slackUsers.stream()
.filter(user ->
user.getProfile()
.flatMap(UserProfile::getEmail) // flatMap just says the profile could be absent, or the email could be absent
.filter("[email protected]"::equalsIgnoreCase) // keep it only if it's the email we want...
.isPresent()) // and we'll filter the original SlackUser list to find the one with the profile that's me!
.findFirst();

if (matchingUser.isPresent()) {
return matchingUser;
}
}

return Optional.empty();
}

ChatPostMessageResponse slackMe(SlackUser me) {
Result<ChatPostMessageResponse, SlackError> postResult = slackClient.postMessage(
ChatPostMessageParams.builder()
.setText("Hello me! Here's a slack message!")
.setChannelId("a fancy channel ID here")
.build()
).join();

return postResult.unwrapOrElseThrow();// again, release failure here as a RTE
}
```

#### Filtering messages in a QA environment to specific channels

```java
public class MySlacker {
private final SlackClient slackClient;

public MySlacker(
SlackWebClient.Factory clientFactory
) {
this.slackClient = clientFactory.build(
SlackClientRuntimeConfig.builder()
.setTokenSupplier(() -> "your token here")
.setMethodFilter(
new SlackMethodAcceptor() {
@Override
public String getFailureExplanation(SlackMethod method, Object params) {
return "Only allow WRITE methods to our special channel in QA!";
}

@Override
public boolean test(SlackMethod slackMethod, Object o) {
if (isQa() && slackMethod.getWriteMode() == MethodWriteMode.WRITE) {
if (o instanceof HasChannel && ((HasChannel) o).getChannelId().equals("snazzy id")) {
return true;
}
return false;
}

return true;
}
})
// ... all your configuration here
.build()
);
}

// then just use the client!
}
```

#### Printing requests for specific methods

```java
public class MySlacker {
private final SlackClient slackClient;

public MySlacker(
SlackWebClient.Factory clientFactory
) {
this.slackClient = clientFactory.build(
SlackClientRuntimeConfig.builder()
.setTokenSupplier(() -> "your token here")
.setRequestDebugger(
new RequestDebugger() {
@Override
public void debug(long requestId, SlackMethod method, HttpRequest request) {
if (method == SlackMethods.chat_postEphemeral) {
LOG.info("Posting ephemeral message {}", format(request));
}
}
}
)
// ... all your configuration here
.builder()
.build()
);
}

// then just use the client!
}
```
```

0 comments on commit 152f416

Please sign in to comment.