mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-26 02:04:37 +08:00
fix(merge): isolate ambiguous private exports
Keep one-member private exports source-local until exact message overlap proves they belong to the same chat. This prevents unrelated outgoing-only chats from losing messages when platform IDs collide.
This commit is contained in:
1 parent
691293b46f
commit
c883e6ab47
2 files changed
+47
-4
No files matched your search
@@ -178,6 +178,46 @@ describe('buildMergedOutput', () => {
|
||||
assert.equal(new Set(result.chatLabData.messages.map((message) => message.platformMessageId)).size, 2)
|
||||
})
|
||||
|
||||
it('keeps ambiguous one-member private chats source-local without verified overlap', () => {
|
||||
const first = createMockSource(
|
||||
{ name: 'Alice', platform: 'telegram', type: 'private' },
|
||||
[{ platformId: 'owner' }],
|
||||
[
|
||||
{
|
||||
platformMessageId: '1',
|
||||
senderPlatformId: 'owner',
|
||||
timestamp: 100,
|
||||
type: 0,
|
||||
content: 'first chat',
|
||||
},
|
||||
]
|
||||
)
|
||||
const second = createMockSource(
|
||||
{ name: 'Bob', platform: 'telegram', type: 'private' },
|
||||
[{ platformId: 'owner' }],
|
||||
[
|
||||
{
|
||||
platformMessageId: '1',
|
||||
senderPlatformId: 'owner',
|
||||
timestamp: 200,
|
||||
type: 0,
|
||||
content: 'second chat',
|
||||
},
|
||||
]
|
||||
)
|
||||
const sources = [
|
||||
{ source: first, filename: 'alice.json' },
|
||||
{ source: second, filename: 'bob.json' },
|
||||
]
|
||||
|
||||
const conflicts = checkConflictsFromSources(sources)
|
||||
const result = buildMergedOutput(sources, 'Merged')
|
||||
|
||||
assert.equal(conflicts.totalMessages, 2)
|
||||
assert.equal(result.chatLabData.messages.length, 2)
|
||||
assert.equal(new Set(result.chatLabData.messages.map((message) => message.platformMessageId)).size, 2)
|
||||
})
|
||||
|
||||
it('deduplicates overlapping private exports when their observed members differ', () => {
|
||||
const meta: MergerSourceMeta = { name: 'Alice', platform: 'qq', type: 'private' }
|
||||
const sharedMessage: MergerInputMessage = {
|
||||
|
||||
@@ -56,12 +56,15 @@ function createMessageScope(meta: MergerSourceMeta | null, members: MergerMember
|
||||
|
||||
const memberIds = [...new Set(members.map((member) => member.platformId))].sort()
|
||||
if (memberIds.length > 0) {
|
||||
if (type === 'private') return JSON.stringify([platform, type, 'members', memberIds])
|
||||
return JSON.stringify([platform, type, 'name-members', meta?.name || '', memberIds])
|
||||
if (type === 'private') {
|
||||
if (memberIds.length >= 2) return JSON.stringify([platform, type, 'members', memberIds])
|
||||
} else {
|
||||
return JSON.stringify([platform, type, 'name-members', meta?.name || '', memberIds])
|
||||
}
|
||||
}
|
||||
|
||||
// Without a stable group ID or participant set, sharing message IDs across
|
||||
// sources could silently merge unrelated chats. Keep those source-local.
|
||||
// A one-sided private export does not identify the other participant. Without
|
||||
// a stable group ID or complete participant set, keep message IDs source-local.
|
||||
return JSON.stringify([platform, type, 'source', sourceIndex])
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user