forked from Kieran/snort
feat: add fallback memory relay
This commit is contained in:
parent
8e33d10319
commit
cb0b75c652
@ -1,5 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src youtube.com www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://nostrnests.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://analytics.v0l.io https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com;
|
Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src youtube.com www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://nostrnests.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://analytics.v0l.io https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com;
|
||||||
Cross-Origin-Resource-Policy: corss-origin
|
|
||||||
Cross-Origin-Opener-Policy: same-origin
|
Cross-Origin-Opener-Policy: same-origin
|
||||||
Cross-Origin-Embedder-Policy: credentialless
|
Cross-Origin-Embedder-Policy: cross-origin
|
@ -11,11 +11,7 @@ import { ProfileCacheRelayWorker } from "./ProfileWorkeCache";
|
|||||||
export const Relay = new WorkerRelayInterface(WorkerRelayPath);
|
export const Relay = new WorkerRelayInterface(WorkerRelayPath);
|
||||||
export async function initRelayWorker() {
|
export async function initRelayWorker() {
|
||||||
try {
|
try {
|
||||||
if (await Relay.init()) {
|
await Relay.init("relay.db");
|
||||||
if (await Relay.open()) {
|
|
||||||
await Relay.migrate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,8 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
headers: {
|
headers: {
|
||||||
"Cross-Origin-Resource-Policy": "corss-origin",
|
|
||||||
"Cross-Origin-Opener-Policy": "same-origin",
|
"Cross-Origin-Opener-Policy": "same-origin",
|
||||||
"Cross-Origin-Embedder-Policy": "credentialless",
|
"Cross-Origin-Embedder-Policy": "require-corp",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import debug from "debug";
|
import { NostrEvent, ReqCommand, WorkerMessage, WorkerMessageCommand } from "./types";
|
||||||
import { NostrEvent, ReqCommand, WorkerMessage } from "./types";
|
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
|
|
||||||
export class WorkerRelayInterface {
|
export class WorkerRelayInterface {
|
||||||
#worker: Worker;
|
#worker: Worker;
|
||||||
#log = (msg: any) => console.debug(msg);
|
|
||||||
#commandQueue: Map<string, (v: unknown, ports: ReadonlyArray<MessagePort>) => void> = new Map();
|
#commandQueue: Map<string, (v: unknown, ports: ReadonlyArray<MessagePort>) => void> = new Map();
|
||||||
|
|
||||||
constructor(path: string) {
|
constructor(path: string) {
|
||||||
this.#log(`Module path: ${path}`);
|
|
||||||
this.#worker = new Worker(path, { type: "module" });
|
this.#worker = new Worker(path, { type: "module" });
|
||||||
this.#worker.onmessage = e => {
|
this.#worker.onmessage = e => {
|
||||||
const cmd = e.data as WorkerMessage<any>;
|
const cmd = e.data as WorkerMessage<any>;
|
||||||
@ -20,16 +17,8 @@ export class WorkerRelayInterface {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init(path: string) {
|
||||||
return (await this.#workerRpc<void, boolean>("init")).result;
|
return (await this.#workerRpc<string, boolean>("init", path)).result;
|
||||||
}
|
|
||||||
|
|
||||||
async open() {
|
|
||||||
return (await this.#workerRpc<void, boolean>("open")).result;
|
|
||||||
}
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
return (await this.#workerRpc<void, boolean>("migrate")).result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async event(ev: NostrEvent) {
|
async event(ev: NostrEvent) {
|
||||||
@ -60,7 +49,7 @@ export class WorkerRelayInterface {
|
|||||||
return (await this.#workerRpc<object, Array<Array<any>>>("sql", { sql, params })).result;
|
return (await this.#workerRpc<object, Array<Array<any>>>("sql", { sql, params })).result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#workerRpc<T, R>(cmd: string, args?: T) {
|
#workerRpc<T, R>(cmd: WorkerMessageCommand, args?: T) {
|
||||||
const id = uuid();
|
const id = uuid();
|
||||||
const msg = {
|
const msg = {
|
||||||
id,
|
id,
|
||||||
|
77
packages/worker-relay/src/memory-relay.ts
Normal file
77
packages/worker-relay/src/memory-relay.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import EventEmitter from "eventemitter3";
|
||||||
|
import { NostrEvent, RelayHandler, RelayHandlerEvents, ReqFilter, eventMatchesFilter } from "./types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A very simple dumb fallback relay using a flat table
|
||||||
|
*/
|
||||||
|
export class InMemoryRelay extends EventEmitter<RelayHandlerEvents> implements RelayHandler {
|
||||||
|
#events: Map<string, NostrEvent> = new Map();
|
||||||
|
#log = (...args: any[]) => console.debug(...args);
|
||||||
|
|
||||||
|
init(path: string): Promise<void> {
|
||||||
|
this.#log("Using in-memory relay");
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
count(req: ReqFilter): number {
|
||||||
|
let ret = 0;
|
||||||
|
for (const [, e] of this.#events) {
|
||||||
|
if (eventMatchesFilter(e, req)) {
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary(): Record<string, number> {
|
||||||
|
let ret = {} as Record<string, number>;
|
||||||
|
for (const [k, v] of this.#events) {
|
||||||
|
ret[v.kind.toString()] ??= 0;
|
||||||
|
ret[v.kind.toString()]++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(): Promise<Uint8Array> {
|
||||||
|
return Promise.resolve(new Uint8Array());
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
event(ev: NostrEvent) {
|
||||||
|
if (this.#events.has(ev.id)) return false;
|
||||||
|
this.#events.set(ev.id, ev);
|
||||||
|
this.emit("event", [ev]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventBatch(evs: NostrEvent[]) {
|
||||||
|
const inserted = [];
|
||||||
|
for (const ev of evs) {
|
||||||
|
if (this.#events.has(ev.id)) continue;
|
||||||
|
this.#events.set(ev.id, ev);
|
||||||
|
inserted.push(ev);
|
||||||
|
}
|
||||||
|
if (inserted.length > 0) {
|
||||||
|
this.emit("event", inserted);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql(sql: string, params: (string | number)[]): (string | number)[][] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
req(id: string, filter: ReqFilter) {
|
||||||
|
const ret = [];
|
||||||
|
for (const [, e] of this.#events) {
|
||||||
|
if (eventMatchesFilter(e, filter)) {
|
||||||
|
ret.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,8 @@
|
|||||||
import sqlite3InitModule, { Database, Sqlite3Static } from "@sqlite.org/sqlite-wasm";
|
import sqlite3InitModule, { Database, Sqlite3Static } from "@sqlite.org/sqlite-wasm";
|
||||||
import debug from "debug";
|
|
||||||
import { EventEmitter } from "eventemitter3";
|
import { EventEmitter } from "eventemitter3";
|
||||||
import { NostrEvent, ReqFilter, unixNowMs } from "./types";
|
import { NostrEvent, RelayHandler, RelayHandlerEvents, ReqFilter, unixNowMs } from "./types";
|
||||||
|
|
||||||
export interface WorkerRelayEvents {
|
export class WorkerRelay extends EventEmitter<RelayHandlerEvents> implements RelayHandler {
|
||||||
event: (evs: Array<NostrEvent>) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class WorkerRelay extends EventEmitter<WorkerRelayEvents> {
|
|
||||||
#sqlite?: Sqlite3Static;
|
#sqlite?: Sqlite3Static;
|
||||||
#log = (...args: any[]) => console.debug(...args);
|
#log = (...args: any[]) => console.debug(...args);
|
||||||
#db?: Database;
|
#db?: Database;
|
||||||
@ -16,16 +11,18 @@ export class WorkerRelay extends EventEmitter<WorkerRelayEvents> {
|
|||||||
/**
|
/**
|
||||||
* Initialize the SQLite driver
|
* Initialize the SQLite driver
|
||||||
*/
|
*/
|
||||||
async init() {
|
async init(path: string) {
|
||||||
if (this.#sqlite) return;
|
if (this.#sqlite) return;
|
||||||
this.#sqlite = await sqlite3InitModule();
|
this.#sqlite = await sqlite3InitModule();
|
||||||
this.#log(`Got SQLite version: ${this.#sqlite.version.libVersion}`);
|
this.#log(`Got SQLite version: ${this.#sqlite.version.libVersion}`);
|
||||||
|
await this.#open(path);
|
||||||
|
this.#migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the database from its path
|
* Open the database from its path
|
||||||
*/
|
*/
|
||||||
async open(path: string) {
|
async #open(path: string) {
|
||||||
if (!this.#sqlite) throw new Error("Must call init first");
|
if (!this.#sqlite) throw new Error("Must call init first");
|
||||||
if (this.#db) return;
|
if (this.#db) return;
|
||||||
|
|
||||||
@ -50,7 +47,7 @@ export class WorkerRelay extends EventEmitter<WorkerRelayEvents> {
|
|||||||
/**
|
/**
|
||||||
* Do database migration
|
* Do database migration
|
||||||
*/
|
*/
|
||||||
migrate() {
|
#migrate() {
|
||||||
if (!this.#db) throw new Error("DB must be open");
|
if (!this.#db) throw new Error("DB must be open");
|
||||||
|
|
||||||
this.#db.exec(
|
this.#db.exec(
|
||||||
@ -88,7 +85,7 @@ export class WorkerRelay extends EventEmitter<WorkerRelayEvents> {
|
|||||||
* Run any SQL command
|
* Run any SQL command
|
||||||
*/
|
*/
|
||||||
sql(sql: string, params: Array<any>) {
|
sql(sql: string, params: Array<any>) {
|
||||||
return this.#db?.selectArrays(sql, params);
|
return this.#db?.selectArrays(sql, params) as Array<Array<string | number>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -229,7 +226,7 @@ export class WorkerRelay extends EventEmitter<WorkerRelayEvents> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
this.open(filePath);
|
await this.#open(filePath);
|
||||||
}
|
}
|
||||||
return new Uint8Array();
|
return new Uint8Array();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,19 @@
|
|||||||
|
import { EventEmitter } from "eventemitter3";
|
||||||
|
|
||||||
|
export type WorkerMessageCommand =
|
||||||
|
| "reply"
|
||||||
|
| "init"
|
||||||
|
| "event"
|
||||||
|
| "req"
|
||||||
|
| "count"
|
||||||
|
| "summary"
|
||||||
|
| "close"
|
||||||
|
| "dumpDb"
|
||||||
|
| "sql";
|
||||||
|
|
||||||
export interface WorkerMessage<T> {
|
export interface WorkerMessage<T> {
|
||||||
id: string;
|
id: string;
|
||||||
cmd: "reply" | "init" | "open" | "migrate" | "event" | "req" | "count" | "summary" | "close" | "dumpDb" | "sql";
|
cmd: WorkerMessageCommand;
|
||||||
args: T;
|
args: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +45,51 @@ export interface ReqFilter {
|
|||||||
[key: string]: Array<string> | Array<number> | string | number | undefined | ReqFilter;
|
[key: string]: Array<string> | Array<number> | string | number | undefined | ReqFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RelayHandler extends EventEmitter<RelayHandlerEvents> {
|
||||||
|
init(path: string): Promise<void>;
|
||||||
|
close(): void;
|
||||||
|
event(ev: NostrEvent): boolean;
|
||||||
|
eventBatch(evs: Array<NostrEvent>): boolean;
|
||||||
|
sql(sql: string, params: Array<string | number>): Array<Array<string | number>>;
|
||||||
|
req(id: string, req: ReqFilter): Array<NostrEvent>;
|
||||||
|
count(req: ReqFilter): number;
|
||||||
|
summary(): Record<string, number>;
|
||||||
|
dump(): Promise<Uint8Array>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RelayHandlerEvents {
|
||||||
|
event: (evs: Array<NostrEvent>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
export function unixNowMs() {
|
export function unixNowMs() {
|
||||||
return new Date().getTime();
|
return new Date().getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function eventMatchesFilter(ev: NostrEvent, filter: ReqFilter) {
|
||||||
|
if (filter.since && ev.created_at < filter.since) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (filter.until && ev.created_at > filter.until) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(filter.ids?.includes(ev.id) ?? true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(filter.authors?.includes(ev.pubkey) ?? true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(filter.kinds?.includes(ev.kind) ?? true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const tags = Object.entries(filter).filter(([k]) => k.startsWith("#"));
|
||||||
|
for (const [k, v] of tags) {
|
||||||
|
const vargs = v as Array<string>;
|
||||||
|
for (const x of vargs) {
|
||||||
|
if (!ev.tags.find(a => a[0] === k.slice(1) && a[1] === x)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
/// <reference lib="webworker" />
|
/// <reference lib="webworker" />
|
||||||
|
|
||||||
|
import { InMemoryRelay } from "./memory-relay";
|
||||||
import { WorkQueueItem, barrierQueue, processWorkQueue } from "./queue";
|
import { WorkQueueItem, barrierQueue, processWorkQueue } from "./queue";
|
||||||
import { WorkerRelay } from "./relay";
|
import { WorkerRelay } from "./relay";
|
||||||
import { NostrEvent, ReqCommand, ReqFilter, WorkerMessage } from "./types";
|
import { NostrEvent, RelayHandler, ReqCommand, ReqFilter, WorkerMessage, eventMatchesFilter } from "./types";
|
||||||
|
|
||||||
interface PortedFilter {
|
interface PortedFilter {
|
||||||
filters: Array<ReqFilter>;
|
filters: Array<ReqFilter>;
|
||||||
@ -12,23 +13,7 @@ interface PortedFilter {
|
|||||||
// Active open subscriptions awaiting new events
|
// Active open subscriptions awaiting new events
|
||||||
const ActiveSubscriptions = new Map<string, PortedFilter>();
|
const ActiveSubscriptions = new Map<string, PortedFilter>();
|
||||||
|
|
||||||
const relay = new WorkerRelay();
|
let relay: RelayHandler | undefined;
|
||||||
relay.on("event", evs => {
|
|
||||||
for (const pf of ActiveSubscriptions.values()) {
|
|
||||||
const pfSend = [];
|
|
||||||
for (const ev of evs) {
|
|
||||||
for (const fx of pf.filters) {
|
|
||||||
if (eventMatchesFilter(ev, fx)) {
|
|
||||||
pfSend.push(ev);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pfSend.length > 0) {
|
|
||||||
pf.port.postMessage(pfSend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function reply<T>(id: string, obj?: T, transferables?: Transferable[]) {
|
async function reply<T>(id: string, obj?: T, transferables?: Transferable[]) {
|
||||||
globalThis.postMessage(
|
globalThis.postMessage(
|
||||||
@ -46,7 +31,7 @@ let eventWriteQueue: Array<NostrEvent> = [];
|
|||||||
async function insertBatch() {
|
async function insertBatch() {
|
||||||
// Only insert event batches when the command queue is empty
|
// Only insert event batches when the command queue is empty
|
||||||
// This is to make req's execute first and not block them
|
// This is to make req's execute first and not block them
|
||||||
if (eventWriteQueue.length > 0 && cmdQueue.length === 0) {
|
if (relay && eventWriteQueue.length > 0 && cmdQueue.length === 0) {
|
||||||
relay.eventBatch(eventWriteQueue);
|
relay.eventBatch(eventWriteQueue);
|
||||||
eventWriteQueue = [];
|
eventWriteQueue = [];
|
||||||
}
|
}
|
||||||
@ -57,31 +42,49 @@ setTimeout(() => insertBatch(), 100);
|
|||||||
const cmdQueue: Array<WorkQueueItem> = [];
|
const cmdQueue: Array<WorkQueueItem> = [];
|
||||||
processWorkQueue(cmdQueue, 50);
|
processWorkQueue(cmdQueue, 50);
|
||||||
|
|
||||||
|
async function tryOpfs() {
|
||||||
|
try {
|
||||||
|
await navigator.storage.getDirectory();
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
globalThis.onclose = () => {
|
globalThis.onclose = () => {
|
||||||
relay.close();
|
relay?.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
globalThis.onmessage = ev => {
|
globalThis.onmessage = async ev => {
|
||||||
const msg = ev.data as WorkerMessage<any>;
|
const msg = ev.data as WorkerMessage<any>;
|
||||||
try {
|
try {
|
||||||
switch (msg.cmd) {
|
switch (msg.cmd) {
|
||||||
case "init": {
|
case "init": {
|
||||||
barrierQueue(cmdQueue, async () => {
|
await barrierQueue(cmdQueue, async () => {
|
||||||
await relay.init();
|
if ("WebAssembly" in globalThis && (await tryOpfs())) {
|
||||||
reply(msg.id, true);
|
relay = new WorkerRelay();
|
||||||
});
|
} else {
|
||||||
break;
|
relay = new InMemoryRelay();
|
||||||
}
|
}
|
||||||
case "open": {
|
|
||||||
barrierQueue(cmdQueue, async () => {
|
relay.on("event", evs => {
|
||||||
await relay.open("/relay.db");
|
for (const pf of ActiveSubscriptions.values()) {
|
||||||
reply(msg.id, true);
|
const pfSend = [];
|
||||||
});
|
for (const ev of evs) {
|
||||||
break;
|
for (const fx of pf.filters) {
|
||||||
}
|
if (eventMatchesFilter(ev, fx)) {
|
||||||
case "migrate": {
|
pfSend.push(ev);
|
||||||
barrierQueue(cmdQueue, async () => {
|
continue;
|
||||||
relay.migrate();
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pfSend.length > 0) {
|
||||||
|
pf.port.postMessage(pfSend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await relay.init(msg.args as string);
|
||||||
reply(msg.id, true);
|
reply(msg.id, true);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@ -97,7 +100,7 @@ globalThis.onmessage = ev => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "req": {
|
case "req": {
|
||||||
barrierQueue(cmdQueue, async () => {
|
await barrierQueue(cmdQueue, async () => {
|
||||||
const req = msg.args as ReqCommand;
|
const req = msg.args as ReqCommand;
|
||||||
const chan = new MessageChannel();
|
const chan = new MessageChannel();
|
||||||
if (req.leaveOpen) {
|
if (req.leaveOpen) {
|
||||||
@ -108,18 +111,18 @@ globalThis.onmessage = ev => {
|
|||||||
}
|
}
|
||||||
const results = [];
|
const results = [];
|
||||||
for (const r of req.filters) {
|
for (const r of req.filters) {
|
||||||
results.push(...relay.req(req.id, r as ReqFilter));
|
results.push(...relay!.req(req.id, r as ReqFilter));
|
||||||
}
|
}
|
||||||
reply(msg.id, results, req.leaveOpen ? [chan.port2] : undefined);
|
reply(msg.id, results, req.leaveOpen ? [chan.port2] : undefined);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "count": {
|
case "count": {
|
||||||
barrierQueue(cmdQueue, async () => {
|
await barrierQueue(cmdQueue, async () => {
|
||||||
const req = msg.args as ReqCommand;
|
const req = msg.args as ReqCommand;
|
||||||
let results = 0;
|
let results = 0;
|
||||||
for (const r of req.filters) {
|
for (const r of req.filters) {
|
||||||
const c = relay.count(r as ReqFilter);
|
const c = relay!.count(r as ReqFilter);
|
||||||
results += c;
|
results += c;
|
||||||
}
|
}
|
||||||
reply(msg.id, results);
|
reply(msg.id, results);
|
||||||
@ -127,26 +130,26 @@ globalThis.onmessage = ev => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "summary": {
|
case "summary": {
|
||||||
barrierQueue(cmdQueue, async () => {
|
await barrierQueue(cmdQueue, async () => {
|
||||||
const res = relay.summary();
|
const res = relay!.summary();
|
||||||
reply(msg.id, res);
|
reply(msg.id, res);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "dumpDb": {
|
case "dumpDb": {
|
||||||
barrierQueue(cmdQueue, async () => {
|
await barrierQueue(cmdQueue, async () => {
|
||||||
const res = await relay.dump();
|
const res = await relay!.dump();
|
||||||
reply(msg.id, res);
|
reply(msg.id, res);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "sql": {
|
case "sql": {
|
||||||
barrierQueue(cmdQueue, async () => {
|
await barrierQueue(cmdQueue, async () => {
|
||||||
const req = msg.args as {
|
const req = msg.args as {
|
||||||
sql: string;
|
sql: string;
|
||||||
params: Array<any>;
|
params: Array<any>;
|
||||||
};
|
};
|
||||||
const res = relay.sql(req.sql, req.params);
|
const res = relay!.sql(req.sql, req.params);
|
||||||
reply(msg.id, res);
|
reply(msg.id, res);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@ -161,22 +164,3 @@ globalThis.onmessage = ev => {
|
|||||||
reply(msg.id, { error: e });
|
reply(msg.id, { error: e });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function eventMatchesFilter(ev: NostrEvent, filter: ReqFilter) {
|
|
||||||
if (filter.since && ev.created_at < filter.since) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (filter.until && ev.created_at > filter.until) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(filter.ids?.includes(ev.id) ?? true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(filter.authors?.includes(ev.pubkey) ?? true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(filter.kinds?.includes(ev.kind) ?? true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user