Files
Cyrene/backend/platform-bridge/internal/adapter/webhook/adapter.go
T

122 lines
3.1 KiB
Go

package webhook
import (
"context"
"fmt"
"time"
"github.com/yourname/cyrene-ai/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
}