2023-04-14 15:02:15 +00:00
|
|
|
import { EventKind } from "@snort/nostr";
|
2023-04-13 18:43:43 +00:00
|
|
|
import { ApiHost } from "Const";
|
|
|
|
import { SubscriptionType } from "Subscription";
|
2023-04-14 15:02:15 +00:00
|
|
|
import { EventPublisher } from "System/EventPublisher";
|
2023-04-13 18:43:43 +00:00
|
|
|
|
|
|
|
export interface RevenueToday {
|
|
|
|
donations: number;
|
|
|
|
nip5: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface RevenueSplit {
|
|
|
|
pubKey: string;
|
|
|
|
split: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface InvoiceResponse {
|
|
|
|
pr: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Subscription {
|
|
|
|
id: string;
|
|
|
|
type: SubscriptionType;
|
2023-04-17 21:22:00 +00:00
|
|
|
created: number;
|
|
|
|
expires: number;
|
2023-04-17 20:33:55 +00:00
|
|
|
state: "new" | "expired" | "paid";
|
2023-04-17 21:22:00 +00:00
|
|
|
handle?: string;
|
2023-04-17 20:33:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export enum SubscriptionErrorCode {
|
|
|
|
InternalError = 1,
|
|
|
|
SubscriptionActive = 2,
|
|
|
|
Duplicate = 3,
|
|
|
|
}
|
|
|
|
|
|
|
|
export class SubscriptionError extends Error {
|
|
|
|
code: SubscriptionErrorCode;
|
|
|
|
|
|
|
|
constructor(msg: string, code: SubscriptionErrorCode) {
|
|
|
|
super(msg);
|
|
|
|
this.code = code;
|
|
|
|
}
|
2023-04-13 18:43:43 +00:00
|
|
|
}
|
|
|
|
|
2023-04-18 11:47:01 +00:00
|
|
|
export interface LinkPreviewData {
|
|
|
|
title?: string;
|
|
|
|
description?: string;
|
|
|
|
image?: string;
|
|
|
|
}
|
|
|
|
|
2023-04-13 18:43:43 +00:00
|
|
|
export default class SnortApi {
|
|
|
|
#url: string;
|
|
|
|
#publisher?: EventPublisher;
|
|
|
|
|
|
|
|
constructor(url?: string, publisher?: EventPublisher) {
|
|
|
|
this.#url = new URL(url ?? ApiHost).toString();
|
|
|
|
this.#publisher = publisher;
|
|
|
|
}
|
|
|
|
|
|
|
|
revenueSplits() {
|
|
|
|
return this.#getJson<Array<RevenueSplit>>("api/v1/revenue/splits");
|
|
|
|
}
|
|
|
|
|
|
|
|
revenueToday() {
|
|
|
|
return this.#getJson<RevenueToday>("api/v1/revenue/today");
|
|
|
|
}
|
|
|
|
|
|
|
|
twitterImport(username: string) {
|
|
|
|
return this.#getJson<Array<string>>(`api/v1/twitter/follows-for-nostr?username=${encodeURIComponent(username)}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
createSubscription(type: number) {
|
|
|
|
return this.#getJsonAuthd<InvoiceResponse>(`api/v1/subscription?type=${type}`, "PUT");
|
|
|
|
}
|
|
|
|
|
2023-04-17 20:33:55 +00:00
|
|
|
renewSubscription(id: string) {
|
|
|
|
return this.#getJsonAuthd<InvoiceResponse>(`api/v1/subscription/${id}/renew`, "GET");
|
|
|
|
}
|
|
|
|
|
2023-04-13 18:43:43 +00:00
|
|
|
listSubscriptions() {
|
|
|
|
return this.#getJsonAuthd<Array<Subscription>>("api/v1/subscription");
|
|
|
|
}
|
|
|
|
|
2023-04-18 11:47:01 +00:00
|
|
|
linkPreview(url: string) {
|
|
|
|
return this.#getJson<LinkPreviewData>(`api/v1/preview?url=${encodeURIComponent(url)}`);
|
|
|
|
}
|
|
|
|
|
2023-04-13 18:43:43 +00:00
|
|
|
async #getJsonAuthd<T>(
|
|
|
|
path: string,
|
|
|
|
method?: "GET" | string,
|
|
|
|
body?: { [key: string]: string },
|
|
|
|
headers?: { [key: string]: string }
|
|
|
|
): Promise<T> {
|
|
|
|
if (!this.#publisher) {
|
|
|
|
throw new Error("Publisher not set");
|
|
|
|
}
|
2023-04-14 15:02:15 +00:00
|
|
|
const auth = await this.#publisher.generic(eb => {
|
2023-04-17 09:14:25 +00:00
|
|
|
return eb
|
|
|
|
.kind(EventKind.HttpAuthentication)
|
|
|
|
.tag(["url", `${this.#url}${path}`])
|
|
|
|
.tag(["method", method ?? "GET"]);
|
2023-04-14 15:02:15 +00:00
|
|
|
});
|
2023-04-13 18:43:43 +00:00
|
|
|
|
|
|
|
return this.#getJson<T>(path, method, body, {
|
|
|
|
...headers,
|
|
|
|
authorization: `Nostr ${window.btoa(JSON.stringify(auth))}`,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async #getJson<T>(
|
|
|
|
path: string,
|
|
|
|
method?: "GET" | string,
|
|
|
|
body?: { [key: string]: string },
|
|
|
|
headers?: { [key: string]: string }
|
|
|
|
): Promise<T> {
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const obj = await rsp.json();
|
|
|
|
if ("error" in obj) {
|
2023-04-17 20:33:55 +00:00
|
|
|
throw new SubscriptionError(obj.error, obj.code);
|
2023-04-13 18:43:43 +00:00
|
|
|
}
|
|
|
|
return obj as T;
|
|
|
|
}
|
|
|
|
}
|