@nostrify/policies 0.36.4 → 0.36.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +28 -5
- package/.turbo/turbo-setup.log +22 -0
- package/.turbo/turbo-test.log +4 -0
- package/AntiDuplicationPolicy.test.ts +54 -41
- package/AntiDuplicationPolicy.ts +7 -3
- package/AnyPolicy.test.ts +15 -14
- package/AnyPolicy.ts +5 -2
- package/AuthorPolicy.test.ts +8 -7
- package/AuthorPolicy.ts +9 -3
- package/CHANGELOG.md +18 -0
- package/DomainPolicy.test.ts +130 -77
- package/DomainPolicy.ts +3 -3
- package/FiltersPolicy.test.ts +14 -7
- package/FiltersPolicy.ts +5 -2
- package/HashtagPolicy.test.ts +25 -14
- package/HashtagPolicy.ts +5 -2
- package/HellthreadPolicy.test.ts +10 -9
- package/HellthreadPolicy.ts +6 -3
- package/InvertPolicy.test.ts +10 -9
- package/InvertPolicy.ts +8 -2
- package/KeywordPolicy.test.ts +18 -12
- package/KeywordPolicy.ts +5 -2
- package/NoOpPolicy.test.ts +8 -7
- package/NoOpPolicy.ts +1 -1
- package/OpenAIPolicy.test.ts +22 -9
- package/OpenAIPolicy.ts +5 -2
- package/PipePolicy.test.ts +18 -17
- package/PipePolicy.ts +5 -2
- package/PowPolicy.test.ts +14 -13
- package/PowPolicy.ts +6 -3
- package/PubkeyBanPolicy.test.ts +15 -8
- package/PubkeyBanPolicy.ts +5 -2
- package/ReadOnlyPolicy.test.ts +9 -8
- package/ReadOnlyPolicy.ts +1 -1
- package/RegexPolicy.test.ts +19 -10
- package/RegexPolicy.ts +5 -2
- package/ReplyBotPolicy.test.ts +43 -27
- package/ReplyBotPolicy.ts +6 -3
- package/SizePolicy.test.ts +9 -8
- package/SizePolicy.ts +6 -2
- package/WhitelistPolicy.test.ts +15 -8
- package/WhitelistPolicy.ts +6 -2
- package/WoTPolicy.test.ts +48 -22
- package/WoTPolicy.ts +5 -2
- package/dist/AntiDuplicationPolicy.d.ts +2 -2
- package/dist/AntiDuplicationPolicy.d.ts.map +1 -1
- package/dist/AntiDuplicationPolicy.js +41 -56
- package/dist/AnyPolicy.d.ts +1 -1
- package/dist/AnyPolicy.d.ts.map +1 -1
- package/dist/AnyPolicy.js +17 -16
- package/dist/AuthorPolicy.d.ts +1 -1
- package/dist/AuthorPolicy.d.ts.map +1 -1
- package/dist/AuthorPolicy.js +19 -20
- package/dist/DomainPolicy.d.ts +2 -2
- package/dist/DomainPolicy.d.ts.map +1 -1
- package/dist/DomainPolicy.js +57 -59
- package/dist/FiltersPolicy.d.ts +1 -1
- package/dist/FiltersPolicy.d.ts.map +1 -1
- package/dist/FiltersPolicy.js +15 -24
- package/dist/HashtagPolicy.d.ts +1 -1
- package/dist/HashtagPolicy.d.ts.map +1 -1
- package/dist/HashtagPolicy.js +16 -23
- package/dist/HellthreadPolicy.d.ts +1 -1
- package/dist/HellthreadPolicy.d.ts.map +1 -1
- package/dist/HellthreadPolicy.js +18 -17
- package/dist/InvertPolicy.d.ts +1 -1
- package/dist/InvertPolicy.d.ts.map +1 -1
- package/dist/InvertPolicy.js +18 -18
- package/dist/KeywordPolicy.d.ts +1 -1
- package/dist/KeywordPolicy.d.ts.map +1 -1
- package/dist/KeywordPolicy.js +16 -23
- package/dist/NoOpPolicy.d.ts +1 -1
- package/dist/NoOpPolicy.d.ts.map +1 -1
- package/dist/NoOpPolicy.js +8 -7
- package/dist/OpenAIPolicy.d.ts +1 -1
- package/dist/OpenAIPolicy.d.ts.map +1 -1
- package/dist/OpenAIPolicy.js +35 -55
- package/dist/PipePolicy.d.ts +1 -1
- package/dist/PipePolicy.d.ts.map +1 -1
- package/dist/PipePolicy.js +16 -33
- package/dist/PowPolicy.d.ts +1 -1
- package/dist/PowPolicy.d.ts.map +1 -1
- package/dist/PowPolicy.js +25 -30
- package/dist/PubkeyBanPolicy.d.ts +1 -1
- package/dist/PubkeyBanPolicy.d.ts.map +1 -1
- package/dist/PubkeyBanPolicy.js +16 -22
- package/dist/ReadOnlyPolicy.d.ts +1 -1
- package/dist/ReadOnlyPolicy.d.ts.map +1 -1
- package/dist/ReadOnlyPolicy.js +8 -7
- package/dist/RegexPolicy.d.ts +1 -1
- package/dist/RegexPolicy.d.ts.map +1 -1
- package/dist/RegexPolicy.js +14 -20
- package/dist/ReplyBotPolicy.d.ts +1 -1
- package/dist/ReplyBotPolicy.d.ts.map +1 -1
- package/dist/ReplyBotPolicy.js +39 -38
- package/dist/SizePolicy.d.ts +1 -1
- package/dist/SizePolicy.d.ts.map +1 -1
- package/dist/SizePolicy.js +17 -25
- package/dist/WhitelistPolicy.d.ts +1 -1
- package/dist/WhitelistPolicy.d.ts.map +1 -1
- package/dist/WhitelistPolicy.js +23 -29
- package/dist/WoTPolicy.d.ts +2 -2
- package/dist/WoTPolicy.d.ts.map +1 -1
- package/dist/WoTPolicy.js +34 -33
- package/dist/mod.d.ts +20 -20
- package/dist/mod.js +42 -21
- package/dist/mod.js.map +7 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/mod.ts +20 -20
- package/package.json +10 -6
- package/tsconfig.json +3 -1
- package/.turbo/daemon/7bb8240f68f7ad88-turbo.log.2025-07-29 +0 -0
- package/dist/AntiDuplicationPolicy.js.map +0 -1
- package/dist/AnyPolicy.js.map +0 -1
- package/dist/AuthorPolicy.js.map +0 -1
- package/dist/DomainPolicy.js.map +0 -1
- package/dist/FiltersPolicy.js.map +0 -1
- package/dist/HashtagPolicy.js.map +0 -1
- package/dist/HellthreadPolicy.js.map +0 -1
- package/dist/InvertPolicy.js.map +0 -1
- package/dist/KeywordPolicy.js.map +0 -1
- package/dist/NoOpPolicy.js.map +0 -1
- package/dist/OpenAIPolicy.js.map +0 -1
- package/dist/PipePolicy.js.map +0 -1
- package/dist/PowPolicy.js.map +0 -1
- package/dist/PubkeyBanPolicy.js.map +0 -1
- package/dist/ReadOnlyPolicy.js.map +0 -1
- package/dist/RegexPolicy.js.map +0 -1
- package/dist/ReplyBotPolicy.js.map +0 -1
- package/dist/SizePolicy.js.map +0 -1
- package/dist/WhitelistPolicy.js.map +0 -1
- package/dist/WoTPolicy.js.map +0 -1
package/SizePolicy.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
1
|
+
import type { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
2
2
|
|
|
3
3
|
/** Policy options for `SizePolicy`. */
|
|
4
4
|
interface SizePolicyOpts {
|
|
@@ -17,7 +17,11 @@ interface SizePolicyOpts {
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export class SizePolicy implements NPolicy {
|
|
20
|
-
|
|
20
|
+
private opts: SizePolicyOpts;
|
|
21
|
+
|
|
22
|
+
constructor(opts: SizePolicyOpts = {}) {
|
|
23
|
+
this.opts = opts;
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
// deno-lint-ignore require-await
|
|
23
27
|
async call(event: NostrEvent): Promise<NostrRelayOK> {
|
package/WhitelistPolicy.test.ts
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { deepStrictEqual } from "node:assert";
|
|
3
|
+
import { finalizeEvent, generateSecretKey } from "nostr-tools";
|
|
3
4
|
|
|
4
|
-
import { WhitelistPolicy } from
|
|
5
|
+
import { WhitelistPolicy } from "./WhitelistPolicy.ts";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
await test("WhitelistPolicy", async () => {
|
|
7
8
|
const [event1, event2, event3] = new Array(3).fill(0).map(() => {
|
|
8
9
|
return finalizeEvent(
|
|
9
|
-
{ kind: 1, content:
|
|
10
|
+
{ kind: 1, content: "", tags: [], created_at: 0 },
|
|
10
11
|
generateSecretKey(),
|
|
11
12
|
);
|
|
12
13
|
});
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
deepStrictEqual((await new WhitelistPolicy([]).call(event1))[2], false);
|
|
16
|
+
deepStrictEqual(
|
|
17
|
+
(await new WhitelistPolicy([event2.pubkey, event1.pubkey]).call(event3))[2],
|
|
18
|
+
false,
|
|
19
|
+
);
|
|
20
|
+
deepStrictEqual(
|
|
21
|
+
(await new WhitelistPolicy([event2.pubkey, event1.pubkey]).call(event2))[2],
|
|
22
|
+
true,
|
|
23
|
+
);
|
|
17
24
|
});
|
package/WhitelistPolicy.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NostrEvent, NostrRelayInfo, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
1
|
+
import type { NostrEvent, NostrRelayInfo, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Allows only the listed pubkeys to post. All other events are rejected.
|
|
@@ -9,7 +9,11 @@ import { NostrEvent, NostrRelayInfo, NostrRelayOK, NPolicy } from '@nostrify/typ
|
|
|
9
9
|
* ```
|
|
10
10
|
*/
|
|
11
11
|
export class WhitelistPolicy implements NPolicy {
|
|
12
|
-
|
|
12
|
+
private pubkeys: Iterable<string>;
|
|
13
|
+
|
|
14
|
+
constructor(pubkeys: Iterable<string>) {
|
|
15
|
+
this.pubkeys = pubkeys;
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
// deno-lint-ignore require-await
|
|
15
19
|
async call({ id, pubkey }: NostrEvent): Promise<NostrRelayOK> {
|
package/WoTPolicy.test.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { ErrorRelay, genEvent, MockRelay } from "@nostrify/nostrify/test";
|
|
3
|
+
import { ok } from "node:assert";
|
|
4
|
+
import { generateSecretKey, getPublicKey } from "nostr-tools";
|
|
4
5
|
|
|
5
|
-
import { WoTPolicy } from
|
|
6
|
+
import { WoTPolicy } from "./WoTPolicy.ts";
|
|
6
7
|
|
|
7
8
|
function keygen(): { pubkey: string; seckey: Uint8Array } {
|
|
8
9
|
const seckey = generateSecretKey();
|
|
@@ -10,26 +11,51 @@ function keygen(): { pubkey: string; seckey: Uint8Array } {
|
|
|
10
11
|
return { pubkey, seckey };
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
await test("WoTPolicy", async () => {
|
|
14
15
|
const store = new MockRelay();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
try {
|
|
17
|
+
const [alex, patrick, fiatjaf, replyguy] = [
|
|
18
|
+
keygen(),
|
|
19
|
+
keygen(),
|
|
20
|
+
keygen(),
|
|
21
|
+
keygen(),
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
await store.event(
|
|
25
|
+
genEvent({ kind: 3, tags: [["p", patrick.pubkey]] }, alex.seckey),
|
|
26
|
+
);
|
|
27
|
+
await store.event(
|
|
28
|
+
genEvent({ kind: 3, tags: [["p", fiatjaf.pubkey]] }, patrick.seckey),
|
|
29
|
+
);
|
|
30
|
+
await store.event(
|
|
31
|
+
genEvent({ kind: 3, tags: [["p", patrick.pubkey]] }, fiatjaf.seckey),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const policy = new WoTPolicy({ store, pubkeys: [alex.pubkey], depth: 2 });
|
|
35
|
+
|
|
36
|
+
ok((await policy.call(genEvent({}, alex.seckey)))[2]);
|
|
37
|
+
ok((await policy.call(genEvent({}, patrick.seckey)))[2]);
|
|
38
|
+
ok((await policy.call(genEvent({}, fiatjaf.seckey)))[2]);
|
|
39
|
+
ok(!(await policy.call(genEvent({}, replyguy.seckey)))[2]);
|
|
40
|
+
} finally {
|
|
41
|
+
await store.close();
|
|
42
|
+
}
|
|
27
43
|
});
|
|
28
44
|
|
|
29
|
-
|
|
45
|
+
await test("WoTPolicy constructor with error store", async () => {
|
|
30
46
|
const store = new ErrorRelay();
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
try {
|
|
48
|
+
const alex = keygen();
|
|
49
|
+
|
|
50
|
+
// Ensure this doesn't result in an unhandled promise rejection.
|
|
51
|
+
new WoTPolicy({ store, pubkeys: [alex.pubkey], depth: 1 });
|
|
52
|
+
} catch {
|
|
53
|
+
// Expected, ErrorRelay throws errors intentionally
|
|
54
|
+
} finally {
|
|
55
|
+
try {
|
|
56
|
+
await store.close();
|
|
57
|
+
} catch {
|
|
58
|
+
// Expected, ErrorRelay.close() throws an error intentionally
|
|
59
|
+
}
|
|
60
|
+
}
|
|
35
61
|
});
|
package/WoTPolicy.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NostrEvent, NostrRelayOK, NPolicy, NStore } from '@nostrify/types';
|
|
1
|
+
import type { NostrEvent, NostrRelayOK, NPolicy, NStore } from '@nostrify/types';
|
|
2
2
|
|
|
3
3
|
/** Options for the `WoTPolicy`. */
|
|
4
4
|
interface WoTPolicyOpts {
|
|
@@ -18,8 +18,11 @@ interface WoTPolicyOpts {
|
|
|
18
18
|
/** Whitelist pubkeys the given user follows, people those users follow, etc. up to `depth`. */
|
|
19
19
|
export class WoTPolicy implements NPolicy {
|
|
20
20
|
private pubkeys: Promise<Set<string>> | undefined;
|
|
21
|
+
private opts: WoTPolicyOpts;
|
|
21
22
|
|
|
22
|
-
constructor(
|
|
23
|
+
constructor(opts: WoTPolicyOpts) {
|
|
24
|
+
this.opts = opts;
|
|
25
|
+
}
|
|
23
26
|
|
|
24
27
|
async call(event: NostrEvent): Promise<NostrRelayOK> {
|
|
25
28
|
this.pubkeys ??= this.getPubkeys();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
2
|
-
import { Kv } from '@deno/kv';
|
|
1
|
+
import type { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
2
|
+
import type { Kv } from '@deno/kv';
|
|
3
3
|
/** Policy options for `AntiDuplicationPolicy`. */
|
|
4
4
|
interface AntiDuplicationPolicyOpts {
|
|
5
5
|
/** Deno.Kv implementation to use. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AntiDuplicationPolicy.d.ts","sourceRoot":"","sources":["../AntiDuplicationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"AntiDuplicationPolicy.d.ts","sourceRoot":"","sources":["../AntiDuplicationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,EAAE,EAAS,MAAM,UAAU,CAAC;AAE1C,kDAAkD;AAClD,UAAU,yBAAyB;IACjC,qCAAqC;IACrC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;IAC5B,qGAAqG;IACrG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qJAAqJ;IACrJ,WAAW,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,qBAAsB,YAAW,OAAO;IACnD,OAAO,CAAC,IAAI,CAA4B;gBAE5B,IAAI,EAAE,yBAAyB;IAIrC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA4BpD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ;CASxB"}
|
|
@@ -1,59 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
class AntiDuplicationPolicy {
|
|
2
|
+
opts;
|
|
3
|
+
constructor(opts) {
|
|
4
|
+
this.opts = opts;
|
|
5
|
+
}
|
|
6
|
+
async call(event) {
|
|
7
|
+
const { id, kind } = event;
|
|
8
|
+
const { kv, expireIn = 6e4, minLength = 50, deobfuscate } = this.opts;
|
|
9
|
+
const content = deobfuscate?.(event) ?? event.content;
|
|
10
|
+
if (kind === 1 && content.length >= minLength) {
|
|
11
|
+
const hash = AntiDuplicationPolicy.hashCode(content);
|
|
12
|
+
const key = ["nostrify", "policies", "antiduplication", hash];
|
|
13
|
+
const { value } = await kv.get(key);
|
|
14
|
+
if (value) {
|
|
15
|
+
await kv.set(key, true, { expireIn });
|
|
16
|
+
return [
|
|
17
|
+
"OK",
|
|
18
|
+
id,
|
|
19
|
+
false,
|
|
20
|
+
"blocked: the same message has been repeated too many times"
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
await kv.set(key, true, { expireIn });
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
false,
|
|
37
|
-
'blocked: the same message has been repeated too many times',
|
|
38
|
-
];
|
|
39
|
-
}
|
|
40
|
-
await kv.set(key, true, { expireIn });
|
|
41
|
-
}
|
|
42
|
-
return ['OK', id, true, ''];
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Get a "good enough" unique identifier for this content.
|
|
46
|
-
* This algorithm was chosen because it's very fast with a low chance of collisions.
|
|
47
|
-
* https://stackoverflow.com/a/8831937
|
|
48
|
-
*/
|
|
49
|
-
static hashCode(str) {
|
|
50
|
-
let hash = 0;
|
|
51
|
-
for (let i = 0, len = str.length; i < len; i++) {
|
|
52
|
-
const chr = str.charCodeAt(i);
|
|
53
|
-
hash = (hash << 5) - hash + chr;
|
|
54
|
-
hash |= 0; // Convert to 32bit integer
|
|
55
|
-
}
|
|
56
|
-
return hash;
|
|
25
|
+
return ["OK", id, true, ""];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get a "good enough" unique identifier for this content.
|
|
29
|
+
* This algorithm was chosen because it's very fast with a low chance of collisions.
|
|
30
|
+
* https://stackoverflow.com/a/8831937
|
|
31
|
+
*/
|
|
32
|
+
static hashCode(str) {
|
|
33
|
+
let hash = 0;
|
|
34
|
+
for (let i = 0, len = str.length; i < len; i++) {
|
|
35
|
+
const chr = str.charCodeAt(i);
|
|
36
|
+
hash = (hash << 5) - hash + chr;
|
|
37
|
+
hash |= 0;
|
|
57
38
|
}
|
|
39
|
+
return hash;
|
|
40
|
+
}
|
|
58
41
|
}
|
|
59
|
-
|
|
42
|
+
export {
|
|
43
|
+
AntiDuplicationPolicy
|
|
44
|
+
};
|
package/dist/AnyPolicy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
1
|
+
import type { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/types';
|
|
2
2
|
/** Similar to `PipePolicy`, but passes if at least one policy passes. */
|
|
3
3
|
export declare class AnyPolicy implements NPolicy {
|
|
4
4
|
private policies;
|
package/dist/AnyPolicy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnyPolicy.d.ts","sourceRoot":"","sources":["../AnyPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"AnyPolicy.d.ts","sourceRoot":"","sources":["../AnyPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEzE,yEAAyE;AACzE,qBAAa,SAAU,YAAW,OAAO;IACvC,OAAO,CAAC,QAAQ,CAAY;gBAChB,QAAQ,EAAE,OAAO,EAAE;IAIzB,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAc3E"}
|
package/dist/AnyPolicy.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (ok) {
|
|
13
|
-
return result;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
1
|
+
class AnyPolicy {
|
|
2
|
+
policies;
|
|
3
|
+
constructor(policies) {
|
|
4
|
+
this.policies = policies;
|
|
5
|
+
}
|
|
6
|
+
async call(event, signal) {
|
|
7
|
+
let result = ["OK", event.id, false, "blocked: no policy passed"];
|
|
8
|
+
for (const policy of this.policies) {
|
|
9
|
+
result = await policy.call(event, signal);
|
|
10
|
+
const ok = result[2];
|
|
11
|
+
if (ok) {
|
|
16
12
|
return result;
|
|
13
|
+
}
|
|
17
14
|
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
18
17
|
}
|
|
19
|
-
|
|
18
|
+
export {
|
|
19
|
+
AnyPolicy
|
|
20
|
+
};
|
package/dist/AuthorPolicy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NostrEvent, NostrRelayOK, NPolicy, NStore } from '@nostrify/types';
|
|
1
|
+
import type { NostrEvent, NostrRelayOK, NPolicy, NStore } from '@nostrify/types';
|
|
2
2
|
/** Rejects events by authors without a kind 0, then optionally applies another policy to the kind 0. */
|
|
3
3
|
export declare class AuthorPolicy implements NPolicy {
|
|
4
4
|
private store;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthorPolicy.d.ts","sourceRoot":"","sources":["../AuthorPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthorPolicy.d.ts","sourceRoot":"","sources":["../AuthorPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEjF,wGAAwG;AACxG,qBAAa,YAAa,YAAW,OAAO;IAC1C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAC,CAAU;gBAEb,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO;IAKrC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAgB3E"}
|
package/dist/AuthorPolicy.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
class AuthorPolicy {
|
|
2
|
+
store;
|
|
3
|
+
policy;
|
|
4
|
+
constructor(store, policy) {
|
|
5
|
+
this.store = store;
|
|
6
|
+
this.policy = policy;
|
|
7
|
+
}
|
|
8
|
+
async call(event, signal) {
|
|
9
|
+
const author = event.kind === 0 ? event : await this.store.query([{ kinds: [0], authors: [event.pubkey], limit: 1 }], { signal }).then(([event2]) => event2);
|
|
10
|
+
if (!author) {
|
|
11
|
+
return ["OK", event.id, false, "blocked: author is missing a kind 0 event"];
|
|
8
12
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
.then(([event]) => event);
|
|
13
|
-
if (!author) {
|
|
14
|
-
return ['OK', event.id, false, 'blocked: author is missing a kind 0 event'];
|
|
15
|
-
}
|
|
16
|
-
if (this.policy) {
|
|
17
|
-
const [, , ok, reason] = await this.policy.call(author, signal);
|
|
18
|
-
return ['OK', event.id, ok, reason];
|
|
19
|
-
}
|
|
20
|
-
return ['OK', event.id, true, ''];
|
|
13
|
+
if (this.policy) {
|
|
14
|
+
const [, , ok, reason] = await this.policy.call(author, signal);
|
|
15
|
+
return ["OK", event.id, ok, reason];
|
|
21
16
|
}
|
|
17
|
+
return ["OK", event.id, true, ""];
|
|
18
|
+
}
|
|
22
19
|
}
|
|
23
|
-
|
|
20
|
+
export {
|
|
21
|
+
AuthorPolicy
|
|
22
|
+
};
|
package/dist/DomainPolicy.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NPolicy, NProfilePointer, NStore } from '@nostrify/types';
|
|
2
|
-
import { AuthorPolicy } from './AuthorPolicy.
|
|
1
|
+
import type { NPolicy, NProfilePointer, NStore } from '@nostrify/types';
|
|
2
|
+
import { AuthorPolicy } from './AuthorPolicy.ts';
|
|
3
3
|
/** Options for `DomainPolicy`. */
|
|
4
4
|
interface DomainPolicyOpts {
|
|
5
5
|
/** Custom NIP-05 lookup function. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DomainPolicy.d.ts","sourceRoot":"","sources":["../DomainPolicy.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"DomainPolicy.d.ts","sourceRoot":"","sources":["../DomainPolicy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEpF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,kCAAkC;AAClC,UAAU,gBAAgB;IACxB,qCAAqC;IACrC,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACvE,0GAA0G;IAC1G,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,mIAAmI;IACnI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,8GAA8G;AAC9G,qBAAa,YAAa,SAAQ,YAAa,YAAW,OAAO;gBACnD,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB;IAmDtD,qFAAqF;IACrF,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAmBlC,wEAAwE;IACxE,OAAO,CAAC,MAAM,CAAC,MAAM;CAMtB"}
|
package/dist/DomainPolicy.js
CHANGED
|
@@ -1,64 +1,62 @@
|
|
|
1
|
-
import { NIP05, NSchema as n } from
|
|
2
|
-
import { AuthorPolicy } from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return ['OK', event.id, false, 'blocked: blacklisted nip05 domain'];
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
const { pubkey } = await lookup(nip05, signal);
|
|
26
|
-
if (pubkey !== event.pubkey) {
|
|
27
|
-
return ['OK', event.id, false, 'blocked: mismatched nip05 pubkey'];
|
|
28
|
-
}
|
|
29
|
-
if (whitelist && !whitelist.includes(domain)) {
|
|
30
|
-
return [
|
|
31
|
-
'OK',
|
|
32
|
-
event.id,
|
|
33
|
-
false,
|
|
34
|
-
'blocked: nip05 domain not in whitelist',
|
|
35
|
-
];
|
|
36
|
-
}
|
|
37
|
-
return ['OK', event.id, true, ''];
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
return ['OK', event.id, false, 'blocked: failed to lookup nip05'];
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
/** Check if a domain is blacklisted, including subdomains of blacklisted domains. */
|
|
46
|
-
static isDomainBlacklisted(domain, blacklist) {
|
|
47
|
-
// Check for exact match
|
|
48
|
-
if (blacklist.includes(domain)) {
|
|
49
|
-
return true;
|
|
1
|
+
import { NIP05, NSchema as n } from "@nostrify/nostrify";
|
|
2
|
+
import { AuthorPolicy } from "./AuthorPolicy.js";
|
|
3
|
+
class DomainPolicy extends AuthorPolicy {
|
|
4
|
+
constructor(store, opts = {}) {
|
|
5
|
+
super(store, {
|
|
6
|
+
async call(event, signal) {
|
|
7
|
+
const { blacklist = [], whitelist, lookup = DomainPolicy.lookup } = opts;
|
|
8
|
+
const metadata = n.json().pipe(n.metadata()).safeParse(event.content);
|
|
9
|
+
if (!metadata.success) {
|
|
10
|
+
return ["OK", event.id, false, "blocked: invalid kind 0 metadata"];
|
|
11
|
+
}
|
|
12
|
+
const { nip05 } = metadata.data;
|
|
13
|
+
if (!nip05) {
|
|
14
|
+
return ["OK", event.id, false, "blocked: missing nip05"];
|
|
15
|
+
}
|
|
16
|
+
const domain = nip05.split("@").pop();
|
|
17
|
+
if (!domain) {
|
|
18
|
+
return ["OK", event.id, false, "blocked: invalid nip05"];
|
|
19
|
+
}
|
|
20
|
+
if (DomainPolicy.isDomainBlacklisted(domain, blacklist)) {
|
|
21
|
+
return ["OK", event.id, false, "blocked: blacklisted nip05 domain"];
|
|
50
22
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
23
|
+
try {
|
|
24
|
+
const { pubkey } = await lookup(nip05, signal);
|
|
25
|
+
if (pubkey !== event.pubkey) {
|
|
26
|
+
return ["OK", event.id, false, "blocked: mismatched nip05 pubkey"];
|
|
27
|
+
}
|
|
28
|
+
if (whitelist && !whitelist.includes(domain)) {
|
|
29
|
+
return [
|
|
30
|
+
"OK",
|
|
31
|
+
event.id,
|
|
32
|
+
false,
|
|
33
|
+
"blocked: nip05 domain not in whitelist"
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
return ["OK", event.id, true, ""];
|
|
37
|
+
} catch {
|
|
38
|
+
return ["OK", event.id, false, "blocked: failed to lookup nip05"];
|
|
56
39
|
}
|
|
57
|
-
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** Check if a domain is blacklisted, including subdomains of blacklisted domains. */
|
|
44
|
+
static isDomainBlacklisted(domain, blacklist) {
|
|
45
|
+
if (blacklist.includes(domain)) {
|
|
46
|
+
return true;
|
|
58
47
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return
|
|
48
|
+
for (const blacklistedDomain of blacklist) {
|
|
49
|
+
if (domain.endsWith("." + blacklistedDomain)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
62
52
|
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
/** Default NIP-05 lookup method if one isn't provided by the caller. */
|
|
56
|
+
static lookup(nip05, signal) {
|
|
57
|
+
return NIP05.lookup(nip05, { signal });
|
|
58
|
+
}
|
|
63
59
|
}
|
|
64
|
-
|
|
60
|
+
export {
|
|
61
|
+
DomainPolicy
|
|
62
|
+
};
|
package/dist/FiltersPolicy.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FiltersPolicy.d.ts","sourceRoot":"","sources":["../FiltersPolicy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"FiltersPolicy.d.ts","sourceRoot":"","sources":["../FiltersPolicy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEtF;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO,CAAC,OAAO,CAAgB;gBACnB,OAAO,EAAE,WAAW,EAAE;IAK5B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;CAOrD"}
|
package/dist/FiltersPolicy.js
CHANGED
|
@@ -1,26 +1,17 @@
|
|
|
1
|
-
import { matchFilters } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
export class FiltersPolicy {
|
|
14
|
-
filters;
|
|
15
|
-
constructor(filters) {
|
|
16
|
-
this.filters = filters;
|
|
17
|
-
}
|
|
18
|
-
// deno-lint-ignore require-await
|
|
19
|
-
async call(event) {
|
|
20
|
-
if (matchFilters(this.filters, event)) {
|
|
21
|
-
return ['OK', event.id, true, ''];
|
|
22
|
-
}
|
|
23
|
-
return ['OK', event.id, false, "blocked: the event doesn't match the allowed filters"];
|
|
1
|
+
import { matchFilters } from "nostr-tools";
|
|
2
|
+
class FiltersPolicy {
|
|
3
|
+
filters;
|
|
4
|
+
constructor(filters) {
|
|
5
|
+
this.filters = filters;
|
|
6
|
+
}
|
|
7
|
+
// deno-lint-ignore require-await
|
|
8
|
+
async call(event) {
|
|
9
|
+
if (matchFilters(this.filters, event)) {
|
|
10
|
+
return ["OK", event.id, true, ""];
|
|
24
11
|
}
|
|
12
|
+
return ["OK", event.id, false, "blocked: the event doesn't match the allowed filters"];
|
|
13
|
+
}
|
|
25
14
|
}
|
|
26
|
-
|
|
15
|
+
export {
|
|
16
|
+
FiltersPolicy
|
|
17
|
+
};
|
package/dist/HashtagPolicy.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HashtagPolicy.d.ts","sourceRoot":"","sources":["../HashtagPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"HashtagPolicy.d.ts","sourceRoot":"","sources":["../HashtagPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;;;;;;GAQG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO,CAAC,QAAQ,CAAW;gBACf,QAAQ,EAAE,MAAM,EAAE;IAKxB,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;CAS5D"}
|