feat: filter receive messages by conversation and query

This commit is contained in:
zhaoyilun
2026-07-10 01:22:17 +08:00
parent bbffa2189d
commit e7324d8aa6
9 changed files with 181 additions and 21 deletions

View File

@@ -23,7 +23,9 @@ type Message struct {
}
type ReceiveMessagesQuery struct {
Limit int
ConversationID string
Query string
Limit int
}
type ReceiveMessagesResult struct {
@@ -41,9 +43,6 @@ func (s EncryptedPacketLogSource) ReceiveMessages(ctx context.Context, query Rec
}
messages := make([]Message, 0, limit)
for index, line := range s.Lines {
if len(messages) == limit {
break
}
select {
case <-ctx.Done():
return ReceiveMessagesResult{}, ctx.Err()
@@ -57,11 +56,43 @@ func (s EncryptedPacketLogSource) ReceiveMessages(ctx context.Context, query Rec
if err != nil {
return ReceiveMessagesResult{}, fmt.Errorf("parse packet log line %d: %w", index, err)
}
messages = append(messages, normalizePacketMessage(parsed))
message := normalizePacketMessage(parsed)
if !receiveMessageMatchesQuery(message, query) {
continue
}
messages = append(messages, message)
if len(messages) == limit {
break
}
}
return ReceiveMessagesResult{Messages: messages}, nil
}
func receiveMessageMatchesQuery(message Message, query ReceiveMessagesQuery) bool {
if strings.TrimSpace(query.ConversationID) != "" && message.ConversationID != strings.TrimSpace(query.ConversationID) {
return false
}
keyword := strings.ToLower(strings.TrimSpace(query.Query))
if keyword == "" {
return true
}
values := []string{
message.ID,
message.ConversationID,
message.SenderID,
message.ReceiverID,
message.Text,
message.Subject,
message.ReceiptID,
}
for _, value := range values {
if strings.Contains(strings.ToLower(value), keyword) {
return true
}
}
return false
}
func normalizePacketMessage(msg packetlog.Message) Message {
sender := bareJID(msg.From)
receiver := bareJID(msg.To)

View File

@@ -42,6 +42,58 @@ func TestEncryptedPacketLogSourceReturnsNormalizedMessages(t *testing.T) {
}
}
func TestEncryptedPacketLogSourceFiltersByConversationAndQuery(t *testing.T) {
first := `--------------------------------------------------------------------------------------------------------------------------------------------
2026/7/7 15:30:07
<message id="msg-alpha" from="sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="receiver@imopenfire1-lanzhou" type="chat">
<body>alpha status update</body>
<received xmlns="urn:xmpp:receipts" id="receipt-alpha" type="1" stamp="" />
<subject>TASK_UPDATE</subject>
<isphere xmlns="isphere.im" type="1001" sendtime="1783423807000" version="1" />
<readed />
</message>`
second := `--------------------------------------------------------------------------------------------------------------------------------------------
2026/7/7 15:31:07
<message id="msg-beta" from="project-room@conference.imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="sender@imopenfire1-lanzhou" type="groupchat">
<body>beta budget redacted-report.docx</body>
<received xmlns="urn:xmpp:receipts" id="receipt-beta" type="1" stamp="" />
<subject>FILE_TRANSFER_CANCEL</subject>
<isphere xmlns="isphere.im" type="1001" sendtime="1783423867000" version="1" />
<readed />
</message>`
source := EncryptedPacketLogSource{Lines: []string{
encryptPacketLineForTest(t, first),
encryptPacketLineForTest(t, second),
}}
got, err := source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{
ConversationID: "project-room@conference.imopenfire1-lanzhou|sender@imopenfire1-lanzhou",
Query: "BUDGET",
Limit: 10,
})
if err != nil {
t.Fatalf("ReceiveMessages returned error: %v", err)
}
if len(got.Messages) != 1 {
t.Fatalf("message count = %d, want 1: %+v", len(got.Messages), got.Messages)
}
if got.Messages[0].ID != "msg-beta" {
t.Fatalf("message id = %q, want msg-beta", got.Messages[0].ID)
}
empty, err := source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{
ConversationID: "project-room@conference.imopenfire1-lanzhou|sender@imopenfire1-lanzhou",
Query: "alpha",
Limit: 10,
})
if err != nil {
t.Fatalf("ReceiveMessages returned error for empty query: %v", err)
}
if len(empty.Messages) != 0 {
t.Fatalf("empty query returned %+v, want none", empty.Messages)
}
}
func encryptPacketLineForTest(t *testing.T, plaintext string) string {
t.Helper()
block, err := des.NewCipher([]byte("hyhccdtm"))