diff --git a/packages/app/src/Components/Embed/LinkPreview.tsx b/packages/app/src/Components/Embed/LinkPreview.tsx index 4f8aedeb..bbe59321 100644 --- a/packages/app/src/Components/Embed/LinkPreview.tsx +++ b/packages/app/src/Components/Embed/LinkPreview.tsx @@ -5,11 +5,11 @@ import { LRUCache } from "typescript-lru-cache"; import { MediaElement } from "@/Components/Embed/MediaElement"; import Spinner from "@/Components/Icons/Spinner"; -import SnortApi, { LinkPreviewData } from "@/External/SnortApi"; +import { LinkPreviewData, NostrServices } from "@/External/NostrServices"; import useImgProxy from "@/Hooks/useImgProxy"; async function fetchUrlPreviewInfo(url: string) { - const api = new SnortApi(); + const api = new NostrServices("https://nostr.api.v0l.io"); try { return await api.linkPreview(url.endsWith(")") ? url.slice(0, -1) : url); } catch (e) { diff --git a/packages/app/src/External/NostrServices.ts b/packages/app/src/External/NostrServices.ts new file mode 100644 index 00000000..ea68627b --- /dev/null +++ b/packages/app/src/External/NostrServices.ts @@ -0,0 +1,19 @@ +import { JsonApi } from "."; + +export interface LinkPreviewData { + title?: string; + description?: string; + image?: string; + og_tags?: Array<[name: string, value: string]>; +} + +export class NostrServices extends JsonApi { + constructor(readonly url: string) { + super(); + url = url.endsWith("/") ? url.slice(0, -1) : url; + } + + linkPreview(url: string) { + return this.getJson(`/api/v1/preview?url=${encodeURIComponent(url)}`); + } +} diff --git a/packages/app/src/External/SnortApi.ts b/packages/app/src/External/SnortApi.ts index 9ae46d7a..35eb85c7 100644 --- a/packages/app/src/External/SnortApi.ts +++ b/packages/app/src/External/SnortApi.ts @@ -43,13 +43,6 @@ export class SubscriptionError extends Error { } } -export interface LinkPreviewData { - title?: string; - description?: string; - image?: string; - og_tags?: Array<[name: string, value: string]>; -} - export interface PushNotifications { endpoint: string; p256dh: string; @@ -119,10 +112,6 @@ export default class SnortApi { return this.#getJsonAuthd>("api/v1/subscription"); } - linkPreview(url: string) { - return this.#getJson(`api/v1/preview?url=${encodeURIComponent(url)}`); - } - onChainDonation() { return this.#getJson<{ address: string }>("p/on-chain"); } diff --git a/packages/app/src/External/index.ts b/packages/app/src/External/index.ts index 011459ad..cad60825 100644 --- a/packages/app/src/External/index.ts +++ b/packages/app/src/External/index.ts @@ -1,2 +1,40 @@ +import { throwIfOffline, unwrap } from "@snort/shared"; + export * from "./NostrBand"; export * from "./SemisolDev"; + +export abstract class JsonApi { + abstract url: string; + protected async getJson( + path: string, + method?: "GET" | string, + body?: object, + headers?: { [key: string]: string }, + ): Promise { + throwIfOffline(); + const rsp = await fetch(`${this.url}${path}`, { + method: method, + body: body ? JSON.stringify(body) : undefined, + headers: { + accept: "application/json", + ...(body ? { "content-type": "application/json" } : {}), + ...headers, + }, + }); + + if (rsp.ok) { + const text = (await rsp.text()) as string | null; + if ((text?.length ?? 0) > 0) { + const obj = JSON.parse(unwrap(text)); + if ("error" in obj) { + throw new Error(obj.error, obj.code); + } + return obj as T; + } else { + return {} as T; + } + } else { + throw new Error("Invalid response"); + } + } +}