feat(channel): KOOK Webhook(WH) 接收模式——与 WS 配置切换(ReceiveMode)
- kook.Config 加 ReceiveMode("ws"默认/"webhook") + WebhookPath(默认/webhook/kook) + WebhookVerifyToken + WebhookEncryptKey(AES-256-CBC)
- 按权威文档(Reference/kaiheila webhook.md)实现: 无X-Signature HMAC, 真实校验=d.verify_token比对(不匹配403)+可选AES解密+zlib解压+challenge回显
- webhook.go: InboundHandler+WebhookPath, POST→zlib解压→AES解密→verify_token校验→challenge回显→归一UnifiedMessage→SetMessageHandler; WS模式Connect不拨网关仅标记connected
- channelbridge/webhookAdapter 接口改用 WebhookPath(); WebhookHandlers 收KOOK WH(ws模式跳过); 既有webhook通道补WebhookPath照常挂载
- namedAdapter 转发InboundHandler/WebhookPath; kook env兜底 +4个CHANNEL_KOOK_*键
- 测试: verify_token 403/challenge/zlib/AES往返/WebhookPath按模式/WH不拨gateway/WebhookHandlers收KOOK; 全仓build/vet/test绿
- 待真token端到端实测(需主人提供CHANNEL_KOOK_TOKEN+开发者后台切WebHook配回调URL)
This commit is contained in:
1 parent
1ebc82fffd
commit
617157262b
11 files changed
+981
-32
No files matched your search
@@ -1,7 +1,9 @@
|
||||
// Package kook implements the built-in KOOK (KaiHeiLa) channel adapter for
|
||||
// Cyrene v2. KOOK is a stateful WebSocket-gateway channel: inbound events are
|
||||
// delivered over a gateway WebSocket (hello/heartbeat/event/resume signaling),
|
||||
// while outbound messages are sent over a bearer-authenticated REST API.
|
||||
// Cyrene v2. KOOK is a stateful channel with two mutually exclusive inbound
|
||||
// modes: a WebSocket-gateway mode (events over a gateway WebSocket with
|
||||
// hello/heartbeat/event/resume signaling) and a Webhook mode (KOOK POSTs event
|
||||
// callbacks to a Cyrene gateway route). Outbound messages are always sent over a
|
||||
// bearer-authenticated REST API.
|
||||
//
|
||||
// The adapter conforms to internal/channel/adapter.PlatformAdapter, translating
|
||||
// native KOOK events into the normalized adapter.UnifiedMessage model and
|
||||
@@ -13,7 +15,7 @@
|
||||
// The design authority is DevDocs/design/08-渠道接入.md §4 (kook) and §7
|
||||
// (framework reusability). It depends on internal/channel/adapter (including the
|
||||
// shared wsutil and httpclient primitives), internal/logger, and the standard
|
||||
// library. The bot token is never logged.
|
||||
// library. The bot token, verify token and encrypt key are never logged.
|
||||
package kook
|
||||
|
||||
import (
|
||||
@@ -37,6 +39,21 @@ const (
|
||||
helloTimeout = 6 * time.Second
|
||||
)
|
||||
|
||||
// Inbound receive modes. KOOK's webhook and websocket modes are mutually
|
||||
// exclusive (DevDocs/design/08 §4): selecting webhook means the gateway WebSocket
|
||||
// no longer delivers events, and vice versa. ReceiveMode decides which path the
|
||||
// adapter uses; the two never run together.
|
||||
const (
|
||||
// modeWS is the default: connect the KOOK gateway WebSocket and receive events.
|
||||
modeWS = "ws"
|
||||
// modeWebhook exposes a Cyrene gateway route that KOOK POSTs callbacks to.
|
||||
modeWebhook = "webhook"
|
||||
// defaultWebhookPath is used when Config.WebhookPath is empty in webhook mode.
|
||||
defaultWebhookPath = "/webhook/kook"
|
||||
// defaultMaxBodyBytes caps an inbound webhook payload at 1 MiB.
|
||||
defaultMaxBodyBytes = 1 << 20
|
||||
)
|
||||
|
||||
// Config holds the settings required to reach the KOOK API.
|
||||
type Config struct {
|
||||
// BotToken is the secret bot token issued by the KOOK developer center. It is
|
||||
@@ -44,9 +61,35 @@ type Config struct {
|
||||
BotToken string `json:"bot_token"`
|
||||
// BaseURL is the KOOK REST API root; empty uses the production default.
|
||||
BaseURL string `json:"base_url"`
|
||||
// ReceiveMode selects the inbound delivery path: "ws" (default) connects the
|
||||
// KOOK gateway WebSocket; "webhook" exposes a gateway route that KOOK POSTs
|
||||
// events to. The two are mutually exclusive.
|
||||
ReceiveMode string `json:"receive_mode"`
|
||||
// WebhookPath is the route the Cyrene gateway mounts the KOOK webhook handler
|
||||
// at when ReceiveMode == "webhook". Empty uses defaultWebhookPath.
|
||||
WebhookPath string `json:"webhook_path"`
|
||||
// WebhookVerifyToken is the KOOK developer-center verify token. When set, every
|
||||
// webhook callback's d.verify_token must match or it is rejected with 403.
|
||||
WebhookVerifyToken string `json:"webhook_verify_token"`
|
||||
// WebhookEncryptKey is the KOOK Encrypt Key. When set, an encrypted callback
|
||||
// body ({"encrypt": ...}) is decrypted with AES-256-CBC before parsing.
|
||||
WebhookEncryptKey string `json:"webhook_encrypt_key"`
|
||||
}
|
||||
|
||||
// Validate checks the configuration for values needed to connect.
|
||||
// normalizedReceiveMode returns ReceiveMode, defaulting empty to "ws".
|
||||
func (c Config) normalizedReceiveMode() string {
|
||||
if strings.TrimSpace(c.ReceiveMode) == "" {
|
||||
return modeWS
|
||||
}
|
||||
return strings.TrimSpace(c.ReceiveMode)
|
||||
}
|
||||
|
||||
// IsWebhook reports whether the adapter should run in webhook mode.
|
||||
func (c Config) IsWebhook() bool { return c.normalizedReceiveMode() == modeWebhook }
|
||||
|
||||
// Validate checks the configuration for values needed to connect. The bot token
|
||||
// is required in both modes because outbound (reply) delivery always uses the
|
||||
// bearer REST API.
|
||||
func (c Config) Validate() error {
|
||||
if strings.TrimSpace(c.BotToken) == "" {
|
||||
return ErrMissingToken
|
||||
|
||||
Reference in new issue
Block a user