Skip to content

Commit 00ec24b

Browse files
Initial commit
1 parent f283907 commit 00ec24b

23 files changed

+168
-544
lines changed

README.md

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
# Bolt for Java Template App
22

3-
This is a generic Bolt for Java template app used to build out Slack apps.
3+
This is a Bolt for Java template app used to build custom steps for use in
4+
[Workflow Builder](https://api.slack.com/start#workflow-builder).
45

5-
Before getting started, make sure you have a development workspace where you have permissions to install apps. If you don’t have one setup, go ahead and [create one](https://slack.com/create).
6+
## Setup
7+
8+
Before getting started, first make sure you have a development workspace where
9+
you have permission to install apps. **Please note that the features in this
10+
project require that the workspace be part of
11+
[a Slack paid plan](https://slack.com/pricing).**
12+
13+
### Developer Program
14+
15+
Join the [Slack Developer Program](https://api.slack.com/developer-program) for
16+
exclusive access to sandbox environments for building and testing your apps,
17+
tooling, and resources created to help developers build and grow.
618

719
## Installation
820

@@ -31,7 +43,7 @@ export SLACK_APP_TOKEN=<your-app-token>
3143

3244
```zsh
3345
# Clone this project onto your machine
34-
git clone https://github.com/slack-samples/bolt-java-starter-template.git
46+
git clone https://github.com/WilliamBergamin/bolt-java-custom-step-template.git
3547

3648
# Change into this project directory
3749
cd bolt-java-template
@@ -78,6 +90,16 @@ gradle run
7890

7991
**NOTE**: If you chose to use Gradle as your build tool you can remove the `pom.xml` file from this project.
8092

93+
## Using Steps in Workflow Builder
94+
95+
With your server running, the `Sample step` is now ready for use in
96+
[Workflow Builder](https://api.slack.com/start#workflow-builder)! Add it as a
97+
custom step in a new or existing workflow, then run the workflow while your app
98+
is running.
99+
100+
For more information on creating workflows and adding custom steps, read more
101+
[here](https://slack.com/help/articles/17542172840595-Create-a-new-workflow-in-Slack).
102+
81103
## Project Structure
82104

83105
### `manifest.json`
@@ -90,7 +112,7 @@ gradle run
90112

91113
### `/listeners`
92114

93-
Every incoming request is routed to a "listener". Inside this directory, we group each listener based on the Slack Platform feature used, so `/listeners/shortcuts` handles incoming [Shortcuts](https://api.slack.com/interactivity/shortcuts) requests, `/listeners/views` handles [View submissions](https://api.slack.com/reference/interaction-payloads/views#view_submission), and so on.
115+
Every incoming request is routed to a "listener". Inside this directory, we group each listener based on the Slack Platform feature used, so `/listeners/actions` handles incoming [Actions](https://docs.slack.dev/reference/interaction-payloads/block_actions-payload) requests and `/listeners/functions` handles [Workflow Steps](https://docs.slack.dev/workflows/workflow-steps).
94116

95117
### `/logback.xml`
96118

@@ -99,29 +121,3 @@ Every incoming request is routed to a "listener". Inside this directory, we grou
99121
### Tests
100122

101123
This project provides some sample unit tests. They can be found in `src/test`. They are to be used as examples to show how unit tests can be implemented. **As you modify this project don't hesitate to modify, add, or remove these tests.**
102-
103-
## App Distribution / OAuth
104-
105-
Only implement OAuth if you plan to distribute your application across multiple workspaces. A separate `OAuthMain.java` file can be found with relevant OAuth settings.
106-
107-
When using OAuth, Slack requires a public URL where it can send requests. In this template app, we've used [`ngrok`](https://ngrok.com/download). Checkout [this guide](https://ngrok.com/docs#getting-started-expose) for setting it up.
108-
109-
Start `ngrok` to access the app on an external network and create a redirect URL for OAuth.
110-
111-
```
112-
ngrok http 3000
113-
```
114-
115-
This output should include a forwarding address for `http` and `https` (we'll use `https`). It should look something like the following:
116-
117-
```
118-
Forwarding https://3cb89939.ngrok.io -> http://localhost:3000
119-
```
120-
121-
Navigate to **OAuth & Permissions** in your app configuration and click **Add a Redirect URL**. The redirect URL should be set to your `ngrok` forwarding address with the `slack/oauth/callback` path appended. For example:
122-
123-
```
124-
https://3cb89939.ngrok.io/slack/oauth/callback
125-
```
126-
127-
*NOTE:* if you do not require OAuth you can remove all `OAUTH DEPENDENCIES` in the `pom.xml` or `build.gradle` files, along with `src/main/java/OAuthMain.java`

manifest.json

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,63 @@
11
{
22
"display_information": {
3-
"name": "Bolt Template App"
3+
"name": "Bolt Workflow Step"
44
},
55
"features": {
66
"app_home": {
7-
"home_tab_enabled": true,
8-
"messages_tab_enabled": false,
7+
"home_tab_enabled": false,
8+
"messages_tab_enabled": true,
99
"messages_tab_read_only_enabled": true
1010
},
1111
"bot_user": {
12-
"display_name": "Bolt Template App",
13-
"always_online": false
14-
},
15-
"shortcuts": [
16-
{
17-
"name": "Run sample shortcut",
18-
"type": "global",
19-
"callback_id": "sample-shortcut-id",
20-
"description": "Runs a sample shortcut"
21-
}
22-
],
23-
"slash_commands": [
24-
{
25-
"command": "/sample-command",
26-
"description": "Runs a sample command",
27-
"should_escape": false
28-
}
29-
]
12+
"display_name": "Bolt Workflow Step",
13+
"always_online": true
14+
}
3015
},
3116
"oauth_config": {
3217
"scopes": {
3318
"bot": [
34-
"channels:history",
35-
"chat:write",
36-
"commands"
19+
"chat:write"
3720
]
3821
}
3922
},
4023
"settings": {
4124
"event_subscriptions": {
4225
"bot_events": [
43-
"app_home_opened",
44-
"message.channels"
26+
"function_executed"
4527
]
4628
},
4729
"interactivity": {
4830
"is_enabled": true
4931
},
50-
"org_deploy_enabled": false,
32+
"org_deploy_enabled": true,
5133
"socket_mode_enabled": true,
52-
"token_rotation_enabled": false
34+
"token_rotation_enabled": false,
35+
"hermes_app_type": "remote",
36+
"function_runtime": "remote"
37+
},
38+
"functions": {
39+
"sample-step": {
40+
"title": "Sample step",
41+
"description": "Runs sample step",
42+
"input_parameters": {
43+
"user_id": {
44+
"type": "slack#/types/user_id",
45+
"title": "User",
46+
"description": "Message recipient",
47+
"is_required": true,
48+
"hint": "Select a user in the workspace",
49+
"name": "user_id"
50+
}
51+
},
52+
"output_parameters": {
53+
"user_id": {
54+
"type": "slack#/types/user_id",
55+
"title": "User",
56+
"description": "User that completed the step",
57+
"is_required": true,
58+
"name": "user_id"
59+
}
60+
}
61+
}
5362
}
5463
}

src/main/java/OAuthMain.java

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/main/java/listeners/Listeners.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@
22

33
import com.slack.api.bolt.App;
44
import listeners.actions.ActionListeners;
5-
import listeners.commands.CommandListeners;
6-
import listeners.events.EventListeners;
7-
import listeners.messages.MessageListeners;
8-
import listeners.shortcuts.ShortcutListeners;
9-
import listeners.views.ViewListeners;
5+
import listeners.functions.FunctionListeners;
106
import org.slf4j.Logger;
117
import org.slf4j.LoggerFactory;
128

@@ -22,13 +18,6 @@ public static void register(App app) {
2218
}
2319

2420
private static ListenerProvider[] getAllListeners() {
25-
return new ListenerProvider[] {
26-
new ActionListeners(),
27-
new CommandListeners(),
28-
new EventListeners(),
29-
new MessageListeners(),
30-
new ShortcutListeners(),
31-
new ViewListeners()
32-
};
21+
return new ListenerProvider[] {new ActionListeners(), new FunctionListeners()};
3322
}
3423
}

src/main/java/listeners/actions/ActionListeners.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
public class ActionListeners implements ListenerProvider {
88
@Override
99
public void register(App app) {
10-
app.blockAction(Constants.ActionIds.CATEGORY, new SampleBlockActionListener(app));
10+
app.blockAction(Constants.ActionIds.WORKFLOW_STEP_BUTTON, new CustomStepButtonActionListener(app));
1111
}
1212
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package listeners.actions;
2+
3+
import com.slack.api.bolt.App;
4+
import com.slack.api.bolt.context.builtin.ActionContext;
5+
import com.slack.api.bolt.handler.builtin.BlockActionHandler;
6+
import com.slack.api.bolt.request.builtin.BlockActionRequest;
7+
import com.slack.api.bolt.response.Response;
8+
import com.slack.api.methods.SlackApiException;
9+
import java.io.IOException;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
public class CustomStepButtonActionListener implements BlockActionHandler {
14+
private final App app;
15+
16+
public CustomStepButtonActionListener(App app) {
17+
this.app = app;
18+
}
19+
20+
@Override
21+
public Response apply(BlockActionRequest req, ActionContext ctx) throws IOException, SlackApiException {
22+
this.app.executorService().submit(() -> {
23+
Map<String, Object> outputs = new HashMap<>();
24+
outputs.put(
25+
"user_id",
26+
req.getPayload()
27+
.getFunctionData()
28+
.getInputs()
29+
.get("user_id")
30+
.asString());
31+
try {
32+
ctx.client().functionsCompleteSuccess(r -> r.functionExecutionId(
33+
req.getPayload().getFunctionData().getExecutionId())
34+
.outputs(outputs));
35+
ctx.client().chatUpdate(r -> r.channel(
36+
req.getPayload().getContainer().getChannelId())
37+
.ts(req.getPayload().getContainer().getMessageTs())
38+
.text("Thank you :heart_hands: for clicking a button!"));
39+
} catch (Exception e) {
40+
ctx.logger.error(
41+
"Failed to call functionsCompleteSuccess or views.update API (error: {})", e.getMessage(), e);
42+
}
43+
});
44+
return ctx.ack();
45+
}
46+
}

src/main/java/listeners/actions/SampleBlockActionListener.java

Lines changed: 0 additions & 80 deletions
This file was deleted.

src/main/java/listeners/commands/CommandListeners.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)