From ab678a9b22e82be8a5884bfbf401d349ca67f8bc Mon Sep 17 00:00:00 2001 From: pfefpo Date: Sat, 19 Aug 2023 18:49:24 -0400 Subject: [PATCH 1/6] Started work on discord integration --- Cargo.lock | 275 ++++++++++++------ Cargo.toml | 2 +- crates/integrations/Cargo.toml | 13 + .../integrations/src/google_books_client.rs | 28 ++ crates/integrations/src/lib.rs | 5 + .../src/notifier/discord_client.rs | 47 +++ crates/integrations/src/notifier/error.rs | 7 + crates/integrations/src/notifier/event.rs | 13 + crates/integrations/src/notifier/mod.rs | 14 + .../src/notifier/telegram_client.rs | 21 ++ pnpm-lock.yaml | 3 + ubuntu | 25 ++ 12 files changed, 366 insertions(+), 87 deletions(-) create mode 100644 crates/integrations/Cargo.toml create mode 100644 crates/integrations/src/google_books_client.rs create mode 100644 crates/integrations/src/lib.rs create mode 100644 crates/integrations/src/notifier/discord_client.rs create mode 100644 crates/integrations/src/notifier/error.rs create mode 100644 crates/integrations/src/notifier/event.rs create mode 100644 crates/integrations/src/notifier/mod.rs create mode 100644 crates/integrations/src/notifier/telegram_client.rs create mode 100644 ubuntu diff --git a/Cargo.lock b/Cargo.lock index b1de23404..b2316bfee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,19 +137,19 @@ version = "0.3.3" source = "git+https://github.com/tokio-rs/async-stream?rev=e1373e4dede24f7700452e499a46561fb45ea515#e1373e4dede24f7700452e499a46561fb45ea515" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] [[package]] name = "async-trait" -version = "0.1.61" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", - "quote 1.0.23", - "syn 1.0.107", + "quote 1.0.33", + "syn 2.0.29", ] [[package]] @@ -302,7 +302,7 @@ checksum = "cc7d7c3e69f305217e317a28172aab29f275667f2e1c15b87451e134fe27c7b1" dependencies = [ "heck 0.4.0", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -355,6 +355,12 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + [[package]] name = "bcrypt" version = "0.10.1" @@ -948,7 +954,7 @@ dependencies = [ "matches", "phf 0.8.0", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "smallvec", "syn 1.0.107", ] @@ -959,7 +965,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -969,7 +975,7 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -1012,7 +1018,7 @@ dependencies = [ "codespan-reporting", "once_cell", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "scratch", "syn 1.0.107", ] @@ -1030,7 +1036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -1053,7 +1059,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "strsim", "syn 1.0.107", ] @@ -1065,7 +1071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -1105,7 +1111,7 @@ checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case 0.4.0", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "rustc_version 0.4.0", "syn 1.0.107", ] @@ -1320,7 +1326,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -1398,7 +1404,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1555,7 +1561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -1800,7 +1806,7 @@ dependencies = [ "proc-macro-crate", "proc-macro-error", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -1905,7 +1911,7 @@ dependencies = [ "proc-macro-crate", "proc-macro-error", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -2068,7 +2074,7 @@ dependencies = [ "mac", "markup5ever", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -2135,7 +2141,7 @@ dependencies = [ "httpdate", "itoa 1.0.5", "pin-project-lite", - "socket2", + "socket2 0.4.7", "tokio", "tower-service", "tracing", @@ -2258,7 +2264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", ] [[package]] @@ -2316,6 +2322,17 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "integrations" +version = "0.1.0" +dependencies = [ + "async-trait", + "reqwest", + "serde_json", + "thiserror", + "tokio", +] + [[package]] name = "introspection-connector" version = "0.1.0" @@ -2511,9 +2528,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libdbus-sys" @@ -2576,7 +2593,7 @@ dependencies = [ "libc", "neli", "thiserror", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2782,7 +2799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e30813093f757be5cf21e50389a24dc7dbb22c49f23b7e8f51d69b508a5ffa" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -2895,14 +2912,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3034,7 +3051,7 @@ dependencies = [ "libc", "mio", "walkdir", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3126,7 +3143,7 @@ checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -3197,7 +3214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" dependencies = [ "pathdiff", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3222,7 +3239,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -3318,7 +3335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6a252f1f8c11e84b3ab59d7a488e48e4478a93937e027076638c49536204639" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3403,7 +3420,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3465,7 +3482,7 @@ dependencies = [ "pest", "pest_meta", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -3552,7 +3569,7 @@ dependencies = [ "phf_shared 0.8.0", "proc-macro-hack", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -3566,7 +3583,7 @@ dependencies = [ "phf_shared 0.10.0", "proc-macro-hack", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -3604,15 +3621,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -3715,7 +3732,7 @@ dependencies = [ "http", "prisma-client-rust-sdk", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "regex", "reqwest", "serde", @@ -3732,7 +3749,7 @@ source = "git+https://github.com/stumpapp/prisma-client-rust?rev=4e9c79c8355dcbb dependencies = [ "convert_case 0.6.0", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -3748,7 +3765,7 @@ dependencies = [ "proc-macro2", "psl", "query-core", - "quote 1.0.23", + "quote 1.0.33", "request-handlers", "serde", "serde_json", @@ -3807,7 +3824,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", "version_check", ] @@ -3819,7 +3836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "version_check", ] @@ -3831,9 +3848,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -4012,9 +4029,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.23" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -4266,11 +4283,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.13.1", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -4374,7 +4391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "rust-embed-utils", "shellexpand", "syn 1.0.107", @@ -4448,7 +4465,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -4616,7 +4633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -4674,7 +4691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -4708,7 +4725,7 @@ checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ "darling", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -4730,7 +4747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -4853,6 +4870,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soup2" version = "0.2.1" @@ -4906,7 +4933,7 @@ dependencies = [ "Inflector", "itertools", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", "termcolor", ] @@ -5082,7 +5109,7 @@ dependencies = [ "phf_generator 0.10.0", "phf_shared 0.10.0", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", ] [[package]] @@ -5108,7 +5135,7 @@ checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" dependencies = [ "heck 0.3.3", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -5221,7 +5248,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote 1.0.33", "unicode-ident", ] @@ -5405,7 +5443,7 @@ dependencies = [ "plist", "png", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "regex", "semver 1.0.16", "serde", @@ -5426,7 +5464,7 @@ checksum = "069319e5ecbe653a799b94b0690d9f9bf5d00f7b1d3989aa331c524d4e354075" dependencies = [ "heck 0.4.0", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", "tauri-codegen", "tauri-utils", @@ -5489,7 +5527,7 @@ dependencies = [ "memchr", "phf 0.10.1", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "semver 1.0.16", "serde", "serde_json", @@ -5577,7 +5615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -5664,33 +5702,32 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.24.1" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.3", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", - "quote 1.0.23", - "syn 1.0.107", + "quote 1.0.33", + "syn 2.0.29", ] [[package]] @@ -5823,7 +5860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -6077,7 +6114,7 @@ version = "0.1.0" source = "git+https://github.com/Brendonovich/prisma-engines?tag=pcr-0.6.5#7cc20cc54a7ab0b5e38c81901826939a91a17ba0" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -6121,7 +6158,7 @@ checksum = "6f2e33027986a4707b3f5c37ed01b33d0e5a53da30204b52ff18f80600f1d0ec" dependencies = [ "proc-macro-error", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -6261,7 +6298,7 @@ dependencies = [ "lazy_static", "log", "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", "wasm-bindgen-shared", ] @@ -6284,7 +6321,7 @@ version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ - "quote 1.0.23", + "quote 1.0.33", "wasm-bindgen-macro-support", ] @@ -6295,7 +6332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -6393,7 +6430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" dependencies = [ "proc-macro2", - "quote 1.0.23", + "quote 1.0.33", "syn 1.0.107", ] @@ -6514,15 +6551,39 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.42.1", "windows_aarch64_msvc 0.42.1", "windows_i686_gnu 0.42.1", "windows_i686_msvc 0.42.1", "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.42.1", "windows_x86_64_msvc 0.42.1", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-tokens" version = "0.39.0" @@ -6535,6 +6596,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.37.0" @@ -6553,6 +6620,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_i686_gnu" version = "0.37.0" @@ -6571,6 +6644,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_msvc" version = "0.37.0" @@ -6589,6 +6668,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_x86_64_gnu" version = "0.37.0" @@ -6607,12 +6692,24 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_msvc" version = "0.37.0" @@ -6631,6 +6728,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "winreg" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index 08c3d9c30..1e87c047e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = [ "apps/server", "core", # "core/integration-tests", - "crates/prisma-cli", + "crates/*", ] [workspace.package] diff --git a/crates/integrations/Cargo.toml b/crates/integrations/Cargo.toml new file mode 100644 index 000000000..8c19c1159 --- /dev/null +++ b/crates/integrations/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "integrations" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.72" +reqwest = { version = "0.11.18", features = [ "json" ] } +serde_json = "1.0.85" +thiserror = "1.0.37" + +[dev-dependencies] +tokio = { version = "1.32.0", features = [ "full" ] } \ No newline at end of file diff --git a/crates/integrations/src/google_books_client.rs b/crates/integrations/src/google_books_client.rs new file mode 100644 index 000000000..342983575 --- /dev/null +++ b/crates/integrations/src/google_books_client.rs @@ -0,0 +1,28 @@ +pub struct GoogleBooksClient { + pub api_key: String, + pub client: reqwest::Client, +} + +impl GoogleBooksClient { + pub fn new(api_key: String) -> Self { + let client = reqwest::Client::new(); + Self { api_key, client } + } + + pub async fn get_book_by_isbn( + &self, + isbn: &str, + ) -> Result<(), Box> { + let url = format!( + "https://www.googleapis.com/books/v1/volumes?q=isbn:{}&key={}", + isbn, self.api_key + ); + let response = self.client.get(&url).send().await?; + let text = response.text().await?; + println!("Response text: {text}"); + // let response = response.json::().await?; + // let book = response.into(); + // Ok(book) + unimplemented!() + } +} diff --git a/crates/integrations/src/lib.rs b/crates/integrations/src/lib.rs new file mode 100644 index 000000000..93278242d --- /dev/null +++ b/crates/integrations/src/lib.rs @@ -0,0 +1,5 @@ +mod google_books_client; +mod notifier; + +pub use google_books_client::GoogleBooksClient; +pub use notifier::{DiscordClient, Notifier, TelegramClient}; diff --git a/crates/integrations/src/notifier/discord_client.rs b/crates/integrations/src/notifier/discord_client.rs new file mode 100644 index 000000000..8ade62a21 --- /dev/null +++ b/crates/integrations/src/notifier/discord_client.rs @@ -0,0 +1,47 @@ +use serde_json::json; + +use super::{error::NotifierResult, Notifier}; + +pub struct DiscordClient { + pub webhook_url: String, + pub client: reqwest::Client, +} + +impl DiscordClient { + pub fn new(webhook_url: String) -> Self { + let client = reqwest::Client::new(); + Self { + webhook_url, + client, + } + } +} + +#[async_trait::async_trait] +impl Notifier for DiscordClient { + async fn send_message(&self, message: &str) -> NotifierResult<()> { + let body = json!({ + "content" : message + }); + let response = self + .client + .post(&self.webhook_url) + .json(&body) + .send() + .await?; + println!("{:?}", response); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_send_message() { + let client = DiscordClient::new(String::from("https://discord.com/api/webhooks/1142566951663698012/8CFg89RjkeAyo7w8_6qJUNzN9Hu_MG5TVa6PYZi_PqTN2OYn3pU-1ii5NlSSLn-dfbHX")); + let response = client.send_message("hello").await; + assert!(response.is_ok()); + } +} diff --git a/crates/integrations/src/notifier/error.rs b/crates/integrations/src/notifier/error.rs new file mode 100644 index 000000000..7fe75ef23 --- /dev/null +++ b/crates/integrations/src/notifier/error.rs @@ -0,0 +1,7 @@ +pub type NotifierResult = Result; + +#[derive(Debug, thiserror::Error)] +pub enum NotifierError { + #[error("Request failed with error: {0}")] + ReqwestError(#[from] reqwest::Error), +} diff --git a/crates/integrations/src/notifier/event.rs b/crates/integrations/src/notifier/event.rs new file mode 100644 index 000000000..f2089ac03 --- /dev/null +++ b/crates/integrations/src/notifier/event.rs @@ -0,0 +1,13 @@ +// TODO(logan): homework -> read https://doc.rust-iang.org/book/ch06-00-enums.html +pub enum NotifierEvent { + // TODO(logan): these will be Stump related events, e.g ScanCompleted + // An example might look like: + // ScanCompleted { + // success: bool, + // library_name: String, + // completed_task_count: u64, + // }, + // Eventually, notifiers would take an event during the `send_message` trait function, + // which would affect how the message gets sent (e.g. discord you can style a certain + // event differently than another -> https://birdie0.github.io/discord-webhooks-guide/structure/embed/color.html +} diff --git a/crates/integrations/src/notifier/mod.rs b/crates/integrations/src/notifier/mod.rs new file mode 100644 index 000000000..b929c1f2b --- /dev/null +++ b/crates/integrations/src/notifier/mod.rs @@ -0,0 +1,14 @@ +mod discord_client; +mod error; +mod telegram_client; + +pub use discord_client::DiscordClient; +pub use telegram_client::TelegramClient; + +use self::error::NotifierResult; + +#[async_trait::async_trait] +pub trait Notifier { + // TODO: MessageConfig struct? So we can style according to NotifierEvent? + async fn send_message(&self, message: &str) -> NotifierResult<()>; +} diff --git a/crates/integrations/src/notifier/telegram_client.rs b/crates/integrations/src/notifier/telegram_client.rs new file mode 100644 index 000000000..a3eb07e8f --- /dev/null +++ b/crates/integrations/src/notifier/telegram_client.rs @@ -0,0 +1,21 @@ +use crate::Notifier; + +use super::error::NotifierResult; + +pub struct TelegramClient { + token: String, + chat_id: String, +} + +impl TelegramClient { + pub fn new(token: String, chat_id: String) -> Self { + Self { token, chat_id } + } +} + +#[async_trait::async_trait] +impl Notifier for TelegramClient { + async fn send_message(&self, message: &str) -> NotifierResult<()> { + unimplemented!("TelegramClient::send_message") + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 197fb4470..23ee028c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7919,6 +7919,7 @@ packages: /bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + requiresBuild: true dependencies: file-uri-to-path: 1.0.0 dev: true @@ -10754,6 +10755,7 @@ packages: /file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + requiresBuild: true dev: true optional: true @@ -14517,6 +14519,7 @@ packages: /nan@2.17.0: resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} + requiresBuild: true dev: true optional: true diff --git a/ubuntu b/ubuntu new file mode 100644 index 000000000..0f0e1f490 --- /dev/null +++ b/ubuntu @@ -0,0 +1,25 @@ + + +Index of config/ubuntu/ + +

Index of config/ubuntu/

+
../
+14.04/                                                                                              
+15.10/                                                                                              
+16.04/                                                                                              
+16.10/                                                                                              
+17.04/                                                                                              
+17.10/                                                                                              
+18.04/                                                                                              
+18.10/                                                                                              
+19.04/                                                                                              
+19.10/                                                                                              
+20.04/                                                                                              
+20.10/                                                                                              
+21.04/                                                                                              
+21.10/                                                                                              
+22.04/                                                                                              
+22.10/                                                                                              
+23.04/                                                                                              
+

+ \ No newline at end of file From 3de821849d63c649bd5336f6521199763512025f Mon Sep 17 00:00:00 2001 From: pfefpo Date: Fri, 22 Sep 2023 16:57:42 -0400 Subject: [PATCH 2/6] Finished discord client notifier, added scan complete event --- .gitignore | 1 + Cargo.lock | 1 + crates/integrations/.env.template | 1 + crates/integrations/Cargo.toml | 3 +- crates/integrations/README.md | 11 ++++ .../src/notifier/discord_client.rs | 59 ++++++++++++++++--- crates/integrations/src/notifier/event.rs | 15 ++--- crates/integrations/src/notifier/mod.rs | 8 ++- .../src/notifier/telegram_client.rs | 11 ++-- 9 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 crates/integrations/.env.template create mode 100644 crates/integrations/README.md diff --git a/.gitignore b/.gitignore index 147fb2bfa..d9c4de544 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ target/ *.min.js *.map *.tsbuildinfo +.env docker-compose.yaml # rust diff --git a/Cargo.lock b/Cargo.lock index b2316bfee..3f1ce7a71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2327,6 +2327,7 @@ name = "integrations" version = "0.1.0" dependencies = [ "async-trait", + "dotenv", "reqwest", "serde_json", "thiserror", diff --git a/crates/integrations/.env.template b/crates/integrations/.env.template new file mode 100644 index 000000000..d11f1d384 --- /dev/null +++ b/crates/integrations/.env.template @@ -0,0 +1 @@ +DUMMY_WEBHOOK_URL= \ No newline at end of file diff --git a/crates/integrations/Cargo.toml b/crates/integrations/Cargo.toml index 8c19c1159..d5374b651 100644 --- a/crates/integrations/Cargo.toml +++ b/crates/integrations/Cargo.toml @@ -10,4 +10,5 @@ serde_json = "1.0.85" thiserror = "1.0.37" [dev-dependencies] -tokio = { version = "1.32.0", features = [ "full" ] } \ No newline at end of file +tokio = { version = "1.32.0", features = [ "full" ] } +dotenv = "0.15.0" \ No newline at end of file diff --git a/crates/integrations/README.md b/crates/integrations/README.md new file mode 100644 index 000000000..3140e9328 --- /dev/null +++ b/crates/integrations/README.md @@ -0,0 +1,11 @@ +# Integrations + +A rust crate providing wrappers around various notification providers. e.g. Discord, Telegram, etc. + +## Running + +TODO + +## Testing + +Create a .env file similar to the template provided and add your webhook url diff --git a/crates/integrations/src/notifier/discord_client.rs b/crates/integrations/src/notifier/discord_client.rs index 8ade62a21..c8bab5265 100644 --- a/crates/integrations/src/notifier/discord_client.rs +++ b/crates/integrations/src/notifier/discord_client.rs @@ -1,6 +1,6 @@ use serde_json::json; -use super::{error::NotifierResult, Notifier}; +use super::{error::NotifierResult, Notifier, NotifierEvent, FAVICON_URL, NOTIFIER_ID}; pub struct DiscordClient { pub webhook_url: String, @@ -19,10 +19,25 @@ impl DiscordClient { #[async_trait::async_trait] impl Notifier for DiscordClient { - async fn send_message(&self, message: &str) -> NotifierResult<()> { - let body = json!({ - "content" : message - }); + fn payload_from_event(event: NotifierEvent) -> serde_json::Value { + match event { + NotifierEvent::ScanCompleted { + books_added, + library_name, + } => json!({ + "username" : NOTIFIER_ID, + "avatar_url" : FAVICON_URL, + "embeds" : [{ + "title" : "Scan Completed!", + "description": format!("{books_added} books added to {library_name}"), + "color" : 13605239, + }] + }), + } + } + + async fn send_message(&self, event: NotifierEvent) -> NotifierResult<()> { + let body = Self::payload_from_event(event); let response = self .client .post(&self.webhook_url) @@ -34,14 +49,44 @@ impl Notifier for DiscordClient { } } +// https://birdie0.github.io/discord-webhooks-guide/structure/embed/color.html + #[cfg(test)] mod tests { use super::*; + use dotenv::dotenv; + + fn get_debug_client() -> DiscordClient { + dotenv().ok(); + let webhook_url = + std::env::var("DUMMY_WEBHOOK_URL").expect("Failed to load webhook URL"); + DiscordClient::new(webhook_url) + } #[tokio::test] async fn test_send_message() { - let client = DiscordClient::new(String::from("https://discord.com/api/webhooks/1142566951663698012/8CFg89RjkeAyo7w8_6qJUNzN9Hu_MG5TVa6PYZi_PqTN2OYn3pU-1ii5NlSSLn-dfbHX")); - let response = client.send_message("hello").await; + let client = get_debug_client(); + let event = NotifierEvent::ScanCompleted { + books_added: 69, + library_name: String::from("deez"), + }; + let response = client.send_message(event).await; assert!(response.is_ok()); } + + #[test] + fn test_scan_completed() { + let event = NotifierEvent::ScanCompleted { + books_added: 5, + library_name: String::from("test"), + }; + let response = DiscordClient::payload_from_event(event); + assert!(response.is_object()); + let embeds = response["embeds"].to_owned(); + assert!(embeds.is_array()); + assert_eq!( + embeds[0]["description"], + String::from("5 books added to test") + ); + } } diff --git a/crates/integrations/src/notifier/event.rs b/crates/integrations/src/notifier/event.rs index f2089ac03..3a040c7da 100644 --- a/crates/integrations/src/notifier/event.rs +++ b/crates/integrations/src/notifier/event.rs @@ -1,13 +1,6 @@ -// TODO(logan): homework -> read https://doc.rust-iang.org/book/ch06-00-enums.html pub enum NotifierEvent { - // TODO(logan): these will be Stump related events, e.g ScanCompleted - // An example might look like: - // ScanCompleted { - // success: bool, - // library_name: String, - // completed_task_count: u64, - // }, - // Eventually, notifiers would take an event during the `send_message` trait function, - // which would affect how the message gets sent (e.g. discord you can style a certain - // event differently than another -> https://birdie0.github.io/discord-webhooks-guide/structure/embed/color.html + ScanCompleted { + books_added: u64, + library_name: String, + }, } diff --git a/crates/integrations/src/notifier/mod.rs b/crates/integrations/src/notifier/mod.rs index b929c1f2b..0d2c25cad 100644 --- a/crates/integrations/src/notifier/mod.rs +++ b/crates/integrations/src/notifier/mod.rs @@ -1,14 +1,20 @@ mod discord_client; mod error; +mod event; mod telegram_client; pub use discord_client::DiscordClient; +pub use event::NotifierEvent; pub use telegram_client::TelegramClient; use self::error::NotifierResult; +pub const NOTIFIER_ID: &str = "Stump Notifier"; +pub const FAVICON_URL: &str = "https://stumpapp.dev/favicon.png"; + #[async_trait::async_trait] pub trait Notifier { // TODO: MessageConfig struct? So we can style according to NotifierEvent? - async fn send_message(&self, message: &str) -> NotifierResult<()>; + fn payload_from_event(event: NotifierEvent) -> serde_json::Value; + async fn send_message(&self, event: NotifierEvent) -> NotifierResult<()>; } diff --git a/crates/integrations/src/notifier/telegram_client.rs b/crates/integrations/src/notifier/telegram_client.rs index a3eb07e8f..08299e0c8 100644 --- a/crates/integrations/src/notifier/telegram_client.rs +++ b/crates/integrations/src/notifier/telegram_client.rs @@ -1,10 +1,10 @@ use crate::Notifier; -use super::error::NotifierResult; +use super::{error::NotifierResult, NotifierEvent}; pub struct TelegramClient { - token: String, - chat_id: String, + pub token: String, + pub chat_id: String, } impl TelegramClient { @@ -15,7 +15,10 @@ impl TelegramClient { #[async_trait::async_trait] impl Notifier for TelegramClient { - async fn send_message(&self, message: &str) -> NotifierResult<()> { + fn payload_from_event(_event: NotifierEvent) -> serde_json::Value { + unimplemented!() + } + async fn send_message(&self, _event: NotifierEvent) -> NotifierResult<()> { unimplemented!("TelegramClient::send_message") } } From 7a6037e3274b0337e31978c94386cf3f59db9675 Mon Sep 17 00:00:00 2001 From: pfefpo Date: Wed, 11 Oct 2023 16:31:55 -0400 Subject: [PATCH 3/6] Added telegram client framework --- crates/integrations/.env.template | 4 +- .../src/notifier/discord_client.rs | 17 ++-- crates/integrations/src/notifier/error.rs | 4 + crates/integrations/src/notifier/event.rs | 18 +++++ crates/integrations/src/notifier/mod.rs | 2 +- .../src/notifier/telegram_client.rs | 79 +++++++++++++++++-- 6 files changed, 107 insertions(+), 17 deletions(-) diff --git a/crates/integrations/.env.template b/crates/integrations/.env.template index d11f1d384..82f4d5cb6 100644 --- a/crates/integrations/.env.template +++ b/crates/integrations/.env.template @@ -1 +1,3 @@ -DUMMY_WEBHOOK_URL= \ No newline at end of file +DUMMY_DISCORD_WEBHOOK_URL= +DUMMY_TG_TOKEN= +DUMMY_TG_CHAT_ID= \ No newline at end of file diff --git a/crates/integrations/src/notifier/discord_client.rs b/crates/integrations/src/notifier/discord_client.rs index c8bab5265..c62e09b1a 100644 --- a/crates/integrations/src/notifier/discord_client.rs +++ b/crates/integrations/src/notifier/discord_client.rs @@ -17,10 +17,12 @@ impl DiscordClient { } } +//https://core.telegram.org/bots/api#message + #[async_trait::async_trait] impl Notifier for DiscordClient { - fn payload_from_event(event: NotifierEvent) -> serde_json::Value { - match event { + fn payload_from_event(event: NotifierEvent) -> NotifierResult { + let payload = match event { NotifierEvent::ScanCompleted { books_added, library_name, @@ -33,11 +35,12 @@ impl Notifier for DiscordClient { "color" : 13605239, }] }), - } + }; + Ok(payload) } async fn send_message(&self, event: NotifierEvent) -> NotifierResult<()> { - let body = Self::payload_from_event(event); + let body = Self::payload_from_event(event)?; let response = self .client .post(&self.webhook_url) @@ -58,8 +61,8 @@ mod tests { fn get_debug_client() -> DiscordClient { dotenv().ok(); - let webhook_url = - std::env::var("DUMMY_WEBHOOK_URL").expect("Failed to load webhook URL"); + let webhook_url = std::env::var("DUMMY_DISCORD_WEBHOOK_URL") + .expect("Failed to load webhook URL"); DiscordClient::new(webhook_url) } @@ -80,7 +83,7 @@ mod tests { books_added: 5, library_name: String::from("test"), }; - let response = DiscordClient::payload_from_event(event); + let response = DiscordClient::payload_from_event(event).unwrap(); assert!(response.is_object()); let embeds = response["embeds"].to_owned(); assert!(embeds.is_array()); diff --git a/crates/integrations/src/notifier/error.rs b/crates/integrations/src/notifier/error.rs index 7fe75ef23..5e02885ac 100644 --- a/crates/integrations/src/notifier/error.rs +++ b/crates/integrations/src/notifier/error.rs @@ -4,4 +4,8 @@ pub type NotifierResult = Result; pub enum NotifierError { #[error("Request failed with error: {0}")] ReqwestError(#[from] reqwest::Error), + #[error("{0}")] + Unimplemented(String), + #[error("Request was unsucessful")] + RequestFailed(String), } diff --git a/crates/integrations/src/notifier/event.rs b/crates/integrations/src/notifier/event.rs index 3a040c7da..c26c0d6ed 100644 --- a/crates/integrations/src/notifier/event.rs +++ b/crates/integrations/src/notifier/event.rs @@ -4,3 +4,21 @@ pub enum NotifierEvent { library_name: String, }, } + +impl NotifierEvent { + pub fn to_message(self) -> String { + match self { + NotifierEvent::ScanCompleted { + books_added, + library_name, + } => { + let is_plural = books_added == 0 || books_added > 1; + let book_or_books = if is_plural { "books" } else { "book" }; + format!( + "{} {} added to {}", + books_added, book_or_books, library_name + ) + }, + } + } +} diff --git a/crates/integrations/src/notifier/mod.rs b/crates/integrations/src/notifier/mod.rs index 0d2c25cad..7167c9f17 100644 --- a/crates/integrations/src/notifier/mod.rs +++ b/crates/integrations/src/notifier/mod.rs @@ -15,6 +15,6 @@ pub const FAVICON_URL: &str = "https://stumpapp.dev/favicon.png"; #[async_trait::async_trait] pub trait Notifier { // TODO: MessageConfig struct? So we can style according to NotifierEvent? - fn payload_from_event(event: NotifierEvent) -> serde_json::Value; + fn payload_from_event(event: NotifierEvent) -> NotifierResult; async fn send_message(&self, event: NotifierEvent) -> NotifierResult<()>; } diff --git a/crates/integrations/src/notifier/telegram_client.rs b/crates/integrations/src/notifier/telegram_client.rs index 08299e0c8..2031e60dc 100644 --- a/crates/integrations/src/notifier/telegram_client.rs +++ b/crates/integrations/src/notifier/telegram_client.rs @@ -1,24 +1,87 @@ use crate::Notifier; -use super::{error::NotifierResult, NotifierEvent}; +use super::{ + error::{NotifierError, NotifierResult}, + NotifierEvent, +}; pub struct TelegramClient { - pub token: String, - pub chat_id: String, + token: String, + chat_id: String, + client: reqwest::Client, } impl TelegramClient { pub fn new(token: String, chat_id: String) -> Self { - Self { token, chat_id } + let client = reqwest::Client::new(); + Self { + token, + chat_id, + client, + } } } #[async_trait::async_trait] impl Notifier for TelegramClient { - fn payload_from_event(_event: NotifierEvent) -> serde_json::Value { - unimplemented!() + fn payload_from_event(_event: NotifierEvent) -> NotifierResult { + Err(NotifierError::Unimplemented( + "Telegram does not support request bodies".to_string(), + )) } - async fn send_message(&self, _event: NotifierEvent) -> NotifierResult<()> { - unimplemented!("TelegramClient::send_message") + async fn send_message(&self, event: NotifierEvent) -> NotifierResult<()> { + let token = self.token.clone(); + let chat_id = self.chat_id.clone(); + let message = event.to_message(); + let response = self + .client + .post(format!("https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text={message}")) + .send() + .await?; + if !response.status().is_success() { + let errmsg = response + .text() + .await + .unwrap_or_else(|_| "sendMessage failed".to_string()); + Err(NotifierError::RequestFailed(errmsg)) + } else { + Ok(()) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use dotenv::dotenv; + + fn get_debug_client() -> TelegramClient { + dotenv().ok(); + let token = std::env::var("DUMMY_TG_TOKEN").expect("Failed to load token"); + let chat_id = std::env::var("DUMMY_TG_CHAT_ID").expect("Failed to load chat ID"); + TelegramClient::new(token, chat_id) + } + #[tokio::test] + async fn test_send_message() { + let client = get_debug_client(); + let event = NotifierEvent::ScanCompleted { + books_added: 69, + library_name: String::from("deez"), + }; + let response = client.send_message(event).await; + assert!(response.is_ok()); + } + + #[tokio::test] + async fn test_send_message_failed() { + let client = TelegramClient::new("bad".to_string(), "bad".to_string()); + let event = NotifierEvent::ScanCompleted { + books_added: 69, + library_name: String::from("deez"), + }; + let response = client.send_message(event).await; + assert!(response.is_err()); + let result = response.unwrap_err(); + println!("{:?}", result); } } From 0e260a79c4de67d616c88b96852d413524955f02 Mon Sep 17 00:00:00 2001 From: pfefpo Date: Wed, 11 Oct 2023 16:58:20 -0400 Subject: [PATCH 4/6] changed readme --- crates/integrations/README.md | 8 ++------ .../integrations/src/notifier/discord_client.rs | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/integrations/README.md b/crates/integrations/README.md index 3140e9328..86ba838a8 100644 --- a/crates/integrations/README.md +++ b/crates/integrations/README.md @@ -1,11 +1,7 @@ # Integrations -A rust crate providing wrappers around various notification providers. e.g. Discord, Telegram, etc. - -## Running - -TODO +A rust crate providing wrappers around various notification providers. e.g. Discord, Telegram, etc. The Notifier trait defines the functions used to make API requests. ## Testing -Create a .env file similar to the template provided and add your webhook url +Create a .env file similar to the template provided and add your Discord webhook url and/or Telegram token and chat ID. diff --git a/crates/integrations/src/notifier/discord_client.rs b/crates/integrations/src/notifier/discord_client.rs index c62e09b1a..240b44fce 100644 --- a/crates/integrations/src/notifier/discord_client.rs +++ b/crates/integrations/src/notifier/discord_client.rs @@ -1,6 +1,9 @@ use serde_json::json; -use super::{error::NotifierResult, Notifier, NotifierEvent, FAVICON_URL, NOTIFIER_ID}; +use super::{ + error::{NotifierError, NotifierResult}, + Notifier, NotifierEvent, FAVICON_URL, NOTIFIER_ID, +}; pub struct DiscordClient { pub webhook_url: String, @@ -47,8 +50,15 @@ impl Notifier for DiscordClient { .json(&body) .send() .await?; - println!("{:?}", response); - Ok(()) + if !response.status().is_success() { + let errmsg = response + .text() + .await + .unwrap_or_else(|_| "sendMessage failed".to_string()); + Err(NotifierError::RequestFailed(errmsg)) + } else { + Ok(()) + } } } From 4d1c9a0ee1e81ba5a000a3d33a746f00bab5ac72 Mon Sep 17 00:00:00 2001 From: pfefpo Date: Wed, 11 Oct 2023 17:02:20 -0400 Subject: [PATCH 5/6] standardized test variables --- crates/integrations/src/notifier/discord_client.rs | 8 ++++---- crates/integrations/src/notifier/telegram_client.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/integrations/src/notifier/discord_client.rs b/crates/integrations/src/notifier/discord_client.rs index 240b44fce..4bb5013e2 100644 --- a/crates/integrations/src/notifier/discord_client.rs +++ b/crates/integrations/src/notifier/discord_client.rs @@ -80,8 +80,8 @@ mod tests { async fn test_send_message() { let client = get_debug_client(); let event = NotifierEvent::ScanCompleted { - books_added: 69, - library_name: String::from("deez"), + books_added: 50, + library_name: String::from("test_library"), }; let response = client.send_message(event).await; assert!(response.is_ok()); @@ -91,7 +91,7 @@ mod tests { fn test_scan_completed() { let event = NotifierEvent::ScanCompleted { books_added: 5, - library_name: String::from("test"), + library_name: String::from("test_library"), }; let response = DiscordClient::payload_from_event(event).unwrap(); assert!(response.is_object()); @@ -99,7 +99,7 @@ mod tests { assert!(embeds.is_array()); assert_eq!( embeds[0]["description"], - String::from("5 books added to test") + String::from("5 books added to test_library") ); } } diff --git a/crates/integrations/src/notifier/telegram_client.rs b/crates/integrations/src/notifier/telegram_client.rs index 2031e60dc..497530604 100644 --- a/crates/integrations/src/notifier/telegram_client.rs +++ b/crates/integrations/src/notifier/telegram_client.rs @@ -65,8 +65,8 @@ mod tests { async fn test_send_message() { let client = get_debug_client(); let event = NotifierEvent::ScanCompleted { - books_added: 69, - library_name: String::from("deez"), + books_added: 50, + library_name: String::from("test_library"), }; let response = client.send_message(event).await; assert!(response.is_ok()); @@ -76,8 +76,8 @@ mod tests { async fn test_send_message_failed() { let client = TelegramClient::new("bad".to_string(), "bad".to_string()); let event = NotifierEvent::ScanCompleted { - books_added: 69, - library_name: String::from("deez"), + books_added: 50, + library_name: String::from("test_library"), }; let response = client.send_message(event).await; assert!(response.is_err()); From 04a2475ac9018d57d056a0a320a314c4a2f20194 Mon Sep 17 00:00:00 2001 From: pfefpo Date: Wed, 11 Oct 2023 17:17:04 -0400 Subject: [PATCH 6/6] adjustment for rust function pnpmnaming rules --- crates/integrations/src/notifier/event.rs | 2 +- crates/integrations/src/notifier/telegram_client.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/integrations/src/notifier/event.rs b/crates/integrations/src/notifier/event.rs index c26c0d6ed..0af50e0fd 100644 --- a/crates/integrations/src/notifier/event.rs +++ b/crates/integrations/src/notifier/event.rs @@ -6,7 +6,7 @@ pub enum NotifierEvent { } impl NotifierEvent { - pub fn to_message(self) -> String { + pub fn into_message(self) -> String { match self { NotifierEvent::ScanCompleted { books_added, diff --git a/crates/integrations/src/notifier/telegram_client.rs b/crates/integrations/src/notifier/telegram_client.rs index 497530604..363a6f205 100644 --- a/crates/integrations/src/notifier/telegram_client.rs +++ b/crates/integrations/src/notifier/telegram_client.rs @@ -32,7 +32,7 @@ impl Notifier for TelegramClient { async fn send_message(&self, event: NotifierEvent) -> NotifierResult<()> { let token = self.token.clone(); let chat_id = self.chat_id.clone(); - let message = event.to_message(); + let message = event.into_message(); let response = self .client .post(format!("https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text={message}"))