mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-01-06 16:04:23 +01:00
feat: base commenting functions
This commit is contained in:
@@ -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 } }), {})
|
||||
}
|
||||
@@ -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
26
src/utils/types/nostr.d.ts
vendored
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user