71f0a1abdb
- 所有Go模块路径从 github.com/yourname/cyrene-ai 迁移到 git.yeij.top/AskaEth/Cyrene - 5个Go Dockerfile添加 GOPROXY=https://goproxy.cn,direct 解决国内构建问题 - ai-core go.mod 添加 pkg/plugins replace 指令 - Caddyfile 简化为 http:// 通配 + handle 保留 /api 前缀 - ethend Dockerfile 适配 (npm install + 仅 COPY package.json) - ethend 新增 RUNNING_IN_DOCKER 环境变量,健康检查改用Docker服务名 - ethend 数据库状态检查支持Docker hostname (postgres/redis/qdrant/minio) - process-manager 新增 CONTAINER_SVC_MAP + Docker模式自动检测 - 统一 docker-compose.dev.db.yml 卷名 (pg_data/redis_data/qdrant_data/minio_data) - docker-compose.yml ethend服务挂载docker.sock + 端口变量化 - 清理 .env 统一后的残留文件与提示信息 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
package webhook
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.yeij.top/AskaEth/Cyrene/platform-bridge/internal/bridge"
|
|
)
|
|
|
|
// WebhookPayload is the standard webhook request body.
|
|
type WebhookPayload struct {
|
|
UserID string `json:"user_id"`
|
|
UserName string `json:"user_name"`
|
|
Content string `json:"content"`
|
|
ContentType string `json:"content_type"`
|
|
ChannelID string `json:"channel_id"`
|
|
ChannelType string `json:"channel_type"`
|
|
MessageID string `json:"message_id,omitempty"`
|
|
ReplyTo string `json:"reply_to,omitempty"`
|
|
Timestamp int64 `json:"timestamp,omitempty"`
|
|
}
|
|
|
|
// WebhookResponse is the standard webhook response body.
|
|
type WebhookResponse struct {
|
|
Messages []WebhookResponseMessage `json:"messages"`
|
|
ReplyTo string `json:"reply_to,omitempty"`
|
|
}
|
|
|
|
// WebhookResponseMessage is a single message in a webhook response.
|
|
type WebhookResponseMessage struct {
|
|
Type string `json:"type"` // "chat", "action", "system_info"
|
|
Content string `json:"content"`
|
|
}
|
|
|
|
// Adapter implements PlatformAdapter for generic webhook integrations.
|
|
type Adapter struct {
|
|
name string
|
|
}
|
|
|
|
func NewAdapter(name string) *Adapter {
|
|
if name == "" {
|
|
name = "webhook"
|
|
}
|
|
return &Adapter{name: name}
|
|
}
|
|
|
|
func (a *Adapter) PlatformName() string { return a.name }
|
|
|
|
func (a *Adapter) Capabilities() bridge.PlatformCapabilities {
|
|
return bridge.PlatformCapabilities{
|
|
MaxMessageLength: 2000,
|
|
SupportsMarkdown: true,
|
|
SupportsImage: false,
|
|
SupportsVoice: false,
|
|
SupportsEmoji: true,
|
|
SupportsReaction: false,
|
|
SupportsTypingHint: false,
|
|
RecommendBurstMax: 2,
|
|
}
|
|
}
|
|
|
|
func (a *Adapter) Connect(ctx context.Context) error {
|
|
fmt.Printf("[webhook:%s] adapter ready\n", a.name)
|
|
return nil
|
|
}
|
|
|
|
func (a *Adapter) Disconnect(ctx context.Context) error { return nil }
|
|
|
|
func (a *Adapter) IsConnected() bool { return true }
|
|
|
|
func (a *Adapter) HealthCheck() error { return nil }
|
|
|
|
// ToUnified converts a webhook payload to UnifiedMessage.
|
|
func (a *Adapter) ToUnified(rawMessage interface{}) (*bridge.UnifiedMessage, error) {
|
|
payload, ok := rawMessage.(*WebhookPayload)
|
|
if !ok {
|
|
return nil, fmt.Errorf("expected *WebhookPayload, got %T", rawMessage)
|
|
}
|
|
|
|
contentType := payload.ContentType
|
|
if contentType == "" {
|
|
contentType = "text"
|
|
}
|
|
channelType := payload.ChannelType
|
|
if channelType == "" {
|
|
channelType = "direct"
|
|
}
|
|
|
|
ts := time.Now()
|
|
if payload.Timestamp > 0 {
|
|
ts = time.Unix(payload.Timestamp, 0)
|
|
}
|
|
|
|
return &bridge.UnifiedMessage{
|
|
SenderID: payload.UserID,
|
|
SenderName: payload.UserName,
|
|
Platform: a.name,
|
|
ChannelID: payload.ChannelID,
|
|
ChannelType: channelType,
|
|
Content: payload.Content,
|
|
ContentType: contentType,
|
|
MessageID: payload.MessageID,
|
|
ReplyTo: payload.ReplyTo,
|
|
RawData: rawMessage,
|
|
Timestamp: ts,
|
|
}, nil
|
|
}
|
|
|
|
// FromUnified converts a unified response to webhook response format.
|
|
func (a *Adapter) FromUnified(response *bridge.UnifiedResponse) ([]bridge.PlatformMessage, error) {
|
|
var msgs []bridge.PlatformMessage
|
|
for _, rm := range response.Messages {
|
|
msgs = append(msgs, bridge.PlatformMessage{
|
|
Content: rm.Content,
|
|
FormatMode: rm.FormatMode,
|
|
ReplyTo: response.ReplyTo,
|
|
})
|
|
}
|
|
return msgs, nil
|
|
}
|