feat: base commenting functions

This commit is contained in:
MTG2000
2022-07-19 17:55:04 +03:00
parent ba10ee629d
commit accbf67b1f
5 changed files with 623 additions and 16 deletions

View File

@@ -0,0 +1,38 @@
import { signEvent } from "nostr-tools";
const prvkey = '3e345e14bbf758be3ccdca67cab6c808d0a7f001433cf2492b3c2c93327ebde8';
const pubkey = 'f183af77e76bd62f0af8820ffa6d708d6826cf4a2adaa6be2d49061c94e22c0b';
export async function signEventByServer(_event) {
// Extract user Id from cookie
// Get his prvkey & pubkey from database
// Generate a new prvkey if not exist & store it in the DB
const event = {
..._event,
pubkey,
tags: _event.tags ?? []
};
if (!event.sig)
event.sig = await signEvent(event, prvkey)
return event;
}
export async function mapPubkeysToUsers(pubkeys) {
const users = await Promise.all(pubkeys.map(pubkey =>
// prisma.user.findUnique({ where: { nostrPubkey: pubkey } })
({
id: 1,
name: "Mtg",
avatar: 'https://i.pravatar.cc/150?img=1',
pubkey,
})
))
return users.reduce((acc, user) => ({ ...acc, [user.pubkey]: { ...user } }), {})
}

View File

@@ -1,7 +1,153 @@
import dayjs from 'dayjs'
import { relayPool } from 'nostr-tools'
import { Nullable } from 'remirror';
import { mapPubkeysToUsers, signEventByServer } from './comment.server';
const pool = relayPool()
export function now(prefix: string) {
const hell = window.localStorage.getItem('test');
if (!hell) window.localStorage.setItem('test', 'test');
return hell + prefix + dayjs()
};
export function connect() {
const RELAYS = [
'wss://rsslay.fiatjaf.com',
'wss://nostr-pub.wellorder.net',
'wss://expensive-relay.fiatjaf.com',
'wss://nostr.bitcoiner.social',
'wss://relayer.fiatjaf.com',
'wss://nostr.rocks'
];
RELAYS.forEach(url => {
pool.addRelay(url, { read: true, write: true })
})
};
const events: Record<string, Required<NostrEvent>> = {};
export function sub(filter: any) {
let sub = pool.sub({
filter,
cb: (event: Required<NostrEvent>) => {
//Got a new event
if (!event.id) return;
if (event.id in events) return
events[event.id] = event
eventsUpdated();
}
});
return () => {
sub.unsub();
};
}
export async function post(data: string, filter: any) {
let event: NostrEvent = {
created_at: Math.round(Date.now() / 1000),
kind: 1,
tags: filter,
content: data
};
event = await signEventByServer(event);
const publishTimeout = setTimeout(() => {
alert(
`failed to publish event ${event.id?.slice(0, 5)}… to any relay.`
)
}, 4000)
pool.publish(event, (status: number, relay: string) => {
switch (status) {
case -1:
console.log(`failed to send ${JSON.stringify(event)} to ${relay}`)
// enable()
// onError()
break
case 1:
clearTimeout(publishTimeout)
console.log(`event ${event.id?.slice(0, 5)}… published to ${relay}.`)
// onSuccess()
break
}
})
}
function extractParentId(event: NostrEvent): Nullable<string> {
event.tags.forEach(([identifier, value]) => {
if (identifier === '#e') {
const [eventId, _, marker] = value.split(' ');
if (marker === 'reply') return eventId;
}
})
return null;
}
export async function eventsUpdated() {
// This function is responsible for transforming the object shaped events into a tree of comments
// ----------------------------------------------------------------------------------------------
// Sort them chronologically from oldest to newest
let sortedEvenets = Object.values(events).sort((a, b) => a.created_at - b.created_at);
type Author = {
id: number;
name: string;
avatar: string;
}
type Comment = {
id: string,
pubkey: string;
author?: Author;
content: any;
created_at: number;
replies: Comment[]
}
// Extract the pubkeys used
const pubkeysSet = new Set();
sortedEvenets.forEach(e => pubkeysSet.add(e.pubkey));
// Make a request to api to get the pubkeys' users' data
const pubkeyToUser = await mapPubkeysToUsers(Array.from(pubkeysSet.values())) as Record<string, Author>;
let eventsTree: Record<string, Comment> = {}
// If event is a reply, connect it to parent
sortedEvenets.forEach(e => {
const parentId = extractParentId(e);
if (parentId) {
eventsTree[parentId]?.replies.push({
...e,
author: pubkeyToUser[e.pubkey],
replies: [],
});
} else {
eventsTree[e.id] = ({
...e,
author: pubkeyToUser[e.pubkey],
replies: [],
});
}
})
// Run the censoring service
// (nothing for now -:-)
// Turn the top roots replies into a sorted array
const sortedTree = Object.values(eventsTree).sort((a, b) => a.created_at - b.created_at)
// Publish the new tree.
return sortedTree;
}

26
src/utils/types/nostr.d.ts vendored Normal file
View File

@@ -0,0 +1,26 @@
interface NostrEvent {
id?: string,
kind: number,
pubkey?: string,
content: string,
tags: Array<Array<string>>,
created_at: number,
sig?: string;
}
declare module 'nostr-tools' {
declare function generatePrivateKey(): void
declare function relayConnect(): void
declare function relayPool(): any
declare function signEvent(event: NostrEvent, key: sting): string
declare function validateEvent(): void
declare function verifySignature(event: NostrEvent): bool
declare function serializeEvent(): void
declare function getEventHash(event: NostrEvent): string
declare function getPublicKey(event: NostrEvent): boolean
declare function getBlankEvent(): void
declare function matchFilter(): void
declare function matchFilters(): void
}