π Slack APIλ‘ μ¬λ μ±λμ Message 보λ΄κΈ°
μλ νμΈμ, μ΄λ² μκ°μλ μ¬λμμ μ 곡λλ APIλ₯Ό ν΅ν΄ Java μ΄ν리μΌμ΄μ μμ Slack μ±λμ λ©μμ§λ₯Ό μ μ‘ν΄λ³΄λλ‘ νκ² μ΅λλ€.
νλ‘μ νΈλ₯Ό μ΄μνλ€λ³΄λ©΄ νΉμ λ¬Έμ (λ‘κ·Έ, μλ¬, λ©λͺ¨λ¦¬, λ°°μΉ μ€ν¨ λ±)κ° λ°μνμ λ μ΄λ¬ν λ¬Έμ μ μ λ°λ‘ νμΈν μ μλλ‘ μ₯μ μ λν΄μλ μλ¦Όμ λ°μ λ¬Έμ λ₯Ό νμΈνλ κ²μ΄ μ€μνλ€κ³ μκ°νλλ°μ, μ΄λ¬ν μλ¦Ό μ€ νλκ° μ¬λμ νμ©νλ λ°©λ²μ λλ€.
μ¬λμ κ²½μ° λ§μ κΈ°μ μμ μ¬μ©νκ³ μκ³ , λν κ΅μ₯ν λ§μ κΈ°λ₯μ μ 곡νκ³ μλλ°μ, μ΄λ¬ν κΈ°λ₯μ νμ©νλ©΄ 무κΆλ¬΄μ§νκ² μ»€μ€ν μ ν μ μμ κ² κ°μ΅λλ€.
ν΄λΉ ν¬μ€ν μμλ μ¬λμ λ€μ΄λ°κ±°λ νμκ°μ νλ λ±μ κΈ°λ³Έμ μΈ μ€μ μ μ μΈν μ¬λμ λ©μΈμ§λ₯Ό λ°μ‘νκΈ° μν μ€μ λΆν° λ°μ‘ μ½λκΉμ§ μ²μλΆν° λκΉμ§ μ΄ν΄λ³΄κ² μ΅λλ€.
Slack App μμ±
λ€μ μ¬μ΄νΈμμ Create New Appμ ν΅ν΄ Appμ μμ±ν΄μ€λλ€.
(μ¬λμ κ°μ νκ±°λ μμ±νλ λ± μ΄κΈ° λ¨κ³λ λ°λ‘ μ€λͺ νμ§ μμ΅λλ€. μ¬λ μ±λμ κΈ°λ³ΈμΌλ‘ publicμΌλ‘ μμ±νμμΌλ privateλ‘ μμ±νμ¬λ λ°©λ²μ μμ΅λλ€. μλμμ μ€λͺ λ릴κ²μ.)
μ’μΈ‘ μ¬μ§μ κΈ°μ‘΄μ Appμ μμ±ν κ²½μ°κ° μλ νλ©΄μ΄κ³ , μ°μΈ‘ μ¬μ§μ Appμ μ²μ μμ±νλ νλ©΄μ λλ€.
λ€μμΌλ‘ From scratchλ₯Ό ν΄λ¦ν©λλ€.
App Nameκ³Ό workspaceλ₯Ό μ€μ νκ³ Create Appμ ν΄λ¦νμ¬ μ±μ μμ±ν©λλ€.
(workspaceμ κ²½μ° μ¬λμμ μλ¦Όμ λ°κ³ μ νλ μν¬νμ΄μ€λ₯Ό μ ννμλ©΄ λ©λλ€.)
Scopes μ€μ λ° Token λ°κΈ
κ·ΈλΌ μμ κ°μ μ΄κΈ°νλ©΄μ΄ λμ¬ν λ°μ, OAuth Tokensλ₯Ό λ°κΈλ°κΈ° μν΄ OAuth & Permissionsλ₯Ό ν΄λ¦ν©λλ€.
κΆν(Authentication)μ λν΄ κΆκΈνμλ€λ©΄ μλ λ§ν¬λ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ π
μ νλ©΄μμ OAuth Scopeλ₯Ό μ€μ ν©λλ€.
μ λ channels:read, chat:write, users:writeλ₯Ό μ ννλλ°μ,
- channels:read - μν¬μ€νμ΄μ€μ public μ±λμ λν μ 보 보기
- chat:write - SlackApiλ‘ message λ°μ‘
- users:write - SlackApiλ₯Ό μν presence(?) μ€μ
μ¬λ μ±λμ λ©μμ§λ₯Ό 보λ΄κΈ° μν΄μλ chat:writeλ λ°λμ μΆκ°λ₯Ό ν΄μΌν©λλ€.
μ μ€μ μΈμλ λ λ§μ μ€μ λ€μ΄ μ‘΄μ¬νλλ°μ, μμΈν μ¬νμ λ¬Έμμμ νμΈν μ μμ΅λλ€ :)
+ νΉμ μ¬λ μ±λμ privateλ‘ μ€μ νμ€ κ²½μ°, groups:read Scopeλ₯Ό μΆκ°μ μΌλ‘ μ€μ ν΄μ£Όμ μΌ ν©λλ€.
OAuth Scope μ€μ μ λ§μΉ ν μλ‘ μ¬λΌκ°μ Install to Workspaceλ₯Ό ν΄λ¦νμ¬ OAuth Tokensμ λ°κΈλ°μ΅λλ€.
β» Tokenμ μΈμ¦ν€λ‘ μ¬μ©λ μ©λλ λ°λμ μΈλΆλ‘ λ ΈμΆν΄μλ μλλ©° κ°μΈλ³΄κ΄μ ν΄μΌ ν©λλ€.
Slackμ Bot Tokenμ xoxb- νμμ λλ€.
Slackμ μ± μ€μ
λ€μμΌλ‘ μμμ μμ±ν Slack Appμ μ±λμμ μ§μ μ±μ λ±λ‘ν©λλ€.
- μλ¦Όμ λ°κ³ μ νλ μ±λ μ°ν΄λ¦ > μ±λ μΈλΆμ 보 μ΄κΈ° > ν΅ν© > μ± μΆκ° ν΄λ¦
- μμμ μ€μ ν μν¬μ€νμ΄μ€(SlackApi) μΆκ°
μλ¦Όμ μ€μ λ°μ Channel ID κ° μ»κΈ°
μ΄κ³³μ μ κ·Όνμ¬ μμμ μ»μ Bot TokenμΈ xoxb~μ ν ν°κ°μ μ λΉ¨κ°μ λ€λͺ¨λ°μ€μ μ€μ νκ³ νλ¨μ Test method λ²νΌμ ν΄λ¦νμ¬ μ¬λμ μ 보λ₯Ό νμΈν©λλ€.
κ·ΈλΌ μμ κ°μ΄ μ¬λμ μ 보λ₯Ό νμΈν μ μμ΅λλ€.
idκ° μ¬λ λ©μμ§μ λ°μ‘ν λ νμν μ±λμ idμ΄κ³ , λ°λ‘ μλ nameμ μ¬λ μ±λλͺ μ λλ€.
idκ°μ μ½λ μμ±ν λ νμν κ°μ΄λ―λ‘, λ°μ‘ν μ±λμ idκ°μ λ°λ‘ 보κ΄ν©λλ€.
+ νΉμ private μ±λμ νμΈνκ³ μΆμ κ²½μ°, μμμ Scopeμ groups:readλ₯Ό μ€μ νμ ν
typesμ private_channelλ₯Ό μ λ ₯νλ©΄ μ 보λ₯Ό νμΈν μ μμ΅λλ€.
μ¬λ μ±λμ Message λ°μ‘νκΈ°
μ¬κΈ°κΉμ§ νμ ¨μΌλ©΄ μ¬λμ λ©μμ§λ₯Ό λ°μ‘νκΈ° μν μ ν μ λμ λλ€.
μ΄μ Kotlin μ½λλ₯Ό μμ±νμ¬ μ¬λμ λ©μμ§λ₯Ό 보λ΄λ³΄κ² μ΅λλ€.
(ν μ€νΈ νκΈ° μν μ½λμ΄λ―λ‘ μ½λλν κ΅μ₯ν λ¨μνλ°μ μ€μ λ‘λ ν¬νμ κ°μ λ²νΌμ λ°μ‘νκ±°λ, μ΄λ―Έμ§, νμΌ, λ©μΌλ°μ‘ λ± λ€μνκ² μ»€μ€ν νμ¬ λ©μΈμ§λ₯Ό λ°μ‘ν μ μμ΅λλ€.)
λ¨Όμ slack-api-client λΌμ΄λΈλ¬λ¦¬ μμ‘΄μ±μ μΆκ°ν©λλ€.
// Gradle
implementation("com.slack.api:slack-api-client:1.20.2")
// Maven
<dependency>
<groupId>com.slack.api</groupId>
<artifactId>slack-api-client</artifactId>
<version>1.20.2</version>
</dependency>
λ€μμΌλ‘ ν μ€νΈλ₯Ό 보λ΄κΈ° μν μ½λλ₯Ό μμ±ν©λλ€.
interface SlackService {
fun sendMessage(text: String)
fun sendMessage(channel: String, text: String)
}
import com.slack.api.Slack
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
@Service
class SlackServiceImpl : SlackService {
private val log = LoggerFactory.getLogger(javaClass)
@Value("\${slack.bot.token}")
lateinit var token: String
@Value("\${slack.monitor.channel.token}")
lateinit var defaultChannel: String
override fun sendMessage(text: String) {
sendMessage(defaultChannel, text)
}
/**
* Send Slack Alarm
*/
override fun sendMessage(channelId: String, text: String) {
val client = Slack.getInstance().methods()
runCatching {
client.chatPostMessage {
it.token(token)
.channel(channelId)
.text(text)
}
}.onFailure { e ->
log.error("Slack Send Error: {}", e.message, e)
}
}
/**
* Slack Channel name, id list
*/
fun showSlackInfo() {
val client = Slack.getInstance().methods()
var result: ConversationsListResponse = ConversationsListResponse()
kotlin.runCatching {
result = client.conversationsList {
it.token(token)
}
}.onSuccess {
result.channels.stream().forEach {
log.info("{} -> {}", it.name, it.id)
}
}
}
}
μ¬μ΄λ νλ‘μ νΈλ₯Ό KotlinμΌλ‘ μ§νμ€μ΄κΈ° λλ¬Έμ μ€νλ§κ³Ό μ½νλ¦°μ μ¬μ©νμ¬ μμ μ½λλ₯Ό μμ±νμ§λ§ κ°λ¨ν ν μ€νΈνλ μ½λμ΄κΈ° λλ¬Έμ μλ°λ‘ λ³ννμ¬ μ¬μ©νλ 무κ΄ν λ― ν©λλ€.
(runCatchingμ κ²½μ° Javaμμμ try-catch ꡬ문μ λλ€.)
token, defaultChannelμ κ²½μ° μμμ μ€μ ν Bot Token(OAuth Token)κ³Ό channel id κ°μ μ€μ ν΄μ£Όλ©΄ λ©λλ€.
sendMessage() λ©μλμ κ²½μ° 2κ°μ λ©μλλ₯Ό λ§λ€μλλ°μ, νμ¬λ μλ¦Όμ λ°μ μ±λμ΄ νκ°λ§ μ‘΄μ¬νμ§λ§, μΆν μ±λμ΄ μΆκ°λλ€λ©΄ μ§μ channelμ idλ₯Ό νλΌλ―Έν°λ‘ λ°κΈ° μν΄ μΆκ°μ μΌλ‘ λ§λ€μμ΅λλ€.
λν SlackServiceλ₯Ό μΈν°νμ΄μ€λ‘ λ§λ€κ³ μ΄λ₯Ό ꡬννλλ‘ SlackServiceImpl ν΄λμ€λ₯Ό μμ±ν΄μ£Όμλλ°μ, μ΄λ νλ‘μ νΈλ₯Ό μ΄μμ€μΈ μλ²μμ μΈλΆ νΈμΆμ ν λ νλ‘μ μλ² λ±μ ν΅ν΄ κ²½μ ν λ μΆκ°μ μΌλ‘ ꡬννμ¬ μ¬μ©ν μ μλλ‘ μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ΅λλ€.
λ§μ§λ§μΌλ‘ showSlackInfo() λ©μλμ κ²½μ° sendMessage() λ©μλμμ μ¬μ©λ μ¬λ μ±λμ μ 보λ₯Ό μ»μ μ μμ΅λλ€.
(μμμ conversations.list μμ νμΈνλ κ²κ³Ό λμΌν©λλ€.)
μ€μ μ sendMessage() λ©μλμ text λ©μΈμ§λ₯Ό μΈμλ‘ μ λ¬ν΄μ ν μ€νΈν΄λ³΄λ©΄ μμ κ°μ΄ μ¬λμ μλ¦Όμ΄ μ€λκ²μ νμΈν μ μμ΅λλ€.
μ 리
μ΄μμΌλ‘ Slack Apiλ₯Ό ν΅ν΄ μ¬λ μ±λμ λ©μμ§λ₯Ό 보λ΄λ λ°©λ²μ λν΄ μμ보μμ΅λλ€.
μ¬λμ κ΅μ₯ν λ€μν μλΉμ€μμ μ°λμ΄ κ°λ₯νκΈ° λλ¬Έμ λλΆλΆμ μλ¦Όμ μ¬λμ ν΅ν΄ λ°κ³ μλλ°μ, μ΄λ¬ν μλ¦Όμ νλ‘μ νΈ μ΄μμ μμ΄ κ±°μ νμμ μΈ λΆλΆμ΄λΌκ³ μκ°ν©λλ€.
νμ§λ§, λ무λ λ§μ μλΉμ€μ μλ¦Ό μ€μ μ ν κ²½μ° μ΄ λν κ΄λ¦¬ ν¬μ΄νΈκ° λ§μμ§λ κ²½μ°κ° μκΈΈ μ μκΈ° λλ¬Έμ, μλΉμ€κ° 컀μ§λ€λ©΄ μλΉμ€μ μν©μ λ§κ² λ°λμ νμν μλ¦Όλ§ μ€μ νμ¬ λ°μ μ μλλ‘ νλκ²μ΄ μ’μ κ² κ°μ΅λλ€ π
'Kotlin' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Kotlin for iterator (1) | 2025.01.17 |
---|---|
Kotlin - Scope functions (let, with, run, apply, also) (0) | 2024.12.15 |
[Kotlin] - Class(ν΄λμ€) (0) | 2021.10.17 |
λκΈ