@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.
Files changed (132) hide show
  1. package/.turbo/turbo-build.log +28 -5
  2. package/.turbo/turbo-setup.log +22 -0
  3. package/.turbo/turbo-test.log +4 -0
  4. package/AntiDuplicationPolicy.test.ts +54 -41
  5. package/AntiDuplicationPolicy.ts +7 -3
  6. package/AnyPolicy.test.ts +15 -14
  7. package/AnyPolicy.ts +5 -2
  8. package/AuthorPolicy.test.ts +8 -7
  9. package/AuthorPolicy.ts +9 -3
  10. package/CHANGELOG.md +18 -0
  11. package/DomainPolicy.test.ts +130 -77
  12. package/DomainPolicy.ts +3 -3
  13. package/FiltersPolicy.test.ts +14 -7
  14. package/FiltersPolicy.ts +5 -2
  15. package/HashtagPolicy.test.ts +25 -14
  16. package/HashtagPolicy.ts +5 -2
  17. package/HellthreadPolicy.test.ts +10 -9
  18. package/HellthreadPolicy.ts +6 -3
  19. package/InvertPolicy.test.ts +10 -9
  20. package/InvertPolicy.ts +8 -2
  21. package/KeywordPolicy.test.ts +18 -12
  22. package/KeywordPolicy.ts +5 -2
  23. package/NoOpPolicy.test.ts +8 -7
  24. package/NoOpPolicy.ts +1 -1
  25. package/OpenAIPolicy.test.ts +22 -9
  26. package/OpenAIPolicy.ts +5 -2
  27. package/PipePolicy.test.ts +18 -17
  28. package/PipePolicy.ts +5 -2
  29. package/PowPolicy.test.ts +14 -13
  30. package/PowPolicy.ts +6 -3
  31. package/PubkeyBanPolicy.test.ts +15 -8
  32. package/PubkeyBanPolicy.ts +5 -2
  33. package/ReadOnlyPolicy.test.ts +9 -8
  34. package/ReadOnlyPolicy.ts +1 -1
  35. package/RegexPolicy.test.ts +19 -10
  36. package/RegexPolicy.ts +5 -2
  37. package/ReplyBotPolicy.test.ts +43 -27
  38. package/ReplyBotPolicy.ts +6 -3
  39. package/SizePolicy.test.ts +9 -8
  40. package/SizePolicy.ts +6 -2
  41. package/WhitelistPolicy.test.ts +15 -8
  42. package/WhitelistPolicy.ts +6 -2
  43. package/WoTPolicy.test.ts +48 -22
  44. package/WoTPolicy.ts +5 -2
  45. package/dist/AntiDuplicationPolicy.d.ts +2 -2
  46. package/dist/AntiDuplicationPolicy.d.ts.map +1 -1
  47. package/dist/AntiDuplicationPolicy.js +41 -56
  48. package/dist/AnyPolicy.d.ts +1 -1
  49. package/dist/AnyPolicy.d.ts.map +1 -1
  50. package/dist/AnyPolicy.js +17 -16
  51. package/dist/AuthorPolicy.d.ts +1 -1
  52. package/dist/AuthorPolicy.d.ts.map +1 -1
  53. package/dist/AuthorPolicy.js +19 -20
  54. package/dist/DomainPolicy.d.ts +2 -2
  55. package/dist/DomainPolicy.d.ts.map +1 -1
  56. package/dist/DomainPolicy.js +57 -59
  57. package/dist/FiltersPolicy.d.ts +1 -1
  58. package/dist/FiltersPolicy.d.ts.map +1 -1
  59. package/dist/FiltersPolicy.js +15 -24
  60. package/dist/HashtagPolicy.d.ts +1 -1
  61. package/dist/HashtagPolicy.d.ts.map +1 -1
  62. package/dist/HashtagPolicy.js +16 -23
  63. package/dist/HellthreadPolicy.d.ts +1 -1
  64. package/dist/HellthreadPolicy.d.ts.map +1 -1
  65. package/dist/HellthreadPolicy.js +18 -17
  66. package/dist/InvertPolicy.d.ts +1 -1
  67. package/dist/InvertPolicy.d.ts.map +1 -1
  68. package/dist/InvertPolicy.js +18 -18
  69. package/dist/KeywordPolicy.d.ts +1 -1
  70. package/dist/KeywordPolicy.d.ts.map +1 -1
  71. package/dist/KeywordPolicy.js +16 -23
  72. package/dist/NoOpPolicy.d.ts +1 -1
  73. package/dist/NoOpPolicy.d.ts.map +1 -1
  74. package/dist/NoOpPolicy.js +8 -7
  75. package/dist/OpenAIPolicy.d.ts +1 -1
  76. package/dist/OpenAIPolicy.d.ts.map +1 -1
  77. package/dist/OpenAIPolicy.js +35 -55
  78. package/dist/PipePolicy.d.ts +1 -1
  79. package/dist/PipePolicy.d.ts.map +1 -1
  80. package/dist/PipePolicy.js +16 -33
  81. package/dist/PowPolicy.d.ts +1 -1
  82. package/dist/PowPolicy.d.ts.map +1 -1
  83. package/dist/PowPolicy.js +25 -30
  84. package/dist/PubkeyBanPolicy.d.ts +1 -1
  85. package/dist/PubkeyBanPolicy.d.ts.map +1 -1
  86. package/dist/PubkeyBanPolicy.js +16 -22
  87. package/dist/ReadOnlyPolicy.d.ts +1 -1
  88. package/dist/ReadOnlyPolicy.d.ts.map +1 -1
  89. package/dist/ReadOnlyPolicy.js +8 -7
  90. package/dist/RegexPolicy.d.ts +1 -1
  91. package/dist/RegexPolicy.d.ts.map +1 -1
  92. package/dist/RegexPolicy.js +14 -20
  93. package/dist/ReplyBotPolicy.d.ts +1 -1
  94. package/dist/ReplyBotPolicy.d.ts.map +1 -1
  95. package/dist/ReplyBotPolicy.js +39 -38
  96. package/dist/SizePolicy.d.ts +1 -1
  97. package/dist/SizePolicy.d.ts.map +1 -1
  98. package/dist/SizePolicy.js +17 -25
  99. package/dist/WhitelistPolicy.d.ts +1 -1
  100. package/dist/WhitelistPolicy.d.ts.map +1 -1
  101. package/dist/WhitelistPolicy.js +23 -29
  102. package/dist/WoTPolicy.d.ts +2 -2
  103. package/dist/WoTPolicy.d.ts.map +1 -1
  104. package/dist/WoTPolicy.js +34 -33
  105. package/dist/mod.d.ts +20 -20
  106. package/dist/mod.js +42 -21
  107. package/dist/mod.js.map +7 -1
  108. package/dist/tsconfig.tsbuildinfo +1 -1
  109. package/mod.ts +20 -20
  110. package/package.json +10 -6
  111. package/tsconfig.json +3 -1
  112. package/.turbo/daemon/7bb8240f68f7ad88-turbo.log.2025-07-29 +0 -0
  113. package/dist/AntiDuplicationPolicy.js.map +0 -1
  114. package/dist/AnyPolicy.js.map +0 -1
  115. package/dist/AuthorPolicy.js.map +0 -1
  116. package/dist/DomainPolicy.js.map +0 -1
  117. package/dist/FiltersPolicy.js.map +0 -1
  118. package/dist/HashtagPolicy.js.map +0 -1
  119. package/dist/HellthreadPolicy.js.map +0 -1
  120. package/dist/InvertPolicy.js.map +0 -1
  121. package/dist/KeywordPolicy.js.map +0 -1
  122. package/dist/NoOpPolicy.js.map +0 -1
  123. package/dist/OpenAIPolicy.js.map +0 -1
  124. package/dist/PipePolicy.js.map +0 -1
  125. package/dist/PowPolicy.js.map +0 -1
  126. package/dist/PubkeyBanPolicy.js.map +0 -1
  127. package/dist/ReadOnlyPolicy.js.map +0 -1
  128. package/dist/RegexPolicy.js.map +0 -1
  129. package/dist/ReplyBotPolicy.js.map +0 -1
  130. package/dist/SizePolicy.js.map +0 -1
  131. package/dist/WhitelistPolicy.js.map +0 -1
  132. 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
- constructor(private opts: SizePolicyOpts = {}) {}
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> {
@@ -1,17 +1,24 @@
1
- import { assertEquals } from '@std/assert';
2
- import { finalizeEvent, generateSecretKey } from 'nostr-tools';
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 './WhitelistPolicy.ts';
5
+ import { WhitelistPolicy } from "./WhitelistPolicy.ts";
5
6
 
6
- Deno.test('WhitelistPolicy', async () => {
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: '', tags: [], created_at: 0 },
10
+ { kind: 1, content: "", tags: [], created_at: 0 },
10
11
  generateSecretKey(),
11
12
  );
12
13
  });
13
14
 
14
- assertEquals((await new WhitelistPolicy([]).call(event1))[2], false);
15
- assertEquals((await new WhitelistPolicy([event2.pubkey, event1.pubkey]).call(event3))[2], false);
16
- assertEquals((await new WhitelistPolicy([event2.pubkey, event1.pubkey]).call(event2))[2], true);
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
  });
@@ -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
- constructor(private pubkeys: Iterable<string>) {}
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 { ErrorRelay, genEvent, MockRelay } from '@nostrify/nostrify/test';
2
- import { assert, assertFalse } from '@std/assert';
3
- import { generateSecretKey, getPublicKey } from 'nostr-tools';
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 './WoTPolicy.ts';
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
- Deno.test('WoTPolicy', async () => {
14
+ await test("WoTPolicy", async () => {
14
15
  const store = new MockRelay();
15
- const [alex, patrick, fiatjaf, replyguy] = [keygen(), keygen(), keygen(), keygen()];
16
-
17
- await store.event(genEvent({ kind: 3, tags: [['p', patrick.pubkey]] }, alex.seckey));
18
- await store.event(genEvent({ kind: 3, tags: [['p', fiatjaf.pubkey]] }, patrick.seckey));
19
- await store.event(genEvent({ kind: 3, tags: [['p', patrick.pubkey]] }, fiatjaf.seckey));
20
-
21
- const policy = new WoTPolicy({ store, pubkeys: [alex.pubkey], depth: 2 });
22
-
23
- assert((await policy.call(genEvent({}, alex.seckey)))[2]);
24
- assert((await policy.call(genEvent({}, patrick.seckey)))[2]);
25
- assert((await policy.call(genEvent({}, fiatjaf.seckey)))[2]);
26
- assertFalse((await policy.call(genEvent({}, replyguy.seckey)))[2]);
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
- Deno.test('WoTPolicy constructor with error store', () => {
45
+ await test("WoTPolicy constructor with error store", async () => {
30
46
  const store = new ErrorRelay();
31
- const alex = keygen();
32
-
33
- // Ensure this doesn't result in an unhandled promise rejection.
34
- new WoTPolicy({ store, pubkeys: [alex.pubkey], depth: 1 });
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(private opts: WoTPolicyOpts) {}
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;AACpE,OAAO,EAAE,EAAE,EAAS,MAAM,UAAU,CAAC;AAErC,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;IACvC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,yBAAyB;IAE7C,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA4BpD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ;CASxB"}
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
- * Prevent messages with the exact same content from being submitted repeatedly.
3
- *
4
- * It stores a hashcode for each content in a Deno.Kv database and rate-limits them. Only messages that meet the minimum length criteria are selected.
5
- * Each time a matching message is submitted, the timer will reset, so spammers sending the same message will only ever get the first one through.
6
- *
7
- * ```ts
8
- * // Open a Deno.KV instance.
9
- * const kv = await Deno.openKv();
10
- *
11
- * // Prevent the same message from being posted within 60 seconds.
12
- * new AntiDuplicationPolicy({ kv, expireIn: 60000 });
13
- *
14
- * // Only enforce the policy on messages with at least 50 characters.
15
- * new AntiDuplicationPolicy({ kv, expireIn: 60000, minLength: 50 });
16
- * ```
17
- */
18
- export class AntiDuplicationPolicy {
19
- opts;
20
- constructor(opts) {
21
- this.opts = opts;
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
- async call(event) {
24
- const { id, kind } = event;
25
- const { kv, expireIn = 60000, minLength = 50, deobfuscate } = this.opts;
26
- const content = deobfuscate?.(event) ?? event.content;
27
- if (kind === 1 && content.length >= minLength) {
28
- const hash = AntiDuplicationPolicy.hashCode(content);
29
- const key = ['nostrify', 'policies', 'antiduplication', hash];
30
- const { value } = await kv.get(key);
31
- if (value) {
32
- await kv.set(key, true, { expireIn });
33
- return [
34
- 'OK',
35
- id,
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
- //# sourceMappingURL=AntiDuplicationPolicy.js.map
42
+ export {
43
+ AntiDuplicationPolicy
44
+ };
@@ -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;
@@ -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;AAEpE,yEAAyE;AACzE,qBAAa,SAAU,YAAW,OAAO;IAC3B,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,OAAO,EAAE;IAEjC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAc3E"}
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
- /** Similar to `PipePolicy`, but passes if at least one policy passes. */
2
- export class AnyPolicy {
3
- policies;
4
- constructor(policies) {
5
- this.policies = policies;
6
- }
7
- async call(event, signal) {
8
- let result = ['OK', event.id, false, 'blocked: no policy passed'];
9
- for (const policy of this.policies) {
10
- result = await policy.call(event, signal);
11
- const ok = result[2];
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
- //# sourceMappingURL=AnyPolicy.js.map
18
+ export {
19
+ AnyPolicy
20
+ };
@@ -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;AAE5E,wGAAwG;AACxG,qBAAa,YAAa,YAAW,OAAO;IAC9B,OAAO,CAAC,KAAK;IAAU,OAAO,CAAC,MAAM,CAAC;gBAA9B,KAAK,EAAE,MAAM,EAAU,MAAM,CAAC,EAAE,OAAO;IAErD,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAgB3E"}
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"}
@@ -1,23 +1,22 @@
1
- /** Rejects events by authors without a kind 0, then optionally applies another policy to the kind 0. */
2
- export class AuthorPolicy {
3
- store;
4
- policy;
5
- constructor(store, policy) {
6
- this.store = store;
7
- this.policy = policy;
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
- async call(event, signal) {
10
- const author = event.kind === 0 ? event : await this.store
11
- .query([{ kinds: [0], authors: [event.pubkey], limit: 1 }], { signal })
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
- //# sourceMappingURL=AuthorPolicy.js.map
20
+ export {
21
+ AuthorPolicy
22
+ };
@@ -1,5 +1,5 @@
1
- import { NPolicy, NProfilePointer, NStore } from '@nostrify/types';
2
- import { AuthorPolicy } from './AuthorPolicy.js';
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,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEnE,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"}
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"}
@@ -1,64 +1,62 @@
1
- import { NIP05, NSchema as n } from '@nostrify/nostrify';
2
- import { AuthorPolicy } from './AuthorPolicy.js';
3
- /** Ban events unless their author has a valid NIP-05 name. Domains can also be whitelisted or blacklisted. */
4
- export class DomainPolicy extends AuthorPolicy {
5
- constructor(store, opts = {}) {
6
- super(store, {
7
- async call(event, signal) {
8
- const { blacklist = [], whitelist, lookup = DomainPolicy.lookup } = opts;
9
- const metadata = n.json().pipe(n.metadata()).safeParse(event.content);
10
- if (!metadata.success) {
11
- return ['OK', event.id, false, 'blocked: invalid kind 0 metadata'];
12
- }
13
- const { nip05 } = metadata.data;
14
- if (!nip05) {
15
- return ['OK', event.id, false, 'blocked: missing nip05'];
16
- }
17
- const domain = nip05.split('@').pop();
18
- if (!domain) {
19
- return ['OK', event.id, false, 'blocked: invalid nip05'];
20
- }
21
- if (DomainPolicy.isDomainBlacklisted(domain, blacklist)) {
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
- // Check if domain is a subdomain of any blacklisted domain
52
- for (const blacklistedDomain of blacklist) {
53
- if (domain.endsWith('.' + blacklistedDomain)) {
54
- return true;
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
- return false;
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
- /** Default NIP-05 lookup method if one isn't provided by the caller. */
60
- static lookup(nip05, signal) {
61
- return NIP05.lookup(nip05, { signal });
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
- //# sourceMappingURL=DomainPolicy.js.map
60
+ export {
61
+ DomainPolicy
62
+ };
@@ -1,4 +1,4 @@
1
- import { NostrEvent, NostrFilter, NostrRelayOK, NPolicy } from '@nostrify/types';
1
+ import type { NostrEvent, NostrFilter, NostrRelayOK, NPolicy } from '@nostrify/types';
2
2
  /**
3
3
  * Reject events which don't match the filters.
4
4
  *
@@ -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;AAEjF;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC/B,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW,EAAE;IAGpC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;CAOrD"}
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"}
@@ -1,26 +1,17 @@
1
- import { matchFilters } from 'nostr-tools';
2
- /**
3
- * Reject events which don't match the filters.
4
- *
5
- * Only messages which **match** the filters are allowed, and all others are dropped.
6
- * The filter is a [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) relay filter.
7
- *
8
- * ```ts
9
- * // Only allow kind 1, 3, 5, and 7 events.
10
- * new FiltersPolicy([{ kinds: [0, 1, 3, 5, 6, 7] }]);
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
- //# sourceMappingURL=FiltersPolicy.js.map
15
+ export {
16
+ FiltersPolicy
17
+ };
@@ -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
  * Reject events containing any of the banned hashtags.
4
4
  *
@@ -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;AAEpE;;;;;;;;GAQG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC/B,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM,EAAE;IAGhC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;CAS5D"}
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"}