diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..f4e8c00 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b2d4394..b96e368 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,13 +59,26 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - # This compiles the application. - - name: Build the application and export it - run: cargo build --verbose + - name: Install stable toolchain + uses: actions-rs/toolchain@v1.0.6 + with: + toolchain: stable + target: wasm32-unknown-unknown + override: true + + - name: Check for errors + uses: actions-rs/cargo@v1.0.1 + with: + command: check + + - name: Install worker-build + uses: actions-rs/cargo@v1.0.1 + with: + command: install + args: worker-build - # Runs unit tests for the application using Jest. - - name: Execute tests using Cargo - run: cargo test --verbose + - name: Build by worker-build + run: worker-build release: name: Create Release diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..e72bb94 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,58 @@ +name: Deploy & Publish +on: + release: + types: [ prereleased, released ] + +jobs: + + # Prepare and publish + deploy: + name: Deploy to Workers + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + + # Check out current repository + - name: Fetch Sources + uses: actions/checkout@v3.6.0 + with: + ref: ${{ github.event.release.tag_name }} + + # Cache dependencies to speed up builds + - name: Cache cargo dependencies + uses: actions/cache@v3.3.2 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1.0.6 + with: + toolchain: stable + target: wasm32-unknown-unknown + override: true + + - name: Install worker-build + uses: actions-rs/cargo@v1.0.1 + with: + command: install + args: worker-build + + - name: Build by worker-build + run: worker-build + + - name: Deploy to Workers + uses: cloudflare/wrangler-action@v3.1.0 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true diff --git a/.gitignore b/.gitignore index 65f5692..7b46c1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target /tmp /report.* +/node_modules +/.wrangler diff --git a/CHANGELOG.md b/CHANGELOG.md index c8cf526..d598eee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,38 @@ All notable changes to this project will be documented in this file. -## [unreleased] +## [1.0.0-alpha.8] - 2023-09-21 + +### Bug Fixes + +- Replace incorrect field mapping in Prop House comment model + +### Refactor + +- Remove caching system from project +- Update fetcher functions to use worker env +- Update fetcher to use GraphQLFetcher struct +- Add caching functionality to enhance performance +- Move code into `lib.rs` for modularity and error handling +- Update caching and fetching mechanism +- Update the `pnpm-lock.yaml` and `Cargo.lock` files +- Update DiscordHandler to use a custom in-memory cache system +- Update formatting and date variable in prop handlers + +### Miscellaneous Tasks + +- Add `package.json` for LilNouns bots project +- Add `wrangler.toml` configuration for deployment +- Add `wasm-pack` and additional dependencies in `Cargo.toml` +- Add `node_modules` to `.gitignore` +- Update `package.json` for deployment and development +- Add `wasm32` target to Cargo configuration +- Update and rearrange dependencies +- Update `dev` script in `package.json` +- Add `.wrangler` to `.gitignore` +- Update build process in GitHub Actions workflow + +## [1.0.0-alpha.7] - 2023-09-19 ### Refactor diff --git a/Cargo.lock b/Cargo.lock index 1d4c3fb..e46506c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,54 +41,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" -dependencies = [ - "anstyle", - "windows-sys", -] - [[package]] name = "anyhow" version = "1.0.75" @@ -112,22 +64,6 @@ dependencies = [ "syn 2.0.32", ] -[[package]] -name = "async-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb" -dependencies = [ - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "tokio", - "tokio-rustls 0.23.4", - "tungstenite", - "webpki-roots 0.22.6", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -149,39 +85,12 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" -[[package]] -name = "bindgen" -version = "0.65.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.32", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -194,15 +103,6 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "bumpalo" version = "3.13.0" @@ -221,24 +121,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ - "jobserver", "libc", ] @@ -248,15 +136,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -278,62 +157,38 @@ dependencies = [ ] [[package]] -name = "clang-sys" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.4.3" +name = "chrono-tz" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6" +checksum = "f1369bc6b9e9a7dfdae2055f6ec151fe9c554a9d23d357c0237cee2e25eaabb7" dependencies = [ - "clap_builder", - "clap_derive", + "chrono", + "chrono-tz-build", + "phf 0.11.2", ] [[package]] -name = "clap_builder" -version = "4.4.2" +name = "chrono-tz-build" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "e2f5ebdc942f57ed96d560a6d1a459bae5851102a25d5bf89dc04ae453e31ecf" dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", + "parse-zoneinfo", + "phf 0.11.2", + "phf_codegen 0.11.2", ] [[package]] -name = "clap_derive" -version = "4.4.2" +name = "colored" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.32", + "is-terminal", + "lazy_static", + "windows-sys", ] -[[package]] -name = "clap_lex" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "combine" version = "3.8.1" @@ -357,6 +212,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -373,44 +238,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "deranged" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" -dependencies = [ - "serde", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "either" version = "1.9.0" @@ -595,16 +422,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.10" @@ -612,8 +429,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -622,12 +441,6 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "graphql-introspection-query" version = "0.2.0" @@ -816,20 +629,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls 0.21.7", - "tokio", - "tokio-rustls 0.24.1", -] - [[package]] name = "hyper-tls" version = "0.5.0" @@ -929,20 +728,11 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] @@ -953,73 +743,31 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "librocksdb-sys" -version = "0.11.0+8.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" -dependencies = [ - "bindgen", - "bzip2-sys", - "cc", - "glob", - "libc", - "libz-sys", - "lz4-sys", -] - -[[package]] -name = "libz-sys" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - [[package]] name = "lilnouns-bots" -version = "1.0.0-alpha.7" +version = "1.0.0-alpha.8" dependencies = [ "anyhow", + "cfg-if", "chrono", - "clap", + "console_error_panic_hook", "env_logger", "futures", + "getrandom", "graphql_client", "html2md", - "lazy_static", "log", "reqwest", - "rocksdb", "serde", "serde_json", - "serenity", - "tokio", + "worker", + "worker_logger", ] [[package]] @@ -1044,16 +792,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "lz4-sys" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "mac" version = "0.1.1" @@ -1067,8 +805,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ "log", - "phf", - "phf_codegen", + "phf 0.10.1", + "phf_codegen 0.10.0", "string_cache", "string_cache_codegen", "tendril", @@ -1086,6 +824,12 @@ dependencies = [ "xml5ever", ] +[[package]] +name = "matchit" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9376a4f0340565ad675d11fc1419227faf5f60cd7ac9cb2e7185a471f30af833" + [[package]] name = "memchr" version = "2.6.3" @@ -1098,22 +842,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1158,16 +886,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "num-traits" version = "0.2.16" @@ -1177,16 +895,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.32.1" @@ -1246,15 +954,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -1279,10 +978,13 @@ dependencies = [ ] [[package]] -name = "peeking_take_while" -version = "0.1.2" +name = "parse-zoneinfo" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] [[package]] name = "percent-encoding" @@ -1296,7 +998,16 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "phf_shared", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared 0.11.2", ] [[package]] @@ -1305,8 +1016,18 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", ] [[package]] @@ -1315,7 +1036,17 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ - "phf_shared", + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", "rand", ] @@ -1329,17 +1060,46 @@ dependencies = [ ] [[package]] -name = "pin-project-lite" -version = "0.2.13" +name = "phf_shared" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "pin-project" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.27" @@ -1358,16 +1118,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "prettyplease" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" -dependencies = [ - "proc-macro2", - "syn 2.0.32", -] - [[package]] name = "proc-macro2" version = "1.0.66" @@ -1460,7 +1210,7 @@ version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ - "base64 0.21.4", + "base64", "bytes", "encoding_rs", "futures-core", @@ -1469,73 +1219,34 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls", "hyper-tls", "ipnet", "js-sys", "log", "mime", - "mime_guess", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.7", - "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls 0.24.1", - "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", "web-sys", - "webpki-roots 0.25.2", "winreg", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "rocksdb" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" -dependencies = [ - "libc", - "librocksdb-sys", -] - [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustix" version = "0.38.13" @@ -1549,49 +1260,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64 0.21.4", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "ryu" version = "1.0.15" @@ -1622,16 +1290,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "security-framework" version = "2.9.2" @@ -1665,13 +1323,14 @@ dependencies = [ ] [[package]] -name = "serde-value" -version = "0.7.0" +name = "serde-wasm-bindgen" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" dependencies = [ - "ordered-float", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -1708,49 +1367,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serenity" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d007dc45584ecc47e791f2a9a7cf17bf98ac386728106f111159c846d624be3f" -dependencies = [ - "async-trait", - "async-tungstenite", - "base64 0.13.1", - "bitflags 1.3.2", - "bytes", - "cfg-if", - "futures", - "mime", - "mime_guess", - "percent-encoding", - "reqwest", - "serde", - "serde-value", - "serde_json", - "time", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" - [[package]] name = "siphasher" version = "0.3.11" @@ -1792,12 +1408,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "string_cache" version = "0.8.7" @@ -1807,7 +1417,7 @@ dependencies = [ "new_debug_unreachable", "once_cell", "parking_lot", - "phf_shared", + "phf_shared 0.10.0", "precomputed-hash", "serde", ] @@ -1818,18 +1428,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro2", "quote", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "syn" version = "1.0.109" @@ -1905,34 +1509,6 @@ dependencies = [ "syn 2.0.32", ] -[[package]] -name = "time" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" -dependencies = [ - "deranged", - "itoa", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "time-macros" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" -dependencies = [ - "time-core", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -1958,24 +1534,11 @@ dependencies = [ "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2 0.5.4", - "tokio-macros", "windows-sys", ] -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.32", -] - [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -1986,27 +1549,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.7", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.8" @@ -2034,23 +1576,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", - "log", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.32", -] - [[package]] name = "tracing-core" version = "0.1.31" @@ -2066,42 +1595,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand", - "rustls 0.20.9", - "sha-1", - "thiserror", - "url", - "utf-8", - "webpki", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.13" @@ -2132,12 +1625,6 @@ dependencies = [ "void", ] -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "url" version = "2.4.1" @@ -2147,7 +1634,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -2156,24 +1642,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "void" version = "1.0.2" @@ -2207,9 +1681,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2217,9 +1691,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" dependencies = [ "bumpalo", "log", @@ -2232,9 +1706,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" dependencies = [ "cfg-if", "js-sys", @@ -2244,9 +1718,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2254,9 +1728,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", @@ -2267,9 +1741,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" [[package]] name = "wasm-streams" @@ -2286,39 +1760,14 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - [[package]] name = "winapi" version = "0.3.9" @@ -2435,6 +1884,89 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "worker" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd7ad167392bdd707a963356f3478844019c74fc89f6af0dfc656914b30af24" +dependencies = [ + "async-trait", + "chrono", + "chrono-tz", + "futures-channel", + "futures-util", + "http", + "js-sys", + "matchit", + "pin-project", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tokio", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "worker-kv", + "worker-macros", + "worker-sys", +] + +[[package]] +name = "worker-kv" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4b9fe1a87b7aef252fceb4f30bf6303036a5de329c81ccad9be9c35d1fdbc7" +dependencies = [ + "js-sys", + "serde", + "serde-wasm-bindgen", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "worker-macros" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306c6b6fc316ce129de9cc393dc614b244afb37d43d8ae7a4dccf45d6f8a5ff5" +dependencies = [ + "async-trait", + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-macro-support", + "worker-sys", +] + +[[package]] +name = "worker-sys" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5db3bd0e45980dbcefe567c978b4930e4526e864cd9e70482252a60229ddd7" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "worker_logger" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3feaee8b9d44f53f5d8100158d30b254539ad4327d545e00de7ad9a2b2f43431" +dependencies = [ + "colored", + "log", + "worker", +] + [[package]] name = "xml5ever" version = "0.17.0" diff --git a/Cargo.toml b/Cargo.toml index af63208..81c7f6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,24 +1,39 @@ [package] name = "lilnouns-bots" -version = "1.0.0-alpha.7" +version = "1.0.0-alpha.8" edition = "2021" include = ["*.graphql"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +# https://github.com/rustwasm/wasm-pack/issues/1247 +[package.metadata.wasm-pack.profile.release] +wasm-opt = false + +[lib] +crate-type = ["cdylib"] + +[features] +default = ["console_error_panic_hook"] + [dependencies] -graphql_client = { version = "0.13.0", features = ["reqwest"] } -serde = { version = "1.0.188", features = ["derive"] } -reqwest = "0.11.20" -tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread"] } anyhow = "1.0.75" -lazy_static = "1.4.0" -log = "0.4.20" +cfg-if = "1.0.0" +chrono = "0.4.31" env_logger = "0.10.0" -serde_json = "1.0.107" futures = "0.3.28" -clap = { version = "4.4.3", features = ["derive"] } -serenity = { version = "0.11.6", default-features = false, features = ["rustls_backend", "model"] } -rocksdb = { version = "0.21.0", default-features = false, features = ["lz4"] } +getrandom = { version = "0.2.10", features = ["js"] } +graphql_client = { version = "0.13.0", features = ["reqwest"] } html2md = "0.2.14" -chrono = "0.4.31" +log = "0.4.20" +reqwest = "0.11.20" +serde = { version = "1.0.188", features = ["derive"] } +serde_json = "1.0.107" +worker = "0.0.18" +worker_logger = { version = "0.2.0", features = ["color"] } +console_error_panic_hook = { version = "0.1.7", optional = true } + +[profile.release] +lto = true +strip = true +codegen-units = 1 diff --git a/package.json b/package.json new file mode 100644 index 0000000..bf0f0ea --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "scripts": { + "deploy": "wrangler deploy", + "dev": "wrangler dev --test-scheduled" + }, + "devDependencies": { + "wrangler": "3.8.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..29f39d6 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,964 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +devDependencies: + wrangler: + specifier: 3.8.0 + version: 3.8.0 + +packages: + + /@cloudflare/kv-asset-handler@0.2.0: + resolution: { integrity: sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A== } + dependencies: + mime: 3.0.0 + dev: true + + /@cloudflare/workerd-darwin-64@1.20230904.0: + resolution: { integrity: sha512-/GDlmxAFbDtrQwP4zOXFbqOfaPvkDxdsCoEa+KEBcAl5uR98+7WW5/b8naBHX+t26uS7p4bLlImM8J5F1ienRQ== } + engines: { node: '>=16' } + cpu: [ x64 ] + os: [ darwin ] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-darwin-arm64@1.20230904.0: + resolution: { integrity: sha512-x8WXNc2xnDqr5y1iirnNdyx8GZY3rL5xiF7ebK3mKQeB+jFjkhO71yuPTkDCzUWtOvw1Wfd4jbwy4wxacMX4mQ== } + engines: { node: '>=16' } + cpu: [ arm64 ] + os: [ darwin ] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-linux-64@1.20230904.0: + resolution: { integrity: sha512-V58xyMS3oDpKO8Dpdh0r0BXm99OzoGgvWe9ufttVraj/1NTMGELwb6i9ySb8k3F1J9m/sO26+TV7pQc/bGC1VQ== } + engines: { node: '>=16' } + cpu: [ x64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-linux-arm64@1.20230904.0: + resolution: { integrity: sha512-VrDaW+pjb5IAKEnNWtEaFiG377kXKmk5Fu0Era4W+jKzPON2BW/qRb/4LNHXQ4yxg/2HLm7RiUTn7JZtt1qO6A== } + engines: { node: '>=16' } + cpu: [ arm64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@cloudflare/workerd-windows-64@1.20230904.0: + resolution: { integrity: sha512-/R/dE8uy+8J2YeXfDhI8/Bg7YUirdbbjH5/l/Vv00ZRE0lC3nPLcYeyBXSwXIQ6/Xht3gN+lksLQgKd0ZWRd+Q== } + engines: { node: '>=16' } + cpu: [ x64 ] + os: [ win32 ] + requiresBuild: true + dev: true + optional: true + + /@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19): + resolution: { integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw== } + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.17.19 + dev: true + + /@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19): + resolution: { integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA== } + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.17.19 + escape-string-regexp: 4.0.0 + rollup-plugin-node-polyfills: 0.2.1 + dev: true + + /@esbuild/android-arm64@0.17.19: + resolution: { integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== } + engines: { node: '>=12' } + cpu: [ arm64 ] + os: [ android ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.17.19: + resolution: { integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== } + engines: { node: '>=12' } + cpu: [ arm ] + os: [ android ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.17.19: + resolution: { integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ android ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.17.19: + resolution: { integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== } + engines: { node: '>=12' } + cpu: [ arm64 ] + os: [ darwin ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.17.19: + resolution: { integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ darwin ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.17.19: + resolution: { integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== } + engines: { node: '>=12' } + cpu: [ arm64 ] + os: [ freebsd ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.17.19: + resolution: { integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ freebsd ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.17.19: + resolution: { integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== } + engines: { node: '>=12' } + cpu: [ arm64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.17.19: + resolution: { integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== } + engines: { node: '>=12' } + cpu: [ arm ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.17.19: + resolution: { integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== } + engines: { node: '>=12' } + cpu: [ ia32 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.17.19: + resolution: { integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== } + engines: { node: '>=12' } + cpu: [ loong64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.17.19: + resolution: { integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== } + engines: { node: '>=12' } + cpu: [ mips64el ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.17.19: + resolution: { integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== } + engines: { node: '>=12' } + cpu: [ ppc64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.17.19: + resolution: { integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== } + engines: { node: '>=12' } + cpu: [ riscv64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.17.19: + resolution: { integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== } + engines: { node: '>=12' } + cpu: [ s390x ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.17.19: + resolution: { integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ linux ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.17.19: + resolution: { integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ netbsd ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.17.19: + resolution: { integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ openbsd ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.17.19: + resolution: { integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ sunos ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.17.19: + resolution: { integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== } + engines: { node: '>=12' } + cpu: [ arm64 ] + os: [ win32 ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.17.19: + resolution: { integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== } + engines: { node: '>=12' } + cpu: [ ia32 ] + os: [ win32 ] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.17.19: + resolution: { integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== } + engines: { node: '>=12' } + cpu: [ x64 ] + os: [ win32 ] + requiresBuild: true + dev: true + optional: true + + /acorn-walk@8.2.0: + resolution: { integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== } + engines: { node: '>=0.4.0' } + dev: true + + /acorn@8.10.0: + resolution: { integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== } + engines: { node: '>=0.4.0' } + hasBin: true + dev: true + + /anymatch@3.1.3: + resolution: { integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== } + engines: { node: '>= 8' } + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /as-table@1.0.55: + resolution: { integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ== } + dependencies: + printable-characters: 1.0.42 + dev: true + + /base64-js@1.5.1: + resolution: { integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== } + dev: true + + /better-sqlite3@8.6.0: + resolution: { integrity: sha512-jwAudeiTMTSyby+/SfbHDebShbmC2MCH8mU2+DXi0WJfv13ypEJm47cd3kljmy/H130CazEvkf2Li//ewcMJ1g== } + requiresBuild: true + dependencies: + bindings: 1.5.0 + prebuild-install: 7.1.1 + dev: true + + /binary-extensions@2.2.0: + resolution: { integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== } + engines: { node: '>=8' } + dev: true + + /bindings@1.5.0: + resolution: { integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== } + dependencies: + file-uri-to-path: 1.0.0 + dev: true + + /bl@4.1.0: + resolution: { integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== } + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /blake3-wasm@2.1.5: + resolution: { integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g== } + dev: true + + /braces@3.0.2: + resolution: { integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== } + engines: { node: '>=8' } + dependencies: + fill-range: 7.0.1 + dev: true + + /buffer-from@1.1.2: + resolution: { integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== } + dev: true + + /buffer@5.7.1: + resolution: { integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== } + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /busboy@1.6.0: + resolution: { integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== } + engines: { node: '>=10.16.0' } + dependencies: + streamsearch: 1.1.0 + dev: true + + /capnp-ts@0.7.0: + resolution: { integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g== } + dependencies: + debug: 4.3.4 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + dev: true + + /chokidar@3.5.3: + resolution: { integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== } + engines: { node: '>= 8.10.0' } + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /chownr@1.1.4: + resolution: { integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== } + dev: true + + /cookie@0.5.0: + resolution: { integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== } + engines: { node: '>= 0.6' } + dev: true + + /data-uri-to-buffer@2.0.2: + resolution: { integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA== } + dev: true + + /debug@4.3.4: + resolution: { integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== } + engines: { node: '>=6.0' } + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decompress-response@6.0.0: + resolution: { integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== } + engines: { node: '>=10' } + dependencies: + mimic-response: 3.1.0 + dev: true + + /deep-extend@0.6.0: + resolution: { integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== } + engines: { node: '>=4.0.0' } + dev: true + + /detect-libc@2.0.2: + resolution: { integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== } + engines: { node: '>=8' } + dev: true + + /end-of-stream@1.4.4: + resolution: { integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== } + dependencies: + once: 1.4.0 + dev: true + + /esbuild@0.17.19: + resolution: { integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== } + engines: { node: '>=12' } + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + dev: true + + /escape-string-regexp@4.0.0: + resolution: { integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== } + engines: { node: '>=10' } + dev: true + + /estree-walker@0.6.1: + resolution: { integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== } + dev: true + + /exit-hook@2.2.1: + resolution: { integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw== } + engines: { node: '>=6' } + dev: true + + /expand-template@2.0.3: + resolution: { integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== } + engines: { node: '>=6' } + dev: true + + /file-uri-to-path@1.0.0: + resolution: { integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== } + dev: true + + /fill-range@7.0.1: + resolution: { integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== } + engines: { node: '>=8' } + dependencies: + to-regex-range: 5.0.1 + dev: true + + /fs-constants@1.0.0: + resolution: { integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== } + dev: true + + /fsevents@2.3.3: + resolution: { integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [ darwin ] + requiresBuild: true + dev: true + optional: true + + /get-source@2.0.12: + resolution: { integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w== } + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + dev: true + + /github-from-package@0.0.0: + resolution: { integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== } + dev: true + + /glob-parent@5.1.2: + resolution: { integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== } + engines: { node: '>= 6' } + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: { integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== } + dev: true + + /http-cache-semantics@4.1.1: + resolution: { integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== } + dev: true + + /ieee754@1.2.1: + resolution: { integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== } + dev: true + + /inherits@2.0.4: + resolution: { integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== } + dev: true + + /ini@1.3.8: + resolution: { integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== } + dev: true + + /is-binary-path@2.1.0: + resolution: { integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== } + engines: { node: '>=8' } + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-extglob@2.1.1: + resolution: { integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== } + engines: { node: '>=0.10.0' } + dev: true + + /is-glob@4.0.3: + resolution: { integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== } + engines: { node: '>=0.10.0' } + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: { integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== } + engines: { node: '>=0.12.0' } + dev: true + + /kleur@4.1.5: + resolution: { integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== } + engines: { node: '>=6' } + dev: true + + /lru-cache@6.0.0: + resolution: { integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== } + engines: { node: '>=10' } + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string@0.25.9: + resolution: { integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== } + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /mime@3.0.0: + resolution: { integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== } + engines: { node: '>=10.0.0' } + hasBin: true + dev: true + + /mimic-response@3.1.0: + resolution: { integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== } + engines: { node: '>=10' } + dev: true + + /miniflare@3.20230904.0: + resolution: { integrity: sha512-+OWQqEk8hV7vZaPCoj5dk1lZr4YUy56OiyNZ45/3ITYf+ZxgQOBPWhQhpw1jCahkRKGPa9Aykz01sc+GhPZYDA== } + engines: { node: '>=16.13' } + dependencies: + acorn: 8.10.0 + acorn-walk: 8.2.0 + better-sqlite3: 8.6.0 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + http-cache-semantics: 4.1.1 + kleur: 4.1.5 + source-map-support: 0.5.21 + stoppable: 1.1.0 + undici: 5.24.0 + workerd: 1.20230904.0 + ws: 8.14.2 + youch: 3.3.1 + zod: 3.22.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /minimist@1.2.8: + resolution: { integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== } + dev: true + + /mkdirp-classic@0.5.3: + resolution: { integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== } + dev: true + + /ms@2.1.2: + resolution: { integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== } + dev: true + + /mustache@4.2.0: + resolution: { integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== } + hasBin: true + dev: true + + /nanoid@3.3.6: + resolution: { integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + dev: true + + /napi-build-utils@1.0.2: + resolution: { integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== } + dev: true + + /node-abi@3.47.0: + resolution: { integrity: sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A== } + engines: { node: '>=10' } + dependencies: + semver: 7.5.4 + dev: true + + /node-forge@1.3.1: + resolution: { integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== } + engines: { node: '>= 6.13.0' } + dev: true + + /normalize-path@3.0.0: + resolution: { integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== } + engines: { node: '>=0.10.0' } + dev: true + + /once@1.4.0: + resolution: { integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== } + dependencies: + wrappy: 1.0.2 + dev: true + + /path-to-regexp@6.2.1: + resolution: { integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== } + dev: true + + /picomatch@2.3.1: + resolution: { integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== } + engines: { node: '>=8.6' } + dev: true + + /prebuild-install@7.1.1: + resolution: { integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw== } + engines: { node: '>=10' } + hasBin: true + dependencies: + detect-libc: 2.0.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.47.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: true + + /printable-characters@1.0.42: + resolution: { integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== } + dev: true + + /pump@3.0.0: + resolution: { integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== } + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /rc@1.2.8: + resolution: { integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== } + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: true + + /readable-stream@3.6.2: + resolution: { integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== } + engines: { node: '>= 6' } + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.6.0: + resolution: { integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== } + engines: { node: '>=8.10.0' } + dependencies: + picomatch: 2.3.1 + dev: true + + /rollup-plugin-inject@3.0.2: + resolution: { integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w== } + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. + dependencies: + estree-walker: 0.6.1 + magic-string: 0.25.9 + rollup-pluginutils: 2.8.2 + dev: true + + /rollup-plugin-node-polyfills@0.2.1: + resolution: { integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA== } + dependencies: + rollup-plugin-inject: 3.0.2 + dev: true + + /rollup-pluginutils@2.8.2: + resolution: { integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== } + dependencies: + estree-walker: 0.6.1 + dev: true + + /safe-buffer@5.2.1: + resolution: { integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== } + dev: true + + /selfsigned@2.1.1: + resolution: { integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== } + engines: { node: '>=10' } + dependencies: + node-forge: 1.3.1 + dev: true + + /semver@7.5.4: + resolution: { integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== } + engines: { node: '>=10' } + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /simple-concat@1.0.1: + resolution: { integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== } + dev: true + + /simple-get@4.0.1: + resolution: { integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== } + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + dev: true + + /source-map-support@0.5.21: + resolution: { integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== } + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: { integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== } + engines: { node: '>=0.10.0' } + dev: true + + /source-map@0.7.4: + resolution: { integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== } + engines: { node: '>= 8' } + dev: true + + /sourcemap-codec@1.4.8: + resolution: { integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== } + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: true + + /stacktracey@2.1.8: + resolution: { integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw== } + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + dev: true + + /stoppable@1.1.0: + resolution: { integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== } + engines: { node: '>=4', npm: '>=6' } + dev: true + + /streamsearch@1.1.0: + resolution: { integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== } + engines: { node: '>=10.0.0' } + dev: true + + /string_decoder@1.3.0: + resolution: { integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== } + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-json-comments@2.0.1: + resolution: { integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== } + engines: { node: '>=0.10.0' } + dev: true + + /tar-fs@2.1.1: + resolution: { integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== } + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: true + + /tar-stream@2.2.0: + resolution: { integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== } + engines: { node: '>=6' } + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /to-regex-range@5.0.1: + resolution: { integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== } + engines: { node: '>=8.0' } + dependencies: + is-number: 7.0.0 + dev: true + + /tslib@2.6.2: + resolution: { integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== } + dev: true + + /tunnel-agent@0.6.0: + resolution: { integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== } + dependencies: + safe-buffer: 5.2.1 + dev: true + + /undici@5.24.0: + resolution: { integrity: sha512-OKlckxBjFl0oXxcj9FU6oB8fDAaiRUq+D8jrFWGmOfI/gIyjk/IeS75LMzgYKUaeHzLUcYvf9bbJGSrUwTfwwQ== } + engines: { node: '>=14.0' } + dependencies: + busboy: 1.6.0 + dev: true + + /util-deprecate@1.0.2: + resolution: { integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== } + dev: true + + /workerd@1.20230904.0: + resolution: { integrity: sha512-t9znszH0rQGK4mJGvF9L3nN0qKEaObAGx0JkywFtAwH8OkSn+YfQbHNZE+YsJ4qa1hOz1DCNEk08UDFRBaYq4g== } + engines: { node: '>=16' } + hasBin: true + requiresBuild: true + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20230904.0 + '@cloudflare/workerd-darwin-arm64': 1.20230904.0 + '@cloudflare/workerd-linux-64': 1.20230904.0 + '@cloudflare/workerd-linux-arm64': 1.20230904.0 + '@cloudflare/workerd-windows-64': 1.20230904.0 + dev: true + + /wrangler@3.8.0: + resolution: { integrity: sha512-sTdD+6fMEpM9ROxv+gcyxgTKpnf7tB5ftRV5+wupsdljWkow5C00UCWU/IWSOUfuitAGAj1PWATjKfrRp9Bk9w== } + engines: { node: '>=16.13.0' } + hasBin: true + dependencies: + '@cloudflare/kv-asset-handler': 0.2.0 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 3.5.3 + esbuild: 0.17.19 + miniflare: 3.20230904.0 + nanoid: 3.3.6 + path-to-regexp: 6.2.1 + selfsigned: 2.1.1 + source-map: 0.7.4 + xxhash-wasm: 1.0.2 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /wrappy@1.0.2: + resolution: { integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== } + dev: true + + /ws@8.14.2: + resolution: { integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== } + engines: { node: '>=10.0.0' } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xxhash-wasm@1.0.2: + resolution: { integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A== } + dev: true + + /yallist@4.0.0: + resolution: { integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== } + dev: true + + /youch@3.3.1: + resolution: { integrity: sha512-Rg9ioi+AkKyje2Hk4qILSVvayaFW98KTsOJ4aIkjDf97LZX5WJVIHZmFLnM4ThcVofHo/fbbwtYajfBPHFOVtg== } + dependencies: + cookie: 0.5.0 + mustache: 4.2.0 + stacktracey: 2.1.8 + dev: true + + /zod@3.22.2: + resolution: { integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg== } + dev: true diff --git a/src/cache.rs b/src/cache.rs index d4505c3..700cecb 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,79 +1,37 @@ -use std::fmt::Debug; -use std::sync::{Arc, Mutex}; - -use anyhow::{anyhow, Result}; -use lazy_static::lazy_static; +use log::error; use serde::de::DeserializeOwned; -use serde::Serialize; - -use rocksdb::{Options, WriteBatch, DB}; +use serde::ser::Serialize; +use worker::kv::KvError; +use worker::Env; -lazy_static! { - pub static ref CACHE: Cache = { - let path = "./tmp/cache"; - let mut opts = Options::default(); - opts.create_if_missing(true); - let db = DB::open(&opts, path).unwrap_or_else(|_| panic!("Could not open storage")); - Cache { - storage: Arc::new(Mutex::new(db)), - } - }; +pub struct Cache<'a> { + store_name: String, + env: &'a Env, } -pub struct Cache { - storage: Arc>, -} - -impl Cache { - pub fn get(&self, key: &K) -> Result> - where - K: Serialize + Debug, - V: DeserializeOwned, - { - let storage = self.storage.lock().unwrap(); - let key_bytes = serde_json::to_vec(&key)?; - - match storage.get(key_bytes) { - Ok(Some(value_bytes)) => { - let value: V = serde_json::from_slice(&value_bytes)?; - Ok(Some(value)) - } - Ok(None) => Ok(None), - Err(err) => Err(anyhow!("Failed to get key {:?} from cache: {:?}", key, err)), - } +impl<'a> Cache<'a> { + pub fn new(store_name: String, env: &'a Env) -> Self { + Self { store_name, env } } - pub fn set(&self, key: K, value: V) -> Result<()> - where - K: Serialize + Debug, - V: Serialize, - { - let storage = self.storage.lock().unwrap(); - let key_bytes = serde_json::to_vec(&key)?; - let value_bytes = serde_json::to_vec(&value)?; - - storage.put(key_bytes, value_bytes)?; + pub fn from(env: &'a Env) -> Self { + let store_name = env.var("KV_STORE_NAME").unwrap().to_string(); - Ok(()) + Self::new(store_name, env) } - pub fn set_batch(&self, items: Vec<(K, V)>) -> Result<()> - where - K: Serialize + Debug, - V: Serialize, - { - let storage = self.storage.lock().unwrap(); - let mut batch = WriteBatch::default(); - - for (key, value) in items { - let key_bytes = serde_json::to_vec(&key)?; - let value_bytes = serde_json::to_vec(&value)?; - - batch.put(key_bytes, value_bytes); + pub async fn put(&self, key: &str, value: &T) { + let kv = self.env.kv(&self.store_name).unwrap(); + if let Ok(put) = kv.put(key, value) { + if let Err(pe) = put.execute().await { + error!("Failed updating KV: {}", pe) + } } + } - storage.write(batch)?; + pub async fn get(&self, key: &str) -> Result, KvError> { + let kv = self.env.kv(&self.store_name).unwrap(); - Ok(()) + kv.get(key).json::().await } } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b1f70f8 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,84 @@ +use cfg_if::cfg_if; +use log::{error, info, Level}; +use worker::{event, Date, Env, Request, Response, Result, ScheduleContext, ScheduledEvent}; + +use prop_house::fetcher::GraphQLFetcher as PropHouseGraphQLFetcher; +use prop_house::handler::DiscordHandler as PropHouseDiscordHandler; +use prop_lot::fetcher::GraphQLFetcher as PropLotGraphQLFetcher; +use prop_lot::handler::DiscordHandler as PropLotDiscordHandler; + +use crate::cache::Cache; + +mod cache; +mod prop_house; +mod prop_lot; + +cfg_if! { + // https://github.com/rustwasm/console_error_panic_hook#readme + if #[cfg(feature = "console_error_panic_hook")] { + pub use console_error_panic_hook::set_once as set_panic_hook; + } else { + #[inline] + pub fn set_panic_hook() {} + } +} + +#[event(scheduled)] +async fn cron(_event: ScheduledEvent, env: Env, _ctx: ScheduleContext) { + worker_logger::init_with_level(&Level::Debug); + set_panic_hook(); + + let cache = Cache::from(&env); + + let prop_lot_key = "PROP_LOT_SETUP"; + let prop_lot_fetcher = PropLotGraphQLFetcher::new(&env).unwrap(); + let prop_lot_handler = PropLotDiscordHandler::new(&env).unwrap(); + + let prop_house_key = "PROP_HOUSE_SETUP"; + let prop_house_fetcher = PropHouseGraphQLFetcher::new(&env).unwrap(); + let prop_house_handler = PropHouseDiscordHandler::new(&env).unwrap(); + + if cache.get::(prop_lot_key).await.ok().is_none() { + if let Err(e) = prop_lot::setup(&cache, &prop_lot_fetcher).await { + error!("Failed to setup prop_lot: {}", e); + } else { + // On successful setup, set the key in the cache. + let now: String = chrono::Utc::now().to_string(); + cache.put(prop_lot_key, &now).await; + } + } + + if let Err(e) = prop_lot::start(&cache, &prop_lot_fetcher, &prop_lot_handler).await { + error!("Failed to start prop_lot: {}", e); + } + + if cache.get::(prop_house_key).await.ok().is_none() { + if let Err(e) = prop_house::setup(&cache, &prop_house_fetcher).await { + error!("Failed to setup prop_house: {}", e); + } else { + // On successful setup, set the key in the cache. + let now = chrono::Utc::now().to_string(); + cache.put(prop_house_key, &now).await; + } + } + + if let Err(e) = prop_house::start(&cache, &prop_house_fetcher, &prop_house_handler).await { + error!("Failed to start prop_house: {}", e); + } +} + +#[event(fetch)] +pub async fn main(req: Request, _env: Env, _ctx: worker::Context) -> Result { + worker_logger::init_with_level(&Level::Debug); + set_panic_hook(); + + info!( + "{} - [{}], located at: {:?}, within: {}", + Date::now().to_string(), + req.path(), + req.cf().coordinates().unwrap_or_default(), + req.cf().region().unwrap_or_else(|| "unknown region".into()) + ); + + Response::error("Bad Request", 400) +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index f74f2e5..0000000 --- a/src/main.rs +++ /dev/null @@ -1,54 +0,0 @@ -use clap::{Parser, Subcommand}; -use env_logger::Env; -use log::{info, warn}; - -mod cache; -mod prop_house; -mod prop_lot; - -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -struct Cli { - #[command(subcommand)] - command: Option, -} - -#[derive(Subcommand)] -enum Commands { - /// Runs setups - Setup { - /// Forces the setup - #[arg(short, long)] - force: bool, - }, - /// Starts the program - Start, -} - -#[tokio::main] -async fn main() { - let env = Env::default() - .filter_or("BOT_LOG_LEVEL", "trace") - .write_style_or("BOT_LOG_STYLE", "always"); - - env_logger::init_from_env(env); - - let cli = Cli::parse(); - - match &cli.command { - Some(Commands::Setup { force }) => { - if *force { - info!("Running setup..."); - prop_lot::setup().await; - prop_house::setup().await; - } else { - warn!("Setup not forced, not running..."); - } - } - Some(Commands::Start) => { - prop_lot::start().await; - prop_house::start().await; - } - None => {} - } -} diff --git a/src/prop_house/cacher.rs b/src/prop_house/cacher.rs deleted file mode 100644 index dc9a719..0000000 --- a/src/prop_house/cacher.rs +++ /dev/null @@ -1,77 +0,0 @@ -use anyhow::Result; - -use crate::cache; -use crate::prop_house::fetcher::{Auction, Proposal, Vote}; - -const AUCTION_CACHE_KEY_PREFIX: &str = "PROP_HOUSE_AUCTION_"; -const PROPOSAL_CACHE_KEY_PREFIX: &str = "PROP_HOUSE_PROPOSAL_"; -const VOTE_CACHE_KEY_PREFIX: &str = "PROP_HOUSE_VOTE_"; - -fn auction_cache_key(id: isize) -> String { - format!("{}{}", AUCTION_CACHE_KEY_PREFIX, id) -} - -fn proposal_cache_key(id: isize) -> String { - format!("{}{}", PROPOSAL_CACHE_KEY_PREFIX, id) -} - -fn vote_cache_key(id: isize) -> String { - format!("{}{}", VOTE_CACHE_KEY_PREFIX, id) -} - -pub(crate) fn set_auction_cache(auction: &Auction) -> Result<()> { - let cache = &cache::CACHE; - cache.set(auction_cache_key(auction.id), auction) -} - -pub(crate) fn set_auctions_cache(auctions: &[Auction]) -> Result<()> { - let cache = &cache::CACHE; - let items: Vec<_> = auctions - .iter() - .map(|auction| (auction_cache_key(auction.id), auction)) - .collect(); - cache.set_batch(items) -} - -pub(crate) fn get_auction_cache(id: isize) -> Result> { - let cache = &cache::CACHE; - cache.get::(&auction_cache_key(id)) -} - -pub(crate) fn set_proposal_cache(proposal: &Proposal) -> Result<()> { - let cache = &cache::CACHE; - cache.set(proposal_cache_key(proposal.id), proposal) -} - -pub(crate) fn set_proposals_cache(proposals: &[Proposal]) -> Result<()> { - let cache = &cache::CACHE; - let items: Vec<_> = proposals - .iter() - .map(|proposal| (proposal_cache_key(proposal.id), proposal)) - .collect(); - cache.set_batch(items) -} - -pub(crate) fn get_proposal_cache(id: isize) -> Result> { - let cache = &cache::CACHE; - cache.get::(&proposal_cache_key(id)) -} - -pub(crate) fn set_vote_cache(vote: &Vote) -> Result<()> { - let cache = &cache::CACHE; - cache.set(vote_cache_key(vote.id), vote) -} - -pub(crate) fn set_votes_cache(votes: &[Vote]) -> Result<()> { - let cache = &cache::CACHE; - let items: Vec<_> = votes - .iter() - .map(|vote| (vote_cache_key(vote.id), vote)) - .collect(); - cache.set_batch(items) -} - -pub(crate) fn get_vote_cache(id: isize) -> Result> { - let cache = &cache::CACHE; - cache.get::(&vote_cache_key(id)) -} diff --git a/src/prop_house/fetcher.rs b/src/prop_house/fetcher.rs index 8e3a535..6568f2c 100644 --- a/src/prop_house/fetcher.rs +++ b/src/prop_house/fetcher.rs @@ -1,11 +1,9 @@ -use std::env; -use std::time::Duration; - use graphql_client::reqwest::post_graphql; use graphql_client::GraphQLQuery; use log::error; use reqwest::Client; use serde::{Deserialize, Serialize}; +use worker::{Env, Result}; #[derive(GraphQLQuery)] #[graphql( @@ -61,116 +59,112 @@ pub(crate) struct Vote { pub(crate) direction: isize, } -async fn fetch( - variables: ::Variables, -) -> Option<::ResponseData> { - let url = env::var("PROP_HOUSE_GRAPHQL_URL") - .map_err(|_| { - error!("PROP_HOUSE_GRAPHQL_URL is not set in env"); - }) - .ok()?; - - let client = Client::builder() - .timeout(Duration::from_secs(30)) - .build() - .map_err(|e| { - error!("Failed to create client: {}", e); - }) - .ok()?; - - post_graphql::(&client, url, variables) - .await - .map_err(|e| { - error!("Failed to execute GraphQL request: {}", e); - }) - .ok() - .and_then(|response| response.data) -} - -pub(crate) async fn fetch_auctions() -> Option> { - let community_id = env::var("PROP_HOUSE_COMMUNITY_ID") - .map_err(|_| { - error!("PROP_HOUSE_GRAPHQL_URL is not set in env"); - }) - .ok()?; - - let variables = auction_query::Variables { - id: community_id.parse().unwrap(), - }; - - let response = fetch::(variables).await?; - - let auctions = response - .community - .auctions - .iter() - .map(|auction| Auction { - id: auction.id.try_into().unwrap(), - title: auction.title.clone(), - description: html2md::parse_html(&auction.description), - }) - .collect(); - - Some(auctions) +pub struct GraphQLFetcher<'a> { + _env: &'a Env, + url: String, + community_id: String, } -pub(crate) async fn fetch_proposals() -> Option> { - let community_id = env::var("PROP_HOUSE_COMMUNITY_ID") - .map_err(|_| { - error!("PROP_HOUSE_GRAPHQL_URL is not set in env"); - }) - .ok()?; - - let variables = proposal_query::Variables { - id: community_id.parse().unwrap(), - }; - - let response = fetch::(variables).await?; - - let proposals = response - .community - .auctions - .iter() - .flat_map(|auction| &auction.proposals) - .map(|proposal| Proposal { - id: proposal.id.try_into().unwrap(), - title: proposal.title.clone(), - tldr: proposal.tldr.clone(), - address: proposal.address.clone(), - auction_id: proposal.auction.id.try_into().unwrap(), - }) - .collect(); +impl<'a> GraphQLFetcher<'a> { + pub fn new(env: &'a Env) -> Result> { + let url = env.var("PROP_HOUSE_GRAPHQL_URL")?.to_string(); - Some(proposals) -} + let community_id = env.var("PROP_HOUSE_COMMUNITY_ID")?.to_string(); -pub(crate) async fn fetch_votes() -> Option> { - let community_id = env::var("PROP_HOUSE_COMMUNITY_ID") - .map_err(|_| { - error!("PROP_HOUSE_GRAPHQL_URL is not set in env"); + Ok(GraphQLFetcher { + _env: env, + url, + community_id, }) - .ok()?; - - let variables = vote_query::Variables { - id: community_id.parse().unwrap(), - }; - - let response = fetch::(variables).await?; - - let votes = response - .community - .auctions - .iter() - .flat_map(|auction| &auction.proposals) - .flat_map(|proposal| &proposal.votes) - .map(|vote| Vote { - id: vote.id.try_into().unwrap(), - address: vote.address.clone(), - auction_id: vote.auction_id.try_into().unwrap(), - proposal_id: vote.proposal_id.try_into().unwrap(), - direction: vote.direction.try_into().unwrap(), - }) - .collect(); - - Some(votes) + } + + async fn fetch( + &self, + variables: ::Variables, + ) -> Option<::ResponseData> { + let client = Client::builder() + .build() + .map_err(|e| { + error!("Failed to create client: {}", e); + }) + .ok()?; + + post_graphql::(&client, &self.url, variables) + .await + .map_err(|e| { + error!("Failed to execute GraphQL request: {}", e); + }) + .ok() + .and_then(|response| response.data) + } + + pub(crate) async fn fetch_auctions(&self) -> Option> { + let variables = auction_query::Variables { + id: self.community_id.parse().unwrap(), + }; + + let response = self.fetch::(variables).await?; + + let auctions = response + .community + .auctions + .iter() + .map(|auction| Auction { + id: auction.id.try_into().unwrap(), + title: auction.title.clone(), + description: html2md::parse_html(&auction.description), + }) + .collect(); + + Some(auctions) + } + + pub(crate) async fn fetch_proposals(&self) -> Option> { + let variables = proposal_query::Variables { + id: self.community_id.parse().unwrap(), + }; + + let response = self.fetch::(variables).await?; + + let proposals = response + .community + .auctions + .iter() + .flat_map(|auction| &auction.proposals) + .map(|proposal| Proposal { + id: proposal.id.try_into().unwrap(), + title: proposal.title.clone(), + tldr: proposal.tldr.clone(), + address: proposal.address.clone(), + auction_id: proposal.auction.id.try_into().unwrap(), + }) + .collect(); + + Some(proposals) + } + + pub(crate) async fn fetch_votes(&self) -> Option> { + let variables = vote_query::Variables { + id: self.community_id.parse().unwrap(), + }; + + let response = self.fetch::(variables).await?; + + let votes = response + .community + .auctions + .iter() + .flat_map(|auction| &auction.proposals) + .flat_map(|proposal| &proposal.votes) + .map(|vote| Vote { + id: vote.id.try_into().unwrap(), + address: vote.address.clone(), + auction_id: vote.auction_id.try_into().unwrap(), + proposal_id: vote.proposal_id.try_into().unwrap(), + direction: vote.direction.try_into().unwrap(), + }) + .collect(); + + Some(votes) + } } diff --git a/src/prop_house/handler.rs b/src/prop_house/handler.rs index 048532c..d194d75 100644 --- a/src/prop_house/handler.rs +++ b/src/prop_house/handler.rs @@ -1,146 +1,181 @@ -use std::env; - -use anyhow::{Context, Result}; use chrono::Local; -use serenity::http::Http; -use serenity::json::Value; -use serenity::model::channel::Embed; -use serenity::model::webhook::Webhook; - -use crate::prop_house::cacher::{ - get_auction_cache, get_proposal_cache, set_auction_cache, set_proposal_cache, set_vote_cache, -}; +use log::error; +use reqwest::{header, Client}; +use serde_json::{json, Value}; +use worker::{Env, Result}; + +use crate::cache::Cache; use crate::prop_house::fetcher::{Auction, Proposal, Vote}; -pub struct DiscordHandler { +pub struct DiscordHandler<'a> { base_url: String, - http: Http, - webhook: Webhook, + webhook_url: String, + cache: Cache<'a>, + client: Client, } -impl DiscordHandler { - pub async fn new() -> Result { - let base_url = - env::var("PROP_HOUSE_BASE_URL").context("PROP_HOUSE_BASE_URL is not set in env")?; +impl<'a> DiscordHandler<'a> { + pub fn new(env: &'a Env) -> Result> { + let base_url = env.var("PROP_HOUSE_BASE_URL")?.to_string(); + let webhook_url = env.var("PROP_HOUSE_DISCORD_WEBHOOK_URL")?.to_string(); - let webhook_url = env::var("PROP_HOUSE_DISCORD_WEBHOOK_URL") - .context("PROP_HOUSE_DISCORD_WEBHOOK_URL is not set in env")?; - - let http = Http::new(""); - let webhook = Webhook::from_url(&http, webhook_url.as_str()) - .await - .context("Failed to create webhook from URL")?; + let cache = Cache::from(env); + let client = Client::new(); - Ok(Self { + Ok(DiscordHandler { base_url, - http, - webhook, + webhook_url, + cache, + client, }) } - async fn execute_webhook(&self, message: Value) -> Result<()> { - self.webhook - .execute(&self.http, false, |w| w.embeds(vec![message])) + async fn execute_webhook(&self, embed: Value) -> Result<()> { + let msg_json = json!({"embeds": [embed]}); + + self.client + .post(&self.webhook_url) + .header(header::CONTENT_TYPE, "application/json") + .body(msg_json.to_string()) + .send() .await - .context("Failed to execute webhook")?; + .map_err(|e| worker::Error::from(format!("Failed to execute webhook: {}", e)))?; Ok(()) } pub(crate) async fn handle_new_auction(&self, auction: &Auction) -> Result<()> { - let message = Embed::fake(|e| { - e.title("New Prop House Round") - .url(format!( - "{}/{}", - self.base_url, - auction.title.replace(' ', "-").to_lowercase() - )) - .description(format!( - "A new Prop House round has been created: {}", - auction.title - )) - .footer(|f| f.text(format!("{}", Local::now().format("%m/%d/%Y %I:%M %p")))) - .colour(0x8A2CE2) + let date = Local::now().format("%m/%d/%Y %I:%M %p"); + + let embed = json!({ + "title": "New Prop House Round", + "description": format!( + "A new Prop House round has been created: {}", + auction.title + ), + "url": format!("{}/{}", self.base_url, auction.title.replace(' ', "-").to_lowercase()), + "color": 0x8A2CE2, + "footer": { + "text": format!("{}", date) + } }); - self.execute_webhook(message).await?; + self.execute_webhook(embed).await?; - set_auction_cache(auction)?; + self.cache + .put(&format!("{}{}", "PROP_HOUSE_AUCTION_", auction.id), auction) + .await; Ok(()) } pub(crate) async fn handle_new_proposal(&self, proposal: &Proposal) -> Result<()> { - let auction = get_auction_cache(proposal.auction_id)? - .ok_or_else(|| anyhow::anyhow!("No auction found for id {}", proposal.auction_id))?; + let date = Local::now().format("%m/%d/%Y %I:%M %p"); - let message = Embed::fake(|e| { - e.author(|a| { - a.name(format!( - "{}...{}", - &proposal.address[0..4], - &proposal.address[38..42] - )) - .url(format!("https://etherscan.io/address/{}", proposal.address)) - }) - .title("New Prop House Proposal") - .url(format!( + let auction = self + .cache + .get::(&format!("{}{}", "PROP_HOUSE_AUCTION_", proposal.auction_id)) + .await? + .unwrap(); + + let embed = json!({ + "title": "New Prop House Proposal", + "description": format!( + "A new Prop House proposal has been created: {}", + proposal.title + ), + "url": format!( "{}/{}/{}", self.base_url, auction.title.replace(' ', "-").to_lowercase(), proposal.id - )) - .description(format!( - "A new Prop House proposal has been created: {}", - proposal.title - )) - .footer(|f| f.text(format!("{}", Local::now().format("%m/%d/%Y %I:%M %p")))) - .colour(0x8A2CE2) + ), + "color": 0x8A2CE2, + "footer": { + "text": format!("{}", date) + }, + "author": { + "name": format!( + "{}...{}", + &proposal.address[0..4], + &proposal.address[38..42] + ), + "url": format!( + "https://etherscan.io/address/{}", + proposal.address + ) + } }); - self.execute_webhook(message).await?; + self.execute_webhook(embed).await?; - set_proposal_cache(proposal)?; + self.cache + .put( + &format!("{}{}", "PROP_HOUSE_PROPOSAL_", proposal.id), + proposal, + ) + .await; Ok(()) } pub(crate) async fn handle_new_vote(&self, vote: &Vote) -> Result<()> { - let proposal = get_proposal_cache(vote.proposal_id)? - .ok_or_else(|| anyhow::anyhow!("No proposal found for id {}", vote.proposal_id))?; - - let message = Embed::fake(|e| { - e.author(|a| { - a.name(format!( + let date = Local::now().format("%m/%d/%Y %I:%M %p"); + + let proposal = match self + .cache + .get::(&format!("{}{}", "PROP_HOUSE_PROPOSAL_", vote.proposal_id)) + .await? + { + Some(i) => i, + None => { + error!("Proposal not found for id: {}", vote.proposal_id); + return Ok(()); + } + }; + + let embed = json!({ + "title": "New Prop House Proposal Vote", + "description": format!( + "{} has voted {} Proposal", + format!( "{}...{}", &vote.address[0..4], &vote.address[38..42] - )) - .url(format!("https://etherscan.io/address/{}", vote.address)) - }) - .title("New Prop House Proposal Vote") - .url(format!( + ), + match vote.direction { + 1 => "for", + _ => "against" + } + ), + "url": format!( "{}/{}/{}", self.base_url, proposal.title.replace(' ', "-").to_lowercase(), proposal.id - )) - .description(format!( - "{} has voted {} Proposal ({})", - format!("{}...{}", &vote.address[0..4], &vote.address[38..42]), - match vote.direction { - 1 => "for", - _ => "against", - }, - proposal.title - )) - .footer(|f| f.text(format!("{}", Local::now().format("%m/%d/%Y %I:%M %p")))) - .colour(0x8A2CE2) + ), + "color": 0x8A2CE2, + "footer": { + "text": format!("{}", date) + }, + "author": { + "name": format!( + "{}...{}", + &vote.address[0..4], + &vote.address[38..42] + ), + "url": format!( + "https://etherscan.io/address/{}", + vote.address + ) + } }); - self.execute_webhook(message).await?; + self.execute_webhook(embed).await?; - set_vote_cache(vote)?; + self.cache + .put(&format!("{}{}", "PROP_HOUSE_VOTE_", vote.id), vote) + .await; Ok(()) } diff --git a/src/prop_house/mod.rs b/src/prop_house/mod.rs index c18eff0..b947ca1 100644 --- a/src/prop_house/mod.rs +++ b/src/prop_house/mod.rs @@ -1,73 +1,97 @@ use log::{error, info}; +use worker::Result; -use fetcher::fetch_auctions; +use fetcher::{Auction, GraphQLFetcher, Proposal, Vote}; +use handler::DiscordHandler; -use crate::prop_house::cacher::{ - get_auction_cache, get_proposal_cache, get_vote_cache, set_auctions_cache, set_proposals_cache, - set_votes_cache, -}; -use crate::prop_house::fetcher::{fetch_proposals, fetch_votes}; -use crate::prop_house::handler::DiscordHandler; +use crate::cache::Cache; -mod cacher; -mod fetcher; -mod handler; +pub mod fetcher; +pub mod handler; -pub async fn setup() { - if let Some(auctions) = fetch_auctions().await { - set_auctions_cache(&auctions).unwrap(); +pub async fn setup(cache: &Cache<'_>, fetcher: &GraphQLFetcher<'_>) -> Result<()> { + if let Some(auctions) = fetcher.fetch_auctions().await { + for auction in auctions { + cache + .put( + &format!("{}{}", "PROP_HOUSE_AUCTION_", auction.id), + &auction, + ) + .await; + } } - if let Some(proposals) = fetch_proposals().await { - set_proposals_cache(&proposals).unwrap(); + if let Some(proposals) = fetcher.fetch_proposals().await { + for proposal in proposals { + cache + .put( + &format!("{}{}", "PROP_HOUSE_PROPOSAL_", proposal.id), + &proposal, + ) + .await; + } } - if let Some(votes) = fetch_votes().await { - set_votes_cache(&votes).unwrap(); + if let Some(votes) = fetcher.fetch_votes().await { + for vote in votes { + cache + .put(&format!("{}{}", "PROP_HOUSE_VOTE_", vote.id), &vote) + .await; + } } -} -pub async fn start() { - let handler = DiscordHandler::new() - .await - .expect("Could not create a new DiscordHandler"); + Ok(()) +} - if let Some(auctions) = fetch_auctions().await { +pub async fn start( + cache: &Cache<'_>, + fetcher: &GraphQLFetcher<'_>, + handler: &DiscordHandler<'_>, +) -> Result<()> { + if let Some(auctions) = fetcher.fetch_auctions().await { for auction in auctions { - if let Ok(cached_auction) = get_auction_cache(auction.id) { - if cached_auction.is_none() { - info!("Handle a new auction... ({:?})", auction.id); - if let Err(err) = handler.handle_new_auction(&auction).await { - error!("Failed to handle new auction: {:?}", err); - } + let cached_auction: Option = cache + .get(&format!("{}{}", "PROP_HOUSE_AUCTION_", auction.id)) + .await?; + + if cached_auction.is_none() { + info!("Handle a new auction... ({:?})", auction.id); + if let Err(err) = handler.handle_new_auction(&auction).await { + error!("Failed to handle new auction: {:?}", err); } } } } - if let Some(proposals) = fetch_proposals().await { + if let Some(proposals) = fetcher.fetch_proposals().await { for proposal in proposals { - if let Ok(cached_proposal) = get_proposal_cache(proposal.id) { - if cached_proposal.is_none() { - info!("Handle a new proposal... ({:?})", proposal.id); - if let Err(err) = handler.handle_new_proposal(&proposal).await { - error!("Failed to handle new proposal: {:?}", err); - } + let cached_proposal: Option = cache + .get(&format!("{}{}", "PROP_HOUSE_PROPOSAL_", proposal.id)) + .await?; + + if cached_proposal.is_none() { + info!("Handle a new proposal... ({:?})", proposal.id); + if let Err(err) = handler.handle_new_proposal(&proposal).await { + error!("Failed to handle new proposal: {:?}", err); } } } } - if let Some(votes) = fetch_votes().await { + if let Some(votes) = fetcher.fetch_votes().await { for vote in votes { - if let Ok(cached_vote) = get_vote_cache(vote.id) { - if cached_vote.is_none() { - info!("Handle a new vote... ({:?})", vote.id); - if let Err(err) = handler.handle_new_vote(&vote).await { - error!("Failed to handle new vote: {:?}", err); - } + let cached_vote: Option = cache + .get(&format!("{}{}", "PROP_HOUSE_VOTE_", vote.id)) + .await?; + + if cached_vote.is_none() { + info!("Handle a new vote... ({:?})", vote.id); + if let Err(err) = handler.handle_new_vote(&vote).await { + error!("Failed to handle new vote: {:?}", err); } } } } + + Ok(()) } diff --git a/src/prop_lot/cacher.rs b/src/prop_lot/cacher.rs deleted file mode 100644 index 9ff421d..0000000 --- a/src/prop_lot/cacher.rs +++ /dev/null @@ -1,79 +0,0 @@ -use anyhow::Result; - -use crate::cache; -use crate::prop_lot::fetcher::{Comment, Idea, Vote}; - -const IDEA_CACHE_KEY_PREFIX: &str = "PROP_LOT_IDEA_"; - -const VOTE_CACHE_KEY_PREFIX: &str = "PROP_LOT_VOTE_"; - -const COMMENT_CACHE_KEY_PREFIX: &str = "PROP_LOT_COMMENT_"; - -fn idea_cache_key(id: isize) -> String { - format!("{}{}", IDEA_CACHE_KEY_PREFIX, id) -} - -fn vote_cache_key(id: isize) -> String { - format!("{}{}", VOTE_CACHE_KEY_PREFIX, id) -} - -fn comment_cache_key(id: isize) -> String { - format!("{}{}", COMMENT_CACHE_KEY_PREFIX, id) -} - -pub(crate) fn set_idea_cache(idea: &Idea) -> Result<()> { - let cache = &cache::CACHE; - cache.set(idea_cache_key(idea.id), idea) -} - -pub(crate) fn set_ideas_cache(ideas: &[Idea]) -> Result<()> { - let cache = &cache::CACHE; - let items: Vec<_> = ideas - .iter() - .map(|idea| (idea_cache_key(idea.id), idea)) - .collect(); - cache.set_batch(items) -} - -pub(crate) fn get_idea_cache(id: isize) -> Result> { - let cache = &cache::CACHE; - cache.get::(&idea_cache_key(id)) -} - -pub(crate) fn set_vote_cache(vote: &Vote) -> Result<()> { - let cache = &cache::CACHE; - cache.set(vote_cache_key(vote.id), vote) -} - -pub(crate) fn set_votes_cache(votes: &[Vote]) -> Result<()> { - let cache = &cache::CACHE; - let items: Vec<_> = votes - .iter() - .map(|vote| (vote_cache_key(vote.id), vote)) - .collect(); - cache.set_batch(items) -} - -pub(crate) fn get_vote_cache(id: isize) -> Result> { - let cache = &cache::CACHE; - cache.get::(&vote_cache_key(id)) -} - -pub(crate) fn set_comment_cache(comment: &Comment) -> Result<()> { - let cache = &cache::CACHE; - cache.set(comment_cache_key(comment.id), comment) -} - -pub(crate) fn set_comments_cache(comments: &[Comment]) -> Result<()> { - let cache = &cache::CACHE; - let items: Vec<_> = comments - .iter() - .map(|comment| (comment_cache_key(comment.id), comment)) - .collect(); - cache.set_batch(items) -} - -pub(crate) fn get_comment_cache(id: isize) -> Result> { - let cache = &cache::CACHE; - cache.get::(&comment_cache_key(id)) -} diff --git a/src/prop_lot/fetcher.rs b/src/prop_lot/fetcher.rs index 26b8f0c..29e8fec 100644 --- a/src/prop_lot/fetcher.rs +++ b/src/prop_lot/fetcher.rs @@ -1,12 +1,11 @@ use std::convert::TryInto; -use std::env; -use std::time::Duration; use graphql_client::reqwest::post_graphql; use graphql_client::GraphQLQuery; use log::error; use reqwest::Client; use serde::{Deserialize, Serialize}; +use worker::{Env, Result}; #[derive(GraphQLQuery)] #[graphql( @@ -62,108 +61,114 @@ pub(crate) struct Comment { pub(crate) body: String, } -async fn fetch( - variables: ::Variables, -) -> Option<::ResponseData> { - let url = env::var("PROP_LOT_GRAPHQL_URL") - .map_err(|_| { - error!("PROP_LOT_GRAPHQL_URL is not set in env"); - }) - .ok()?; - - let client = Client::builder() - .timeout(Duration::from_secs(30)) - .build() - .map_err(|e| { - error!("Failed to create client: {}", e); - }) - .ok()?; - - post_graphql::(&client, url, variables) - .await - .map_err(|e| { - error!("Failed to execute GraphQL request: {}", e); - }) - .ok() - .and_then(|response| response.data) +pub struct GraphQLFetcher<'a> { + _env: &'a Env, + url: String, } -pub(crate) async fn fetch_ideas() -> Option> { - let variables = idea_query::Variables { - options: idea_query::IdeaInputOptions { - idea_id: None, - sort: Some(idea_query::SORT_TYPE::OLDEST), - }, - }; - - let response = fetch::(variables).await?; - - let ideas = response - .ideas - .as_ref()? - .iter() - .map(|idea| Idea { - id: idea.id.try_into().unwrap(), - title: idea.title.clone(), - tldr: idea.tldr.clone(), - creator_id: idea.creator_id.clone(), - }) - .collect(); - - Some(ideas) -} - -pub(crate) async fn fetch_votes() -> Option> { - let variables = vote_query::Variables { - options: vote_query::IdeaInputOptions { - idea_id: None, - sort: Some(vote_query::SORT_TYPE::LATEST), - }, - }; - - let response = fetch::(variables).await?; - - let votes = response - .ideas - .as_ref()? - .iter() - .flat_map(|idea| idea.votes.iter()) - .flat_map(|vote| vote.iter()) - .map(|vote| Vote { - id: vote.id.try_into().unwrap(), - voter_id: vote.voter_id.clone(), - idea_id: vote.idea_id.try_into().unwrap(), - direction: vote.direction.try_into().unwrap(), - voter_weight: vote.voter_weight.try_into().unwrap(), - }) - .collect(); - - Some(votes) -} - -pub(crate) async fn fetch_comments() -> Option> { - let variables = comment_query::Variables { - options: comment_query::IdeaInputOptions { - idea_id: None, - sort: Some(comment_query::SORT_TYPE::LATEST), - }, - }; - - let response = fetch::(variables).await?; - - let comments = response - .ideas - .as_ref()? - .iter() - .flat_map(|idea| idea.comments.iter()) - .flat_map(|comment| comment.iter()) - .map(|comment| Comment { - id: comment.id.try_into().unwrap(), - idea_id: comment.id.try_into().unwrap(), - author_id: comment.author_id.clone(), - body: comment.body.clone(), - }) - .collect(); - - Some(comments) +impl<'a> GraphQLFetcher<'a> { + pub fn new(env: &'a Env) -> Result> { + let url = env.var("PROP_LOT_GRAPHQL_URL")?.to_string(); + + Ok(GraphQLFetcher { _env: env, url }) + } + async fn fetch( + &self, + variables: ::Variables, + ) -> Option<::ResponseData> { + let client = Client::builder() + .build() + .map_err(|e| { + error!("Failed to create client: {}", e); + }) + .ok()?; + + post_graphql::(&client, &self.url, variables) + .await + .map_err(|e| { + error!("Failed to execute GraphQL request: {}", e); + }) + .ok() + .and_then(|response| response.data) + } + + pub(crate) async fn fetch_ideas(&self) -> Option> { + let variables = idea_query::Variables { + options: idea_query::IdeaInputOptions { + idea_id: None, + sort: Some(idea_query::SORT_TYPE::OLDEST), + }, + }; + + let response = self.fetch::(variables).await?; + + let ideas = response + .ideas + .as_ref()? + .iter() + .map(|idea| Idea { + id: idea.id.try_into().unwrap(), + title: idea.title.clone(), + tldr: idea.tldr.clone(), + creator_id: idea.creator_id.clone(), + }) + .collect(); + + Some(ideas) + } + + pub(crate) async fn fetch_votes(&self) -> Option> { + let variables = vote_query::Variables { + options: vote_query::IdeaInputOptions { + idea_id: None, + sort: Some(vote_query::SORT_TYPE::LATEST), + }, + }; + + let response = self.fetch::(variables).await?; + + let votes = response + .ideas + .as_ref()? + .iter() + .flat_map(|idea| idea.votes.iter()) + .flat_map(|vote| vote.iter()) + .map(|vote| Vote { + id: vote.id.try_into().unwrap(), + voter_id: vote.voter_id.clone(), + idea_id: vote.idea_id.try_into().unwrap(), + direction: vote.direction.try_into().unwrap(), + voter_weight: vote.voter_weight.try_into().unwrap(), + }) + .collect(); + + Some(votes) + } + + pub(crate) async fn fetch_comments(&self) -> Option> { + let variables = comment_query::Variables { + options: comment_query::IdeaInputOptions { + idea_id: None, + sort: Some(comment_query::SORT_TYPE::LATEST), + }, + }; + + let response = self.fetch::(variables).await?; + + let comments = response + .ideas + .as_ref()? + .iter() + .flat_map(|idea| idea.comments.iter()) + .flat_map(|comment| comment.iter()) + .map(|comment| Comment { + id: comment.id.try_into().unwrap(), + idea_id: comment.idea_id.try_into().unwrap(), + author_id: comment.author_id.clone(), + body: comment.body.clone(), + }) + .collect(); + + Some(comments) + } } diff --git a/src/prop_lot/handler.rs b/src/prop_lot/handler.rs index d23b800..62d1d5b 100644 --- a/src/prop_lot/handler.rs +++ b/src/prop_lot/handler.rs @@ -1,132 +1,169 @@ -use std::env; - -use anyhow::{Context, Result}; use chrono::Local; -use serenity::json::Value; -use serenity::{ - http::Http, - model::{channel::Embed, webhook::Webhook}, -}; +use log::error; +use reqwest::{header, Client}; +use serde_json::{json, Value}; +use worker::{Env, Result}; -use crate::prop_lot::cacher::{get_idea_cache, set_comment_cache, set_idea_cache, set_vote_cache}; +use crate::cache::Cache; use crate::prop_lot::fetcher::{Comment, Idea, Vote}; -pub struct DiscordHandler { +pub struct DiscordHandler<'a> { base_url: String, - http: Http, - webhook: Webhook, + webhook_url: String, + cache: Cache<'a>, + client: Client, } -impl DiscordHandler { - pub async fn new() -> Result { - let base_url = - env::var("PROP_LOT_BASE_URL").context("PROP_LOT_BASE_URL is not set in env")?; - - let webhook_url = env::var("PROP_LOT_DISCORD_WEBHOOK_URL") - .context("PROP_LOT_DISCORD_WEBHOOK_URL is not set in env")?; +impl<'a> DiscordHandler<'a> { + pub fn new(env: &'a Env) -> Result> { + let base_url = env.var("PROP_LOT_BASE_URL")?.to_string(); + let webhook_url = env.var("PROP_LOT_DISCORD_WEBHOOK_URL")?.to_string(); - let http = Http::new(""); - let webhook = Webhook::from_url(&http, webhook_url.as_str()) - .await - .context("Failed to create webhook from URL")?; + let cache = Cache::from(env); + let client = Client::new(); - Ok(Self { + Ok(DiscordHandler { base_url, - http, - webhook, + webhook_url, + cache, + client, }) } - async fn execute_webhook(&self, message: Value) -> Result<()> { - self.webhook - .execute(&self.http, false, |w| w.embeds(vec![message])) + async fn execute_webhook(&self, embed: Value) -> Result<()> { + let msg_json = json!({"embeds": [embed]}); + + self.client + .post(&self.webhook_url) + .header(header::CONTENT_TYPE, "application/json") + .body(msg_json.to_string()) + .send() .await - .context("Failed to execute webhook")?; + .map_err(|e| worker::Error::from(format!("Failed to execute webhook: {}", e)))?; Ok(()) } pub(crate) async fn handle_new_idea(&self, idea: &Idea) -> Result<()> { - let message = Embed::fake(|e| { - e.author(|a| { - a.name(format!( + let date = Local::now().format("%m/%d/%Y %I:%M %p"); + + let embed = json!({ + "title": "New Prop Lot Proposal", + "description": format!( + "A new Prop Lot proposal has been created: {}", + idea.title + ), + "url": format!( + "{}/idea/{}", + self.base_url, + idea.id + ), + "color": 0xFFB911, + "footer": { + "text": format!("{}", date) + }, + "author": { + "name": format!( "{}...{}", &idea.creator_id[0..4], &idea.creator_id[38..42] - )) - .url(format!("https://etherscan.io/address/{}", idea.creator_id)) - }) - .title("New Prop Lot Proposal") - .url(format!("{}/idea/{}", self.base_url, idea.id)) - .description(format!( - "A new Prop Lot proposal has been created: {}", - idea.title - )) - .footer(|f| f.text(format!("{}", Local::now().format("%m/%d/%Y %I:%M %p")))) - .colour(0xFFB911) + ), + "url": format!( + "{}/idea/{}", + self.base_url, + idea.id + ) + } }); - self.execute_webhook(message).await?; + self.execute_webhook(embed).await?; - set_idea_cache(idea)?; + self.cache + .put(&format!("{}{}", "PROP_LOT_IDEA_", idea.id), idea) + .await; Ok(()) } pub(crate) async fn handle_new_vote(&self, vote: &Vote) -> Result<()> { - let idea = get_idea_cache(vote.idea_id)? - .ok_or_else(|| anyhow::anyhow!("No idea found for id {}", vote.idea_id))?; - - let message = Embed::fake(|e| { - e.author(|a| { - a.name(format!( + let date = Local::now().format("%m/%d/%Y %I:%M %p"); + + let idea = match self + .cache + .get::(&format!("{}{}", "PROP_LOT_IDEA_", vote.idea_id)) + .await? + { + Some(i) => i, + None => { + error!("Idea not found for id: {}", vote.idea_id); + return Ok(()); + } + }; + + let embed = json!({ + "title": "New Prop Lot Proposal Vote", + "description": format!( + "{} has voted {} Proposal ({})", + format!( "{}...{}", &vote.voter_id[0..4], &vote.voter_id[38..42] - )) - .url(format!("https://etherscan.io/address/{}", vote.voter_id)) - }) - .title("New Prop Lot Proposal Vote") - .url(format!("{}/idea/{}", self.base_url, idea.id)) - .description(format!( - "{} has voted {} Proposal ({})", - format!("{}...{}", &vote.voter_id[0..4], &vote.voter_id[38..42]), + ), match vote.direction { 1 => "for", _ => "against", }, idea.title - )) - .footer(|f| f.text(format!("{}", Local::now().format("%m/%d/%Y %I:%M %p")))) - .colour(0x8A2CE2) + ), + "url": format!( + "{}/idea/{}", + self.base_url, + idea.id + ), + "color": 0xFFB911, + "footer": { + "text": format!("{}", date) + }, + "author": { + "name": format!( + "{}...{}", + &vote.voter_id[0..4], + &vote.voter_id[38..42] + ), + "url": format!( + "https://etherscan.io/address/{}", + vote.voter_id + ) + } }); - self.execute_webhook(message).await?; + self.execute_webhook(embed).await?; - set_vote_cache(vote)?; + self.cache + .put(&format!("{}{}", "PROP_LOT_VOTE_", vote.id), vote) + .await; Ok(()) } pub(crate) async fn handle_new_comment(&self, comment: &Comment) -> Result<()> { - let idea = get_idea_cache(comment.idea_id)? - .ok_or_else(|| anyhow::anyhow!("No idea found for id {}", comment.idea_id))?; - - let message = Embed::fake(|e| { - e.author(|a| { - a.name(format!( - "{}...{}", - &comment.author_id[0..4], - &comment.author_id[38..42] - )) - .url(format!( - "https://etherscan.io/address/{}", - comment.author_id - )) - }) - .title("New Prop Lot Proposal Comment") - .url(format!("{}/idea/{}", self.base_url, idea.id)) - .description(format!( + let date = Local::now().format("%m/%d/%Y %I:%M %p"); + + let idea = match self + .cache + .get::(&format!("{}{}", "PROP_LOT_IDEA_", comment.idea_id)) + .await? + { + Some(i) => i, + None => { + error!("Idea not found for id: {}", comment.idea_id); + return Ok(()); + } + }; + + let embed = json!({ + "title": "New Prop Lot Proposal Comment", + "description": format!( "{} has commented on Proposal ({})", format!( "{}...{}", @@ -134,14 +171,34 @@ impl DiscordHandler { &comment.author_id[38..42] ), idea.title - )) - .footer(|f| f.text(format!("{}", Local::now().format("%m/%d/%Y %I:%M %p")))) - .colour(0x8A2CE2) + ), + "url": format!( + "{}/idea/{}", + self.base_url, + idea.id + ), + "color": 0xFFB911, + "footer": { + "text": format!("{}", date) + }, + "author": { + "name": format!( + "{}...{}", + &comment.author_id[0..4], + &comment.author_id[38..42] + ), + "url": format!( + "https://etherscan.io/address/{}", + comment.author_id + ) + } }); - self.execute_webhook(message).await?; + self.execute_webhook(embed).await?; - set_comment_cache(comment)?; + self.cache + .put(&format!("{}{}", "PROP_LOT_COMMENT_", comment.id), comment) + .await; Ok(()) } diff --git a/src/prop_lot/mod.rs b/src/prop_lot/mod.rs index 20b8e3c..c7c6728 100644 --- a/src/prop_lot/mod.rs +++ b/src/prop_lot/mod.rs @@ -1,73 +1,91 @@ use log::{error, info}; +use worker::Result; -use fetcher::fetch_ideas; +use fetcher::{Comment, GraphQLFetcher, Idea, Vote}; +use handler::DiscordHandler; -use crate::prop_lot::cacher::{ - get_comment_cache, get_idea_cache, get_vote_cache, set_comments_cache, set_ideas_cache, - set_votes_cache, -}; -use crate::prop_lot::fetcher::{fetch_comments, fetch_votes}; -use crate::prop_lot::handler::DiscordHandler; +use crate::cache::Cache; -mod cacher; -mod fetcher; -mod handler; +pub mod fetcher; +pub mod handler; -pub async fn setup() { - if let Some(ideas) = fetch_ideas().await { - set_ideas_cache(&ideas).unwrap(); +pub async fn setup(cache: &Cache<'_>, fetcher: &GraphQLFetcher<'_>) -> Result<()> { + if let Some(ideas) = fetcher.fetch_ideas().await { + for idea in ideas { + cache + .put(&format!("{}{}", "PROP_LOT_IDEA_", idea.id), &idea) + .await; + } } - if let Some(votes) = fetch_votes().await { - set_votes_cache(&votes).unwrap(); + if let Some(votes) = fetcher.fetch_votes().await { + for vote in votes { + cache + .put(&format!("{}{}", "PROP_LOT_VOTE_", vote.id), &vote) + .await; + } } - if let Some(comments) = fetch_comments().await { - set_comments_cache(&comments).unwrap(); + if let Some(comments) = fetcher.fetch_comments().await { + for comment in comments { + cache + .put(&format!("{}{}", "PROP_LOT_COMMENT_", comment.id), &comment) + .await; + } } -} -pub async fn start() { - let handler = DiscordHandler::new() - .await - .expect("Could not create a new DiscordHandler"); + Ok(()) +} - if let Some(ideas) = fetch_ideas().await { +pub async fn start( + cache: &Cache<'_>, + fetcher: &GraphQLFetcher<'_>, + handler: &DiscordHandler<'_>, +) -> Result<()> { + if let Some(ideas) = fetcher.fetch_ideas().await { for idea in &ideas { - if let Ok(cached_idea) = get_idea_cache(idea.id) { - if cached_idea.is_none() { - info!("Handle a new idea... ({:?})", idea.id); - if let Err(err) = handler.handle_new_idea(idea).await { - error!("Failed to handle new idea: {:?}", err); - } + let cached_idea: Option = cache + .get(&format!("{}{}", "PROP_LOT_IDEA_", idea.id)) + .await?; + + if cached_idea.is_none() { + info!("Handle a new idea... ({:?})", idea.id); + if let Err(err) = handler.handle_new_idea(idea).await { + error!("Failed to handle new idea: {:?}", err); } } } } - if let Some(votes) = fetch_votes().await { + if let Some(votes) = fetcher.fetch_votes().await { for vote in &votes { - if let Ok(cached_vote) = get_vote_cache(vote.id) { - if cached_vote.is_none() { - info!("Handle a new vote... ({:?})", vote.id); - if let Err(err) = handler.handle_new_vote(vote).await { - error!("Failed to handle new vote: {:?}", err); - } + let cached_vote: Option = cache + .get(&format!("{}{}", "PROP_LOT_VOTE_", vote.id)) + .await?; + + if cached_vote.is_none() { + info!("Handle a new vote... ({:?})", vote.id); + if let Err(err) = handler.handle_new_vote(vote).await { + error!("Failed to handle new vote: {:?}", err); } } } } - if let Some(comments) = fetch_comments().await { + if let Some(comments) = fetcher.fetch_comments().await { for comment in &comments { - if let Ok(cached_comment) = get_comment_cache(comment.id) { - if cached_comment.is_none() { - info!("Handle a new comment... ({:?})", comment.id); - if let Err(err) = handler.handle_new_comment(comment).await { - error!("Failed to handle new comment: {:?}", err); - } + let cached_comment: Option = cache + .get(&format!("{}{}", "PROP_LOT_COMMENT_", comment.id)) + .await?; + + if cached_comment.is_none() { + info!("Handle a new comment... ({:?})", comment.id); + if let Err(err) = handler.handle_new_comment(comment).await { + error!("Failed to handle new comment: {:?}", err); } } } } + + Ok(()) } diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..621a38f --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,6 @@ +name = "lilnouns-bots" +main = "build/worker/shim.mjs" +compatibility_date = "2023-03-22" + +[build] +command = "cargo install -q worker-build && worker-build --release"