feat: extract groups from message logs

This commit is contained in:
zhaoyilun
2026-07-09 23:42:56 +08:00
parent 7e616a1f10
commit 4502a05bb4
4 changed files with 172 additions and 4 deletions

View File

@@ -0,0 +1,81 @@
package isphere
import (
"sort"
"strings"
)
type Group struct {
GroupID string
DisplayName string
Source string
Confidence float64
RawRef string
}
type SearchGroupsQuery struct {
Query string
Limit int
}
type SearchGroupsResult struct {
Groups []Group
}
func SearchGroupsFromMessages(messages []Message, query SearchGroupsQuery) SearchGroupsResult {
unique := map[string]Group{}
for _, message := range messages {
if strings.EqualFold(message.ConversationType, "groupchat") {
addMessageGroup(unique, message.SenderID)
addMessageGroup(unique, message.ReceiverID)
continue
}
if isLikelyGroupJID(message.SenderID) {
addMessageGroup(unique, message.SenderID)
}
if isLikelyGroupJID(message.ReceiverID) {
addMessageGroup(unique, message.ReceiverID)
}
}
queryText := strings.ToLower(strings.TrimSpace(query.Query))
ids := make([]string, 0, len(unique))
for id := range unique {
if queryText == "" || strings.Contains(strings.ToLower(id), queryText) || strings.Contains(strings.ToLower(unique[id].DisplayName), queryText) {
ids = append(ids, id)
}
}
sort.Strings(ids)
limit := query.Limit
if limit <= 0 || limit > len(ids) {
limit = len(ids)
}
groups := make([]Group, 0, limit)
for _, id := range ids[:limit] {
groups = append(groups, unique[id])
}
return SearchGroupsResult{Groups: groups}
}
func addMessageGroup(unique map[string]Group, id string) {
trimmed := strings.TrimSpace(id)
if trimmed == "" || !isLikelyGroupJID(trimmed) {
return
}
if _, exists := unique[trimmed]; exists {
return
}
unique[trimmed] = Group{
GroupID: trimmed,
DisplayName: trimmed,
Source: "local_readonly",
Confidence: 0.6,
RawRef: "groupchat_jid",
}
}
func isLikelyGroupJID(id string) bool {
lower := strings.ToLower(strings.TrimSpace(id))
return strings.Contains(lower, "conference") || strings.Contains(lower, "muc") || strings.Contains(lower, "group")
}

View File

@@ -0,0 +1,22 @@
package isphere
import (
"reflect"
"testing"
)
func TestSearchGroupsFromMessagesMatchesGroupchatJIDs(t *testing.T) {
messages := []Message{
{ID: "msg-1", ConversationType: "groupchat", SenderID: "project-room@conference.imopenfire1-lanzhou", ReceiverID: "user@imopenfire1-lanzhou"},
{ID: "msg-2", ConversationType: "chat", SenderID: "alice@imopenfire1-lanzhou", ReceiverID: "bob@imopenfire1-lanzhou"},
{ID: "msg-3", ConversationType: "groupchat", SenderID: "project-room@conference.imopenfire1-lanzhou", ReceiverID: "other@imopenfire1-lanzhou"},
}
got := SearchGroupsFromMessages(messages, SearchGroupsQuery{Query: "project", Limit: 10})
want := SearchGroupsResult{Groups: []Group{
{GroupID: "project-room@conference.imopenfire1-lanzhou", DisplayName: "project-room@conference.imopenfire1-lanzhou", Source: "local_readonly", Confidence: 0.6, RawRef: "groupchat_jid"},
}}
if !reflect.DeepEqual(got, want) {
t.Fatalf("SearchGroupsFromMessages() = %#v, want %#v", got, want)
}
}