mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-09 23:16:50 +02:00
refactor: move NIP-29 member list fallback to adapter level
Move the participant fallback logic from ChatViewer to the NIP-29 adapter's resolveConversation() method. This keeps protocol-specific behavior in the adapter rather than leaking it into the view. When no member list events (kind 39001/39002) are found, the adapter now fetches recent messages (kind 9) and derives participants from message authors. https://claude.ai/code/session_01Qikw63P4kxwR6ceCQuFMAM
This commit is contained in:
@@ -31,7 +31,7 @@ import { Nip10Adapter } from "@/lib/chat/adapters/nip-10-adapter";
|
||||
import { Nip29Adapter } from "@/lib/chat/adapters/nip-29-adapter";
|
||||
import { Nip53Adapter } from "@/lib/chat/adapters/nip-53-adapter";
|
||||
import type { ChatProtocolAdapter } from "@/lib/chat/adapters/base-adapter";
|
||||
import type { Message, ParticipantRole } from "@/types/chat";
|
||||
import type { Message } from "@/types/chat";
|
||||
import type { ChatAction } from "@/types/chat-actions";
|
||||
import { parseSlashCommand } from "@/lib/chat/slash-command-parser";
|
||||
import {
|
||||
@@ -895,29 +895,6 @@ export function ChatViewer({
|
||||
return participants;
|
||||
}
|
||||
|
||||
// NIP-29 groups: use static participants but fallback to message authors if empty
|
||||
// Some relays may not provide kind 39001/39002 member list events
|
||||
if (protocol === "nip-29" && messages) {
|
||||
const staticParticipants = conversation?.participants || [];
|
||||
|
||||
// If we have static participants from member list events, use them as base
|
||||
// and augment with message authors
|
||||
const participants: { pubkey: string; role?: ParticipantRole }[] = [
|
||||
...staticParticipants,
|
||||
];
|
||||
const seen = new Set(staticParticipants.map((p) => p.pubkey));
|
||||
|
||||
// Add message authors who aren't already in the list as members
|
||||
for (const msg of messages) {
|
||||
if (msg.type !== "system" && !seen.has(msg.author)) {
|
||||
seen.add(msg.author);
|
||||
participants.push({ pubkey: msg.author, role: "member" });
|
||||
}
|
||||
}
|
||||
|
||||
return participants;
|
||||
}
|
||||
|
||||
// Other protocols: use static participants from conversation
|
||||
return conversation?.participants || [];
|
||||
}, [
|
||||
|
||||
@@ -269,11 +269,46 @@ export class Nip29Adapter extends ChatProtocolAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
const participants = Array.from(participantsMap.values());
|
||||
let participants = Array.from(participantsMap.values());
|
||||
|
||||
console.log(
|
||||
`[NIP-29] Found ${participants.length} participants (${adminEvents.length} admin events, ${memberEvents.length} member events)`,
|
||||
);
|
||||
|
||||
// Fallback: if no member list found, derive participants from recent messages
|
||||
if (participants.length === 0) {
|
||||
console.log(
|
||||
`[NIP-29] No member list found, fetching recent messages for participant fallback`,
|
||||
);
|
||||
|
||||
const messagesFilter: Filter = {
|
||||
kinds: [9],
|
||||
"#h": [groupId],
|
||||
limit: 50,
|
||||
};
|
||||
|
||||
const recentMessages = await firstValueFrom(
|
||||
pool
|
||||
.request([relayUrl], [messagesFilter], { eventStore })
|
||||
.pipe(toArray()),
|
||||
);
|
||||
|
||||
// Extract unique authors from messages
|
||||
const messageAuthors = new Set<string>();
|
||||
for (const event of recentMessages) {
|
||||
messageAuthors.add(event.pubkey);
|
||||
}
|
||||
|
||||
participants = Array.from(messageAuthors).map((pubkey) => ({
|
||||
pubkey,
|
||||
role: "member" as const,
|
||||
}));
|
||||
|
||||
console.log(
|
||||
`[NIP-29] Derived ${participants.length} participants from ${recentMessages.length} messages`,
|
||||
);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[NIP-29] Metadata - title: ${title}, icon: ${icon}, description: ${description}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user