feat: extract contacts from message logs

This commit is contained in:
zhaoyilun
2026-07-09 23:30:53 +08:00
parent 878b729015
commit 2621d34336
4 changed files with 160 additions and 4 deletions

View File

@@ -0,0 +1,69 @@
package isphere
import (
"sort"
"strings"
)
type Contact struct {
ContactID string
DisplayName string
Account string
Source string
Confidence float64
RawRef string
}
type SearchContactsQuery struct {
Query string
Limit int
}
type SearchContactsResult struct {
Contacts []Contact
}
func SearchContactsFromMessages(messages []Message, query SearchContactsQuery) SearchContactsResult {
unique := map[string]Contact{}
for _, message := range messages {
addMessageContact(unique, message.SenderID)
addMessageContact(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)
}
contacts := make([]Contact, 0, limit)
for _, id := range ids[:limit] {
contacts = append(contacts, unique[id])
}
return SearchContactsResult{Contacts: contacts}
}
func addMessageContact(unique map[string]Contact, id string) {
trimmed := strings.TrimSpace(id)
if trimmed == "" {
return
}
if _, exists := unique[trimmed]; exists {
return
}
unique[trimmed] = Contact{
ContactID: trimmed,
DisplayName: trimmed,
Account: trimmed,
Source: "local_readonly",
Confidence: 0.6,
RawRef: "message_jid",
}
}

View File

@@ -0,0 +1,22 @@
package isphere
import (
"reflect"
"testing"
)
func TestSearchContactsFromMessagesMatchesBareJIDs(t *testing.T) {
messages := []Message{
{ID: "msg-1", SenderID: "alice@imopenfire1-lanzhou", ReceiverID: "bob@imopenfire1-lanzhou"},
{ID: "msg-2", SenderID: "alice@imopenfire1-lanzhou", ReceiverID: "carol@imopenfire1-lanzhou"},
}
got := SearchContactsFromMessages(messages, SearchContactsQuery{Query: "imopenfire1", Limit: 2})
want := SearchContactsResult{Contacts: []Contact{
{ContactID: "alice@imopenfire1-lanzhou", DisplayName: "alice@imopenfire1-lanzhou", Account: "alice@imopenfire1-lanzhou", Source: "local_readonly", Confidence: 0.6, RawRef: "message_jid"},
{ContactID: "bob@imopenfire1-lanzhou", DisplayName: "bob@imopenfire1-lanzhou", Account: "bob@imopenfire1-lanzhou", Source: "local_readonly", Confidence: 0.6, RawRef: "message_jid"},
}}
if !reflect.DeepEqual(got, want) {
t.Fatalf("SearchContactsFromMessages() = %#v, want %#v", got, want)
}
}