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 }