2023-09-06 21:04:25 +00:00
|
|
|
import { NostrAccountContext, NostrEvent, NostrKind } from "../lib/nostr-ts/nostr.ts";
|
2023-11-15 13:21:45 +00:00
|
|
|
import { ConnectionPool, RelayAdder, RelayGetter, RelayRemover } from "../lib/nostr-ts/relay-pool.ts";
|
2023-10-07 10:59:06 +00:00
|
|
|
import { parseJSON } from "../features/profile.ts";
|
2023-11-15 13:21:45 +00:00
|
|
|
import { SingleRelayConnection } from "../lib/nostr-ts/relay-single.ts";
|
|
|
|
import { RelayConfigChange } from "./setting.tsx";
|
2023-11-24 10:35:27 +00:00
|
|
|
import { blowater, damus } from "../lib/nostr-ts/relay-list.test.ts";
|
2023-07-09 07:06:13 +00:00
|
|
|
|
2023-07-11 09:19:57 +00:00
|
|
|
export const defaultRelays = [
|
2023-10-22 03:39:26 +00:00
|
|
|
"wss://relay.blowater.app",
|
2023-09-02 23:38:24 +00:00
|
|
|
"wss://nos.lol",
|
|
|
|
"wss://relay.damus.io",
|
2023-08-28 20:34:41 +00:00
|
|
|
"wss://relay.nostr.wirednet.jp",
|
2023-06-30 14:05:57 +00:00
|
|
|
];
|
|
|
|
|
2023-07-19 08:25:36 +00:00
|
|
|
export class RelayConfig {
|
2023-11-15 13:21:45 +00:00
|
|
|
private config = new Set<string>();
|
2023-11-18 17:11:07 +00:00
|
|
|
private readonly ctx: NostrAccountContext;
|
|
|
|
private readonly relayPool: RelayAdder & RelayRemover & RelayGetter;
|
|
|
|
|
2023-11-14 06:22:50 +00:00
|
|
|
private constructor(
|
2023-11-18 17:11:07 +00:00
|
|
|
args: {
|
|
|
|
ctx: NostrAccountContext;
|
|
|
|
relayPool: RelayAdder & RelayRemover & RelayGetter;
|
|
|
|
},
|
|
|
|
) {
|
|
|
|
this.ctx = args.ctx;
|
|
|
|
this.relayPool = args.relayPool;
|
|
|
|
}
|
2023-09-06 16:29:27 +00:00
|
|
|
|
2023-11-24 10:35:27 +00:00
|
|
|
static Default(args: { ctx: NostrAccountContext; relayPool: RelayAdder & RelayRemover & RelayGetter }) {
|
|
|
|
const config = new RelayConfig(args);
|
|
|
|
config.add(blowater).then((res) => {
|
|
|
|
if (res instanceof Error) {
|
|
|
|
console.error(res);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
config.add(damus).then((res) => {
|
|
|
|
if (res instanceof Error) {
|
|
|
|
console.error(res);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return config;
|
2023-09-06 21:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// The the relay config of this account from local storage
|
2023-11-18 17:11:07 +00:00
|
|
|
static async FromLocalStorage(args: {
|
|
|
|
ctx: NostrAccountContext;
|
|
|
|
relayPool: RelayAdder & RelayRemover & RelayGetter;
|
|
|
|
}) {
|
|
|
|
const encodedConfigStr = localStorage.getItem(this.localStorageKey(args.ctx));
|
2023-09-06 21:04:25 +00:00
|
|
|
if (encodedConfigStr == null) {
|
2023-11-24 10:35:27 +00:00
|
|
|
return RelayConfig.Default(args);
|
2023-11-15 13:21:45 +00:00
|
|
|
}
|
|
|
|
let relayArray = parseJSON<string[]>(encodedConfigStr);
|
|
|
|
if (relayArray instanceof Error) {
|
|
|
|
console.log(relayArray.message);
|
|
|
|
relayArray = [];
|
2023-09-06 21:04:25 +00:00
|
|
|
}
|
2023-11-18 17:11:07 +00:00
|
|
|
const relayConfig = new RelayConfig(args);
|
2023-11-15 13:21:45 +00:00
|
|
|
for (const relay of relayArray) {
|
2023-11-18 17:11:07 +00:00
|
|
|
const err = await relayConfig.add(relay);
|
|
|
|
if (err instanceof Error) {
|
|
|
|
console.error(err);
|
|
|
|
}
|
2023-11-14 06:22:50 +00:00
|
|
|
}
|
2023-09-06 21:04:25 +00:00
|
|
|
return relayConfig;
|
|
|
|
}
|
|
|
|
static localStorageKey(ctx: NostrAccountContext) {
|
|
|
|
return `${RelayConfig.name}-${ctx.publicKey.bech32()}`;
|
|
|
|
}
|
|
|
|
|
2023-11-15 13:21:45 +00:00
|
|
|
async addEvent(event: NostrEvent<NostrKind.Custom_App_Data>) {
|
|
|
|
const content = await this.ctx.encrypt(this.ctx.publicKey.hex, event.content);
|
|
|
|
if (content instanceof Error) {
|
|
|
|
return content;
|
2023-09-06 16:29:27 +00:00
|
|
|
}
|
2023-11-15 13:21:45 +00:00
|
|
|
const configChange = parseJSON<RelayConfigChange>(content);
|
|
|
|
if (configChange instanceof Error) {
|
|
|
|
return configChange;
|
2023-10-07 10:59:06 +00:00
|
|
|
}
|
2023-11-15 13:21:45 +00:00
|
|
|
if (configChange.type != "RelayConfigChange") {
|
|
|
|
return; // ignore
|
|
|
|
}
|
|
|
|
if (configChange.kind == "add") {
|
|
|
|
this.config.add(configChange.url);
|
|
|
|
} else {
|
|
|
|
this.config.delete(configChange.url);
|
2023-09-06 16:29:27 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-19 08:25:36 +00:00
|
|
|
|
2023-07-21 08:50:38 +00:00
|
|
|
getRelayURLs() {
|
2023-11-15 13:21:45 +00:00
|
|
|
return this.config;
|
2023-09-06 16:29:27 +00:00
|
|
|
}
|
|
|
|
|
2023-11-18 17:11:07 +00:00
|
|
|
saveToLocalStorage() {
|
|
|
|
console.log(RelayConfig.name, ":: saveToLocalStorage");
|
|
|
|
localStorage.setItem(RelayConfig.localStorageKey(this.ctx), JSON.stringify(Array.from(this.config)));
|
2023-09-06 16:29:27 +00:00
|
|
|
}
|
|
|
|
|
2023-11-15 13:21:45 +00:00
|
|
|
async add(url: string): Promise<Error | SingleRelayConnection> {
|
2023-11-18 17:11:07 +00:00
|
|
|
console.log(RelayConfig.name, ":: add relay config", url);
|
2023-11-24 10:35:27 +00:00
|
|
|
this.config.add(url);
|
2023-11-15 13:21:45 +00:00
|
|
|
const relay = await this.relayPool.addRelayURL(url);
|
|
|
|
if (relay instanceof Error) {
|
|
|
|
return relay;
|
2023-09-06 16:29:27 +00:00
|
|
|
}
|
2023-11-18 17:11:07 +00:00
|
|
|
this.saveToLocalStorage();
|
2023-11-15 13:21:45 +00:00
|
|
|
return relay;
|
2023-07-19 08:25:36 +00:00
|
|
|
}
|
|
|
|
|
2023-09-06 16:29:27 +00:00
|
|
|
async remove(url: string) {
|
2023-11-24 10:35:27 +00:00
|
|
|
if (url == blowater) {
|
|
|
|
return new RemoveBlowaterRelay();
|
|
|
|
}
|
2023-11-18 17:11:07 +00:00
|
|
|
await this.relayPool.removeRelay(url);
|
|
|
|
const ok = this.config.delete(url);
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
return ok;
|
2023-09-06 16:29:27 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-19 08:25:36 +00:00
|
|
|
|
2023-09-06 16:29:27 +00:00
|
|
|
export function applyPoolToRelayConfig(pool: ConnectionPool, relayConfig: RelayConfig) {
|
|
|
|
for (const relay of pool.getRelays()) {
|
|
|
|
relayConfig.add(relay.url);
|
2023-07-19 08:25:36 +00:00
|
|
|
}
|
2023-06-30 14:05:57 +00:00
|
|
|
}
|
2023-11-24 10:35:27 +00:00
|
|
|
|
|
|
|
export class RemoveBlowaterRelay extends Error {}
|