Skip to content

Instantly share code, notes, and snippets.

@seratch
Last active October 7, 2019 12:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seratch/c29969f8bc341eb6d26d78054fc3795f to your computer and use it in GitHub Desktop.
Save seratch/c29969f8bc341eb6d26d78054fc3795f to your computer and use it in GitHub Desktop.
Lightning ⚡app in Kotlin
plugins {
id("org.jetbrains.kotlin.jvm") version "1.3.50"
}
repositories {
mavenCentral()
}
dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("com.github.seratch:jslack-lightning:3.0.0-M2")
implementation("com.github.seratch:jslack-lightning-jetty:3.0.0-M2")
implementation("org.slf4j:slf4j-simple:1.7.28")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}
package examples.echo
import com.github.seratch.jslack.lightning.App
import com.github.seratch.jslack.lightning.jetty.SlackAppServer
import org.slf4j.LoggerFactory
fun main() {
val logger = LoggerFactory.getLogger("main")
// export SLACK_BOT_TOKEN=xoxb-***
// export SLACK_SIGNING_SECRET=123abc***
val app = App()
app.command("/echo") { req, ctx ->
val text = "You said ${req.payload.text} at <#${req.payload.channelId}|${req.payload.channelName}>"
val res = ctx.respond { it.text(text) }
logger.info("respond result - {}", res)
ctx.ack()
}
val server = SlackAppServer(app)
server.start()
}
package examples.meeting_arrangement
import com.github.seratch.jslack.api.model.block.composition.PlainTextObject
import com.github.seratch.jslack.app_backend.interactive_messages.response.Option
import com.github.seratch.jslack.lightning.App
import com.github.seratch.jslack.lightning.jetty.SlackAppServer
import com.github.seratch.jslack.lightning.response.Response
import org.slf4j.LoggerFactory
fun main() {
val logger = LoggerFactory.getLogger("main")
// export SLACK_BOT_TOKEN=xoxb-***
// export SLACK_SIGNING_SECRET=123abc***
val app = App()
app.use { req, _, chain ->
logger.info("Request - $req")
val resp = chain.next(req)
logger.info("Response - $resp")
resp
}
app.command("/meeting") { _, ctx ->
val res = ctx.client().viewsOpen { it.triggerId(ctx.triggerId).viewAsString(view) }
logger.info("views.open result - {}", res)
if (res.isOk) ctx.ack()
else Response.builder().statusCode(500).body(res.error).build()
}
// when a user enters some word in "Topics"
app.blockSuggestion("topics-input") { req, ctx ->
val keyword = req.payload.value
val options = allOptions.filter { (it.text as PlainTextObject).text.contains(keyword) }
ctx.ack { it.options(if (options.isEmpty()) allOptions else options) }
}
// when a user chooses an item from the "Topics"
app.blockAction("topics-input") { _, ctx -> ctx.ack() }
// when a user clicks "Submit"
app.viewSubmission("meeting-arrangement") { req, ctx ->
val stateValues = req.payload.view.state.values
val agenda = stateValues["agenda"]!!["agenda-input"]!!.value
val errors = mutableMapOf<String, String>()
if (agenda.length <= 10) {
errors["agenda"] = "Agenda needs to be longer than 10 characters."
}
if (errors.isNotEmpty()) {
ctx.ack { it.responseAction("errors").errors(errors) }
} else {
// Operate something with the data
logger.info("state: $stateValues private_metadata: ${req.payload.view.privateMetadata}")
ctx.ack()
}
}
// when a user clicks "Cancel"
app.viewClosed("meeting-arrangement") { _, ctx ->
ctx.ack()
}
val server = SlackAppServer(app)
server.start()
}
val allOptions = listOf(
Option(PlainTextObject("Schedule", true), "schedule"),
Option(PlainTextObject("Budget", true), "budget"),
Option(PlainTextObject("Assignment", true), "assignment")
)
val view = """
{
"callback_id": "meeting-arrangement",
"type": "modal",
"notify_on_close": true,
"title": {
"type": "plain_text",
"text": "Meeting Arrangement",
"emoji": true
},
"submit": {
"type": "plain_text",
"text": "Submit",
"emoji": true
},
"close": {
"type": "plain_text",
"text": "Cancel",
"emoji": true
},
"blocks": [
{
"block_id": "date",
"type": "input",
"element": {
"action_id": "date-input",
"type": "datepicker",
"initial_date": "2019-10-22",
"placeholder": {
"type": "plain_text",
"text": "Select a date",
"emoji": true
}
},
"label": {
"type": "plain_text",
"text": "Meeting Date",
"emoji": true
}
},
{
"block_id": "topics",
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Select the meeting topics"
},
"accessory": {
"action_id": "topics-input",
"type": "multi_external_select",
"min_query_length": 1,
"placeholder": {
"type": "plain_text",
"text": "Select",
"emoji": true
}
}
},
{
"block_id": "agenda",
"type": "input",
"element": {
"action_id": "agenda-input",
"type": "plain_text_input",
"multiline": true
},
"label": {
"type": "plain_text",
"text": "Detailed Agenda",
"emoji": true
}
}
]
}
""".trimIndent()
@seratch
Copy link
Author

seratch commented Oct 6, 2019

@seratch
Copy link
Author

seratch commented Oct 7, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment