refactor: upgrade nip17

This commit is contained in:
kieran 2024-04-29 17:41:11 +01:00
parent c775236438
commit 87144d9395
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
15 changed files with 97 additions and 33 deletions

View File

@ -27,4 +27,8 @@ export class ChatCache extends FeedCache<NostrEvent> {
takeSnapshot(): Array<NostrEvent> {
return [...this.cache.values()];
}
async search() {
return <Array<NostrEvent>>[];
}
}

View File

@ -24,6 +24,17 @@ export class EventCacheWorker extends EventEmitter<CacheEvents> implements Cache
this.#keys = new Set<string>(ids as unknown as Array<string>);
}
async search(q: string) {
const results = await this.#relay.query([
"REQ",
"events-search",
{
search: q
},
]);
return results;
}
keysOnTable(): string[] {
return [...this.#keys];
}

View File

@ -1,10 +1,9 @@
import { EventKind, EventPublisher, RequestBuilder, TaggedNostrEvent } from "@snort/system";
import { EventKind, EventPublisher, TaggedNostrEvent } from "@snort/system";
import { db, UnwrappedGift } from "@/Db";
import { findTag, unwrap } from "@/Utils";
import { LoginSession, LoginSessionType } from "@/Utils/Login";
import { RefreshFeedCache } from "./RefreshFeedCache";
import { RefreshFeedCache, TWithCreated } from "./RefreshFeedCache";
export class GiftWrapCache extends RefreshFeedCache<UnwrappedGift> {
constructor() {
@ -15,11 +14,8 @@ export class GiftWrapCache extends RefreshFeedCache<UnwrappedGift> {
return of.id;
}
buildSub(session: LoginSession, rb: RequestBuilder): void {
const pubkey = session.publicKey;
if (pubkey && session.type === LoginSessionType.PrivateKey) {
rb.withFilter().kinds([EventKind.GiftWrap]).tag("p", [pubkey]).since(this.newest());
}
buildSub(): void {
// not used
}
takeSnapshot(): Array<UnwrappedGift> {
@ -57,4 +53,8 @@ export class GiftWrapCache extends RefreshFeedCache<UnwrappedGift> {
}
await this.bulkSet(unwrapped);
}
search(): Promise<TWithCreated<UnwrappedGift>[]> {
throw new Error("Method not implemented.");
}
}

View File

@ -29,6 +29,18 @@ export class ProfileCacheRelayWorker extends EventEmitter<CacheEvents> implement
this.#log(`Loaded %d/%d in %d ms`, this.#cache.size, this.#keys.size, (unixNowMs() - start).toLocaleString());
}
async search(q: string) {
const profiles = await this.#relay.query([
"REQ",
"profiles-search",
{
kinds: [0],
search: q
},
]);
return removeUndefined(profiles.map(mapEventToProfile));
}
keysOnTable(): string[] {
return [...this.#keys];
}

View File

@ -29,6 +29,18 @@ export class UserFollowsWorker extends EventEmitter<CacheEvents> implements Cach
this.#log(`Loaded %d/%d in %d ms`, this.#cache.size, this.#keys.size, (unixNowMs() - start).toLocaleString());
}
async search(q: string) {
const results = await this.#relay.query([
"REQ",
"contacts-search",
{
kinds: [3],
search: q
},
]);
return removeUndefined(results.map(mapEventToUserFollows));
}
keysOnTable(): string[] {
return [...this.#keys];
}

View File

@ -31,21 +31,20 @@ export default function useLoginFeed() {
const subLogin = useMemo(() => {
if (!login || !pubKey) return null;
const b = new RequestBuilder(`login:${pubKey.slice(0, 12)}`);
b.withOptions({
leaveOpen: true,
});
b.withFilter().authors([pubKey]).kinds([EventKind.DirectMessage]);
if (CONFIG.features.subscriptions && !login.readonly) {
const b = new RequestBuilder(`login:${pubKey.slice(0, 12)}`);
b.withOptions({
leaveOpen: true,
});
b.withFilter()
.relay("wss://relay.snort.social/")
.kinds([EventKind.SnortSubscriptions])
.authors([bech32ToHex(SnortPubKey)])
.tag("p", [pubKey])
.limit(10);
return b;
}
return b;
}, [pubKey, login]);
const loginFeed = useRequestBuilder(subLogin);

View File

@ -31,7 +31,7 @@ export default function NewChatWindow() {
useEffect(() => {
setNewChat([]);
setSearchTerm("");
setResults(followList);
setResults(followList.slice(0, 5));
}, [show]);
useEffect(() => {
@ -51,7 +51,7 @@ export default function NewChatWindow() {
function startChat() {
setShow(false);
if (newChat.length === 1) {
navigate(createChatLink(ChatType.DirectMessage, newChat[0]));
navigate(createChatLink(ChatType.PrivateDirectMessage, newChat[0]));
} else {
navigate(createChatLink(ChatType.PrivateGroupChat, ...newChat));
}

View File

@ -22,7 +22,7 @@ import { findTag } from "@/Utils";
import { LoginSession } from "@/Utils/Login";
import { Nip4Chats, Nip4ChatSystem } from "./nip4";
import { Nip24ChatSystem } from "./nip24";
import { Nip17Chats, Nip17ChatSystem } from "./nip17";
import { Nip28Chats, Nip28ChatSystem } from "./nip28";
export enum ChatType {
@ -124,7 +124,7 @@ export function createChatLink(type: ChatType, ...params: Array<string>) {
case ChatType.PrivateDirectMessage: {
if (params.length > 1) throw new Error("Must only contain one pubkey");
return `/messages/${encodeTLVEntries(
"chat24" as NostrPrefix,
"chat17" as NostrPrefix,
{
type: TLVEntryType.Author,
length: params[0].length,
@ -134,7 +134,7 @@ export function createChatLink(type: ChatType, ...params: Array<string>) {
}
case ChatType.PrivateGroupChat: {
return `/messages/${encodeTLVEntries(
"chat24" as NostrPrefix,
"chat17" as NostrPrefix,
...params.map(
a =>
({
@ -156,8 +156,8 @@ export function createEmptyChatObject(id: string, messages?: Array<TaggedNostrEv
if (id.startsWith("chat41")) {
return Nip4ChatSystem.createChatObj(id, messages ?? []);
}
if (id.startsWith("chat241")) {
return Nip24ChatSystem.createChatObj(id, []);
if (id.startsWith("chat171")) {
return Nip17ChatSystem.createChatObj(id, []);
}
if (id.startsWith("chat281")) {
return Nip28ChatSystem.createChatObj(id, messages ?? []);
@ -187,8 +187,9 @@ export function useChatSystem(chat: ChatSystem) {
export function useChatSystems() {
const nip4 = useChatSystem(Nip4Chats);
const nip28 = useChatSystem(Nip28Chats);
const nip17 = useChatSystem(Nip17Chats);
return [...nip4, ...nip28];
return [...nip4, ...nip28, ...nip17];
}
export function useChat(id: string) {
@ -196,6 +197,9 @@ export function useChat(id: string) {
if (id.startsWith("chat41")) {
return Nip4Chats;
}
if (id.startsWith("chat171")) {
return Nip17Chats;
}
if (id.startsWith("chat281")) {
return Nip28Chats;
}

View File

@ -1,12 +1,14 @@
import { dedupe, ExternalStore } from "@snort/shared";
import { decodeTLV, encodeTLVEntries, EventKind, NostrEvent, NostrPrefix, TLVEntry, TLVEntryType } from "@snort/system";
import { decodeTLV, encodeTLVEntries, EventKind, NostrEvent, NostrPrefix, RequestBuilder, TLVEntry, TLVEntryType } from "@snort/system";
import { GiftsCache } from "@/Cache";
import { GiftWrapCache } from "@/Cache/GiftWrapCache";
import { Chat, ChatSystem, ChatType, lastReadInChat } from "@/chat";
import { UnwrappedGift } from "@/Db";
import { LoginSession } from "@/Utils/Login";
import { GetPowWorker } from "@/Utils/wasm";
export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatSystem {
export class Nip17ChatSystem extends ExternalStore<Array<Chat>> implements ChatSystem {
#cache: GiftWrapCache;
constructor(cache: GiftWrapCache) {
@ -15,13 +17,13 @@ export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatS
this.#cache.on("change", () => this.notifyChange());
}
subscription() {
// ignored
return undefined;
}
subscription(session: LoginSession) {
const pk = session.publicKey;
if (!pk || session.readonly) return;
onEvent() {
// ignored
const rb = new RequestBuilder(`nip17:${pk.slice(0, 12)}`);
rb.withFilter().kinds([EventKind.GiftWrap]).tag("p", [pk]);
return rb;
}
listChats(pk: string): Chat[] {
@ -33,7 +35,7 @@ export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatS
.filter(a => a !== pk);
return encodeTLVEntries(
"chat24" as NostrPrefix,
"chat17" as NostrPrefix,
...pTags.map(
v =>
({
@ -46,7 +48,7 @@ export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatS
};
return dedupe(messages.map(a => chatId(a))).map(a => {
const chatMessages = messages.filter(b => chatId(b) === a);
return Nip24ChatSystem.createChatObj(a, chatMessages);
return Nip17ChatSystem.createChatObj(a, chatMessages);
});
}
@ -124,3 +126,5 @@ export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatS
return sn.filter(a => a.inner.kind === EventKind.SealedRumor);
}
}
export const Nip17Chats = new Nip17ChatSystem(GiftsCache);

View File

@ -40,6 +40,7 @@ export type CachedTable<T> = {
buffer(keys: Array<string>): Promise<Array<string>>;
key(of: T): string;
snapshot(): Array<T>;
search(q: string): Promise<Array<T>>;
} & EventEmitter<CacheEvents>;
/**
@ -225,4 +226,5 @@ export abstract class FeedCache<TCached> extends EventEmitter<CacheEvents> imple
abstract key(of: TCached): string;
abstract takeSnapshot(): Array<TCached>;
abstract search(q: string): Promise<Array<TCached>>;
}

View File

@ -5,7 +5,7 @@ import { SnortContext } from "./context";
export function useUserSearch() {
const system = useContext(SnortContext);
const cache = system.profileLoader.cache as UserProfileCache;
const cache = system.profileLoader.cache;
async function search(input: string): Promise<Array<string>> {
// try exact match first

View File

@ -19,4 +19,8 @@ export class EventsCache extends FeedCache<NostrEvent> {
takeSnapshot(): Array<NostrEvent> {
return [...this.cache.values()];
}
async search() {
return <Array<NostrEvent>>[];
}
}

View File

@ -19,4 +19,8 @@ export class RelayMetricCache extends FeedCache<RelayMetrics> {
takeSnapshot(): Array<RelayMetrics> {
return [...this.cache.values()];
}
async search() {
return <Array<RelayMetrics>>[];
}
}

View File

@ -26,4 +26,8 @@ export class UserFollowsCache extends FeedCache<UsersFollows> {
takeSnapshot(): Array<UsersFollows> {
return [...this.cache.values()];
}
async search() {
return <Array<UsersFollows>>[];
}
}

View File

@ -26,4 +26,8 @@ export class UserRelaysCache extends FeedCache<UsersRelays> {
takeSnapshot(): Array<UsersRelays> {
return [...this.cache.values()];
}
async search() {
return <Array<UsersRelays>>[];
}
}