chore: cleanup chat links

This commit is contained in:
Kieran 2024-08-27 14:11:23 +01:00
parent 2c58239e2c
commit 8f0b1d3f66
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
10 changed files with 23 additions and 133 deletions

View File

@ -1,5 +1,5 @@
import { unwrap } from "@snort/shared";
import { decodeTLV, EventKind, RequestBuilder, TLVEntryType } from "@snort/system";
import { decodeTLV, EventKind, NostrPrefix, RequestBuilder, TLVEntryType } from "@snort/system";
import { useRequestBuilder } from "@snort/system-react";
import { useMemo } from "react";
@ -9,7 +9,7 @@ export function useEmptyChatSystem(id?: string) {
const sub = useMemo(() => {
if (!id) return;
if (id.startsWith("chat281")) {
if (id.startsWith(NostrPrefix.Chat28)) {
const cx = unwrap(decodeTLV(id).find(a => a.type === TLVEntryType.Special)).value as string;
const rb = new RequestBuilder(`nip28:${id}`);
rb.withFilter().ids([cx]).kinds([EventKind.PublicChatChannel, EventKind.PublicChatMetadata]);

View File

@ -18,7 +18,7 @@ export default function HelpPage() {
values={{
link: (
<Link
to={`/messages/${encodeTLVEntries("chat4" as NostrPrefix, {
to={`/messages/${encodeTLVEntries(NostrPrefix.Chat17, {
type: TLVEntryType.Author,
length: 64,
value: bech32ToHex(KieranPubKey),

View File

@ -1,4 +1,4 @@
import { decodeTLV, EventKind } from "@snort/system";
import { decodeTLV, EventKind, NostrPrefix } from "@snort/system";
import { useUserSearch } from "@snort/system-react";
import React, { useEffect, useState } from "react";
import { FormattedMessage } from "react-intl";
@ -125,7 +125,7 @@ export default function NewChatWindow() {
const evList = await publisher?.generic(eb => {
eb.kind(EventKind.PublicChatsList);
chats.forEach(c => {
if (c.startsWith("chat281")) {
if (c.startsWith(NostrPrefix.Chat28)) {
eb.tag(["e", decodeTLV(c)[0].value as string]);
}
});

View File

@ -74,9 +74,9 @@ const AvatarSection = ({
<IconButton
onClick={() =>
navigate(
`/messages/${encodeTLVEntries("chat4" as NostrPrefix, {
`/messages/${encodeTLVEntries(NostrPrefix.Chat17, {
type: TLVEntryType.Author,
length: 32,
length: 64,
value: id,
})}`,
)

View File

@ -22,12 +22,10 @@ import useModeration from "@/Hooks/useModeration";
import { findTag } from "@/Utils";
import { LoginSession } from "@/Utils/Login";
import { Nip4Chats, Nip4ChatSystem } from "./nip4";
import { Nip17Chats, Nip17ChatSystem } from "./nip17";
import { Nip28Chats, Nip28ChatSystem } from "./nip28";
export enum ChatType {
DirectMessage = 1,
PublicGroupChat = 2,
PrivateGroupChat = 3,
PrivateDirectMessage = 4,
@ -116,31 +114,17 @@ export function setLastReadIn(id: string) {
export function createChatLink(type: ChatType, ...params: Array<string>) {
switch (type) {
case ChatType.DirectMessage: {
if (params.length > 1) throw new Error("Must only contain one pubkey");
return `/messages/${encodeTLVEntries(
"chat4" as NostrPrefix,
{
type: TLVEntryType.Author,
length: params[0].length,
value: params[0],
} as TLVEntry,
)}`;
}
case ChatType.PrivateDirectMessage: {
if (params.length > 1) throw new Error("Must only contain one pubkey");
return `/messages/${encodeTLVEntries(
"chat17" as NostrPrefix,
{
type: TLVEntryType.Author,
length: params[0].length,
value: params[0],
} as TLVEntry,
)}`;
return `/messages/${encodeTLVEntries(NostrPrefix.Chat17, {
type: TLVEntryType.Author,
length: params[0].length,
value: params[0],
} as TLVEntry)}`;
}
case ChatType.PrivateGroupChat: {
return `/messages/${encodeTLVEntries(
"chat17" as NostrPrefix,
NostrPrefix.Chat17,
...params.map(
a =>
({
@ -159,13 +143,10 @@ export function createChatLink(type: ChatType, ...params: Array<string>) {
}
export function createEmptyChatObject(id: string, messages?: Array<TaggedNostrEvent>) {
if (id.startsWith("chat41")) {
return Nip4ChatSystem.createChatObj(id, messages ?? []);
}
if (id.startsWith("chat171")) {
if (id.startsWith(NostrPrefix.Chat17)) {
return Nip17ChatSystem.createChatObj(id, []);
}
if (id.startsWith("chat281")) {
if (id.startsWith(NostrPrefix.Chat28)) {
return Nip28ChatSystem.createChatObj(id, messages ?? []);
}
throw new Error("Cant create new empty chat, unknown id");
@ -198,7 +179,6 @@ export function useChatSystem(chat: ChatSystem) {
}
export function useChatSystems() {
//const nip4 = useChatSystem(Nip4Chats);
const nip28 = useChatSystem(Nip28Chats);
const nip17 = useChatSystem(Nip17Chats);
@ -207,13 +187,10 @@ export function useChatSystems() {
export function useChat(id: string) {
const getStore = () => {
if (id.startsWith("chat41")) {
return Nip4Chats;
}
if (id.startsWith("chat171")) {
if (id.startsWith(NostrPrefix.Chat17)) {
return Nip17Chats;
}
if (id.startsWith("chat281")) {
if (id.startsWith(NostrPrefix.Chat28)) {
return Nip28Chats;
}
throw new Error("Unsupported chat system");

View File

@ -53,7 +53,7 @@ export class Nip17ChatSystem extends ExternalStore<Array<Chat>> implements ChatS
.filter(a => a !== pk);
return encodeTLVEntries(
"chat17" as NostrPrefix,
NostrPrefix.Chat17,
...pTags.map(
v =>
({

View File

@ -26,7 +26,7 @@ export class Nip28ChatSystem implements ChatSystem {
];
subscription(session: LoginSession): RequestBuilder | undefined {
const chats = (session.extraChats ?? []).filter(a => a.startsWith("chat281"));
const chats = (session.extraChats ?? []).filter(a => a.startsWith(NostrPrefix.Chat28));
if (chats.length === 0) return;
const chatId = (v: string) => unwrap(decodeTLV(v).find(a => a.type === TLVEntryType.Special)).value as string;
@ -57,7 +57,7 @@ export class Nip28ChatSystem implements ChatSystem {
}
static chatId(id: string) {
return encodeTLVEntries("chat28" as NostrPrefix, {
return encodeTLVEntries(NostrPrefix.Chat28, {
type: TLVEntryType.Special,
value: id,
length: id.length,

View File

@ -1,89 +0,0 @@
import {
decodeTLV,
encodeTLVEntries,
EventKind,
NostrEvent,
NostrPrefix,
RequestBuilder,
SystemInterface,
TaggedNostrEvent,
TLVEntryType,
} from "@snort/system";
import { Chat, ChatSystem, ChatType, inChatWith, lastReadInChat } from "@/chat";
import { LoginSession } from "@/Utils/Login";
export class Nip4ChatSystem implements ChatSystem {
subscription(session: LoginSession) {
const pk = session.publicKey;
if (!pk || session.readonly) return;
const rb = new RequestBuilder(`nip4:${pk.slice(0, 12)}`);
rb.withFilter().authors([pk]).kinds([EventKind.DirectMessage]);
rb.withFilter().kinds([EventKind.DirectMessage]).tag("p", [pk]);
return rb;
}
listChats(pk: string, evs: Array<TaggedNostrEvent>): Chat[] {
const myDms = this.#nip4Events(evs);
const chats = myDms.reduce(
(acc, v) => {
const chatId = inChatWith(v, pk);
acc[chatId] ??= [];
acc[chatId].push(v);
return acc;
},
{} as Record<string, Array<NostrEvent>>,
);
return [...Object.entries(chats)].map(([k, v]) => Nip4ChatSystem.createChatObj(Nip4ChatSystem.makeChatId(k), v));
}
static makeChatId(pubkey: string) {
return encodeTLVEntries("chat4" as NostrPrefix, {
type: TLVEntryType.Author,
value: pubkey,
length: 32,
});
}
static createChatObj(id: string, messages: Array<NostrEvent>) {
const last = lastReadInChat(id);
const participants = decodeTLV(id)
.filter(v => v.type === TLVEntryType.Author)
.map(v => ({
type: "pubkey",
id: v.value as string,
}));
return {
type: ChatType.DirectMessage,
id,
unread: messages.reduce((acc, v) => (v.created_at > last ? acc++ : acc), 0),
lastMessage: messages.reduce((acc, v) => (v.created_at > acc ? v.created_at : acc), 0),
participants,
messages: messages.map(m => ({
id: m.id,
created_at: m.created_at,
from: m.pubkey,
tags: m.tags,
content: "",
needsDecryption: true,
decrypt: async pub => {
return await pub.decryptDm(m);
},
})),
createMessage: async (msg, pub) => {
return await Promise.all(participants.map(v => pub.sendDm(msg, v.id)));
},
sendMessage: (ev, system: SystemInterface) => {
ev.forEach(a => system.BroadcastEvent(a));
},
} as Chat;
}
#nip4Events(evs: Array<TaggedNostrEvent>) {
return evs.filter(a => a.kind === EventKind.DirectMessage);
}
}
export const Nip4Chats = new Nip4ChatSystem();

View File

@ -182,7 +182,7 @@ self.addEventListener("notificationclick", event => {
}
} else if (ev.type === PushType.DirectMessage) {
const reaction = ev.data as CompactReaction;
return `/messages/${encodeTLVEntries("chat4" as NostrPrefix, {
return `/messages/${encodeTLVEntries(NostrPrefix.Chat17, {
type: TLVEntryType.Author,
value: reaction.author.pubkey,
length: 32,

View File

@ -13,6 +13,8 @@ export enum NostrPrefix {
Relay = "nrelay",
Address = "naddr",
Req = "nreq",
Chat17 = "nchat17",
Chat28 = "nchat28",
}
export enum TLVEntryType {