Skip to content

Instantly share code, notes, and snippets.

@comdotlinux
Forked from seratch/Application.kt
Created March 25, 2020 11:09
Show Gist options
  • Save comdotlinux/38166004c95cecfe3c97a3e0a871c75b to your computer and use it in GitHub Desktop.
Save comdotlinux/38166004c95cecfe3c97a3e0a871c75b to your computer and use it in GitHub Desktop.
Building Slack apps with Ktor framework
export SLACK_SIGNING_SECRET=(find this at Settings > Basic Information > App Credentials > Signing Secret)
export SLACK_BOT_TOKEN=xoxb-(find this at Settings > Install App)
gradle run
ktor {
deployment {
port = 3000
port = ${?PORT}
}
application {
modules = [com.example.ApplicationKt.module]
}
}
package com.example
import com.slack.api.bolt.App
import com.slack.api.bolt.AppConfig
import com.slack.api.bolt.request.Request
import com.slack.api.bolt.request.RequestHeaders
import com.slack.api.bolt.response.Response
import com.slack.api.bolt.util.QueryStringParser
import com.slack.api.bolt.util.SlackRequestParser
import com.slack.api.model.block.Blocks.asBlocks
import com.slack.api.model.block.Blocks.section
import com.slack.api.model.block.composition.BlockCompositions.markdownText
import com.slack.api.model.block.composition.BlockCompositions.plainText
import com.slack.api.model.block.element.BlockElements.button
import io.ktor.application.Application
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.content.TextContent
import io.ktor.features.origin
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.request.queryString
import io.ktor.request.receiveText
import io.ktor.request.uri
import io.ktor.response.header
import io.ktor.response.respond
import io.ktor.routing.post
import io.ktor.routing.routing
import io.ktor.util.toMap
val appConfig = AppConfig()
val requestParser = SlackRequestParser(appConfig)
val app = App(appConfig)
fun Application.module() {
app.command("/ktor") { _, ctx ->
ctx.ack(asBlocks(
section { section ->
section
.text(markdownText("Ktor is a framework for building asynchronous servers and clients in connected systems using the powerful Kotlin programming language."))
.accessory(
button { btn ->
btn.actionId("link")
.text(plainText("Ktor website"))
.url("https://ktor.io/")
}
)
}
))
}
app.blockAction("link") { _, ctx ->
ctx.ack()
}
routing {
post("/slack/events") {
respond(call, app.run(parseRequest(call)))
}
}
}
suspend fun parseRequest(call: ApplicationCall): Request<*> {
val requestBody = call.receiveText()
val queryString = QueryStringParser.toMap(call.request.queryString())
val headers = RequestHeaders(call.request.headers.toMap())
return requestParser.parse(
SlackRequestParser.HttpRequest.builder()
.requestUri(call.request.uri)
.queryString(queryString)
.requestBody(requestBody)
.headers(headers)
.remoteAddress(call.request.origin.remoteHost)
.build()
)
}
suspend fun respond(call: ApplicationCall, slackResp: Response) {
for (header in slackResp.headers) {
for (value in header.value) {
call.response.header(header.key, value)
}
}
call.response.status(HttpStatusCode.fromValue(slackResp.statusCode))
if (slackResp.body != null) {
call.respond(TextContent(slackResp.body, ContentType.parse(slackResp.contentType)))
}
}
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
group 'com.example'
version '0.0.1'
mainClassName = "io.ktor.server.netty.EngineMain"
sourceSets {
main.kotlin.srcDirs = main.java.srcDirs = ['src']
test.kotlin.srcDirs = test.java.srcDirs = ['test']
main.resources.srcDirs = ['resources']
test.resources.srcDirs = ['testresources']
}
repositories {
mavenLocal()
jcenter()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "com.slack.api:bolt:$slack_sdk_version"
implementation "ch.qos.logback:logback-classic:$logback_version"
testImplementation "io.ktor:ktor-server-tests:$ktor_version"
}
ktor_version=1.3.0
kotlin.code.style=official
kotlin_version=1.3.71
logback_version=1.2.3
slack_sdk_version=1.0.1
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment