Files
lume/packages/system/src/event.ts
2024-05-26 08:23:29 +07:00

202 lines
4.4 KiB
TypeScript

import { EventWithReplies, Kind, NostrEvent } from "@lume/types";
import { commands } from "./commands";
import { generateContentTags } from "@lume/utils";
export class LumeEvent {
public id: string;
public pubkey: string;
public created_at: number;
public kind: Kind;
public tags: string[][];
public content: string;
public sig: string;
public relay?: string;
#raw: NostrEvent;
constructor(event: NostrEvent) {
this.#raw = event;
Object.assign(this, event);
}
get mentions() {
return this.tags.filter((tag) => tag[0] === "p").map((tag) => tag[1]);
}
static getEventThread(tags: string[][], gossip?: boolean) {
let root: string = null;
let reply: string = null;
// Get all event references from tags, ignore mention
const events = tags.filter((el) => el[0] === "e" && el[3] !== "mention");
if (gossip) {
const relays = tags.filter((el) => el[0] === "e" && el[2]?.length);
if (relays.length >= 1) {
for (const relay of relays) {
if (relay[2]?.length)
commands
.connectRelay(relay[2])
.then(() => console.log("[gossip]: ", relay[2]));
}
}
}
if (events.length === 1) {
root = events[0][1];
}
if (events.length > 1) {
root = events.find((el) => el[3] === "root")?.[1] ?? events[0][1];
reply = events.find((el) => el[3] === "reply")?.[1] ?? events[1][1];
}
// Fix some rare case when root === reply
if (root && reply && root === reply) {
reply = null;
}
return {
root,
reply,
};
}
static async getReplies(id: string) {
const query = await commands.getReplies(id);
if (query.status === "ok") {
const events = query.data.map(
(item) => JSON.parse(item) as EventWithReplies,
);
if (events.length > 0) {
const replies = new Set();
for (const event of events) {
const tags = event.tags.filter(
(el) => el[0] === "e" && el[1] !== id && el[3] !== "mention",
);
if (tags.length > 0) {
for (const tag of tags) {
const rootIndex = events.findIndex((el) => el.id === tag[1]);
if (rootIndex !== -1) {
const rootEvent = events[rootIndex];
if (rootEvent?.replies) {
rootEvent.replies.push(event);
} else {
rootEvent.replies = [event];
}
replies.add(event.id);
}
}
}
}
return events.filter((ev) => !replies.has(ev.id));
}
return events;
}
}
static async publish(
content: string,
reply_to?: string,
quote?: boolean,
nsfw?: boolean,
) {
const g = await generateContentTags(content);
const eventContent = g.content;
const eventTags = g.tags;
if (reply_to) {
const queryReply = await commands.getEvent(reply_to);
if (queryReply.status === "ok") {
const replyEvent = JSON.parse(queryReply.data) as NostrEvent;
const relayHint =
replyEvent.tags.find((ev) => ev[0] === "e")?.[0][2] ?? "";
if (quote) {
eventTags.push(["e", replyEvent.id, relayHint, "mention"]);
eventTags.push(["q", replyEvent.id]);
} else {
const rootEvent = replyEvent.tags.find((ev) => ev[3] === "root");
if (rootEvent) {
eventTags.push([
"e",
rootEvent[1],
rootEvent[2] || relayHint,
"root",
]);
}
eventTags.push(["e", replyEvent.id, relayHint, "reply"]);
eventTags.push(["p", replyEvent.pubkey]);
}
}
}
if (nsfw) {
eventTags.push(["L", "content-warning"]);
eventTags.push(["l", "reason", "content-warning"]);
eventTags.push(["content-warning", "nsfw"]);
}
const query = await commands.publish(eventContent, eventTags);
if (query.status === "ok") {
return query.data;
} else {
throw new Error(query.error);
}
}
static async zap(id: string, amount: number, message: string) {
const query = await commands.zapEvent(id, amount.toString(), message);
if (query.status === "ok") {
return query.data;
} else {
throw new Error(query.error);
}
}
public async idAsBech32() {
const query = await commands.eventToBech32(this.id, []);
if (query.status === "ok") {
return query.data;
} else {
throw new Error(query.error);
}
}
public async pubkeyAsBech32() {
const query = await commands.userToBech32(this.pubkey, []);
if (query.status === "ok") {
return query.data;
} else {
throw new Error(query.error);
}
}
public async repost() {
const query = await commands.repost(JSON.stringify(this.#raw));
if (query.status === "ok") {
return query.data;
} else {
throw new Error(query.error);
}
}
}