Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAW-275 디스코드 웹훅 작업 #85

Merged
merged 5 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions adapter/webhook/discord/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar

plugins {
kotlin("plugin.spring")
}

dependencies {
implementation(project(":domain"))
implementation(project(":support:logging"))

implementation("org.springframework.boot:spring-boot-starter-webflux:${Versions.SPRING_BOOT}")
}

tasks {
withType<Jar> { enabled = true }
withType<BootJar> { enabled = false }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.xorker.draw.webhook.discord

import com.xorker.draw.webhook.discord.dto.DiscordMessage
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.service.annotation.PostExchange
import reactor.core.publisher.Mono

internal interface DiscordClient {
@PostExchange("/api/webhooks/{path}")
fun sendMessage(
@PathVariable("path") path: String,
@RequestBody discordMessage: DiscordMessage,
): Mono<Void>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.xorker.draw.webhook.discord

import com.xorker.draw.notify.NotifyRepository
import com.xorker.draw.notify.NotifyType
import com.xorker.draw.support.logging.logger
import com.xorker.draw.webhook.discord.config.DiscordProperties
import com.xorker.draw.webhook.discord.dto.DiscordEmbed
import com.xorker.draw.webhook.discord.dto.DiscordMessage
import org.springframework.stereotype.Component

@Component
internal class DiscordWebHookAdapter(
private val discordClient: DiscordClient,
private val discordProperties: DiscordProperties,
) : NotifyRepository {
val logger = logger()

override fun notifyMessage(notifyType: NotifyType) {
try {
when (notifyType) {
is NotifyType.DiscordRandomMatchingNotifyType ->
discordClient.sendMessage(discordProperties.randomMatchingUrl, notifyType.toDiscordMessage()).block()

is NotifyType.DiscordStartGameNotifyType ->
discordClient.sendMessage(discordProperties.startGameUrl, notifyType.toDiscordMessage()).block()
}
} catch (ex: Exception) {
logger.warn(ex.message, ex)
}
}

fun NotifyType.toDiscordMessage(): DiscordMessage = when (this) {
is NotifyType.DiscordRandomMatchingNotifyType -> DiscordMessage(listOf(DiscordEmbed(this.message)))
is NotifyType.DiscordStartGameNotifyType -> DiscordMessage(listOf(DiscordEmbed(this.message)))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.xorker.draw.webhook.discord.config

import com.xorker.draw.webhook.discord.DiscordClient
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.support.WebClientAdapter
import org.springframework.web.service.invoker.HttpServiceProxyFactory

@EnableConfigurationProperties(DiscordProperties::class)
@Configuration
internal class DiscordClientConfig {

@Bean
fun webClient(): WebClient = WebClient.create("https://discord.com")

@Bean
fun discordClient(): DiscordClient {
val factory = HttpServiceProxyFactory.builder()
.exchangeAdapter(WebClientAdapter.create(webClient()))
.build()

return factory.createClient(DiscordClient::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.xorker.draw.webhook.discord.config

import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "discord")
internal data class DiscordProperties(
val randomMatchingUrl: String,
val startGameUrl: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.xorker.draw.webhook.discord.dto

data class DiscordEmbed(
val title: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.xorker.draw.webhook.discord.dto

data class DiscordMessage(
val embeds: List<DiscordEmbed>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
discord:
random-matching-url: ${WEBHOOK_RANDOM_MATCHING_URL}
start-game-url: ${WEBHOOK_START_GAME_URL}
1 change: 1 addition & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies {
implementation(project(":adapter:memory"))
implementation(project(":adapter:oauth"))
implementation(project(":adapter:rdb"))
implementation(project(":adapter:webhook:discord"))
implementation(project(":support:jwt"))
implementation(project(":support:time"))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.xorker.draw.mafia

import com.xorker.draw.exception.InvalidRequestOtherPlayingException
import com.xorker.draw.notify.NotifyRepository
import com.xorker.draw.notify.NotifyType
import com.xorker.draw.websocket.WaitingQueueSession
import com.xorker.draw.websocket.WaitingQueueSessionEventListener
import org.springframework.stereotype.Service
Expand All @@ -10,6 +12,7 @@ internal class MafiaGameRandomMatchingService(
private val mafiaGameUseCase: MafiaGameUseCase,
private val mafiaGameWaitingQueueRepository: MafiaGameWaitingQueueRepository,
private val mafiaGameMessenger: MafiaGameMessenger,
private val notifyRepository: NotifyRepository,
) : WaitingQueueSessionEventListener {

override fun connectSession(session: WaitingQueueSession) {
Expand All @@ -22,6 +25,8 @@ internal class MafiaGameRandomMatchingService(
mafiaGameWaitingQueueRepository.enqueue(4, session)

mafiaGameMessenger.unicastRandomMatching(user.id)

notifyRepository.notifyMessage(NotifyType.DiscordRandomMatchingNotifyType(user.name, session.locale))
}

override fun exitSession(session: WaitingQueueSession) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.xorker.draw.mafia.phase
import com.xorker.draw.mafia.MafiaGameInfo
import com.xorker.draw.mafia.MafiaKeywordRepository
import com.xorker.draw.mafia.MafiaPhase
import com.xorker.draw.notify.NotifyRepository
import com.xorker.draw.notify.NotifyType
import com.xorker.draw.timer.TimerRepository
import org.springframework.stereotype.Component
import kotlin.random.Random
Expand All @@ -11,6 +13,7 @@ import kotlin.random.Random
internal class MafiaPhaseStartGameProcessor(
private val mafiaKeywordRepository: MafiaKeywordRepository,
private val timerRepository: TimerRepository,
private val notifyRepository: NotifyRepository,
) {
private val random: Random = Random(System.currentTimeMillis())

Expand All @@ -34,6 +37,8 @@ internal class MafiaPhaseStartGameProcessor(
)
gameInfo.phase = phase

notifyRepository.notifyMessage(NotifyType.DiscordStartGameNotifyType(room.id, room.locale))

return phase
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.xorker.draw.notify

interface NotifyRepository {
fun notifyMessage(notifyType: NotifyType)
}
52 changes: 52 additions & 0 deletions domain/src/main/kotlin/com/xorker/draw/notify/NotifyType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.xorker.draw.notify

import com.xorker.draw.exception.UnSupportedException
import com.xorker.draw.room.RoomId

sealed class NotifyType {
class DiscordRandomMatchingNotifyType(
name: String,
language: LanguageType,
) : NotifyType() {
val message: String = language.content + " ${name}님이 빠른 게임 상대를 기다리고 있어요."

companion object {
private fun from(name: String, language: String):
DiscordRandomMatchingNotifyType = DiscordRandomMatchingNotifyType(name, getLanguageType(language))

operator fun invoke(name: String, language: String): DiscordRandomMatchingNotifyType = from(name, language)
}
}

class DiscordStartGameNotifyType(
roomId: RoomId,
language: LanguageType,
) : NotifyType() {
val message: String = language.content + " ${roomId.value} 방에서 게임이 시작되었어요."

companion object {
private fun from(roomId: RoomId, language: String):
DiscordStartGameNotifyType = DiscordStartGameNotifyType(roomId, getLanguageType(language))

operator fun invoke(roomId: RoomId, language: String): DiscordStartGameNotifyType = from(roomId, language)
}
}

companion object {
fun getLanguageType(language: String): LanguageType {
return when (language) {
"ko" -> LanguageType.KOREAN
"en" -> LanguageType.ENGLISH
else -> throw UnSupportedException
}
}
}
}

enum class LanguageType(
val content: String,
) {
KOREAN("\uD83C\uDDF0\uD83C\uDDF7"),
ENGLISH("\uD83C\uDDFA\uD83C\uDDF8"),
;
comforest marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include(
"adapter:memory",
"adapter:oauth",
"adapter:rdb",
"adapter:webhook:discord",
"app:api",
"app:support:auth",
"app:support:exception",
Expand Down
Loading