Skip to content

Commit 3058558

Browse files
authored
Merge pull request #503 from emanguy/kotlin-dsl-docs
Add Kotlin DSL documentation (English)
2 parents 5f2fa68 + 36f667a commit 3058558

File tree

7 files changed

+234
-1
lines changed

7 files changed

+234
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ All released versions are available on the Maven Central repositories. The lates
6161
|groupId:artifactId|Description|
6262
|---|---|
6363
|[**com.slack.api:slack-api-model**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model)|This module is a collection of the classes representing the [Slack core objects](https://api.slack.com/types) such as conversations, messages, users, surfaces, and blocks. As this one is an essential part of the SDK, all others depend on this.|
64+
|[**com.slack.api:slack-api-model-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model-kotlin-extension)|This contains the Block Kit Kotlin DSL builder, which allows you to define Block Kit structures via a Kotlin-native DSL.|
6465
|[**com.slack.api:slack-api-client**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-client)|This is a collection of the Slack API clients. The supported are Basic API Methods, RTM (Real Time Messaging) API, SCIM API, Audit Logs API, and Status API.|
66+
|[**com.slack.api:slack-api-client-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-client-kotlin-extension)|This contains extension methods for various slack client message builders so you can seamlessly use the Block Kit Kotlin DSL directly on the Java message builders.|
6567
|[**com.slack.api:slack-app-backend**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-app-backend)|This module is a set of Slack app server-side handlers and data classes for Events API, Interactive Components, Slash Commands, Actions, and OAuth flow. These are used by Bolt framework as the foundation of it in primitive layers.|
6668
|[**com.slack.api:bolt**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:bolt)|Bolt is a framework that offers an abstraction layer to build Slack apps safely and quickly. The most commonly used Servlet environment is supported out-of-the-box.|
6769
|[**com.slack.api:bolt-servlet**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:bolt-servlet)|This is an adapter for Servlet environments.|

docs/guides/app-home.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ app.event(AppHomeOpenedEvent::class.java) { event, ctx ->
101101
}
102102
```
103103

104+
You can also build the view in the above example with the [Block Kit Kotlin DSL]({{ site.url | append: site.baseurl }}/guides/composing-messages#block-kit-kotlin-dsl) like so:
105+
106+
```kotlin
107+
// These imports are necessary for this code
108+
import com.slack.api.model.kotlin_extension.view.blocks
109+
import com.slack.api.model.view.Views.view
110+
111+
val appHomeView = view {
112+
it.type("home")
113+
.blocks {
114+
section {
115+
markdownText(":wave: Hello, App Home! (Last updated: ${now}")
116+
}
117+
image {
118+
imageUrl("https://www.example.com/foo.png")
119+
}
120+
}
121+
}
122+
```
123+
104124
### Under the Hood
105125

106126
Refer to [the Events API guide]({{ site.url | append: site.baseurl }}/guides/events-api).

docs/guides/composing-messages.md

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,156 @@ ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> r
6969
);
7070
```
7171

72-
You can use this way also for building a message for Incoming Webhooks and `response_url` calls.
72+
You can use this way also for building a message for Incoming Webhooks and `response_url` calls.
73+
74+
---
75+
## Block Kit Kotlin DSL
76+
77+
If you're using Kotlin, the Java Slack SDK also provides Kotlin-style builders which you can use to build your Block Kit structures.
78+
79+
```kotlin
80+
import com.slack.api.Slack
81+
import com.slack.api.model.block.Blocks.*
82+
import com.slack.api.model.kotlin_extension.request.chat.blocks
83+
84+
val slack = Slack.getInstance()
85+
val token = System.getenv("token")
86+
val response = slack.methods(token).chatPostMessage { req -> req
87+
.channel("C1234567")
88+
.blocks {
89+
section {
90+
// "text" fields can be constructed via plainText() and markdownText()
91+
markdownText("*Please select a restaurant:*")
92+
}
93+
divider()
94+
actions {
95+
// To align with the JSON structure, you could put the elements { } block around the buttons but for brevity it can be omitted
96+
// The same is true for things such as the section block's "accessory" container
97+
button {
98+
// For instances where only plain text is acceptable, the field's name can be filled with plain text inputs
99+
text("Farmhouse", emoji = true)
100+
value("v1")
101+
}
102+
button {
103+
text("Kin Khao", emoji = true)
104+
value("v2")
105+
}
106+
}
107+
}
108+
}
109+
```
110+
111+
### Installation
112+
113+
You can add the Block Kit Kotlin DSL via 2 artifacts:
114+
115+
* The `slack-api-model` Kotlin extension, which adds the Kotlin DSL itself as well as the standalone `withBlocks { }` builder and `View.ViewBuilder`'s `.blocks { }` extension function
116+
* The `slack-api-client` Kotlin extension, which adds the `.blocks { }` extension function to `MethodsClient`'s request object builders for seamless use of the DSL with the Java builders
117+
* The `.blocks { }` extension function is available on the following Java builders:
118+
* ChatPostEphemeralRequestBuilder
119+
* ChatPostMessageRequestBuilder
120+
* ChatScheduleMessageRequestBuilder
121+
* ChatUpdateRequestBuilder
122+
123+
**Adding via Gradle:**
124+
125+
```groovy
126+
dependencies {
127+
implementation "com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}"
128+
implementation "com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}"
129+
}
130+
```
131+
132+
**Adding via Gradle Kotlin DSL:**
133+
134+
```kotlin
135+
dependencies {
136+
implementation("com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}")
137+
implementation("com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}")
138+
}
139+
```
140+
141+
### Notable examples and features
142+
143+
**Standalone withBlocks builder which comes with the model extension**:
144+
145+
You can create lists of blocks outside of the `slack-api-client` Kotlin extension functions with the `withBlocks { }` builder.
146+
147+
```kotlin
148+
import com.slack.api.model.kotlin_extension.block.withBlocks
149+
150+
val blocks = withBlocks {
151+
section {
152+
plainText("Now this can be passed to anything that requires a list of LayoutBlocks")
153+
}
154+
}
155+
```
156+
157+
**Type safe enums for inputs which require specific string inputs**:
158+
159+
Type-safe enums are available for properties of some block elements which require specific input strings. With this, you get the benefit of verifying your inputs are correct at compile time and you gain access to Kotlin enum features such as being able to iterate over or retrieve all possible values for these inputs. Versions of these inputs which accept strings are also available, if you prefer.
160+
161+
```kotlin
162+
import com.slack.api.model.kotlin_extension.block.element.ButtonStyle
163+
import com.slack.api.model.kotlin_extension.block.element.ConversationType
164+
import com.slack.api.model.kotlin_extension.block.withBlocks
165+
166+
val blocks = withBlocks {
167+
section {
168+
plainText("Please select the person or group you would like to send a cat GIF to.")
169+
170+
// "accessory" is provided here, but it can be omitted for brevity
171+
accessory {
172+
conversationsSelect {
173+
// Or alternatively, provide strings via filter("im", "mpim") if you'd prefer
174+
filter(ConversationType.IM, ConversationType.MULTIPARTY_IM)
175+
placeholder("Where should we send the cat?")
176+
177+
confirm {
178+
title("Confirm destination")
179+
plainText("Are you sure you want to send a cat GIF to this person or group?")
180+
confirm("Yes, send it")
181+
deny("Don't send it")
182+
183+
style(ButtonStyle.PRIMARY)
184+
}
185+
}
186+
}
187+
}
188+
}
189+
```
190+
191+
**Write DSL extension functions for message templating**:
192+
193+
Because it is a Kotlin DSL, you benefit from Kotlin language features while you are constructing your messages, one of which being able to create extension functions which reproduce common Block Kit structures. This makes your code less repetitive and easier to read. You also benefit from being able to use conditionals and loops as you construct your blocks.
194+
195+
```kotlin
196+
import com.slack.api.model.kotlin_extension.block.ActionsBlockBuilder
197+
import com.slack.api.model.kotlin_extension.block.withBlocks
198+
199+
fun ActionsBlockBuilder.presentOptions(vararg optionNames: String, prompt: String? = null) {
200+
staticSelect {
201+
if (prompt != null) {
202+
placeholder(prompt)
203+
}
204+
205+
options {
206+
for (optionName in optionNames) {
207+
option {
208+
plainText(optionName)
209+
value(optionName.toLowerCase())
210+
}
211+
}
212+
}
213+
}
214+
}
215+
216+
val blocks = withBlocks {
217+
section {
218+
markdownText("Please select your favorite color.")
219+
}
220+
actions {
221+
presentOptions("Green", "Red", "Blue", "Yellow", "Orange", "Black", prompt = "Pick a color...")
222+
}
223+
}
224+
```

docs/guides/modals.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,57 @@ val res = ctx.client().viewsOpen { it
228228
}
229229
```
230230
231+
Alternatively, you can use the [Block Kit DSL]({{ site.url | append: site.baseurl }}/guides/composing-messages#block-kit-kotlin-dsl) in conjunction with the Java Builder to construct your view. The Java example above would look like this in Kotlin:
232+
233+
```kotlin
234+
import com.slack.api.model.kotlin_extension.view.blocks
235+
import com.slack.api.model.view.Views.*
236+
237+
fun buildView(): View {
238+
return view { thisView -> thisView
239+
.callbackId("meeting-arrangement")
240+
.type("modal")
241+
.notifyOnClose(true)
242+
.title(viewTitle { it.type("plain_text").text("Meeting Arrangement").emoji(true) })
243+
.submit(viewSubmit { it.type("plain_text").text("Submit").emoji(true) })
244+
.close(viewClose { it.type("plain_text").text("Cancel").emoji(true) })
245+
.privateMetadata("""{"response_url":"https://hooks.slack.com/actions/T1ABCD2E12/330361579271/0dAEyLY19ofpLwxqozy3firz"}""")
246+
.blocks {
247+
section {
248+
blockId("category-block")
249+
markdownText("Select a category of the meeting!")
250+
staticSelect {
251+
actionId("category-selection-action")
252+
placeholder("Select a category")
253+
options {
254+
option {
255+
description("Customer")
256+
value("customer")
257+
}
258+
option {
259+
description("Partner")
260+
value("partner")
261+
}
262+
option {
263+
description("Internal")
264+
value("internal")
265+
}
266+
}
267+
}
268+
}
269+
input {
270+
blockId("agenda-block")
271+
plainTextInput {
272+
actionId("agenda-action")
273+
multiline(true)
274+
}
275+
label("Detailed Agenda", emoji = true)
276+
}
277+
}
278+
}
279+
}
280+
```
281+
231282
### `"block_actions"` requests
232283
233284
Basically it's the same with [Interactive Components]({{ site.url | append: site.baseurl }}/guides/interactive-components) but the only difference is that a payload coming from a modal has `view` and also its `private_metadata`

docs/guides/web-api-basics.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ val response = slack.methods(token).chatPostMessage { it
127127
}
128128
```
129129

130+
In addition, you can check out the [Block Kit Kotlin DSL]({{ site.url | append: site.baseurl }}/guides/composing-messages#block-kit-kotlin-dsl) for a Kotlin-native way of constructing rich messages.
131+
130132
### Handle Responses
131133

132134
If you're not yet familiar with the Slack Web API response format, read the [Evaluating responses](https://api.slack.com/web#responses) guide to understand it. All Web API responses contain a JSON object, which always contains a top-level boolean property `"ok"`, indicating success or failure.

docs/guides/web-api-client-setup.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ dependencies {
134134
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
135135
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
136136
implementation("com.slack.api:slack-api-client:{{ site.sdkLatestVersion }}")
137+
138+
// Add these dependencies if you want to use the Kotlin DSL for building rich messages
139+
implementation("com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}")
140+
implementation("com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}")
137141
}
138142
application {
139143
mainClassName = "ExampleKt" // add "Kt" suffix for main function source file

docs/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ All released versions are available on the Maven Central repositories. The lates
3535
|groupId:artifactId|Description|
3636
|---|---|
3737
|[**com.slack.api:slack-api-model**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model) [📖](https://oss.sonatype.org/service/local/repositories/releases/archive/com/slack/api/slack-api-model/{{ site.sdkLatestVersion }}/slack-api-model-{{ site.sdkLatestVersion }}-javadoc.jar/!/index.html#package)|This is a collection of the classes representing the [Slack core objects](https://api.slack.com/types) such as conversations, messages, users, blocks, and surfaces. As this is an essential part of the SDK, all other modules depend on this.|
38+
|[**com.slack.api:slack-api-model-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model-kotlin-extension)|This contains the Block Kit Kotlin DSL builder, which allows you to define block kit structures via a Kotlin-native DSL.|
3839
|[**com.slack.api:slack-api-client**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-client) [📖](https://oss.sonatype.org/service/local/repositories/releases/archive/com/slack/api/slack-api-client/{{ site.sdkLatestVersion }}/slack-api-client-{{ site.sdkLatestVersion }}-javadoc.jar/!/index.html#package)|This is a collection of the Slack API clients. The supported are Basic API Methods, RTM (Real Time Messaging) API, SCIM API, Audit Logs API, and Status API.|
40+
|[**com.slack.api:slack-api-client-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-client-kotlin-extension)|This contains extension methods for various slack client message builders so you can seamlessly use the Block Kit Kotlin DSL directly on the Java message builders.|
3941
|[**com.slack.api:slack-app-backend**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-app-backend) [📖](https://oss.sonatype.org/service/local/repositories/releases/archive/com/slack/api/slack-app-backend/{{ site.sdkLatestVersion }}/slack-app-backend-{{ site.sdkLatestVersion }}-javadoc.jar/!/index.html#package)|This module is a set of Slack app server-side handlers and data classes for Events API, Interactive Components, Slash Commands, Actions, and OAuth flow. These are used by Bolt framework as the foundation of it in primitive layers.|
4042

4143
---

0 commit comments

Comments
 (0)