feat: add im group mention flows

This commit is contained in:
richjohnrambo
2026-08-12 15:33:56 +08:00
parent 943ebe1397
commit 774a448c12
5 changed files with 345 additions and 0 deletions
+69
View File
@@ -1052,6 +1052,14 @@ func (t *Topic) saveAndBroadcastMessage(msg *ClientComMessage, asUid types.Uid,
return types.ErrPermissionDenied
}
}
if t.cat == types.TopicCatGrp && head != nil && msg.sess != nil && msg.sess.authLvl != auth.LevelRoot {
normalized, err := t.validateAndNormalizeMentions(asUid, head)
if err != nil {
msg.sess.queueOut(ErrPermissionDenied(msg.Id, t.original(asUid), msg.Timestamp))
return err
}
head = normalized
}
if t.cat == types.TopicCatP2P && msg.sess != nil && msg.sess.authLvl != auth.LevelRoot &&
store.Relations != nil && store.Store != nil && store.Store.IsOpen() {
peer := t.p2pOtherUser(asUid)
@@ -1196,6 +1204,67 @@ func (t *Topic) handlePubBroadcast(msg *ClientComMessage) {
}
}
func (t *Topic) validateAndNormalizeMentions(asUid types.Uid, head map[string]any) (map[string]any, error) {
mentionAll, _ := head["mention_all"].(bool)
rawMentions, hasMentions := head["mentions"]
if !mentionAll && !hasMentions {
return head, nil
}
pud := t.perUser[asUid]
access := pud.modeGiven & pud.modeWant
if mentionAll && !access.IsAdmin() {
return nil, types.ErrPermissionDenied
}
validMembers := make(map[string]struct{}, len(t.perUser))
for uid, pud := range t.perUser {
mode := pud.modeGiven & pud.modeWant
if !pud.deleted && mode.IsJoiner() && mode.IsReader() {
validMembers[uid.UserId()] = struct{}{}
}
}
normalized := make(map[string]any, len(head))
for key, value := range head {
normalized[key] = value
}
if hasMentions {
filtered := filterValidMentions(rawMentions, validMembers)
if len(filtered) == 0 {
delete(normalized, "mentions")
} else {
normalized["mentions"] = filtered
}
}
return normalized, nil
}
func filterValidMentions(raw any, validMembers map[string]struct{}) []map[string]any {
mentions, ok := raw.([]any)
if !ok {
if typed, ok := raw.([]map[string]any); ok {
mentions = make([]any, 0, len(typed))
for _, item := range typed {
mentions = append(mentions, item)
}
}
}
if len(mentions) == 0 {
return nil
}
filtered := make([]map[string]any, 0, len(mentions))
for _, item := range mentions {
mention, ok := item.(map[string]any)
if !ok {
continue
}
userID, _ := mention["user_id"].(string)
if _, ok = validMembers[userID]; !ok {
continue
}
filtered = append(filtered, mention)
}
return filtered
}
// handleNoteBroadcast fans out {note} -> {info} messages to recipients in a master topic.
// This is a NON-proxy broadcast (at master topic).
func (t *Topic) handleNoteBroadcast(msg *ClientComMessage) {