Sync Relay Config (#85)

update nostr.ts
This commit is contained in:
BlowaterNostr 2023-07-19 16:25:36 +08:00 committed by BlowaterNostr
parent bd96687205
commit 7a7d8e53a0
8 changed files with 142 additions and 49 deletions

View File

@ -29,8 +29,6 @@ import { getSocialPosts } from "../features/social.ts";
import * as time from "../time.ts";
import { PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts";
import {
DecryptionFailure,
decryptNostrEvent,
NostrAccountContext,
NostrEvent,
NostrKind,
@ -41,13 +39,11 @@ import {
} from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts";
import { getCurrentSignInCtx, setSignInState, SignIn } from "./signIn.tsx";
import { AppList } from "./app-list.tsx";
import { LinkColor, PrimaryTextColor, SecondaryBackgroundColor } from "./style/colors.ts";
import { SecondaryBackgroundColor } from "./style/colors.ts";
import { EventSyncer } from "./event_syncer.ts";
import { getRelayURLs } from "./setting.ts";
import { RelayConfig } from "./setting.ts";
import { DexieDatabase } from "./dexie-db.ts";
import { DividerClass } from "./components/tw.ts";
import { About } from "./about.tsx";
import { computeThreads } from "../nostr.ts";
export async function Start(database: DexieDatabase) {
const model = initialModel();
@ -143,12 +139,6 @@ async function initProfileSyncer(
}
})();
///////////////////////////////////
// Add relays to Connection Pool //
///////////////////////////////////
const relayURLs = getRelayURLs(database);
pool.addRelayURLs(relayURLs);
return profilesSyncer;
}
@ -156,6 +146,7 @@ export class App {
profileSyncer!: ProfilesSyncer;
eventSyncer: EventSyncer;
public readonly allUsersInfo: AllUsersInformation;
public readonly relayConfig: RelayConfig;
constructor(
public readonly database: Database_Contextual_View,
@ -163,24 +154,37 @@ export class App {
public readonly model: Model,
public readonly myAccountContext: NostrAccountContext,
public readonly eventBus: EventBus<UI_Interaction_Event>,
public readonly relayPool: ConnectionPool,
relayPool: ConnectionPool,
) {
this.eventSyncer = new EventSyncer(this.relayPool, this.database);
this.eventSyncer = new EventSyncer(relayPool, this.database);
this.allUsersInfo = new AllUsersInformation(myAccountContext);
this.relayConfig = new RelayConfig(relayPool, this.myAccountContext);
}
initApp = async (accountContext: NostrAccountContext) => {
// const events = this.database.filterEvents((e) => e.kind == NostrKind.TEXT_NOTE);
console.log("App.initApp");
const profilesSyncer = await initProfileSyncer(this.relayPool, accountContext, this.database);
this.allUsersInfo.addEvents(this.database.events);
{
///////////////////////////////////
// Add relays to Connection Pool //
///////////////////////////////////
const events = [];
for (const e of this.database.events) {
if (e.kind == NostrKind.CustomAppData) {
events.push(e);
}
}
await this.relayConfig.addEvents(events);
}
console.log("relay urls::", this.relayConfig.getRelayURLs());
const profilesSyncer = await initProfileSyncer(this.relayConfig.pool, accountContext, this.database);
if (profilesSyncer instanceof Error) {
return profilesSyncer;
}
this.profileSyncer = profilesSyncer;
this.allUsersInfo.addEvents(this.database.events);
console.log("App allUsersInfo");
this.model.social.threads = getSocialPosts(this.database, this.allUsersInfo.userInfos);
@ -224,6 +228,7 @@ export class App {
this.lamport,
this.eventBus,
this.allUsersInfo,
this.relayConfig,
)
) {
render(<AppComponent model={this.model} eventBus={this.eventBus} />, document.body);
@ -322,7 +327,7 @@ export function AppComponent(props: {
>
{Setting({
logout: app.logout,
pool: app.relayPool,
relayConfig: app.relayConfig,
eventBus: app.eventBus,
AddRelayButtonClickedError: model.AddRelayButtonClickedError,
AddRelayInput: model.AddRelayInput,
@ -361,7 +366,7 @@ export function AppComponent(props: {
eventEmitter: app.eventBus,
myAccountContext: myAccountCtx,
db: app.database,
pool: app.relayPool,
pool: app.relayConfig.pool,
allUserInfo: app.allUsersInfo.userInfos,
profilesSyncer: app.profileSyncer,
eventSyncer: app.eventSyncer,
@ -386,7 +391,7 @@ export function AppComponent(props: {
profilePicURL: model.myProfile?.picture,
publicKey: myAccountCtx.publicKey,
database: app.database,
pool: app.relayPool,
pool: app.relayConfig.pool,
eventEmitter: app.eventBus,
AddRelayButtonClickedError: model.AddRelayButtonClickedError,
AddRelayInput: model.AddRelayInput,
@ -421,7 +426,7 @@ export function AppComponent(props: {
profilePicURL={model.myProfile?.picture}
publicKey={myAccountCtx.publicKey}
database={app.database}
pool={app.relayPool}
pool={app.relayConfig.pool}
eventEmitter={app.eventBus}
AddRelayButtonClickedError={model.AddRelayButtonClickedError}
AddRelayInput={model.AddRelayInput}

View File

@ -38,6 +38,7 @@ import {
import { MessageThread } from "./dm.tsx";
import { DexieDatabase } from "./dexie-db.ts";
import { getSocialPosts } from "../features/social.ts";
import { RelayConfig } from "./setting.ts";
export type UI_Interaction_Event =
| RemoveRelayButtonClicked
@ -144,7 +145,7 @@ export async function* UI_Interaction_Update(
//
if (event.type == "AddRelayButtonClicked") {
// todo: need to think about concurrent/async UI update
model.app.relayPool.addRelayURL(event.url).then((err) => {
model.app.relayConfig.addRelayURL(event.url).then((err) => {
if (err instanceof Error) {
model.AddRelayButtonClickedError = err.message;
} else {
@ -155,7 +156,7 @@ export async function* UI_Interaction_Update(
} else if (event.type == "AddRelayInputChange") {
model.AddRelayInput = event.url;
} else if (event.type == "RemoveRelayButtonClicked") {
await model.app.relayPool.removeRelay(event.url);
await model.app.relayConfig.removeRelay(event.url);
} //
//
// Search
@ -220,7 +221,7 @@ export async function* UI_Interaction_Update(
console.error(nostrEvent);
continue;
}
const err = await model.app.relayPool.sendEvent(nostrEvent);
const err = await model.app.relayConfig.pool.sendEvent(nostrEvent);
if (err instanceof Error) {
console.error(err);
}
@ -241,7 +242,7 @@ export async function* UI_Interaction_Update(
files: event.files,
kind: event.target.kind,
lamport_timestamp: model.app.lamport.now(),
pool: model.app.relayPool,
pool: model.app.relayConfig.pool,
waitAll: false,
tags: event.tags,
});
@ -259,7 +260,7 @@ export async function* UI_Interaction_Update(
sender: model.app.myAccountContext,
message: event.text,
lamport_timestamp: model.app.lamport.now(),
pool: model.app.relayPool,
pool: model.app.relayConfig.pool,
tags: event.tags,
});
if (event.id == "social") {
@ -328,7 +329,7 @@ export async function* UI_Interaction_Update(
await saveProfile(
event.profile,
model.app.myAccountContext,
model.app.relayPool,
model.app.relayConfig.pool,
);
} else if (event.type == "EditNewProfileFieldKey") {
model.newProfileField.key = event.key;
@ -450,6 +451,7 @@ export async function* Database_Update(
lamport: LamportTime,
eventEmitter: EventEmitter<SelectProfile>,
allUserInfo: AllUsersInformation,
relayConfig: RelayConfig,
) {
const changes = database.onChange((_) => true);
while (true) {
@ -469,6 +471,15 @@ export async function* Database_Update(
}
let hasKind_1 = false;
{
const events = [];
for (const e of changes_events) {
if (e.kind == NostrKind.CustomAppData) {
events.push(e);
}
}
await relayConfig.addEvents(events);
}
for (let e of changes_events) {
allUserInfo.addEvents([e]);
const t = getTags(e).lamport_timestamp;

View File

@ -220,9 +220,6 @@ export class AllUsersInformation {
case NostrKind.DELETE:
break;
case NostrKind.CustomAppData: {
if (event.kind == NostrKind.CustomAppData) {
event;
}
const obj: CustomAppData = JSON.parse(event.decryptedContent);
if (obj.type == "PinContact" || obj.type == "UnpinContact") {
const userInfo = this.userInfos.get(obj.pubkey);

View File

@ -2,13 +2,9 @@
"version": "2",
"remote": {
"https://deno.land/std@0.176.0/encoding/hex.ts": "50f8c95b52eae24395d3dfcb5ec1ced37c5fe7610ef6fffdcc8b0fdc38e3b32f",
"https://deno.land/std@0.176.0/fmt/colors.ts": "938c5d44d889fb82eff6c358bea8baa7e85950a16c9f6dae3ec3a7a729164471",
"https://deno.land/std@0.176.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea",
"https://deno.land/std@0.176.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7",
"https://deno.land/std@0.176.0/testing/asserts.ts": "984ab0bfb3faeed92ffaa3a6b06536c66811185328c5dd146257c702c41b01ab",
"https://esm.sh/preact@10.11.3": "ad3c24796c4132c84b4b392f812228d53a0fd600fa64648f27aebd05ec09b24e",
"https://esm.sh/stable/preact@10.11.3/denonext/preact.mjs": "c828d9020ea26f07ba07b2f0a3ef97fd7ceb1c2a772c380ca05e2647ac8d3923",
"https://esm.sh/twind@0.16.16": "6c8934ebceb225d94d9e11f42338e09a94cf9e7bce84d9817a1123a0cea44cd2",
"https://esm.sh/twind@0.16.16": "e6e76f9434facce39a98842576a98921cc62e52ca5e8fbe5ed285d09472a491e",
"https://esm.sh/v128/csstype@3.1.2/index.d.ts": "4c68749a564a6facdf675416d75789ee5a557afda8960e0803cf6711fa569288",
"https://esm.sh/v128/preact@10.11.3/src/index.d.ts": "76842a9d103548261ee001f2aee5fa5cacc8b1b4b4032af537ed84603c8f4a31",
"https://esm.sh/v128/preact@10.11.3/src/jsx.d.ts": "77ce5bd7324455c9f6dc85bfc3c94b733acb92cc98fdf82e4b1059c8bca7866d",
@ -19,8 +15,8 @@
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/ende.ts": "00807d3602a65d5a6881c8fbb01d6886bf7a6640a2cc5c7c1bf00dd00b320ae7",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts": "1830bb6eded80c71aeae6a94ce921dbf09fcdf4820a3b846f8e8d9e23ce17119",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nip19.ts": "880aa40c85bb770703b5e85d72f29fed96f21777dc17906017c385873aedfd44",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts": "aeac23272327a1a0c576aaa66a040497474ec0d325fa27bbb112b2b36110abb3",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts": "93c5c6fe196dc9cae7c0e82ee8057a5350f77e69ae7d395fdb141a25b2664739",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts": "8cee22b9a14ec735cbea9d00b06a634417d54cf5b847eef3d93c7ca4906742d8",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts": "c58ac282ec1c980ee5eac6f3d1fc323f24d25dbea9f07af6381b9e6d3f1d5109",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/scure.js": "fbc4be16918272bd167fff1184a7f5bbd1a676bad2a73130bb530d78df893a99",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/vendor/esm.sh/v106/@noble/secp256k1@1.7.1/es2022/secp256k1.js": "69e32f6c686cc651ff2e6d4d22ed6e9b6f86b38311b405b47b2abdf3cb98eb4d",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/websocket.ts": "d817c40d32fe45e30bfb30255287e76a977930f6709c9585772dc54e077a31ed",

View File

@ -1,4 +1,9 @@
import { Database_Contextual_View } from "../database.ts";
import {
NostrAccountContext,
prepareCustomAppDataEvent,
} from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
import { ConnectionPool } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts";
import { CustomAppData, Decrypted_Nostr_Event } from "../nostr.ts";
const damus = "wss://relay.damus.io";
const nos = "wss://nos.lol";
@ -9,6 +14,74 @@ export const defaultRelays = [
"wss://relay.nostr.wirednet.jp",
];
export function getRelayURLs(db: Database_Contextual_View): string[] {
return defaultRelays;
export class RelayConfig {
private readonly relaySet = new Set<string>();
constructor(
public readonly pool: ConnectionPool,
public readonly ctx: NostrAccountContext,
) {}
getRelayURLs(): string[] {
const urls = this.pool.getRelays().map((r) => r.url);
if (urls.length == 0) {
return defaultRelays;
}
return urls;
}
async addEvents(events: Decrypted_Nostr_Event[]) {
for (const event of events) {
const obj: CustomAppData = JSON.parse(event.decryptedContent);
if (obj.type == "AddRelay") {
this.relaySet.add(obj.url);
} else if (obj.type == "RemoveRelay") {
this.relaySet.delete(obj.url);
}
}
const s = new Set(this.pool.getRelays().map((r) => r.url));
// add
for (const url of this.relaySet) {
if (!s.has(url)) {
const err = await this.pool.addRelayURL(url);
if (err instanceof Error) {
console.error(err);
continue;
}
}
}
// remove
for (const url of s) {
if (!this.relaySet.has(url)) {
this.pool.removeRelay(url);
}
}
}
async addRelayURL(url: string) {
const err = await this.pool.addRelayURL(url);
if (err instanceof Error) {
return err;
}
const event = await prepareCustomAppDataEvent<CustomAppData>(this.ctx, {
type: "AddRelay",
url: url,
});
if (event instanceof Error) {
return event;
}
return this.pool.sendEvent(event);
}
async removeRelay(url: string) {
await this.pool.removeRelay(url);
const event = await prepareCustomAppDataEvent<CustomAppData>(this.ctx, {
type: "RemoveRelay",
url: url,
});
if (event instanceof Error) {
return event;
}
return this.pool.sendEvent(event);
}
}

View File

@ -1,5 +1,5 @@
/** @jsx h */
import { Fragment, FunctionComponent, h } from "https://esm.sh/preact@10.11.3";
import { Fragment, h } from "https://esm.sh/preact@10.11.3";
import { tw } from "https://esm.sh/twind@0.16.16";
import { EventBus } from "../event-bus.ts";
@ -31,10 +31,11 @@ import {
} from "./style/colors.ts";
import { RelayIcon } from "./icons2/relay-icon.tsx";
import { DeleteIcon } from "./icons2/delete-icon.tsx";
import { RelayConfig } from "./setting.ts";
export interface SettingProps {
logout: () => void;
pool: ConnectionPool;
relayConfig: RelayConfig;
eventBus: EventBus<UI_Interaction_Event>;
AddRelayButtonClickedError: string;
AddRelayInput: string;
@ -48,8 +49,8 @@ const colors = {
"Closed": ErrorColor,
};
export const Setting: FunctionComponent<SettingProps> = (props: SettingProps) => {
const relays = props.pool.getRelays().map(
export const Setting = (props: SettingProps) => {
const relays = props.relayConfig.pool.getRelays().map(
(r) => ({
url: r.url,
status: r.ws.status(),

View File

@ -8,7 +8,7 @@
"https://deno.land/std@0.176.0/testing/asserts.ts": "984ab0bfb3faeed92ffaa3a6b06536c66811185328c5dd146257c702c41b01ab",
"https://esm.sh/preact@10.11.3": "ad3c24796c4132c84b4b392f812228d53a0fd600fa64648f27aebd05ec09b24e",
"https://esm.sh/stable/preact@10.11.3/denonext/preact.mjs": "c828d9020ea26f07ba07b2f0a3ef97fd7ceb1c2a772c380ca05e2647ac8d3923",
"https://esm.sh/twind@0.16.16": "6c8934ebceb225d94d9e11f42338e09a94cf9e7bce84d9817a1123a0cea44cd2",
"https://esm.sh/twind@0.16.16": "e6e76f9434facce39a98842576a98921cc62e52ca5e8fbe5ed285d09472a491e",
"https://esm.sh/v128/csstype@3.1.2/index.d.ts": "4c68749a564a6facdf675416d75789ee5a557afda8960e0803cf6711fa569288",
"https://esm.sh/v128/preact@10.11.3/src/index.d.ts": "76842a9d103548261ee001f2aee5fa5cacc8b1b4b4032af537ed84603c8f4a31",
"https://esm.sh/v128/preact@10.11.3/src/jsx.d.ts": "77ce5bd7324455c9f6dc85bfc3c94b733acb92cc98fdf82e4b1059c8bca7866d",
@ -19,8 +19,8 @@
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/ende.ts": "00807d3602a65d5a6881c8fbb01d6886bf7a6640a2cc5c7c1bf00dd00b320ae7",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts": "1830bb6eded80c71aeae6a94ce921dbf09fcdf4820a3b846f8e8d9e23ce17119",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nip19.ts": "880aa40c85bb770703b5e85d72f29fed96f21777dc17906017c385873aedfd44",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts": "aeac23272327a1a0c576aaa66a040497474ec0d325fa27bbb112b2b36110abb3",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts": "93c5c6fe196dc9cae7c0e82ee8057a5350f77e69ae7d395fdb141a25b2664739",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts": "8cee22b9a14ec735cbea9d00b06a634417d54cf5b847eef3d93c7ca4906742d8",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts": "c58ac282ec1c980ee5eac6f3d1fc323f24d25dbea9f07af6381b9e6d3f1d5109",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/scure.js": "fbc4be16918272bd167fff1184a7f5bbd1a676bad2a73130bb530d78df893a99",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/vendor/esm.sh/v106/@noble/secp256k1@1.7.1/es2022/secp256k1.js": "69e32f6c686cc651ff2e6d4d22ed6e9b6f86b38311b405b47b2abdf3cb98eb4d",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/websocket.ts": "d817c40d32fe45e30bfb30255287e76a977930f6709c9585772dc54e077a31ed",

View File

@ -299,7 +299,7 @@ export type PlainText_Nostr_Event =
export type Profile_Nostr_Event = Parsed_Event<NostrKind.META_DATA> & {
profile: ProfileData;
};
export type CustomAppData = PinContact | UnpinContact | UserLogin;
export type CustomAppData = PinContact | UnpinContact | UserLogin | AddRelay | RemoveRelay;
export type PinContact = {
type: "PinContact";
@ -314,3 +314,13 @@ export type UnpinContact = {
export type UserLogin = {
type: "UserLogin";
};
export type AddRelay = {
type: "AddRelay";
url: string;
};
export type RemoveRelay = {
type: "RemoveRelay";
url: string;
};