mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-10 15:36:53 +02:00
* fix: hide zap reply previews for missing or non-chat events Only show reply previews for zaps when: 1. The replied-to event exists in the event store 2. The replied-to event is a chat kind (9, 9321, or 1311) This prevents showing loading states or reply previews for zaps replying to events we don't have or non-chat events. * refactor: extract CHAT_KINDS constant and include zap receipts - Create CHAT_KINDS constant in types/chat.ts with all chat event kinds - Include kind 9735 (zap receipts) as a chat kind - Update ChatViewer to use the new constant for validation - Improves maintainability and makes it easier to update chat kinds Chat kinds now include: - 9: NIP-29 group chat messages - 9321: NIP-61 nutzaps - 1311: NIP-53 live chat messages - 9735: NIP-57 zap receipts --------- Co-authored-by: Claude <noreply@anthropic.com>
260 lines
5.9 KiB
TypeScript
260 lines
5.9 KiB
TypeScript
import type { NostrEvent } from "./nostr";
|
|
|
|
/**
|
|
* Event kinds that are considered chat messages across all protocols
|
|
* Used for filtering and validating chat-related events
|
|
*/
|
|
export const CHAT_KINDS = [
|
|
9, // NIP-29: Group chat messages
|
|
9321, // NIP-61: Nutzaps (ecash zaps in groups/live chats)
|
|
1311, // NIP-53: Live chat messages
|
|
9735, // NIP-57: Zap receipts (part of chat context)
|
|
] as const;
|
|
|
|
/**
|
|
* Chat protocol identifier
|
|
*/
|
|
export type ChatProtocol = "nip-c7" | "nip-17" | "nip-28" | "nip-29" | "nip-53";
|
|
|
|
/**
|
|
* Conversation type
|
|
*/
|
|
export type ConversationType = "dm" | "channel" | "group" | "live-chat";
|
|
|
|
/**
|
|
* Participant role in a conversation
|
|
*/
|
|
export type ParticipantRole = "admin" | "moderator" | "member" | "host";
|
|
|
|
/**
|
|
* Participant in a conversation
|
|
*/
|
|
export interface Participant {
|
|
pubkey: string;
|
|
role?: ParticipantRole;
|
|
permissions?: string[];
|
|
}
|
|
|
|
/**
|
|
* Live activity metadata for NIP-53
|
|
*/
|
|
export interface LiveActivityMetadata {
|
|
status: "planned" | "live" | "ended";
|
|
streaming?: string;
|
|
recording?: string;
|
|
starts?: number;
|
|
ends?: number;
|
|
hostPubkey: string;
|
|
currentParticipants?: number;
|
|
totalParticipants?: number;
|
|
hashtags: string[];
|
|
relays: string[];
|
|
}
|
|
|
|
/**
|
|
* Protocol-specific conversation metadata
|
|
*/
|
|
export interface ConversationMetadata {
|
|
// NIP-28 channel
|
|
channelEvent?: NostrEvent; // kind 40 creation event
|
|
|
|
// NIP-29 group
|
|
groupId?: string; // host'group-id format
|
|
relayUrl?: string; // Relay enforcing group rules
|
|
description?: string; // Group description
|
|
icon?: string; // Group icon/picture URL
|
|
|
|
// NIP-53 live chat
|
|
activityAddress?: {
|
|
kind: number;
|
|
pubkey: string;
|
|
identifier: string;
|
|
};
|
|
liveActivity?: LiveActivityMetadata;
|
|
|
|
// NIP-17 DM
|
|
encrypted?: boolean;
|
|
giftWrapped?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Generic conversation abstraction
|
|
* Works across all messaging protocols
|
|
*/
|
|
export interface Conversation {
|
|
id: string; // Protocol-specific identifier
|
|
type: ConversationType;
|
|
protocol: ChatProtocol;
|
|
title: string;
|
|
participants: Participant[];
|
|
metadata?: ConversationMetadata;
|
|
lastMessage?: Message;
|
|
unreadCount: number;
|
|
}
|
|
|
|
/**
|
|
* Message metadata (reactions, zaps, encryption status, etc.)
|
|
*/
|
|
export interface MessageMetadata {
|
|
encrypted?: boolean;
|
|
reactions?: NostrEvent[];
|
|
zaps?: NostrEvent[];
|
|
deleted?: boolean;
|
|
hidden?: boolean; // NIP-28 channel hide
|
|
// Zap-specific metadata (for type: "zap" messages)
|
|
zapAmount?: number; // Amount in sats
|
|
zapRecipient?: string; // Pubkey of zap recipient
|
|
// NIP-61 nutzap-specific metadata
|
|
nutzapUnit?: string; // Unit for nutzap amount (sat, usd, eur, etc.)
|
|
}
|
|
|
|
/**
|
|
* Message type - system messages for events like join/leave, user messages for chat, zaps for stream tips
|
|
*/
|
|
export type MessageType = "user" | "system" | "zap";
|
|
|
|
/**
|
|
* Generic message abstraction
|
|
* Works across all messaging protocols
|
|
*/
|
|
export interface Message {
|
|
id: string;
|
|
conversationId: string;
|
|
author: string; // pubkey
|
|
content: string;
|
|
timestamp: number;
|
|
type?: MessageType; // Defaults to "user" if not specified
|
|
replyTo?: string; // Parent message ID
|
|
metadata?: MessageMetadata;
|
|
protocol: ChatProtocol;
|
|
event: NostrEvent; // Original Nostr event for verification
|
|
}
|
|
|
|
/**
|
|
* NIP-29 group identifier
|
|
*/
|
|
export interface GroupIdentifier {
|
|
type: "group";
|
|
/** Group ID (e.g., "bitcoin-dev") */
|
|
value: string;
|
|
/** Relay URL where the group is hosted (required for NIP-29) */
|
|
relays: string[];
|
|
}
|
|
|
|
/**
|
|
* NIP-53 live activity identifier
|
|
*/
|
|
export interface LiveActivityIdentifier {
|
|
type: "live-activity";
|
|
/** Address pointer for the live activity */
|
|
value: {
|
|
kind: 30311;
|
|
pubkey: string;
|
|
identifier: string;
|
|
};
|
|
/** Relay hints from naddr encoding */
|
|
relays?: string[];
|
|
}
|
|
|
|
/**
|
|
* NIP-C7/NIP-17 direct message identifier (resolved pubkey)
|
|
*/
|
|
export interface DMIdentifier {
|
|
type: "dm-recipient" | "chat-partner";
|
|
/** Recipient pubkey (hex) */
|
|
value: string;
|
|
/** Relay hints */
|
|
relays?: string[];
|
|
}
|
|
|
|
/**
|
|
* NIP-C7 NIP-05 identifier (needs resolution)
|
|
*/
|
|
export interface NIP05Identifier {
|
|
type: "chat-partner-nip05";
|
|
/** NIP-05 address to resolve */
|
|
value: string;
|
|
/** Relay hints */
|
|
relays?: string[];
|
|
}
|
|
|
|
/**
|
|
* NIP-28 channel identifier (future)
|
|
*/
|
|
export interface ChannelIdentifier {
|
|
type: "channel";
|
|
/** Channel creation event ID or address */
|
|
value: string;
|
|
/** Relay hints */
|
|
relays?: string[];
|
|
}
|
|
|
|
/**
|
|
* Group list identifier (kind 10009)
|
|
* Used to open multi-room chat interface
|
|
*/
|
|
export interface GroupListIdentifier {
|
|
type: "group-list";
|
|
/** Address pointer for the group list (kind 10009) */
|
|
value: {
|
|
kind: 10009;
|
|
pubkey: string;
|
|
identifier: string;
|
|
};
|
|
/** Relay hints from naddr encoding */
|
|
relays?: string[];
|
|
}
|
|
|
|
/**
|
|
* Protocol-specific identifier - discriminated union
|
|
* Returned by adapter parseIdentifier()
|
|
*/
|
|
export type ProtocolIdentifier =
|
|
| GroupIdentifier
|
|
| LiveActivityIdentifier
|
|
| DMIdentifier
|
|
| NIP05Identifier
|
|
| ChannelIdentifier
|
|
| GroupListIdentifier;
|
|
|
|
/**
|
|
* Chat command parsing result
|
|
*/
|
|
export interface ChatCommandResult {
|
|
protocol: ChatProtocol;
|
|
identifier: ProtocolIdentifier;
|
|
adapter: any; // Will be ChatProtocolAdapter but avoiding circular dependency
|
|
}
|
|
|
|
/**
|
|
* Message loading options
|
|
*/
|
|
export interface LoadMessagesOptions {
|
|
limit?: number;
|
|
before?: number; // Unix timestamp
|
|
after?: number; // Unix timestamp
|
|
}
|
|
|
|
/**
|
|
* Conversation creation parameters
|
|
*/
|
|
export interface CreateConversationParams {
|
|
type: ConversationType;
|
|
title?: string;
|
|
participants: string[]; // pubkeys
|
|
metadata?: Record<string, any>;
|
|
}
|
|
|
|
/**
|
|
* Chat capabilities - what features a protocol supports
|
|
*/
|
|
export interface ChatCapabilities {
|
|
supportsEncryption: boolean;
|
|
supportsThreading: boolean;
|
|
supportsModeration: boolean;
|
|
supportsRoles: boolean;
|
|
supportsGroupManagement: boolean;
|
|
canCreateConversations: boolean;
|
|
requiresRelay: boolean;
|
|
}
|