add nostr-fetch
This commit is contained in:
@@ -1,53 +1,67 @@
|
||||
import { NDKFilter } from '@nostr-dev-kit/ndk';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { NDKUser } from '@nostr-dev-kit/ndk';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { prefetchEvents } from '@libs/ndk/utils';
|
||||
import {
|
||||
countTotalNotes,
|
||||
createChat,
|
||||
createNote,
|
||||
getLastLogin,
|
||||
updateAccount,
|
||||
updateLastLogin,
|
||||
} from '@libs/storage';
|
||||
|
||||
import { LoaderIcon, LumeIcon } from '@shared/icons';
|
||||
|
||||
import { dateToUnix, getHourAgo } from '@utils/date';
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { useAccount } from '@utils/hooks/useAccount';
|
||||
|
||||
const totalNotes = await countTotalNotes();
|
||||
const lastLogin = await getLastLogin();
|
||||
|
||||
export function Root() {
|
||||
const now = useRef(new Date());
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { ndk } = useNDK();
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, account } = useAccount();
|
||||
|
||||
async function getFollows() {
|
||||
const authors: string[] = [];
|
||||
|
||||
const user = ndk.getUser({ hexpubkey: account.pubkey });
|
||||
const follows = await user.follows();
|
||||
|
||||
follows.forEach((follow: NDKUser) => {
|
||||
authors.push(nip19.decode(follow.npub).data as string);
|
||||
});
|
||||
|
||||
// update follows in db
|
||||
await updateAccount('follows', authors, account.pubkey);
|
||||
|
||||
return authors;
|
||||
}
|
||||
|
||||
async function fetchNotes() {
|
||||
try {
|
||||
const follows = JSON.parse(account.follows);
|
||||
const follows = await getFollows();
|
||||
|
||||
if (follows.length > 0) {
|
||||
let since: number;
|
||||
|
||||
if (totalNotes === 0 || lastLogin === 0) {
|
||||
since = dateToUnix(getHourAgo(48, now.current));
|
||||
since = nHoursAgo(48);
|
||||
} else {
|
||||
since = lastLogin;
|
||||
}
|
||||
|
||||
const filter: NDKFilter = {
|
||||
kinds: [1, 6],
|
||||
authors: follows,
|
||||
since: since,
|
||||
};
|
||||
|
||||
const events = await prefetchEvents(ndk, filter);
|
||||
for (const event of events) {
|
||||
const events = fetcher.allEventsIterator(
|
||||
relayUrls,
|
||||
{ kinds: [1], authors: follows },
|
||||
{ since: since },
|
||||
{ skipVerification: true }
|
||||
);
|
||||
for await (const event of events) {
|
||||
await createNote(
|
||||
event.id,
|
||||
event.pubkey,
|
||||
@@ -67,20 +81,23 @@ export function Root() {
|
||||
|
||||
async function fetchChats() {
|
||||
try {
|
||||
const sendFilter: NDKFilter = {
|
||||
kinds: [4],
|
||||
authors: [account.pubkey],
|
||||
since: lastLogin,
|
||||
};
|
||||
const sendMessages = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [4],
|
||||
authors: [account.pubkey],
|
||||
},
|
||||
{ since: lastLogin }
|
||||
);
|
||||
|
||||
const receiveFilter: NDKFilter = {
|
||||
kinds: [4],
|
||||
'#p': [account.pubkey],
|
||||
since: lastLogin,
|
||||
};
|
||||
|
||||
const sendMessages = await prefetchEvents(ndk, sendFilter);
|
||||
const receiveMessages = await prefetchEvents(ndk, receiveFilter);
|
||||
const receiveMessages = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [4],
|
||||
'#p': [account.pubkey],
|
||||
},
|
||||
{ since: lastLogin }
|
||||
);
|
||||
|
||||
const events = [...sendMessages, ...receiveMessages];
|
||||
for (const event of events) {
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import { NDKFilter } from '@nostr-dev-kit/ndk';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
|
||||
import { Note } from '@shared/notes/note';
|
||||
|
||||
import { dateToUnix, getHourAgo } from '@utils/date';
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { LumeEvent } from '@utils/types';
|
||||
|
||||
export function UserFeed({ pubkey }: { pubkey: string }) {
|
||||
const { ndk } = useNDK();
|
||||
const { fetcher, relayUrls } = useNDK();
|
||||
const { status, data } = useQuery(['user-feed', pubkey], async () => {
|
||||
const now = new Date();
|
||||
const filter: NDKFilter = {
|
||||
kinds: [1],
|
||||
authors: [pubkey],
|
||||
since: dateToUnix(getHourAgo(48, now)),
|
||||
};
|
||||
const events = await ndk.fetchEvents(filter);
|
||||
return [...events];
|
||||
const events = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{ kinds: [1], authors: [pubkey] },
|
||||
{ since: nHoursAgo(48) },
|
||||
{ sort: true }
|
||||
);
|
||||
return events as unknown as LumeEvent[];
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
// source: https://github.com/nostr-dev-kit/ndk-react/
|
||||
import NDK from '@nostr-dev-kit/ndk';
|
||||
import { ndkAdapter } from '@nostr-fetch/adapter-ndk';
|
||||
import { NostrFetcher, normalizeRelayUrls } from 'nostr-fetch';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { getSetting } from '@libs/storage';
|
||||
|
||||
const setting = await getSetting('relays');
|
||||
const relays = JSON.parse(setting);
|
||||
const relays = normalizeRelayUrls(JSON.parse(setting));
|
||||
|
||||
export const NDKInstance = () => {
|
||||
const [ndk, setNDK] = useState<NDK | undefined>(undefined);
|
||||
const [relayUrls, setRelayUrls] = useState<string[]>(relays);
|
||||
const [fetcher, setFetcher] = useState<NostrFetcher>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
loadNdk(relays);
|
||||
@@ -26,11 +29,13 @@ export const NDKInstance = () => {
|
||||
|
||||
setNDK(ndkInstance);
|
||||
setRelayUrls(explicitRelayUrls);
|
||||
setFetcher(NostrFetcher.withCustomPool(ndkAdapter(ndkInstance)));
|
||||
}
|
||||
|
||||
return {
|
||||
ndk,
|
||||
relayUrls,
|
||||
fetcher,
|
||||
loadNdk,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// source: https://github.com/nostr-dev-kit/ndk-react/
|
||||
import NDK from '@nostr-dev-kit/ndk';
|
||||
import { NostrFetcher } from 'nostr-fetch';
|
||||
import { PropsWithChildren, createContext, useContext } from 'react';
|
||||
|
||||
import { NDKInstance } from '@libs/ndk/instance';
|
||||
@@ -7,17 +8,19 @@ import { NDKInstance } from '@libs/ndk/instance';
|
||||
interface NDKContext {
|
||||
ndk: NDK;
|
||||
relayUrls: string[];
|
||||
fetcher: NostrFetcher;
|
||||
loadNdk: (_: string[]) => void;
|
||||
}
|
||||
|
||||
const NDKContext = createContext<NDKContext>({
|
||||
ndk: new NDK({}),
|
||||
relayUrls: [],
|
||||
fetcher: undefined,
|
||||
loadNdk: undefined,
|
||||
});
|
||||
|
||||
const NDKProvider = ({ children }: PropsWithChildren<object>) => {
|
||||
const { ndk, relayUrls, loadNdk } = NDKInstance();
|
||||
const { ndk, relayUrls, fetcher, loadNdk } = NDKInstance();
|
||||
|
||||
if (ndk)
|
||||
return (
|
||||
@@ -25,6 +28,7 @@ const NDKProvider = ({ children }: PropsWithChildren<object>) => {
|
||||
value={{
|
||||
ndk,
|
||||
relayUrls,
|
||||
fetcher,
|
||||
loadNdk,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import NDK, { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
|
||||
|
||||
export async function prefetchEvents(
|
||||
ndk: NDK,
|
||||
filter: NDKFilter
|
||||
): Promise<Set<NDKEvent>> {
|
||||
return new Promise((resolve) => {
|
||||
const events: Map<string, NDKEvent> = new Map();
|
||||
|
||||
const relaySetSubscription = ndk.subscribe(filter, {
|
||||
closeOnEose: true,
|
||||
});
|
||||
|
||||
relaySetSubscription.on('event', (event: NDKEvent) => {
|
||||
event.ndk = ndk;
|
||||
events.set(event.tagId(), event);
|
||||
});
|
||||
|
||||
relaySetSubscription.on('eose', () => {
|
||||
setTimeout(() => resolve(new Set(events.values())), 3000);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -440,7 +440,9 @@ export async function createMetadata(id: string, pubkey: string, content: string
|
||||
// get metadata
|
||||
export async function getUserMetadata(pubkey: string) {
|
||||
const db = await connect();
|
||||
const result = await db.select(`SELECT content FROM metadata WHERE id = "${pubkey}";`);
|
||||
const result = await db.select(
|
||||
`SELECT content, created_at FROM metadata WHERE id = "${pubkey}";`
|
||||
);
|
||||
if (result[0]) {
|
||||
return JSON.parse(result[0].content);
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Fragment, useRef, useState } from 'react';
|
||||
import { Fragment, useState } from 'react';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
|
||||
@@ -9,29 +9,26 @@ import { BellIcon, CancelIcon, LoaderIcon } from '@shared/icons';
|
||||
import { NotificationUser } from '@shared/notification/user';
|
||||
import { User } from '@shared/user';
|
||||
|
||||
import { dateToUnix, getHourAgo } from '@utils/date';
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { LumeEvent } from '@utils/types';
|
||||
|
||||
export function NotificationModal({ pubkey }: { pubkey: string }) {
|
||||
const now = useRef(new Date());
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const { ndk } = useNDK();
|
||||
const { fetcher, relayUrls } = useNDK();
|
||||
const { status, data } = useQuery(
|
||||
['user-notification', pubkey],
|
||||
['notification', pubkey],
|
||||
async () => {
|
||||
const filter: NDKFilter = {
|
||||
'#p': [pubkey],
|
||||
kinds: [1, 6, 7, 9735],
|
||||
since: dateToUnix(getHourAgo(48, now.current)),
|
||||
};
|
||||
const events = await ndk.fetchEvents(filter);
|
||||
return [...events];
|
||||
const events = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{ '#p': [pubkey], kinds: [1, 6, 7, 9735] },
|
||||
{ since: nHoursAgo(48) },
|
||||
{ sort: true }
|
||||
);
|
||||
return events as unknown as LumeEvent[];
|
||||
},
|
||||
{
|
||||
refetchOnMount: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: Infinity,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -20,3 +20,6 @@ export function dateToUnix(_date?: Date) {
|
||||
|
||||
return Math.floor(date.getTime() / 1000);
|
||||
}
|
||||
|
||||
export const nHoursAgo = (hrs: number): number =>
|
||||
Math.floor((Date.now() - hrs * 60 * 60 * 1000) / 1000);
|
||||
|
||||
@@ -4,26 +4,26 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { createNote } from '@libs/storage';
|
||||
|
||||
import { dateToUnix, getHourAgo } from '@utils/date';
|
||||
import { dateToUnix, getHourAgo, nHoursAgo } from '@utils/date';
|
||||
import { useAccount } from '@utils/hooks/useAccount';
|
||||
import { usePublish } from '@utils/hooks/usePublish';
|
||||
import { nip02ToArray } from '@utils/transform';
|
||||
import { LumeEvent } from '@utils/types';
|
||||
|
||||
export function useSocial() {
|
||||
const queryClient = useQueryClient();
|
||||
const publish = usePublish();
|
||||
|
||||
const { ndk } = useNDK();
|
||||
const { ndk, fetcher, relayUrls } = useNDK();
|
||||
const { account } = useAccount();
|
||||
const { status, data: userFollows } = useQuery(
|
||||
['userFollows', account.pubkey],
|
||||
async () => {
|
||||
const res = await ndk.fetchEvents({
|
||||
const res = await fetcher.fetchLastEvent(relayUrls, {
|
||||
kinds: [3],
|
||||
authors: [account.pubkey],
|
||||
});
|
||||
const latest = [...res].slice(-1)[0];
|
||||
const list = nip02ToArray(latest.tags);
|
||||
const list = nip02ToArray(res.tags);
|
||||
return list;
|
||||
},
|
||||
{
|
||||
@@ -68,14 +68,14 @@ export function useSocial() {
|
||||
});
|
||||
|
||||
// fetch events
|
||||
const filter: NDKFilter = {
|
||||
authors: [pubkey],
|
||||
kinds: [1, 6],
|
||||
since: dateToUnix(getHourAgo(48, new Date())),
|
||||
};
|
||||
const events = await ndk.fetchEvents(filter);
|
||||
events.forEach((event: NDKEvent) => {
|
||||
createNote(
|
||||
const events = await fetcher.fetchAllEvents(
|
||||
relayUrls,
|
||||
{ authors: [pubkey], kinds: [1, 6] },
|
||||
{ since: nHoursAgo(48) }
|
||||
);
|
||||
|
||||
for (const event of events) {
|
||||
await createNote(
|
||||
event.id,
|
||||
event.pubkey,
|
||||
event.kind,
|
||||
@@ -83,7 +83,7 @@ export function useSocial() {
|
||||
event.content,
|
||||
event.created_at
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return { status, userFollows, follow, unfollow };
|
||||
|
||||
Reference in New Issue
Block a user