diff --git a/deno.lock b/deno.lock index 975a6ba..af01131 100644 --- a/deno.lock +++ b/deno.lock @@ -1,6 +1,122 @@ { "version": "2", "remote": { + "https://deno.land/std@0.177.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", + "https://deno.land/std@0.177.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", + "https://deno.land/std@0.177.0/bytes/index_of_needle.ts": "65c939607df609374c4415598fa4dad04a2f14c4d98cd15775216f0aaf597f24", + "https://deno.land/std@0.177.0/crypto/_wasm/lib/deno_std_wasm_crypto.generated.mjs": "5dedb7f9aa05f0e18ed017691c58df5f4686e4cbbd70368c6f896e5cca03f2b4", + "https://deno.land/std@0.177.0/crypto/_wasm/mod.ts": "e2df88236fc061eac7a89e8cb0b97843f5280b08b2a990e473b7397a3e566003", + "https://deno.land/std@0.177.0/crypto/timing_safe_equal.ts": "8d69ab611c67fe51b6127d97fcfb4d8e7d0e1b6b4f3e0cc4ab86744c3691f965", + "https://deno.land/std@0.177.0/encoding/base64.ts": "7de04c2f8aeeb41453b09b186480be90f2ff357613b988e99fabb91d2eeceba1", + "https://deno.land/std@0.177.0/encoding/base64url.ts": "3f1178f6446834457b16bfde8b559c1cd3481727fe384d3385e4a9995dc2d851", + "https://deno.land/std@0.177.0/encoding/hex.ts": "50f8c95b52eae24395d3dfcb5ec1ced37c5fe7610ef6fffdcc8b0fdc38e3b32f", + "https://deno.land/std@0.177.0/flags/mod.ts": "d1cdefa18472ef69858a17df5cf7c98445ed27ac10e1460183081303b0ebc270", + "https://deno.land/std@0.177.0/node/_core.ts": "9a58c0ef98ee77e9b8fcc405511d1b37a003a705eb6a9b6e95f75434d8009adc", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/base/buffer.js": "c9364c761681134015ec8ba6f33b39c067d6e5dd59860d55face8d5be8522744", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/base/node.js": "8f7f23bfa300990bbd6db7e7395e9688b54a04e3eb2fab5cab9a9a72e26c525f", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/base/reporter.js": "788aec7662991da549e5f7f3edbc3e3d6c6cecabc894b18d1a705b0f204e06c3", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/constants/der.js": "57181db0519bb3864a6cdf4e7eb9bfeb1bf5f80605187fbe80e27083b473e367", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/decoders/der.js": "fdc4de98c9b0b59db169a2b225895741e2ab34b00e14315ac2ff5e389d6db16e", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/decoders/pem.js": "fd7f0072c193c82959fec0374f4fd3adf3f4ac38594fd404d66b3e8724107151", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/encoders/der.js": "137bc4f8fe66b9950c743025e199789e25342f791e2d52353ceb016ad2854b42", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/encoders/pem.js": "e43bc706973c4c27e1e2f96262daba3d38822cb10f5b494f6944c726ee655160", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/asn1.js/mod.js": "1f88293688296be7a6c735bd8ea39425f5b274b94db1d6b7968dddfb54ac9d37", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/bn.js/bn.js": "f3f3c1dae1aa55de9e6472af1d6bec5ccda4b4890ee5c52a90961137fe99564e", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/aes.js": "698e1ed386b7dff27b2d59fa1c75f506beceec96b78670a15a734e438c08f138", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/auth_cipher.js": "5c245b5685b066356a7c9529a3a441bf5f57823a6946ce1b0ef2e1af32bb76f4", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/decrypter.js": "39152b2b3409893b8548feeab7e5997ceb1595f31df0dedaf765708be8f025c0", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/encrypter.js": "f9cc703d5a7b5255999c1a3600fbf48ff564b65f827744877526803093ceebff", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/ghash.js": "759d80b760f44cd3a454b4f161fd03a7d6c359901446f0a907a6870cb66d6767", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/incr32.js": "2bdea27b74b3990ee56807a1a5abe335f118826beabeeb905459c8768094b28f", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/mod.js": "fe4affebbd210d885b2e5135c668751f9d10bc14aa0cc3905cbfff66f04b4c58", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/cbc.js": "ff24b4506522a724ba7a03c1403ad8938aba45056f9fd47c7f0b4fcb3a640adf", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/cfb.js": "643720a1db969b6bcc896c95523630838a8335513d02f340514fd524bb4113cb", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/cfb1.js": "01c9a46aa3affd84a54ae33652fb0fa0ff7c862be2a459d9cb188cb8e2c4b11e", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/cfb8.js": "97476cee25103e02a02b196d7fe6f28a9f0f9e47ee344687d7492bc7282a59f8", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/ctr.js": "1e3835adb753cfe6761e4df8c43d190e31e1ca6a586fd582747c8255c82ed78d", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/ecb.js": "79677b96d4af50c49f0a4f698e5c7e5a64f1d2926b799e0d2eac2cdd5ec7488c", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/mod.js": "fe3db429b867a0a8066c64d7b33b840a1f24cad9174156384a763733f68cf518", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/modes/ofb.js": "3553308f98d078e2006eac39bb6d91818f8bb376b01d962ae98eabf6ee79ad4e", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/stream_cipher.js": "70f50f37ddec530ae95911ca2f286ebd2ddbd54d914ab0be461ec1dc3c61990f", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_aes/xor.ts": "7132baacdb39ba82c3bfe325a60e68ca87469c0ed0cdd0508caf6f40bab852b8", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/browserify_rsa.js": "96e0e4fee7c2cf75ef86d958c709bfc239297a080fd17ace5ea5ab699a1b6174", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/cipher_base.js": "9ebc6ccc364cf7b23024821054d2e72a2d8da8d8a2a36cacdc5aa6cc6770ef93", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/evp_bytes_to_key.ts": "7c4c27b6e321b2d7065a6703d90264921e9a805d91d9dfdb21103393228024e2", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/parse_asn1/asn1.js": "7d99b6df508164169a33377346e8840d519fe2defccb362a023c92c5bd503433", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/parse_asn1/certificate.js": "5795348417b3ec7aafa4854ba55f364e0148eadfdd29d1566c90e617237621bb", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/parse_asn1/fix_proc.js": "858dd3e6ce264d75822cadc21bb55114f4e4867a706abde1663548aa2710fc1b", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/parse_asn1/mod.js": "ea164fbd497ce3d710426742d4b72f71da8954c4ebaeb7eadc33316c5b0060f1", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/public_encrypt/mgf.js": "dfac5008a550b3e7e6b851c4fb42e984aa9e7fae64707888f47f2aa0991c004d", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/public_encrypt/mod.js": "0704326ff3ee2bb0764a964995d1aa62b1147b714ad5465e878ba4d57731e3db", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/public_encrypt/private_decrypt.js": "8a1d11edb176d95d1e3bdf1aff5c3248a986bf9734d1a6b07508e29132d2f65c", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/public_encrypt/public_encrypt.js": "f88b0e3c228d84096fdbc03e614e86bef86e56013cb9628b2425e31b3b142b2c", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/public_encrypt/with_public.js": "752da754d253b5743d89c0f2432b6eb6f8815b80efd9ee588683e10a13d34400", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/public_encrypt/xor.js": "087ebef8f6fcb8ca4c7216cc22de728d9a61ec27b9a036b900681ff25d6409af", + "https://deno.land/std@0.177.0/node/_crypto/crypto_browserify/randombytes.ts": "23bde8be640e274d7bb88cf10d1da8bba252654252dc6a877fed86a77da5952c", + "https://deno.land/std@0.177.0/node/_events.d.ts": "1347437fd6b084d7c9a4e16b9fe7435f00b030970086482edeeb3b179d0775af", + "https://deno.land/std@0.177.0/node/_events.mjs": "d4ba4e629abe3db9f1b14659fd5c282b7da8b2b95eaf13238eee4ebb142a2448", + "https://deno.land/std@0.177.0/node/_global.d.ts": "2d88342f38b4083b858998e27c706725fb03a74aa14ef8d985dc18438b5188e4", + "https://deno.land/std@0.177.0/node/_next_tick.ts": "9a3cf107d59b019a355d3cf32275b4c6157282e4b68ea85b46a799cb1d379305", + "https://deno.land/std@0.177.0/node/_process/exiting.ts": "6e336180aaabd1192bf99ffeb0d14b689116a3dec1dfb34a2afbacd6766e98ab", + "https://deno.land/std@0.177.0/node/_process/process.ts": "c96bb1f6253824c372f4866ee006dcefda02b7050d46759736e403f862d91051", + "https://deno.land/std@0.177.0/node/_process/stdio.mjs": "cf17727eac8da3a665851df700b5aca6a12bacc3ebbf33e63e4b919f80ba44a6", + "https://deno.land/std@0.177.0/node/_stream.d.ts": "112e1a0677cd6db932c3ce0e6e5bbdc7a2ac1874572f449044ecc82afcf5ee2e", + "https://deno.land/std@0.177.0/node/_stream.mjs": "d6e2c86c1158ac65b4c2ca4fa019d7e84374ff12e21e2175345fe68c0823efe3", + "https://deno.land/std@0.177.0/node/_utils.ts": "7fd55872a0cf9275e3c080a60e2fa6d45b8de9e956ebcde9053e72a344185884", + "https://deno.land/std@0.177.0/node/buffer.ts": "85617be2063eccaf177dbb84c7580d1e32023724ed14bd9df4e453b152a26167", + "https://deno.land/std@0.177.0/node/crypto.ts": "2c94fa0f76e90190fbc34df891dc5c284bddb86c932fae8ac11747de3f75293c", + "https://deno.land/std@0.177.0/node/events.ts": "d2de352d509de11a375e2cb397d6b98f5fed4e562fc1d41be33214903a38e6b0", + "https://deno.land/std@0.177.0/node/internal/buffer.d.ts": "bdfa991cd88cb02fd08bf8235d2618550e3e511c970b2a8f2e1a6885a2793cac", + "https://deno.land/std@0.177.0/node/internal/buffer.mjs": "e92303a3cc6d9aaabcd270a937ad9319825d9ba08cb332650944df4562029b27", + "https://deno.land/std@0.177.0/node/internal/crypto/_keys.ts": "8f3c3b5a141aa0331a53c205e9338655f1b3b307a08085fd6ff6dda6f7c4190b", + "https://deno.land/std@0.177.0/node/internal/crypto/_randomBytes.ts": "36dd164747f73b830ba86562abb160a8ac5bea34aaeb816a67f3005a00d41177", + "https://deno.land/std@0.177.0/node/internal/crypto/_randomFill.ts": "297186f290eba87a1ad7b8aa42a960ff4278a8b6b0c963fa81918c326d5c0b58", + "https://deno.land/std@0.177.0/node/internal/crypto/_randomInt.ts": "6cf19da9684b67520e67a2d99f2581a3f841140842c7ce2e014d166457550fe1", + "https://deno.land/std@0.177.0/node/internal/crypto/certificate.ts": "b4a6695f82e70a42e85247c74a7691ed4b3a904646451af0287e49efe1a28814", + "https://deno.land/std@0.177.0/node/internal/crypto/cipher.ts": "2bae9b4d94c465e4d1c70e5a9e8fd67ce20bcc66fecd2eec6be00d35144ca4eb", + "https://deno.land/std@0.177.0/node/internal/crypto/constants.ts": "544d605703053218499b08214f2e25cf4310651d535b7ab995891c4b7a217693", + "https://deno.land/std@0.177.0/node/internal/crypto/diffiehellman.ts": "9cfb219c5b2936db773f559b6affe6d25b0e40531010389f05df3f05ce7eebf5", + "https://deno.land/std@0.177.0/node/internal/crypto/hash.ts": "d01f5d3ad5477655b432036d2d553c7a0c31a901ac0e1e9e0d8b3975daae7624", + "https://deno.land/std@0.177.0/node/internal/crypto/hkdf.ts": "5bd801234e56468fbd47466f46e88bdadc66432d625e3616abe38878d410bb66", + "https://deno.land/std@0.177.0/node/internal/crypto/keygen.ts": "530cc1a00acf71a43719bb876a2dc563b6196095d080eba77c92c9f39658a5b9", + "https://deno.land/std@0.177.0/node/internal/crypto/keys.ts": "c4dfa5aa3420cf700178b87203593a0989c8a93934bfef2b29adb3399d687958", + "https://deno.land/std@0.177.0/node/internal/crypto/pbkdf2.ts": "0a0a3e0d3d45db0638fe75a4199c7ed7ca2164405750a520e786e4adebdb45a4", + "https://deno.land/std@0.177.0/node/internal/crypto/random.ts": "85f3147e14cb45c18e016da45d319a5c663309411232a956fdc09c2317acdd9f", + "https://deno.land/std@0.177.0/node/internal/crypto/scrypt.ts": "b55a0fcd12b295af4127d05b1c0bc3098b74fc0e3c62321c2a43c20f9ed18209", + "https://deno.land/std@0.177.0/node/internal/crypto/sig.ts": "25819a89d49c1ebfe3baa1f9464501ec599a36cf53e9b600ec0399e568b9dccc", + "https://deno.land/std@0.177.0/node/internal/crypto/types.ts": "52feb182bcbd59206f3e2f4a3cb8a5775d4452c2a8045c3e613e2178d32c2a86", + "https://deno.land/std@0.177.0/node/internal/crypto/util.ts": "db282c0413aeee28bc0665fcfc1c08a65fc96dc12ed4d03282f2da4907fcf0ce", + "https://deno.land/std@0.177.0/node/internal/crypto/x509.ts": "0e8a541c4f58ecb83862c373d3f7d2371aa8f5108f55bc837b190c4ab3408764", + "https://deno.land/std@0.177.0/node/internal/error_codes.ts": "8495e33f448a484518d76fa3d41d34fc20fe03c14b30130ad8e936b0035d4b8b", + "https://deno.land/std@0.177.0/node/internal/errors.ts": "1c699b8a3cb93174f697a348c004b1c6d576b66688eac8a48ebb78e65c720aae", + "https://deno.land/std@0.177.0/node/internal/fixed_queue.ts": "62bb119afa5b5ae8fc0c7048b50502347bec82e2588017d0b250c4671d6eff8f", + "https://deno.land/std@0.177.0/node/internal/hide_stack_frames.ts": "9dd1bad0a6e62a1042ce3a51eb1b1ecee2f246907bff44835f86e8f021de679a", + "https://deno.land/std@0.177.0/node/internal/normalize_encoding.mjs": "fd1d9df61c44d7196432f6e8244621468715131d18cc79cd299fc78ac549f707", + "https://deno.land/std@0.177.0/node/internal/options.ts": "888f267c3fe8f18dc7b2f2fbdbe7e4a0fd3302ff3e99f5d6645601e924f3e3fb", + "https://deno.land/std@0.177.0/node/internal/primordials.mjs": "a72d86b5aa55d3d50b8e916b6a59b7cc0dc5a31da8937114b4a113ad5aa08c74", + "https://deno.land/std@0.177.0/node/internal/streams/destroy.mjs": "b665fc71178919a34ddeac8389d162a81b4bc693ff7dc2557fa41b3a91011967", + "https://deno.land/std@0.177.0/node/internal/streams/end-of-stream.mjs": "a4fb1c2e32d58dff440d4e716e2c4daaa403b3095304a028bb428575cfeed716", + "https://deno.land/std@0.177.0/node/internal/streams/utils.mjs": "f2fe2e6bdc506da24c758970890cc2a21642045b129dee618bd3827c60dd9e33", + "https://deno.land/std@0.177.0/node/internal/streams/writable.mjs": "775928726d0483ace8e45a35f30db2019a22dd7b9a81b67b158420e21cc692c5", + "https://deno.land/std@0.177.0/node/internal/util.mjs": "f7fe2e1ca5e66f550ad0856b9f5ee4d666f0c071fe212ea7fc7f37cfa81f97a5", + "https://deno.land/std@0.177.0/node/internal/util/inspect.mjs": "11d7c9cab514b8e485acc3978c74b837263ff9c08ae4537fa18ad56bae633259", + "https://deno.land/std@0.177.0/node/internal/util/types.ts": "0e587b44ec5e017cf228589fc5ce9983b75beece6c39409c34170cfad49d6417", + "https://deno.land/std@0.177.0/node/internal/validators.mjs": "e02f2b02dd072a5d623970292588d541204dc82207b4c58985d933a5f4b382e6", + "https://deno.land/std@0.177.0/node/internal_binding/_libuv_winerror.ts": "30c9569603d4b97a1f1a034d88a3f74800d5ea1f12fcc3d225c9899d4e1a518b", + "https://deno.land/std@0.177.0/node/internal_binding/_node.ts": "cb2389b0eab121df99853eb6a5e3a684e4537e065fb8bf2cca0cbf219ce4e32e", + "https://deno.land/std@0.177.0/node/internal_binding/_timingSafeEqual.ts": "7d9732464d3c669ff07713868ce5d25bc974a06112edbfb5f017fc3c70c0853e", + "https://deno.land/std@0.177.0/node/internal_binding/_utils.ts": "7c58a2fbb031a204dee9583ba211cf9c67922112fe77e7f0b3226112469e9fe1", + "https://deno.land/std@0.177.0/node/internal_binding/_winerror.ts": "3e8cfdfe22e89f13d2b28529bab35155e6b1730c0221ec5a6fc7077dc037be13", + "https://deno.land/std@0.177.0/node/internal_binding/buffer.ts": "31729e0537921d6c730ad0afea44a7e8a0a1044d070ade8368226cb6f7390c8b", + "https://deno.land/std@0.177.0/node/internal_binding/constants.ts": "21ff9d1ee71d0a2086541083a7711842fc6ae25e264dbf45c73815aadce06f4c", + "https://deno.land/std@0.177.0/node/internal_binding/crypto.ts": "29e8f94f283a2e7d4229d3551369c6a40c2af9737fad948cb9be56bef6c468cd", + "https://deno.land/std@0.177.0/node/internal_binding/node_options.ts": "0b5cb0bf4379a39278d7b7bb6bb2c2751baf428fe437abe5ed3e8441fae1f18b", + "https://deno.land/std@0.177.0/node/internal_binding/string_decoder.ts": "54c3c1cbd5a9254881be58bf22637965dc69535483014dab60487e299cb95445", + "https://deno.land/std@0.177.0/node/internal_binding/types.ts": "2187595a58d2cf0134f4db6cc2a12bf777f452f52b15b6c3aed73fa072aa5fc3", + "https://deno.land/std@0.177.0/node/internal_binding/util.ts": "808ff3b92740284184ab824adfc420e75398c88c8bccf5111f0c24ac18c48f10", + "https://deno.land/std@0.177.0/node/internal_binding/uv.ts": "eb0048e30af4db407fb3f95563e30d70efd6187051c033713b0a5b768593a3a3", + "https://deno.land/std@0.177.0/node/stream.ts": "09e348302af40dcc7dc58aa5e40fdff868d11d8d6b0cfb85cbb9c75b9fe450c7", + "https://deno.land/std@0.177.0/node/string_decoder.ts": "1a17e3572037c512cc5fc4b29076613e90f225474362d18da908cb7e5ccb7e88", "https://deno.land/std@0.181.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", "https://deno.land/std@0.181.0/bytes/bytes_list.ts": "b4cbdfd2c263a13e8a904b12d082f6177ea97d9297274a4be134e989450dfa6a", "https://deno.land/std@0.181.0/bytes/concat.ts": "d26d6f3d7922e6d663dacfcd357563b7bf4a380ce5b9c2bbe0c8586662f25ce2", @@ -53,59 +169,39 @@ "https://deno.land/x/sqlite@v2.3.2/src/error.ts": "c305a89b28ab5b56e425074849c6544d23e855b92670935d9e965ee68f9a6a9e", "https://deno.land/x/sqlite@v2.3.2/src/row_objects.ts": "cf7ad165bb14c0fd346c46a7f3ea08043ace747d1abae3787bbe4b36be11b09c", "https://deno.land/x/sqlite@v2.3.2/src/rows.ts": "1b05730096f8df626bfc9d1597a776cc5ac7d989910a20711fa28c7a8daebb0e", - "https://deno.land/x/sqlite@v2.3.2/src/wasm.ts": "9747b8c4de5542f2359a35461317f08a244fe8a0933c7e279caad27a0190e6bf" - }, - "npm": { - "specifiers": { - "nostr-tools@^1.7.4": "nostr-tools@1.7.4" - }, - "packages": { - "@noble/hashes@1.0.0": { - "integrity": "sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==", - "dependencies": {} - }, - "@noble/hashes@1.2.0": { - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dependencies": {} - }, - "@noble/secp256k1@1.7.1": { - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "dependencies": {} - }, - "@scure/base@1.1.1": { - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "dependencies": {} - }, - "@scure/bip32@1.1.5": { - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dependencies": { - "@noble/hashes": "@noble/hashes@1.2.0", - "@noble/secp256k1": "@noble/secp256k1@1.7.1", - "@scure/base": "@scure/base@1.1.1" - } - }, - "@scure/bip39@1.1.1": { - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dependencies": { - "@noble/hashes": "@noble/hashes@1.2.0", - "@scure/base": "@scure/base@1.1.1" - } - }, - "nostr-tools@1.7.4": { - "integrity": "sha512-YowDJ+S3UW9KCYPDZfZXXMITrJSMjiCmFOK5HohyKkg+w6EipFUTkFRBPRA2BTLXO/qw8gukKXfL0B7Dv3jtcQ==", - "dependencies": { - "@noble/hashes": "@noble/hashes@1.0.0", - "@noble/secp256k1": "@noble/secp256k1@1.7.1", - "@scure/base": "@scure/base@1.1.1", - "@scure/bip32": "@scure/bip32@1.1.5", - "@scure/bip39": "@scure/bip39@1.1.1", - "prettier": "prettier@2.8.4" - } - }, - "prettier@2.8.4": { - "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", - "dependencies": {} - } - } + "https://deno.land/x/sqlite@v2.3.2/src/wasm.ts": "9747b8c4de5542f2359a35461317f08a244fe8a0933c7e279caad27a0190e6bf", + "https://esm.sh/v113/@noble/curves@0.8.3/deno/abstract/modular.js": "d91c510811b267efedd3bdefd8b73413359aef5bce4448a6fc766feb5b90aa23", + "https://esm.sh/v113/@noble/curves@0.8.3/deno/secp256k1.js": "20f0e8991377f43483c2d20c0933444954db1c5608c48118282d9d0698f1c31d", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/_assert.js": "72a2c390121ef64189358442e9c762a8254ad26a1067f094f19b993c2ee0410f", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/crypto.js": "5155cc032738707f4a4e27e2743be57bdddd21d2462837c328adba2cb190755c", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/hmac.js": "5ee68684fd06b98bb07039b5a0b3d3f32c2a82638a2fe8b1dbdc0860ab77303e", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/pbkdf2.js": "f15a067b29ae22bee69ad1e91aec374dc1b3d819132b519b3b5a49db263eac3a", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/ripemd160.js": "0e25b8733bfb9adcee81e111efcc0169ff652f32f2f2550caaee9512a18e4302", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/sha256.js": "a23d2b298cd8089ab1dee3f1d60641cb11ed551ed649c5d30555a34ca19f400b", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/sha512.js": "ee47ce36636a562bd6ef44d1f743ed62c74a8e6485382eb41e260139bf1acf45", + "https://esm.sh/v113/@noble/hashes@1.3.0/deno/utils.js": "d39d84af712da02d6789734c1e2084ae0f4f452be618861e1981ee10ab2c96ef", + "https://esm.sh/v113/@noble/secp256k1@1.7.1/deno/secp256k1.mjs": "9616385c64e9ad73da07cbe7342e22f28d16092f632681e5bc19b6f403f7a28d", + "https://esm.sh/v113/@scure/base@1.1.1/deno/base.mjs": "c9be265179789182c8a9f719bfce436c09b512a42afa09c3c66d91a9f7d8659e", + "https://esm.sh/v113/@scure/bip32@1.2.0/deno/bip32.mjs": "0fdfc6f8f21d710a4808506efd7d9ad3dcd50745ae9c47a164be9f9f17d9b831", + "https://esm.sh/v113/@scure/bip39@1.2.0/deno/bip39.mjs": "2f7c3a19892a67fea235337aa73160c57b5170a30db88f38df18ced956cb0c2d", + "https://esm.sh/v113/@scure/bip39@1.2.0/deno/wordlists/english.js.js": "d2f68b7928869a1b362d5e9cbb85f796fd7387f6129b0278a499db28ea7daac5", + "https://esm.sh/v113/nostr-tools@1.8.1": "8fa03509e71eb78beff8ecb81a33c91581eb61b48f7d0437f59ddb2ff6875d4b", + "https://esm.sh/v113/nostr-tools@1.8.1/deno/nostr-tools.mjs": "745e9e2498ace50eca097fa5a8616c3edb39210f863190d201487298fcb78007", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/event.d.ts": "5ff40da5677bcf4fd16309dec9b2dd271e6ed8dce43de6995066efc6c2f0727c", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/fakejson.d.ts": "7f56a105c7db5ba6b525c278a4c2e2a4e9bd67fa954e9bc523705f266a39eb53", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/filter.d.ts": "41cc390b0e7ae40cbb423031c3cf9500adc8bc91d632c3b0324dddd53f73b21d", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/index.d.ts": "9fedd273dab24ff887f604095f1fc27fc5665fe3b953d1f8aa8d00890cbeba82", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/keys.d.ts": "a95ae8881851ae3e38125606ea1710dc0c684232db18fbfab632d274b58ef04a", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip04.d.ts": "1d7576fda27eba5279dd28cffe2be414335fd2dffb894efd77b61fd30fe89cbd", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip05.d.ts": "f181522bd2d2247f8634a0175579bcc47eec67fdc3a0703328fff1bd1f164e39", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip06.d.ts": "e2cf12b2fa49e0fe1a8f251b5ff8b3bba8d98d26c0c591e3a0e39cf3120ead1e", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip19.d.ts": "8baed9c741f2935c7ae61af63cfc14ecf5e8228088dc8b51601a63a237f06a82", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip26.d.ts": "e3dd5da8f9afe76e87dd1aa67f976fd2c0fab09253d02d669d0969b9f434d048", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip39.d.ts": "f508df907affd5310fdd509124e3092be35a039a04c8f06aa367d13782f23416", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/nip57.d.ts": "a7434735da9b5073aa533f88241516d74f6a37da81b097277e8ad90233c50bfc", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/pool.d.ts": "ff40f2acad2252493c04a3a6bf200e44bfc71ad0c3e6eb368475c4ce9c3572b6", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/references.d.ts": "b2e39f5c439380a1dc8e578b471ba3992f33e3936aa0eecf625734c7ba669098", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/relay.d.ts": "9bc6f2897a95ec12d128e94b2e7d6161d30a6bfe8d4350e217fbf4b710988db3", + "https://esm.sh/v113/nostr-tools@1.8.1/lib/utils.d.ts": "6f37b09db0dce09f17ff7b70b921b9bb809bcb18c3bc058cb914afdf3c0e774e" } } diff --git a/mod.ts b/mod.ts index 8a8a930..628a6d2 100644 --- a/mod.ts +++ b/mod.ts @@ -1,16 +1,15 @@ -export { default as antiDuplicationPolicy } from './src/policies/anti-duplication-policy.ts'; -export { default as filterPolicy } from './src/policies/filter-policy.ts'; -export { default as hellthreadPolicy } from './src/policies/hellthread-policy.ts'; +export { type AntiDuplication, default as antiDuplicationPolicy } from './src/policies/anti-duplication-policy.ts'; +export { default as filterPolicy, type Filter } from './src/policies/filter-policy.ts'; +export { default as hellthreadPolicy, type Hellthread } from './src/policies/hellthread-policy.ts'; export { default as keywordPolicy } from './src/policies/keyword-policy.ts'; export { default as noopPolicy } from './src/policies/noop-policy.ts'; export { default as pubkeyBanPolicy } from './src/policies/pubkey-ban-policy.ts'; -export { default as rateLimitPolicy } from './src/policies/rate-limit-policy.ts'; +export { default as rateLimitPolicy, type RateLimit } from './src/policies/rate-limit-policy.ts'; export { default as readOnlyPolicy } from './src/policies/read-only-policy.ts'; export { default as regexPolicy } from './src/policies/regex-policy.ts'; export { default as whitelistPolicy } from './src/policies/whitelist-policy.ts'; export { readStdin, writeStdout } from './src/io.ts'; -export { default as pipeline } from './src/pipeline.ts'; +export { default as pipeline, type PolicyTuple } from './src/pipeline.ts'; -export type { Event, InputMessage, OutputMessage, Policy } from './src/types.ts'; -export type { PolicyTuple } from './src/pipeline.ts'; +export type { Event, InputMessage, IterablePubkeys, OutputMessage, Policy } from './src/types.ts'; diff --git a/src/io.ts b/src/io.ts index cf8f6ec..601c63b 100644 --- a/src/io.ts +++ b/src/io.ts @@ -5,6 +5,14 @@ import type { InputMessage, OutputMessage } from './types.ts'; /** * Parse strfy messages from stdin. * strfry may batch multiple messages at once. + * + * @example + * ```ts + * // Loop through strfry input messages + * for await (const msg of readStdin()) { + * // handle `msg` + * } + * ``` */ async function* readStdin(): AsyncGenerator { for await (const line of readLines(Deno.stdin)) { diff --git a/src/pipeline.ts b/src/pipeline.ts index dc0e62d..16a41e1 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -12,7 +12,25 @@ type Policies = { [K in keyof T]: PolicyTuple | Policy; }; -/** Processes messages through multiple policies, bailing early on rejection. */ +/** + * Processes messages through multiple policies. + * + * If any policy returns a `reject` or `shadowReject` action, the pipeline will stop and return the rejected message. + * + * @example + * ```ts + * const result = await pipeline(msg, [ + * noopPolicy, + * [filterPolicy, { kinds: [0, 1, 3, 5, 7, 1984, 9734, 9735, 10002] }], + * [keywordPolicy, ['https://t.me/']], + * [regexPolicy, /(🟠|🔥|😳)ChtaGPT/i], + * [pubkeyBanPolicy, ['e810fafa1e89cdf80cced8e013938e87e21b699b24c8570537be92aec4b12c18']], + * [hellthreadPolicy, { limit: 100 }], + * [rateLimitPolicy, { whitelist: ['127.0.0.1'] }], + * [antiDuplicationPolicy, { ttl: 60000, minLength: 50 }], + * ]); + * ``` + */ async function pipeline(msg: InputMessage, policies: [...Policies]): Promise { for (const item of policies as (Policy | PolicyTuple)[]) { const [policy, opts] = toTuple(item); diff --git a/src/policies/anti-duplication-policy.ts b/src/policies/anti-duplication-policy.ts index f1fb57e..1862711 100755 --- a/src/policies/anti-duplication-policy.ts +++ b/src/policies/anti-duplication-policy.ts @@ -2,6 +2,7 @@ import { Keydb } from '../deps.ts'; import type { Policy } from '../types.ts'; +/** Policy options for `antiDuplicationPolicy`. */ interface AntiDuplication { /** Time in ms until a message with this content may be posted again. Default: `60000` (1 minute). */ ttl?: number; @@ -13,8 +14,21 @@ interface AntiDuplication { /** * Prevent messages with the exact same content from being submitted repeatedly. - * It stores a hashcode for each content in an SQLite database and rate-limits them. - * Only messages that meet the minimum length criteria are selected. + * + * It stores a hashcode for each content in an SQLite database and rate-limits them. Only messages that meet the minimum length criteria are selected. + * 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. + * + * @example + * ```ts + * // Prevent the same message from being posted within 60 seconds. + * antiDuplicationPolicy(msg, { ttl: 60000 }); + * + * // Only enforce the policy on messages with at least 50 characters. + * antiDuplicationPolicy(msg, { ttl: 60000, minLength: 50 }); + * + * // Use a custom SQLite path. + * antiDuplicationPolicy(msg, { databaseUrl: 'sqlite:///media/ramdisk/nostr-contenthash.sqlite3' }); + * ``` */ const antiDuplicationPolicy: Policy = async (msg, opts = {}) => { const { diff --git a/src/policies/filter-policy.ts b/src/policies/filter-policy.ts index b5b8a2a..b3ae745 100644 --- a/src/policies/filter-policy.ts +++ b/src/policies/filter-policy.ts @@ -1,8 +1,19 @@ import { Policy } from '../types.ts'; -import { Filter, matchFilter } from 'npm:nostr-tools@^1.7.4'; +import { type Filter, matchFilter } from 'https://esm.sh/v113/nostr-tools@1.8.1'; -/** Reject all events which don't match the filter. */ +/** + * Reject all events which don't match the filter. + * + * Only messages which **match** the filter are allowed, and all others are dropped. + * The filter is a [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) relay filter. + * + * @example + * ```ts + * // Only allow kind 1, 3, 5, and 7 events. + * filterPolicy(msg, { kinds: [0, 1, 3, 5, 7] }); + * ``` + */ const filterPolicy: Policy = ({ event }, filter = {}) => { if (matchFilter(filter, event)) { return { diff --git a/src/policies/hellthread-policy.ts b/src/policies/hellthread-policy.ts index cc5d31f..411a0cf 100755 --- a/src/policies/hellthread-policy.ts +++ b/src/policies/hellthread-policy.ts @@ -1,11 +1,23 @@ import type { Policy } from '../types.ts'; +/** Policy options for `hellthreadPolicy`. */ interface Hellthread { - /** Total number of "p" tags a kind 1 note may have before it's rejected. Default: `100` */ + /** Total number of "p" tags a kind 1 note may have before it's rejected. Default: `100` */ limit?: number; } -/** Reject messages that tag too many participants. */ +/** + * Reject messages that tag too many participants. + * + * This policy is useful to prevent unwanted notifications by limiting the number of "p" tags a kind 1 event may have. + * Only kind 1 events are impacted by this policy, since kind 3 events will commonly exceed this number. + * + * @example + * ```ts + * // Reject events with more than 15 mentions. + * hellthreadPolicy(msg, { limit: 15 }); + * ``` + */ const hellthreadPolicy: Policy = (msg, opts) => { const limit = opts?.limit ?? 100; diff --git a/src/policies/keyword-policy.ts b/src/policies/keyword-policy.ts index a377840..f5257f2 100644 --- a/src/policies/keyword-policy.ts +++ b/src/policies/keyword-policy.ts @@ -1,6 +1,14 @@ import { Policy } from '../types.ts'; -/** Reject events containing any of the strings in its content. */ +/** + * Reject events containing any of the strings in its content. + * + * @example + * ```ts + * // Reject events with bad words. + * keywordPolicy(msg, ['moo', 'oink', 'honk']); + * ``` + */ const keywordPolicy: Policy> = ({ event: { id, content } }, words = []) => { for (const word of words) { if (content.toLowerCase().includes(word.toLowerCase())) { diff --git a/src/policies/noop-policy.ts b/src/policies/noop-policy.ts index 0d5e86d..b8ce9df 100755 --- a/src/policies/noop-policy.ts +++ b/src/policies/noop-policy.ts @@ -1,9 +1,6 @@ import type { Policy } from '../types.ts'; -/** - * Minimal sample policy for demonstration purposes. - * Allows all events through. - */ +/** Minimal sample policy for demonstration purposes. Allows all events through. */ const noopPolicy: Policy = (msg) => ({ id: msg.event.id, action: 'accept', diff --git a/src/policies/pubkey-ban-policy.ts b/src/policies/pubkey-ban-policy.ts index 0f60e44..3c109d0 100644 --- a/src/policies/pubkey-ban-policy.ts +++ b/src/policies/pubkey-ban-policy.ts @@ -1,11 +1,21 @@ -import { Policy } from '../types.ts'; +import { IterablePubkeys, Policy } from '../types.ts'; /** * Ban individual pubkeys from publishing events to the relay. - * Pass an array of pubkeys or an iterable, making it efficient to load pubkeys from a large file. + * + * @example + * ```ts + * // Ban a specific pubkey. + * pubkeyBanPolicy(msg, ['e810fafa1e89cdf80cced8e013938e87e21b699b24c8570537be92aec4b12c18']); + * + * // Load banned pubkeys from a text file. + * import { readLines } from 'https://deno.land/std/io/mod.ts'; + * const pubkeys = readLines(await Deno.open('pubkeys.txt')); + * const result = await pubkeyBanPolicy(msg, pubkeys); + * ``` */ -const pubkeyBanPolicy: Policy> = ({ event: { id, pubkey } }, pubkeys = []) => { - for (const p of pubkeys) { +const pubkeyBanPolicy: Policy = async ({ event: { id, pubkey } }, pubkeys = []) => { + for await (const p of pubkeys) { if (p === pubkey) { return { id, diff --git a/src/policies/rate-limit-policy.ts b/src/policies/rate-limit-policy.ts index deff9db..959ef00 100755 --- a/src/policies/rate-limit-policy.ts +++ b/src/policies/rate-limit-policy.ts @@ -2,6 +2,7 @@ import { Keydb } from '../deps.ts'; import type { Policy } from '../types.ts'; +/** Policy options for `rateLimitPolicy`. */ interface RateLimit { /** How often (ms) to check whether `max` has been exceeded. Default: `60000` (1 minute). */ interval?: number; @@ -15,8 +16,14 @@ interface RateLimit { /** * Rate-limits users by their IP address. - * IPs are stored in an SQLite database. If you are running internal services, - * it's a good idea to at least whitelist `127.0.0.1` etc. + * + * IPs are stored in an SQLite database. If you are running internal services, it's a good idea to at least whitelist `127.0.0.1` etc. + * + * @example + * ```ts + * // Limit to 10 events per second. + * rateLimitPolicy(msg, { max: 10, interval: 60000 }); + * ``` */ const rateLimitPolicy: Policy = async (msg, opts = {}) => { const { diff --git a/src/policies/regex-policy.ts b/src/policies/regex-policy.ts index 4d8cc75..5731cce 100644 --- a/src/policies/regex-policy.ts +++ b/src/policies/regex-policy.ts @@ -1,6 +1,14 @@ import { Policy } from '../types.ts'; -/** Reject events whose content matches the regex. */ +/** + * Reject events whose content matches the regex. + * + * @example + * ```ts + * // Ban events matching a regex. + * regexPolicy(msg, /(🟠|🔥|😳)ChtaGPT/i); + * ``` + */ const regexPolicy: Policy = ({ event: { id, content } }, regex) => { if (regex?.test(content)) { return { diff --git a/src/policies/whitelist-policy.ts b/src/policies/whitelist-policy.ts index c08dc71..3e9c42d 100644 --- a/src/policies/whitelist-policy.ts +++ b/src/policies/whitelist-policy.ts @@ -1,11 +1,18 @@ -import type { Policy } from '../types.ts'; +import type { IterablePubkeys, Policy } from '../types.ts'; /** * Allows only the listed pubkeys to post to the relay. All other events are rejected. - * Pass an array of pubkeys or an iterable, making it efficient to load pubkeys from a large file. + + * @example + * ```ts + * // Load allowed pubkeys from a text file. + * import { readLines } from 'https://deno.land/std/io/mod.ts'; + * const pubkeys = readLines(await Deno.open('pubkeys.txt')); + * const result = await whitelistPolicy(msg, pubkeys); + * ``` */ -const whitelistPolicy: Policy> = ({ event: { id, pubkey } }, pubkeys = []) => { - for (const p of pubkeys) { +const whitelistPolicy: Policy = async ({ event: { id, pubkey } }, pubkeys = []) => { + for await (const p of pubkeys) { if (p === pubkey) { return { id, diff --git a/src/types.ts b/src/types.ts index f5e45c5..0b1ff5c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,6 @@ /** * strfry input message from stdin. + * * https://github.com/hoytech/strfry/blob/master/docs/plugins.md#input-messages */ interface InputMessage { @@ -17,6 +18,7 @@ interface InputMessage { /** * strfry output message to be printed as JSONL (minified JSON followed by a newline) to stdout. + * * https://github.com/hoytech/strfry/blob/master/docs/plugins.md#output-messages */ interface OutputMessage { @@ -30,6 +32,7 @@ interface OutputMessage { /** * Nostr event. + * * https://github.com/nostr-protocol/nips/blob/master/01.md */ interface Event { @@ -48,4 +51,7 @@ interface Event { */ type Policy = (msg: InputMessage, opts?: Opts) => Promise | OutputMessage; -export type { Event, InputMessage, OutputMessage, Policy }; +/** Sync or async iterable of pubkeys, designed for efficiently loading from large files. */ +type IterablePubkeys = Iterable | AsyncIterable; + +export type { Event, InputMessage, IterablePubkeys, OutputMessage, Policy };