second commit
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
package dispatch
|
||||
|
||||
// Event types and helper functions for the enhanced dispatch system.
|
||||
//
|
||||
// Reference: Chatwoot event naming conventions
|
||||
// - Chatwoot uses Wisper-style event names like "conversation.created",
|
||||
// "message.created", "contact.created", etc.
|
||||
// - In gochat, channel.EventType already defines these constants.
|
||||
// - This file provides additional event types specific to the dispatch layer
|
||||
// and helper functions for event construction.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gochat/gochat/internal/channel"
|
||||
)
|
||||
|
||||
// DispatchEvent defines additional event types specific to the dispatch layer.
|
||||
// These complement the channel.EventType constants already defined in
|
||||
// channel/event.go.
|
||||
type DispatchEvent string
|
||||
|
||||
const (
|
||||
// Auto-assignment events (triggered by autoassignment listener)
|
||||
DispatchEventAutoAssign DispatchEvent = "auto_assignment.assign"
|
||||
DispatchEventAutoAssignFailed DispatchEvent = "auto_assignment.assign_failed"
|
||||
DispatchEventAutoAssignSkipped DispatchEvent = "auto_assignment.assign_skipped"
|
||||
|
||||
// Reporting events (for analytics and reporting)
|
||||
DispatchEventReportGenerated DispatchEvent = "report.generated"
|
||||
DispatchEventReportFailed DispatchEvent = "report.failed"
|
||||
|
||||
// CSAT survey events
|
||||
DispatchEventCsatSurveySent DispatchEvent = "csat_survey.sent"
|
||||
DispatchEventCsatResponseReceived DispatchEvent = "csat_survey.response_received"
|
||||
|
||||
// Campaign events
|
||||
DispatchEventCampaignStarted DispatchEvent = "campaign.started"
|
||||
DispatchEventCampaignCompleted DispatchEvent = "campaign.completed"
|
||||
|
||||
// Webhook/hook events
|
||||
DispatchEventHookTriggered DispatchEvent = "hook.triggered"
|
||||
DispatchEventWebhookSent DispatchEvent = "webhook.sent"
|
||||
DispatchEventWebhookFailed DispatchEvent = "webhook.failed"
|
||||
)
|
||||
|
||||
// NewChannelEvent creates a ChannelEvent with the given type and data.
|
||||
// Timestamp is set to the current Unix milliseconds.
|
||||
func NewChannelEvent(eventType string, data map[string]interface{}) *channel.ChannelEvent {
|
||||
if data == nil {
|
||||
data = make(map[string]interface{})
|
||||
}
|
||||
return &channel.ChannelEvent{
|
||||
Type: channel.EventType(eventType),
|
||||
Data: data,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewDispatchEvent creates a ChannelEvent from a DispatchEvent type.
|
||||
func NewDispatchEvent(eventType DispatchEvent, data map[string]interface{}) *channel.ChannelEvent {
|
||||
return NewChannelEvent(string(eventType), data)
|
||||
}
|
||||
|
||||
// EventDataWithConversation creates event data containing a conversation ID.
|
||||
// This is a common pattern where events need to reference a specific conversation.
|
||||
func EventDataWithConversation(conversationID uint, accountID uint, inboxID uint) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"conversation_id": conversationID,
|
||||
"account_id": accountID,
|
||||
"inbox_id": inboxID,
|
||||
}
|
||||
}
|
||||
|
||||
// EventDataWithAssignment creates event data for an assignment event,
|
||||
// including the agent who was assigned.
|
||||
func EventDataWithAssignment(conversationID uint, accountID uint, inboxID uint, assigneeID uint) map[string]interface{} {
|
||||
data := EventDataWithConversation(conversationID, accountID, inboxID)
|
||||
data["assignee_id"] = assigneeID
|
||||
return data
|
||||
}
|
||||
|
||||
// ExtractConversationID extracts a conversation ID from event data.
|
||||
// Returns 0 and an error if not found or not a valid uint.
|
||||
func ExtractConversationID(data map[string]interface{}) (uint, error) {
|
||||
raw, ok := data["conversation_id"]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("conversation_id not found in event data")
|
||||
}
|
||||
switch v := raw.(type) {
|
||||
case uint:
|
||||
return v, nil
|
||||
case int:
|
||||
return uint(v), nil
|
||||
case float64:
|
||||
return uint(v), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unexpected type for conversation_id: %T", raw)
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractAccountID extracts an account ID from event data.
|
||||
func ExtractAccountID(data map[string]interface{}) (uint, error) {
|
||||
raw, ok := data["account_id"]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("account_id not found in event data")
|
||||
}
|
||||
switch v := raw.(type) {
|
||||
case uint:
|
||||
return v, nil
|
||||
case int:
|
||||
return uint(v), nil
|
||||
case float64:
|
||||
return uint(v), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unexpected type for account_id: %T", raw)
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractInboxID extracts an inbox ID from event data.
|
||||
func ExtractInboxID(data map[string]interface{}) (uint, error) {
|
||||
raw, ok := data["inbox_id"]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("inbox_id not found in event data")
|
||||
}
|
||||
switch v := raw.(type) {
|
||||
case uint:
|
||||
return v, nil
|
||||
case int:
|
||||
return uint(v), nil
|
||||
case float64:
|
||||
return uint(v), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unexpected type for inbox_id: %T", raw)
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractAssigneeID extracts an assignee (agent) ID from event data.
|
||||
func ExtractAssigneeID(data map[string]interface{}) (uint, error) {
|
||||
raw, ok := data["assignee_id"]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("assignee_id not found in event data")
|
||||
}
|
||||
switch v := raw.(type) {
|
||||
case uint:
|
||||
return v, nil
|
||||
case int:
|
||||
return uint(v), nil
|
||||
case float64:
|
||||
return uint(v), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unexpected type for assignee_id: %T", raw)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user