136 lines
3.3 KiB
TypeScript
136 lines
3.3 KiB
TypeScript
import { NDKUser } from '@nostr-dev-kit/ndk';
|
|
import { LRUCache } from 'lru-cache';
|
|
import { NostrEvent } from 'nostr-fetch';
|
|
import { nip19 } from 'nostr-tools';
|
|
|
|
import { useNDK } from '@libs/ndk/provider';
|
|
import {
|
|
countTotalNotes,
|
|
createChat,
|
|
createNote,
|
|
getActiveAccount,
|
|
getLastLogin,
|
|
updateAccount,
|
|
} from '@libs/storage';
|
|
|
|
import { nHoursAgo } from '@utils/date';
|
|
|
|
export function useNostr() {
|
|
const { ndk, relayUrls, fetcher } = useNDK();
|
|
|
|
async function fetchNetwork() {
|
|
const account = await getActiveAccount();
|
|
const follows = new Set<string>();
|
|
const lruNetwork = new LRUCache<string, string, void>({ max: 300 });
|
|
|
|
let network: string[];
|
|
|
|
// fetch user's follows
|
|
const user = ndk.getUser({ hexpubkey: account.pubkey });
|
|
const list = await user.follows();
|
|
list.forEach((item: NDKUser) => {
|
|
follows.add(nip19.decode(item.npub).data as string);
|
|
});
|
|
|
|
// fetch network
|
|
if (!account.network) {
|
|
const events = await fetcher.fetchAllEvents(
|
|
relayUrls,
|
|
{ kinds: [3], authors: [...follows] },
|
|
{ since: 0 },
|
|
{ skipVerification: true }
|
|
);
|
|
|
|
events.forEach((event: NostrEvent) => {
|
|
event.tags.forEach((tag) => {
|
|
if (tag[0] === 'p') lruNetwork.set(tag[1], tag[1]);
|
|
});
|
|
});
|
|
|
|
network = [...network.values()] as string[];
|
|
} else {
|
|
network = account.network;
|
|
}
|
|
|
|
// update user in db
|
|
await updateAccount('follows', [...follows]);
|
|
await updateAccount('network', network);
|
|
|
|
return [...new Set([...follows, ...network])];
|
|
}
|
|
|
|
const fetchNotes = async () => {
|
|
try {
|
|
const network = (await fetchNetwork()) as string[];
|
|
|
|
const totalNotes = await countTotalNotes();
|
|
const lastLogin = await getLastLogin();
|
|
|
|
if (network.length > 0) {
|
|
let since: number;
|
|
if (totalNotes === 0 || lastLogin === 0) {
|
|
since = nHoursAgo(6);
|
|
} else {
|
|
since = lastLogin;
|
|
}
|
|
|
|
const events = await fetcher.fetchAllEvents(
|
|
relayUrls,
|
|
{ kinds: [1], authors: network },
|
|
{ since: since },
|
|
{ skipVerification: true }
|
|
);
|
|
|
|
for (const event of events) {
|
|
await createNote(
|
|
event.id,
|
|
event.pubkey,
|
|
event.kind,
|
|
event.tags,
|
|
event.content,
|
|
event.created_at
|
|
);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} catch (e) {
|
|
console.log('error: ', e);
|
|
}
|
|
};
|
|
|
|
const fetchChats = async () => {
|
|
try {
|
|
const account = await getActiveAccount();
|
|
const lastLogin = await getLastLogin();
|
|
const incomingMessages = await fetcher.fetchAllEvents(
|
|
relayUrls,
|
|
{
|
|
kinds: [4],
|
|
'#p': [account.pubkey],
|
|
},
|
|
{ since: lastLogin },
|
|
{ skipVerification: true }
|
|
);
|
|
|
|
for (const event of incomingMessages) {
|
|
const receiverPubkey = event.tags.find((t) => t[0] === 'p')[1] || account.pubkey;
|
|
await createChat(
|
|
event.id,
|
|
receiverPubkey,
|
|
event.pubkey,
|
|
event.content,
|
|
event.tags,
|
|
event.created_at
|
|
);
|
|
}
|
|
|
|
return true;
|
|
} catch (e) {
|
|
console.log('error: ', e);
|
|
}
|
|
};
|
|
|
|
return { fetchNotes, fetchChats };
|
|
}
|