TOS for stream providers

This commit is contained in:
2023-08-01 15:51:07 +01:00
parent 786631e45e
commit 508abaad1f
7 changed files with 98 additions and 25 deletions

144
src/providers/zsz.ts Normal file
View File

@ -0,0 +1,144 @@
import {
StreamProvider,
StreamProviderEndpoint,
StreamProviderInfo,
StreamProviderStreamInfo,
StreamProviders,
} from ".";
import { EventKind, NostrEvent } from "@snort/system";
import { Login, StreamState } from "index";
import { getPublisher } from "login";
import { findTag } from "utils";
export class Nip103StreamProvider implements StreamProvider {
#url: string;
constructor(url: string) {
this.#url = url;
}
get name() {
return new URL(this.#url).host;
}
get type() {
return StreamProviders.NostrType;
}
async info() {
const rsp = await this.#getJson<AccountResponse>("GET", "account");
return {
type: StreamProviders.NostrType,
name: this.name,
state: StreamState.Planned,
viewers: 0,
streamInfo: rsp.event,
balance: rsp.balance,
tosAccepted: rsp.tos?.accepted,
tosLink: rsp.tos?.link,
endpoints: rsp.endpoints.map((a) => {
return {
name: a.name,
url: a.url,
key: a.key,
rate: a.cost.rate,
unit: a.cost.unit,
capabilities: a.capabilities,
} as StreamProviderEndpoint;
}),
} as StreamProviderInfo;
}
createConfig() {
return {
type: StreamProviders.NostrType,
url: this.#url,
};
}
async updateStreamInfo(ev: NostrEvent): Promise<void> {
const title = findTag(ev, "title");
const summary = findTag(ev, "summary");
const image = findTag(ev, "image");
const tags = ev?.tags.filter((a) => a[0] === "t").map((a) => a[1]);
const contentWarning = findTag(ev, "content-warning");
await this.#getJson("PATCH", "event", {
title,
summary,
image,
tags,
content_warning: contentWarning,
});
}
async topup(amount: number): Promise<string> {
const rsp = await this.#getJson<TopUpResponse>(
"GET",
`topup?amount=${amount}`
);
return rsp.pr;
}
async acceptTos(): Promise<void> {
await this.#getJson("PATCH", "account", {
accept_tos: true,
});
}
async #getJson<T>(
method: "GET" | "POST" | "PATCH",
path: string,
body?: unknown
): Promise<T> {
const login = Login.snapshot();
const pub = login && getPublisher(login);
if (!pub) throw new Error("No signer");
const u = `${this.#url}${path}`;
const token = await pub.generic((eb) => {
return eb
.kind(EventKind.HttpAuthentication)
.content("")
.tag(["u", u])
.tag(["method", method]);
});
const rsp = await fetch(u, {
method: method,
body: body ? JSON.stringify(body) : undefined,
headers: {
"content-type": "application/json",
authorization: `Nostr ${btoa(JSON.stringify(token))}`,
},
});
const json = await rsp.text();
if (!rsp.ok) {
throw new Error(json);
}
return json.length > 0 ? (JSON.parse(json) as T) : ({} as T);
}
}
interface AccountResponse {
balance: number;
event?: StreamProviderStreamInfo;
endpoints: Array<IngestEndpoint>;
tos?: {
accepted: boolean;
link: string;
};
}
interface IngestEndpoint {
name: string;
url: string;
key: string;
cost: {
unit: string;
rate: number;
};
capabilities: Array<string>;
}
interface TopUpResponse {
pr: string;
}