jSlack is a Java library to easily integrate your operations with Slack. The library currently supports the following APIs.
- Incoming Webhooks
- API Methods
- Real Time Messaging API
- SCIM API
- Audit Logs API
- Status API
- Useful modules to build Slack App backend services
Check the latest version on the Maven Central repository.
The following is an example using Maven. Of course, it's also possible to grab the library via Gradle, sbt and any other build tools.
<groupId>com.github.seratch</groupId>
<artifactId>jslack</artifactId>
<version>{latest version}</version>
See also: Getting started with groovysh
If you really don't need classes for building Slack app backend (= you need only Webhook/Web API/RTM API clients), just depending on jslack-api-client
would be enough.
<groupId>com.github.seratch</groupId>
<artifactId>jslack-api-client</artifactId>
<version>{latest version}</version>
If you like using Kotlin, check this repository as well 🙌
Incoming Webhooks is a simple way to post messages from external sources into Slack via ordinary HTTP requests.
https://api.slack.com/incoming-webhooks
jSlack naturally wraps its interface in Java. After lightly reading the official guide, you should be able to use it immediately.
import com.github.seratch.jslack.*;
import com.github.seratch.jslack.api.webhook.*;
// https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
String url = System.getenv("SLACK_WEBHOOK_URL");
Payload payload = Payload.builder()
.text("Hello World!")
.build();
Slack slack = Slack.getInstance();
WebhookResponse response = slack.send(url, payload);
// response.code, response.message, response.body
Here is a small example using Block Kit.
ButtonElement button = ButtonElement.builder()
.text(PlainTextObject.builder().emoji(true).text("Farmhouse").build())
.value("click_me_123")
.build();
LayoutBlock block = ActionsBlock.builder().elements(Arrays.asList(button)).build();
List<LayoutBlock> blocks = Arrays.asList(block);
Payload payload = Payload.builder().blocks(blocks).build();
Slack slack = Slack.getInstance();
WebhookResponse response = slack.send(url, payload);
// response.code, response.message, response.body
It's also possible to directly give a raw payload.
String payload = "{\"text\": \"Hello there!\"}";
WebhookResponse response = slack.send(url, payload);
There are lots of APIs to integrate external sources into Slack. They follow HTTP RPC-style methods.
When the API call has been completed successfully, its response contains "ok": true
and other specific fields.
{
"ok": true
}
In some cases, it may contain warning
field too.
{
"ok": true,
"warning": "something_problematic"
}
When the API call failed or had some warnings, its response contains "ok": false'
and also have the error
field which holds a string error code.
{
"ok": false,
"error": "something_bad"
}
jSlack simply wrap API interface. Find more examples in this library's test code.
import com.github.seratch.jslack.*;
import com.github.seratch.jslack.api.methods.request.conversations.*;
import com.github.seratch.jslack.api.methods.response.conversations.*;
Slack slack = Slack.getInstance();
String token = System.getenv("SLACK_BOT_TEST_API_TOKEN");
ConversationsCreateRequest req = ConversationsCreateRequest.builder().name(channelName).isPrivate(false).build();
ConversationsCreateResponse resp = slack.methods(token).conversationsCreate(publicChannelCreation);
Or, using lambda function to build a request could be much simpler. You don't need to type the long class name!
final String token = System.getenv("SLACK_BOT_TEST_API_TOKEN");
ChannelsCreateResponse response =
slack.methods(token).conversationsCreate(req -> req.name(channelName).isPrivate(false));
You can find more examples here: https://github.com/seratch/jslack/tree/master/src/test/java/com/github/seratch/jslack
Slack slack = Slack.getInstance();
String token = "xoxb-************************************";
// find all channels in the team
ConversationsListResponse listResponse =
slack.methods(token).conversationsList(req -> req.excludeArchived(true).limit(10));
// find #general
Conversation general = listResponse.getChannels().stream()
.filter(c -> c.getName().equals("general"))
.findFirst().get();
// https://slack.com/api/chat.postMessage
ChatPostMessageResponse postResponse =
slack.methods(token).chatPostMessage(req -> req.channel(general.getId()).text("Hello World!"));
// timestamp of the posted message
String messageTs = postResponse.getMessage().getTs();
ChatDeleteResponse deleteResponse =
slack.methods(token).chatDelete(req -> req.channel(general.getId()).ts(messageTs));
final String token = "xoxb-************************************";
// Required. See https://api.slack.com/dialogs#implementation
final String triggerId = "trigger-id";
Slack slack = Slack.getInstance();
DialogTextElement quanityTextElement = DialogTextElement.builder()
.subtype(SubType.NUMBER)
.label("Quantity")
.name("quantity")
.hint("The number you need")
.maxLength(3)
.minLength(1)
.placeholder("Required quantity")
.value("1")
.build();
DialogSelectElement colourSelectElement = DialogSelectElement.builder()
.name("colour")
.label("Colour")
.placeholder("Choose your preferred colour")
.options(Arrays.asList(
Option.builder().label("Red").value("#FF0000").build(),
Option.builder().label("Green").value("#00FF00").build(),
Option.builder().label("Blue").value("#0000FF").build(),
Option.builder().label("Black").value("#000000").build(),
Option.builder().label("White").value("#FFFFFF").build()
))
.build();
Dialog dialog = Dialog.builder()
.title("Request pens")
.callbackId("pens-1122")
.elements(Arrays.asList(quanityTextElement, colourSelectElement))
.submitLabel("")
.build();
DialogOpenResponse openDialogResponse = slack.methods().dialogOpen(req -> req
.token(token)
.triggerId(triggerId)
.dialog(dialog));
final Slack slack = Slack.getInstance();
final String token = "xoxb-************************************";
final String triggerId = payload.getTriggerId(); // from command, block_actions, etc
final List<LayoutBlock> blocks = Arrays.asList(InputBlock.builder()
.blockId("text_input")
.label(PlainTextObject.builder().text("text").build())
.element(PlainTextInputElement.builder().actionId("single").multiline(true).build())
.build());
final View view = View.builder()
.type("modal")
.callbackId("callback_id")
.title(ViewTitle.builder().type("plain_text").text("Title").build())
.submit(ViewSubmit.builder().type("plain_text").text("Submit").build())
.notifyOnClose(true)
.blocks(blocks)
.build();
ViewsOpenResponse apiResponse = slack.methods(token).viewsOpen(req -> req
.view(view)
.triggerId(triggerId));
The Events API is a streamlined, easy way to build apps and bots that respond to activities in Slack. All you need is a Slack app and a secure place for us to send your events.
https://api.slack.com/events-api
AppUninstalledHandler appUninstalledEventHandler = new AppUninstalledHandler {
@Override
public void handle(AppUninstalledPayload event) {
// do something here
}
};
public class SampleServlet extends SlackEventsApiServlet {
@Override
protected void setupDispatcher(EventsDispatcher dispatcher) {
dispatcher.register(appUninstalledEventHandler);
}
}
Real Time Messaging API is a WebSocket-based API that allows you to receive events from Slack in real time and send messages as user.
When you use this API through jSlack library, you need adding additional WebSocket libraries:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus.bundles</groupId>
<artifactId>tyrus-standalone-client</artifactId>
<version>1.13</version>
</dependency>
The following example shows you a simple usage of RTM API.
import com.github.seratch.jslack.*;
import com.github.seratch.jslack.api.rtm.*;
import com.google.gson.*;
JsonParser jsonParser = new JsonParser();
String token = System.getenv("SLACK_BOT_API_TOKEN");
try (RTMClient rtm = new Slack().rtm(token)) {
rtm.addMessageHandler((message) -> {
JsonObject json = jsonParser.parse(message).getAsJsonObject();
if (json.get("type") != null) {
log.info("Handled type: {}", json.get("type").getAsString());
}
});
RTMMessageHandler handler2 = (message) -> {
log.info("Hello!");
};
rtm.addMessageHandler(handler2);
// must connect within 30 seconds after issuing wss endpoint
rtm.connect();
rtm.sendMessage(Typing.builder()
.id(System.currentTimeMillis())
.channel(channelId)
.build().toJSONString());
rtm.sendMessage(Message.builder()
.id(System.currentTimeMillis())
.channel(channelId)
.text("Hi!")
.build().toJSONString());
rtm.removeMessageHandler(handler2);
} // #close method does #disconnect
The message
, argument of messageHandler, is a string value in JSON format. You need to deserialize it with your favorite JSON library.
jSlack already depends on google-gson library. So you can use Gson as above example shows. If you prefer Jackson or other libraries, it's also possible.
- SCIM (System for Cross-domain Identity Management)
- RFC 7644: System for Cross-domain Identity Management: Protocol
- SCIM API Response
// users
User newUser = buildNewUser(); // omitted
UsersCreateResponse creationResp = slack.scim(token).createUser(req -> req.user(newUser));
// https://api.slack.com/scim#filter
String filter = "userName eq \"" + newUser.getUserName() + "\"";
UsersSearchResponse searchResp = slack.scim(token).searchUsers(req -> req.count(1).filter(filter));
assertThat(searchResp.getItemsPerPage(), is(1));
assertThat(searchResp.getResources().size(), is(1));
User partialUpdate = new User();
partialUpdate.setUserName(newUserName);
slack.scim(token).patchUser(req -> req.id(userId).user(partialUpdate));
slack.scim(token).updateUser(req -> req.id(modifiedUser.getId()).user(modifiedUser));
// groups
GroupsSearchResponse pagination = slack.scim(token).searchGroups(req -> req.count(1));
SchemasResponse response = slack.audit(token).getSchemas();
ActionsResponse response = slack.audit(token).getActions();
LogsResponse response = slack.audit(token).getLogs(req -> req.oldest(1521214343).action("user_login").limit(10));
Slack slack = Slack.getInstance();
ApiToken token = ApiToken.of(System.getenv("SLACK_OAUTH_ACCESS_TOKEN"));
Shortcut shortcut = slack.shortcut(token);
List<Message> messages = shortcut.findRecentMessagesByName(ChannelName.of("general"));
ReactionsAddResponse addReaction = shortcut.addReaction(messages.get(0), ReactionName.of("smile"));
ChatPostMessageResponse response = shortcut.post(ChannelName.of("general"), "hello, hello!");
// Good old attachments
Attachment attachment = Attachment.builder().text("text").footer("footer").build();
List<Attachment> attachments = Arrays.asList(attachment);
ChatPostMessageResponse response = shortcut.postAsBot(ChannelName.of("general"), "hello, hello!");
// Block Kit
SectionBlock section = SectionBlock.builder()
.text(MarkdownTextObject.builder().text("Some rich text").build())
.accessory(ImageElement.builder().imageUrl("https://example.com/foo.jpg").altText("This is an image").build())
.build();
DividerBlock divider = new DividerBlock();
ChatPostMessageResponse response = shortcut.post(ChannelName.of("general"),
Arrays.asList(section, divider));
You need to select all permission scopes except for identity.*
. After that, you also need to run "Reinstall App".
Set the OAuth access tokens as env variables.
export SLACK_TEST_OAUTH_ACCESS_TOKEN=xoxp-*******************************************************
export SLACK_BOT_USER_TEST_OAUTH_ACCESS_TOKEN=xoxb-************************************
Manually create a Slack user which has an email address for a unit test.
export SLACK_WEBHOOK_TEST_URL=https://hooks.slack.com/services/Txxxx/yyy/zzz
export SLACK_WEBHOOK_TEST_CHANNEL=C12345678 (or #random)
- Features > Event Subscriptions > App Unfurl Domains
- Add
youtube.com
to the domain list - Re-install your Slack app
- Add
export SLACK_TEST_SHARED_CHANNEL_ID=C12345678
export SLACK_TEST_ADMIN_OAUTH_ACCESS_TOKEN=xoxp-xxxx
mvn test
mvn deploy -P release-sign-artifacts -D maven.test.skip=true
(The MIT License)
Copyright (c) Kazuhiro Sera