diff --git a/apps/badges/app/layout.tsx b/apps/badges/app/layout.tsx index df7c484..6fb63aa 100644 --- a/apps/badges/app/layout.tsx +++ b/apps/badges/app/layout.tsx @@ -1,5 +1,5 @@ export const metadata = { - metadataBase: new URL("https://badges.page"), + metadataBase: new URL('https://badges.page'), title: "Badges", description: "Create, collect and award badges", }; diff --git a/apps/emojis/app/utils.ts b/apps/emojis/app/utils.ts new file mode 100644 index 0000000..d9bd79e --- /dev/null +++ b/apps/emojis/app/utils.ts @@ -0,0 +1,33 @@ +import { Relay, Tag } from "@ngine/core"; + +export function encodeRelayURL(url: string): string { + url = url.trim(); + if (url.startsWith("wss://")) { + url = url.slice(6); + } + return encodeURIComponent(url); +} + +export function relayToTag(r: Relay): Tag { + if (r.read && !r.write) { + return ["r", r.url, "read"]; + } + if (r.write && !r.read) { + return ["r", r.url, "write"]; + } + return ["r", r.url]; +} + +export function tagToRelay(t: Tag): Relay { + const url = t[1].replace(/\/$/, ""); + + if (t[2] === "read") { + return { url, read: true, write: false }; + } + + if (t[2] === "write") { + return { url, read: false, write: true }; + } + + return { url, read: true, write: true }; +} diff --git a/apps/emojis/ui/layout.tsx b/apps/emojis/ui/layout.tsx index 8a1d803..ca81129 100644 --- a/apps/emojis/ui/layout.tsx +++ b/apps/emojis/ui/layout.tsx @@ -15,11 +15,7 @@ import { theme } from "./theme"; const cacheAdapter = new NDKCacheAdapterDexie({ dbName: "emojis" }); const ndk = new NDK({ - explicitRelayUrls: [ - "wss://nos.lol", - "wss://relay.nostr.band", - "wss://frens.nostr1.com", - ], + explicitRelayUrls: ["wss://nos.lol", "wss://relay.nostr.band", "wss://frens.nostr1.com"], outboxRelayUrls: ["wss://purplepag.es"], enableOutboxModel: true, cacheAdapter, diff --git a/apps/relays/app/components/footer.tsx b/apps/relays/app/components/footer.tsx index 383a2f0..914e989 100644 --- a/apps/relays/app/components/footer.tsx +++ b/apps/relays/app/components/footer.tsx @@ -13,9 +13,9 @@ export default function Footer(props: StackProps) { {...props} > - Relay data provided by - - nostr.watch + Made with ❤️ by{" "} + + verbiricha diff --git a/apps/relays/app/components/relay-link.tsx b/apps/relays/app/components/relay-link.tsx index e21e88b..fd2186b 100644 --- a/apps/relays/app/components/relay-link.tsx +++ b/apps/relays/app/components/relay-link.tsx @@ -5,7 +5,7 @@ import { useRelays } from "@ngine/core"; import Link from "./link"; import RelayFavicon from "./relay-favicon"; -import { humanize, encode } from "@lib/urls"; +import { encodeRelayURL } from "../utils"; interface RelayLinkProps { url: string; @@ -13,12 +13,11 @@ interface RelayLinkProps { export default function RelayLink({ url }: RelayLinkProps) { const relays = useRelays(); - const isInMyRelays = useMemo( - () => relays.map(humanize).includes(humanize(url)), - [relays, url], - ); - const encoded = useMemo(() => `/relay/${encode(url)}`, [url]); - const domain = useMemo(() => humanize(url), [url]); + const isInMyRelays = useMemo(() => relays.includes(url), [relays, url]); + const encoded = useMemo(() => `/relay/${encodeRelayURL(url)}`, [url]); + const domain = useMemo(() => { + return url.replace("ws://", "").replace("wss://", ""); + }, [url]); return ( diff --git a/apps/relays/app/components/relay-metadata.tsx b/apps/relays/app/components/relay-metadata.tsx index d9eae7f..3d6f122 100644 --- a/apps/relays/app/components/relay-metadata.tsx +++ b/apps/relays/app/components/relay-metadata.tsx @@ -7,7 +7,6 @@ import RelayFavicon from "./relay-favicon"; import RelaySummary from "./relay-summary"; import ToggleRelay from "./toggle-relay"; import { RelayMetadata } from "../hooks/useRelayMetadata"; -import { humanize } from "@lib/urls"; export default function Metadata({ url, @@ -16,7 +15,9 @@ export default function Metadata({ url: string; metadata: RelayMetadata; }) { - const domain = useMemo(() => humanize(url), [url]); + const domain = useMemo(() => { + return url.replace("ws://", "").replace("wss://", ""); + }, [url]); return ( diff --git a/apps/relays/app/components/relays.tsx b/apps/relays/app/components/relays.tsx index b959a75..06b3363 100644 --- a/apps/relays/app/components/relays.tsx +++ b/apps/relays/app/components/relays.tsx @@ -3,73 +3,58 @@ import { useRouter } from "next/navigation"; import { useState, useMemo } from "react"; import { + Alert, + AlertIcon, Stack, Button, + Text, Icon, Input, InputGroup, InputLeftElement, InputRightElement, - Stat, - StatLabel, - StatNumber, - StatGroup, } from "@chakra-ui/react"; +import { useQuery } from "@tanstack/react-query"; import { useIntl, FormattedMessage } from "react-intl"; import { useRelays } from "@ngine/core"; import RelayLink from "./relay-link"; import RelayIcon from "./relay-icon"; -import { humanize, encode } from "@lib/urls"; -import useRelayStatus from "@hooks/useRelayStatus"; +import { encodeRelayURL } from "../utils"; export default function Relays() { const { formatMessage } = useIntl(); const router = useRouter(); const [relay, setRelay] = useState(""); - const { events, online, offline } = useRelayStatus(); const myRelays = useRelays(); - const relaySet = useMemo(() => new Set(myRelays.map(humanize)), [myRelays]); + const { data, isFetched, isError } = useQuery({ + queryKey: ["relays"], + queryFn: () => + fetch(`https://api.nostr.watch/v1/online`).then((r) => r.json()), + }); function relayScore(url: string) { - if (relaySet.has(humanize(url))) { - return 42; + if (myRelays.includes(url)) { + return 1; } return 0; } const relays = useMemo(() => { - const raw = [...online].sort((a, b) => relayScore(b) - relayScore(a)); + const raw = data + ? [...data].sort((a, b) => relayScore(b) - relayScore(a)) + : []; return raw .filter((url) => url.toLowerCase().includes(relay.toLowerCase())) .slice(0, 21); - }, [online, relay]); + }, [relay, data, myRelays]); function goToRelay(url: string) { - router.push(`/relay/${encode(url)}`); + router.push(`/relay/${encodeRelayURL(url)}`); } return ( - - {/* @ts-ignore */} - - {events.length} - Relays - - - {/* @ts-ignore */} - - {online.length} - Online - - - {/* @ts-ignore */} - - {offline.length} - Offline - - - {relays.map((url) => ( - - ))} + {isError && ( + + + + + )} + {isFetched && + relays.map((url: string) => )} + {isFetched && relays.length === 0 && ( + + + + )} ); diff --git a/apps/relays/app/utils.ts b/apps/relays/app/utils.ts index 676fb91..d9bd79e 100644 --- a/apps/relays/app/utils.ts +++ b/apps/relays/app/utils.ts @@ -19,7 +19,7 @@ export function relayToTag(r: Relay): Tag { } export function tagToRelay(t: Tag): Relay { - const url = t[1]; + const url = t[1].replace(/\/$/, ""); if (t[2] === "read") { return { url, read: true, write: false }; diff --git a/apps/relays/hooks/useRelayStatus.ts b/apps/relays/hooks/useRelayStatus.ts deleted file mode 100644 index 50f52c8..0000000 --- a/apps/relays/hooks/useRelayStatus.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { NDKKind, NDKSubscriptionCacheUsage } from "@nostr-dev-kit/ndk"; -import { useEvent, useEvents } from "@ngine/core"; - -export function useStatus(url: string) { - const event = useEvent( - { - kinds: [30_066 as NDKKind], - "#d": [url], - authors: [ - "151c17c9d234320cf0f189af7b761f63419fd6c38c6041587a008b7682e4640f", - ], - }, - { - cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST, - }, - ); - return event; -} - -export default function useRelayStatus() { - const { events } = useEvents( - { - kinds: [30_066 as NDKKind], - authors: [ - "151c17c9d234320cf0f189af7b761f63419fd6c38c6041587a008b7682e4640f", - ], - }, - { - cacheUsage: NDKSubscriptionCacheUsage.PARALLEL, - }, - ); - const online = events - .filter((e) => e.tagValue("s") === "online") - .map((e) => e.tagValue("d")) - .filter((s) => s) as string[]; - const offline = events - .filter((e) => e.tagValue("s") !== "online") - .map((e) => e.tagValue("d")) - .filter((s) => s) as string[]; - return { events, online, offline }; -} diff --git a/apps/relays/lib/urls.ts b/apps/relays/lib/urls.ts deleted file mode 100644 index f6a224e..0000000 --- a/apps/relays/lib/urls.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function encode(url: string): string { - url = url.trim(); - return encodeURIComponent(humanize(url)); -} - -export function humanize(url: string) { - return url.replace("ws://", "").replace("wss://", "").replace(/\/$/, ""); -} diff --git a/apps/relays/tsconfig.json b/apps/relays/tsconfig.json index 38ebcf9..1cd8a4d 100644 --- a/apps/relays/tsconfig.json +++ b/apps/relays/tsconfig.json @@ -16,8 +16,6 @@ "baseUrl": "./", "paths": { "@ui/*": ["ui/*"], - "@hooks/*": ["hooks/*"], - "@lib/*": ["lib/*"], } }, "include": [ diff --git a/packages/core/src/state.ts b/packages/core/src/state.ts index 7752898..2876604 100644 --- a/packages/core/src/state.ts +++ b/packages/core/src/state.ts @@ -18,7 +18,7 @@ export const relaysAtom = atom((get) => { relayList?.tags .filter((t) => t[0] === "r") .map((t) => { - const url = t[1]; + const url = t[1].replace(/\/$/, ""); const read = t.length === 2 || t[2] === "read"; const write = t.length === 2 || t[2] === "write"; return { url, read, write };