Files
im_server/server/im_business_events.go
T

91 lines
2.8 KiB
Go

package main
import (
"encoding/json"
"strings"
"time"
"github.com/tinode/chat/server/logs"
"github.com/tinode/chat/server/store"
"github.com/tinode/chat/server/store/types"
)
func stableIMEventID(parts ...any) string {
return types.StableEventID(parts...)
}
func enqueueIMBusinessEvent(tenantID types.TenantID, eventID, targetType, target string,
actor types.Uid, eventType string, payload any) error {
if tenantID.IsZero() || eventID == "" || target == "" || eventType == "" {
return types.ErrMalformed
}
encoded, err := json.Marshal(payload)
if err != nil {
return err
}
return publishIMBusinessRealtimeEvent(tenantID, targetType, target, actor, eventType, encoded)
}
func publishIMBusinessRealtimeEvent(tenantID types.TenantID, targetType, target string, actor types.Uid, eventType string, payload json.RawMessage) error {
from := ""
if !actor.IsZero() {
from = actor.UserId()
}
if len(payload) == 0 {
payload = json.RawMessage(`{}`)
}
message := &ServerComMessage{
TenantID: tenantID, RcptTo: target, AsUser: from, Timestamp: time.Now().UTC().Round(time.Millisecond),
Info: &MsgServerInfo{Topic: target, From: from, What: "im", Event: eventType, Payload: payload},
}
switch targetType {
case "user":
uid := types.ParseUserId(target)
if uid.IsZero() {
return types.ErrMalformed
}
if globals.sessionStore != nil {
globals.sessionStore.DeliverToUser(tenantID, uid, "", message)
}
publishRealtimeUserMessage(uid, message)
case "topic":
if globals.hub != nil {
select {
case globals.hub.routeSrv <- message:
default:
logs.Warn.Printf("business realtime: hub queue full target=%s event=%s", strings.TrimSpace(target), eventType)
}
}
publishRealtimeTopicMessage(target, message)
default:
return types.ErrMalformed
}
return nil
}
func createIMSystemNotification(tenantID types.TenantID, uid types.Uid, eventID, eventType,
title, summary string, action types.KVMap) error {
if uid.IsZero() {
return types.ErrMalformed
}
return store.Security.CreateSystemNotification(tenantID, &types.SystemNotification{
TenantID: tenantID, UserID: uid, EventID: eventID, EventType: eventType,
Title: title, Summary: summary, Action: action,
})
}
func publishIMRelationEvent(tenantID types.TenantID, actor, target types.Uid, stableID, eventType, title, summary string) error {
if target.IsZero() {
return types.ErrMalformed
}
eventID := stableIMEventID("relation", stableID, eventType, target.UserId())
if target != actor && title != "" {
if err := createIMSystemNotification(tenantID, target, stableIMEventID(eventID, "notification"), eventType,
title, summary, types.KVMap{"user_id": actor.UserId()}); err != nil {
return err
}
}
return enqueueIMBusinessEvent(tenantID, eventID, "user", target.UserId(), actor, eventType,
map[string]any{"user_id": actor.UserId()})
}