90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
package platformadapter
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/bridge/ai-customer-service/internal/domain/message"
|
|
"github.com/bridge/ai-customer-service/internal/service/dialog"
|
|
)
|
|
|
|
type Sub2APIAdapter struct{}
|
|
|
|
func NewSub2APIAdapter() *Sub2APIAdapter {
|
|
return &Sub2APIAdapter{}
|
|
}
|
|
|
|
func (a *Sub2APIAdapter) Platform() string {
|
|
return "sub2api"
|
|
}
|
|
|
|
func (a *Sub2APIAdapter) ParseInbound(_ *http.Request, body []byte, ctx IngressContext) (*message.UnifiedMessage, *PlatformInboundMeta, error) {
|
|
var payload Sub2APIInboundPayload
|
|
decoder := json.NewDecoder(strings.NewReader(string(body)))
|
|
decoder.DisallowUnknownFields()
|
|
if err := decoder.Decode(&payload); err != nil {
|
|
return nil, nil, NewRequestError(http.StatusBadRequest, "CS_REQ_4001", "invalid request body")
|
|
}
|
|
|
|
payload.Channel = strings.TrimSpace(payload.Channel)
|
|
payload.OpenID = strings.TrimSpace(payload.OpenID)
|
|
payload.UserID = strings.TrimSpace(payload.UserID)
|
|
payload.Content = strings.TrimSpace(payload.Content)
|
|
payload.ContentType = strings.TrimSpace(payload.ContentType)
|
|
payload.ReplyTo = strings.TrimSpace(payload.ReplyTo)
|
|
if ctx.PathChannel != "" {
|
|
payload.Channel = strings.TrimSpace(ctx.PathChannel)
|
|
}
|
|
if payload.Channel == "" || payload.OpenID == "" || payload.Content == "" {
|
|
return nil, nil, NewRequestError(http.StatusBadRequest, "CS_REQ_4002", "channel, open_id and content are required")
|
|
}
|
|
if payload.Timestamp.IsZero() {
|
|
payload.Timestamp = ctx.ReceivedAt
|
|
}
|
|
|
|
msg := &message.UnifiedMessage{
|
|
MessageID: payload.MessageID,
|
|
Channel: payload.Channel,
|
|
OpenID: payload.OpenID,
|
|
UserID: payload.UserID,
|
|
Content: payload.Content,
|
|
ContentType: payload.ContentType,
|
|
Timestamp: payload.Timestamp,
|
|
ReplyTo: payload.ReplyTo,
|
|
}
|
|
meta := &PlatformInboundMeta{
|
|
EventID: buildEventID("sub2api", payload.MessageID, payload.OpenID, ctx.ReceivedAt),
|
|
Platform: a.Platform(),
|
|
Channel: payload.Channel,
|
|
SourceMessageID: payload.MessageID,
|
|
SourceUserID: payload.OpenID,
|
|
}
|
|
return msg, meta, nil
|
|
}
|
|
|
|
func (a *Sub2APIAdapter) BuildIngressAck(result *dialog.Result, meta *PlatformInboundMeta) any {
|
|
resp := map[string]any{
|
|
"accepted": true,
|
|
"platform": a.Platform(),
|
|
}
|
|
if meta != nil {
|
|
resp["event_id"] = meta.EventID
|
|
}
|
|
if result != nil {
|
|
resp["session_id"] = result.SessionID
|
|
if strings.TrimSpace(result.TicketID) != "" {
|
|
resp["ticket_id"] = result.TicketID
|
|
}
|
|
}
|
|
return resp
|
|
}
|
|
|
|
func buildEventID(platform, messageID, openID string, now time.Time) string {
|
|
if strings.TrimSpace(messageID) != "" {
|
|
return strings.ToLower(strings.TrimSpace(platform)) + ":" + strings.TrimSpace(messageID)
|
|
}
|
|
return strings.ToLower(strings.TrimSpace(platform)) + ":" + strings.TrimSpace(openID) + ":" + now.UTC().Format(time.RFC3339Nano)
|
|
}
|