Skip to content

Instantly share code, notes, and snippets.

@seratch
Last active October 5, 2020 02:57
Show Gist options
  • Save seratch/a900efbbf68a31fdc96121ad0b9f4c97 to your computer and use it in GitHub Desktop.
Save seratch/a900efbbf68a31fdc96121ad0b9f4c97 to your computer and use it in GitHub Desktop.
Steps from Apps in Kotlin
plugins {
id("org.jetbrains.kotlin.jvm") version "1.4.10"
id("application")
}
repositories {
mavenCentral()
}
dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9")
implementation("com.slack.api:bolt-jetty:1.2.0-RC2")
implementation("com.slack.api:slack-api-client-kotlin-extension:1.2.0-RC2")
implementation("org.slf4j:slf4j-simple:1.7.30") // or logback-classic
}
application {
mainClassName = "MyAppKt" // add "Kt" suffix for main function source file
}
import com.slack.api.bolt.App
import com.slack.api.bolt.jetty.SlackAppServer
import com.slack.api.bolt.middleware.builtin.WorkflowStep
import com.slack.api.model.block.Blocks.divider
import com.slack.api.model.block.Blocks.section
import com.slack.api.model.block.LayoutBlock
import com.slack.api.model.block.composition.BlockCompositions.plainText
import com.slack.api.model.kotlin_extension.block.withBlocks
import com.slack.api.model.view.Views.view
import com.slack.api.model.view.Views.viewTitle
import com.slack.api.model.workflow.WorkflowSteps.stepInput
import com.slack.api.model.workflow.WorkflowSteps.stepOutput
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
fun main() {
System.setProperty("org.slf4j.simpleLogger.log.com.slack.api", "debug")
val pseudoDatabase = mutableMapOf<String, MutableList<Map<String, Any?>>>()
// export SLACK_BOT_TOKEN=xoxb-
// export SLACK_SIGNING_SECRET=
val app = App()
val step = WorkflowStep.builder()
.callbackId("copy_review")
.edit { _, ctx ->
ctx.configure(withBlocks {
section {
blockId("intro-section")
plainText("Create a task in one of the listed projects. The link to the task and other details will be available as variable data in later steps.")
}
input {
blockId("task_name_input")
element {
plainTextInput {
actionId("task_name")
placeholder("Write a task name")
}
}
label("Task name")
}
input {
blockId("task_description_input")
element {
plainTextInput {
actionId("task_description")
placeholder("Write a description for your task")
}
}
label("Task description")
}
input {
blockId("task_author_input")
element {
plainTextInput {
actionId("task_author")
placeholder("Write a task name")
}
}
label("Task author")
}
})
ctx.ack()
}
.save { req, ctx ->
val values = req.payload.view.state.values
val inputs = mapOf(
"taskName" to stepInput { it.value(values["task_name_input"]?.get("task_name")?.value) },
"taskDescription" to stepInput { it.value(values["task_description_input"]?.get("task_description")?.value) },
"taskAuthorEmail" to stepInput { it.value(values["task_author_input"]?.get("task_author")?.value) },
)
val outputs = listOf(
stepOutput { it.name("taskName").type("text").label("Task Name") },
stepOutput { it.name("taskDescription").type("text").label("Task Description") },
stepOutput { it.name("taskAuthorEmail").type("text").label("Task Author Email") },
)
ctx.update(inputs, outputs)
ctx.ack()
}
.executeAutoAcknowledgement(false)
.execute { req, ctx ->
val step = req.payload.event.workflowStep
GlobalScope.async {
try {
val email = step.inputs["taskAuthorEmail"]?.value.toString()
val outputs = mapOf(
"taskName" to step.inputs["taskName"]?.value,
"taskDescription" to step.inputs["taskDescription"]?.value,
"taskAuthorEmail" to email,
)
ctx.complete(outputs)
val userLookup = ctx.client().usersLookupByEmail { it.email(email) }
if (userLookup.isOk) {
val userId = userLookup.user.id
val newTask = mapOf(
"taskName" to step.inputs["taskName"]?.value,
"taskDescription" to step.inputs["taskDescription"]?.value,
)
val tasks = pseudoDatabase.getOrDefault(userId, mutableListOf())
tasks.add(newTask)
pseudoDatabase[userId] = tasks
val blocks = mutableListOf<LayoutBlock>()
tasks.forEach { task ->
blocks.add(section { it.text(plainText { pt -> pt.text(task["taskName"].toString()) }) })
blocks.add(divider())
}
ctx.client().viewsPublish {
it.userId(userId).view(view { v ->
v.type("home")
.title(viewTitle { vt -> vt.type("plain_text").text("Your tasks!") })
.blocks(blocks)
})
}
} else {
ctx.fail(mapOf("message" to "User not found by $email"))
}
} catch (e: Exception) {
ctx.fail(mapOf("message" to "Something wrong! ($e)"))
}
}
ctx.ack()
}
.build()
app.step(step)
val server = SlackAppServer(app)
server.start() // http://localhost:3000/slack/events
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment