增加钉钉通知

This commit is contained in:
2025-11-04 17:19:28 +08:00
parent 1de86a2f46
commit 4845094577
11 changed files with 398 additions and 42 deletions

View File

@@ -0,0 +1,100 @@
package com.pomelotea.hoperun.sign.notify
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.pomelotea.hoperun.sign.api.model.DingTalkMarkdownRequest
import com.pomelotea.hoperun.sign.api.model.DingTalkNotifyRequest
import com.pomelotea.hoperun.sign.api.model.DingTalkNotifyResponse
import com.pomelotea.hoperun.sign.api.model.MarkdownContent
import com.pomelotea.hoperun.sign.common.client
import com.pomelotea.hoperun.sign.config.DingTalkConfig
import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler.Companion.logger
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.springframework.stereotype.Service
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.util.Base64
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import kotlin.experimental.and
@Service
open class DingTalkNotifyHelper(
private val dingTalkConfig: DingTalkConfig
) {
fun sendText(content: String): DingTalkNotifyResponse {
if (!dingTalkConfig.enabled) {
logger.info("钉钉通知未启用,跳过发送消息")
return DingTalkNotifyResponse(0, "钉钉通知未启用")
}
val request = DingTalkNotifyRequest(
text = com.pomelotea.hoperun.sign.api.model.TextContent(content)
)
return sendRequest(request)
}
fun sendMarkdown(title: String, content: String): DingTalkNotifyResponse {
if (!dingTalkConfig.enabled) {
logger.info("钉钉通知未启用,跳过发送消息")
return DingTalkNotifyResponse(0, "钉钉通知未启用")
}
val request = DingTalkMarkdownRequest(
markdown = MarkdownContent(title, content)
)
return sendRequest(request)
}
private fun sendRequest(request: Any): DingTalkNotifyResponse {
try {
val url = generateSignedUrl()
val jsonBody = JSON.toJSONString(request)
logger.info("发送钉钉消息: $jsonBody")
val httpRequest = Request.Builder()
.url(url)
.post(jsonBody.toRequestBody("application/json;charset=utf-8".toMediaTypeOrNull()))
.build()
val response = client.newCall(httpRequest).execute()
val responseBody = response.body?.string()
logger.info("钉钉响应: $responseBody")
return JSONObject.parseObject(responseBody, DingTalkNotifyResponse::class.java)
} catch (e: Exception) {
logger.error("发送钉钉消息失败", e)
return DingTalkNotifyResponse(-1, "发送钉钉消息失败: ${e.message}")
}
}
private fun generateSignedUrl(): String {
val webhook = dingTalkConfig.webhook
val secret = dingTalkConfig.secret
if (secret.isEmpty()) {
return webhook
}
val timestamp = System.currentTimeMillis()
val sign = generateSign(timestamp.toString(), secret)
return "$webhook&timestamp=$timestamp&sign=$sign"
}
private fun generateSign(timestamp: String, secret: String): String {
val stringToSign = "$timestamp\n$secret"
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(secret.toByteArray(StandardCharsets.UTF_8), "HmacSHA256"))
val signData = mac.doFinal(stringToSign.toByteArray(StandardCharsets.UTF_8))
val sign = Base64.getEncoder().encodeToString(signData)
return URLEncoder.encode(sign, StandardCharsets.UTF_8.name())
}
}