diff --git a/Cargo.lock b/Cargo.lock index 4711cdc..7de5054 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,12 +28,11 @@ dependencies = [ [[package]] name = "allrisbot" -version = "0.1.1" +version = "0.1.2" dependencies = [ "bot-utils", "chrono", "clap", - "env_logger", "frankenstein", "futures-util", "log", @@ -49,6 +48,7 @@ dependencies = [ "tokio", "tokio-retry", "tokio-stream", + "tracing-subscriber", "url", ] @@ -108,21 +108,15 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - [[package]] name = "async-trait" version = "0.1.88" @@ -148,9 +142,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -158,7 +152,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -169,9 +163,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bon" @@ -204,9 +198,9 @@ version = "0.1.0" dependencies = [ "frankenstein", "futures-util", - "log", "regex", "tokio", + "tracing", ] [[package]] @@ -229,9 +223,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.20" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" +checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" dependencies = [ "shlex", ] @@ -265,9 +259,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -275,9 +269,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -439,29 +433,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_filter" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -485,9 +456,9 @@ dependencies = [ [[package]] name = "frankenstein" -version = "0.40.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb8f97b9b2fefaa34071c0ccb9df53d7d15d5c4a375c07cd701e133dac048af" +checksum = "d8d49b6a362726062969e5184f0b6b7fdeae7aa48ba7fa9508de3e3078a6c3f7" dependencies = [ "async-trait", "bon", @@ -596,9 +567,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "js-sys", @@ -616,9 +587,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -719,11 +690,10 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.5" +version = "0.27.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" dependencies = [ - "futures-util", "http", "hyper", "hyper-util", @@ -737,17 +707,21 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", "tokio", @@ -781,21 +755,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -804,31 +779,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -836,67 +791,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -916,9 +858,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -940,6 +882,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -952,30 +904,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "jiff" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", -] - -[[package]] -name = "jiff-static" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "js-sys" version = "0.3.77" @@ -986,6 +914,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.172" @@ -994,9 +928,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" @@ -1014,6 +948,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mac" version = "0.1.1" @@ -1061,6 +1001,15 @@ dependencies = [ "syn", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.7.4" @@ -1094,13 +1043,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1109,6 +1058,16 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1152,6 +1111,18 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.3" @@ -1172,7 +1143,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -1272,18 +1243,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "portable-atomic" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" dependencies = [ - "portable-atomic", + "zerovec", ] [[package]] @@ -1322,9 +1287,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", "cfg_aliases", @@ -1342,12 +1307,13 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbafbbdbb0f638fe3f35f3c56739f77a8a1d070cb25603226c83339b391472b" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "getrandom 0.3.2", + "getrandom 0.3.3", + "lru-slab", "rand 0.9.1", "ring", "rustc-hash", @@ -1445,16 +1411,15 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] name = "redis" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "438a4e5f8e9aa246d6f3666d6978441bf1b37d5f417b50c4dd220be09f5fcc17" +checksum = "0bc1ea653e0b2e097db3ebb5b7f678be339620b8041f66b30a308c1d45d36a7f" dependencies = [ - "arc-swap", "bytes", "cfg-if", "combine", @@ -1475,9 +1440,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags", ] @@ -1490,8 +1455,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1502,9 +1476,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -1513,9 +1493,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "2bf597b113be201cb2269b4c39b39a804d01b99ee95a4278f0ed04e45cff1c71" dependencies = [ "base64", "bytes", @@ -1539,7 +1519,6 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", @@ -1549,6 +1528,7 @@ dependencies = [ "tokio-rustls", "tokio-util", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", @@ -1556,7 +1536,6 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots", - "windows-registry", ] [[package]] @@ -1587,9 +1566,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "once_cell", "ring", @@ -1599,29 +1578,21 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "web-time", + "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -1630,9 +1601,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -1761,6 +1732,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1799,9 +1779,9 @@ checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1929,11 +1909,21 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -1956,9 +1946,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -2043,6 +2033,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -2062,9 +2070,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.33" @@ -2072,6 +2092,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2116,12 +2166,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -2134,6 +2178,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "want" version = "0.3.1" @@ -2264,24 +2314,46 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37493cadf42a2a939ed404698ded7fb378bf301b5011f973361779a3a74f8c93" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", - "windows-strings 0.4.0", + "windows-strings", ] [[package]] @@ -2312,40 +2384,20 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result", - "windows-strings 0.3.1", - "windows-targets 0.53.0", -] - [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -2356,7 +2408,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2365,7 +2417,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2374,30 +2426,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -2406,96 +2442,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "wit-bindgen-rt" version = "0.39.0" @@ -2505,23 +2493,17 @@ dependencies = [ "bitflags", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -2531,9 +2513,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -2588,11 +2570,22 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -2601,9 +2594,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index c1bfb2d..3b29b01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ [package] name = "allrisbot" description = "Telegram bot that notifies users about newly published documents in the Allris 4 council information system" -version = "0.1.1" +version = "0.1.2" edition = "2024" repository = "https://github.com/jdertmann/AllrisBot" license = "AGPL-3.0-or-later" @@ -17,12 +17,11 @@ license = "AGPL-3.0-or-later" bot-utils = { path = "bot-utils" } chrono = { version = "0.4.40", features = ["serde"] } clap = { version = "4.5", features = ["derive", "env"] } -env_logger = "0.11" -frankenstein = { version = "0.40.0", features = ["client-reqwest"] } +frankenstein = { version = "0.41.0", features = ["client-reqwest"] } futures-util = { default-features = false, version = "0.3" } log = "0.4" rand = "0.9.0" -redis = { version = "0.30", default-features = false, features = ["keep-alive", "tokio-comp", "script", "json"] } +redis = { version = "0.31", default-features = false, features = ["keep-alive", "tokio-comp", "script", "json"] } regex = "1.11.1" reqwest = { version = "0.12", default-features = false, features = ["charset", "http2", "json", "rustls-tls"] } scraper = { version = "0.23", default-features = false } @@ -33,4 +32,5 @@ thiserror = "2" tokio = { version = "1.39", features = ["macros", "rt-multi-thread", "signal", "sync", "time"] } tokio-retry = "0.3" tokio-stream = { version = "0.1.17", features = ["sync"] } +tracing-subscriber = { version = "0.3.19", features = ["env-filter", "tracing-log"] } url = { version = "2.5", features = ["serde"] } diff --git a/bot-utils/Cargo.toml b/bot-utils/Cargo.toml index 1a53133..c2e9985 100644 --- a/bot-utils/Cargo.toml +++ b/bot-utils/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] -frankenstein = { version = "0.40", features = ["trait-async"] } +frankenstein = { version = "0.41", features = ["trait-async"] } futures-util = { version = "0.3", default-features = false, features = ["alloc"] } -log = "0.4" regex = "1.11.1" tokio = { version = "1.44.2", features = ["sync", "time", "rt-multi-thread", "macros"] } +tracing = "0.1.41" diff --git a/bot-utils/src/broadcasting.rs b/bot-utils/src/broadcasting.rs index 2bf6d40..aee77b1 100644 --- a/bot-utils/src/broadcasting.rs +++ b/bot-utils/src/broadcasting.rs @@ -26,42 +26,22 @@ use std::pin::pin; use std::sync::Arc; use std::time::Duration; -use frankenstein::Error as RequestError; -use frankenstein::response::{ErrorResponse, ResponseParameters}; -use futures_util::future::{Fuse, FusedFuture}; -use futures_util::stream::{FusedStream, FuturesUnordered, StreamExt as _}; -use futures_util::{FutureExt, Stream}; +use futures_util::stream::{FusedStream, FuturesUnordered, Stream, StreamExt as _}; use tokio::sync::{mpsc, oneshot, watch}; use tokio::task::JoinHandle; use tokio::time::{Instant, MissedTickBehavior, interval, sleep, sleep_until}; +use tracing::instrument; use super::ChatId; +use crate::response::RequestError; const BROADCASTS_PER_SECOND: f32 = 30.; const MESSAGE_INTERVAL_CHAT: Duration = Duration::from_secs(1); const MESSAGE_INTERVAL_GROUP: Duration = Duration::from_secs(3); -/// error messages that imply we're not allowed to send messages -/// to this chat in the future. -const TELEGRAM_ERRORS: [&str; 14] = [ - "Bad Request: CHAT_WRITE_FORBIDDEN", - "Bad Request: TOPIC_CLOSED", - "Bad Request: chat not found", - "Bad Request: have no rights to send a message", - "Bad Request: not enough rights to send text messages to the chat", - "Bad Request: need administrator rights in the channel chat", - "Forbidden: bot is not a member of the channel chat", - "Forbidden: bot is not a member of the supergroup chat", - "Forbidden: bot was blocked by the user", - "Forbidden: bot was kicked from the channel chat", - "Forbidden: bot was kicked from the group chat", - "Forbidden: bot was kicked from the supergroup chat", - "Forbidden: the group chat was deleted", - "Forbidden: user is deactivated", -]; - -enum ChatStatus { - Processed(B::UpdateId), +#[derive(Debug)] +enum ChatStatus { + Processed(U), OutOfSync, Stopped, ShuttingDown, @@ -76,7 +56,10 @@ fn delay(chat_id: ChatId) -> Duration { } } -type OneshotResponse = (Result, ::Error>, bool); +type OneshotResponse = ( + Result::UpdateId>, ::Error>, + bool, +); type SendMessage = (ScheduledMessage, oneshot::Sender>); pub enum NextUpdate { @@ -151,11 +134,7 @@ impl ScheduledMessage { .unacknowledge(self.chat_id, self.update) .await?; if !r { - log::warn!( - "Failed to unacknowledge message {:?} for chat {}", - self.update, - self.chat_id - ); + tracing::warn!("Failed to unacknowledge message!"); } Ok(r) } @@ -163,11 +142,13 @@ impl ScheduledMessage { async fn handle_response( &self, shared: &SharedDependencies, - response: Result<(), RequestError>, + response: Result<(), frankenstein::Error>, backoff: Option, - ) -> Result, Duration>, B::Error> { + ) -> Result, Duration>, B::Error> { if let Err(e) = response.as_ref() { - log::warn!("Failed to send message: {e}"); + tracing::error!(error=%e, "Sending message failed"); + } else { + tracing::info!("Message has been sent!"); } macro_rules! retry_with_backoff { @@ -180,85 +161,69 @@ impl ScheduledMessage { }; } - macro_rules! retry { - () => { + let response = response.as_ref().map_err(crate::response::map_error); + + let result = match response { + Ok(_) => ChatStatus::Processed(self.update), + Err(RequestError::InvalidToken) => { + tracing::error!("Invalid token! Was it revoked?"); + shared.hard_shutdown.send_replace(true); + _ = self.unacknowledge(shared).await?; + ChatStatus::ShuttingDown + } + Err(RequestError::BotBlocked) => { + shared.backend.remove_chat(self.chat_id).await?; + tracing::info!("Bot is unable to send to this chat, subscription was removed!"); + ChatStatus::Stopped + } + Err(RequestError::ChatMigrated(new_chat_id)) => { + _ = self.unacknowledge(shared).await?; + shared + .backend + .migrate_chat(self.chat_id, new_chat_id) + .await?; + tracing::info!("Chat has been migrated to {new_chat_id}!"); + ChatStatus::MigratedTo(new_chat_id) + } + Err(RequestError::RetryAfter(dur)) => retry_with_backoff!(dur), + Err(RequestError::ClientError) => { + tracing::error!("Client error, won't retry!"); + ChatStatus::Processed(self.update) + } + Err(RequestError::Other) => { if let Some(backoff) = backoff { retry_with_backoff!(backoff) } else { - log::error!("Sending failed definitely, not retrying!"); + tracing::error!("Max number of retries reached, won't retry!"); ChatStatus::Processed(self.update) } - }; - } - - let result = match response { - Ok(()) => ChatStatus::Processed(self.update), - Err(RequestError::Api(e)) => match e { - ErrorResponse { - error_code: 401 | 404, - .. - } => { - log::error!("Invalid token! Was it revoked?"); - shared.hard_shutdown.send_replace(true); - _ = self.unacknowledge(shared).await?; - ChatStatus::ShuttingDown - } - ErrorResponse { - parameters: - Some(ResponseParameters { - migrate_to_chat_id: Some(new_chat_id), - .. - }), - .. - } => { - _ = self.unacknowledge(shared).await?; - shared - .backend - .migrate_chat(self.chat_id, new_chat_id) - .await?; - ChatStatus::MigratedTo(new_chat_id) - } - ErrorResponse { - parameters: - Some(ResponseParameters { - retry_after: Some(secs), - .. - }), - .. - } => { - retry_with_backoff!(Duration::from_secs(secs as u64)) - } - ErrorResponse { description, .. } - if TELEGRAM_ERRORS.contains(&description.as_str()) => - { - shared.backend.remove_chat(self.chat_id).await?; - ChatStatus::Stopped - } - _ => retry!(), - }, - _ => retry!(), + } }; Ok(ControlFlow::Break(result)) } /// Sends a message. Will retry a number of times if it fails + #[tracing::instrument(skip_all, fields(chat_id=self.chat_id, update_id=?self.update))] async fn send_message( &self, shared: &SharedDependencies, message_sent: &mut bool, - ) -> Result, B::Error> { + ) -> Result, B::Error> { let mut backoff = backoff_strategy(); loop { + tracing::debug!("Starting attempt to send message!"); *message_sent = false; let ack = shared .backend .acknowledge(self.chat_id, self.update) .await?; if !ack { + tracing::warn!("Failed to acknowledged message!"); return Ok(ChatStatus::OutOfSync); } + tracing::trace!("Message was acknowledged, trying to send it!"); let response = shared.backend.send(self.chat_id, &self.message).await; *message_sent = true; @@ -266,21 +231,29 @@ impl ScheduledMessage { .handle_response(shared, response, backoff.next()) .await? { - ControlFlow::Break(result) => return Ok(result), - ControlFlow::Continue(retry_after) => sleep(retry_after).await, + ControlFlow::Break(result) => { + tracing::debug!("Message was sent or failed definitely"); + return Ok(result); + } + ControlFlow::Continue(retry_after) => { + tracing::info!("Retrying in {retry_after:?} ..."); + sleep(retry_after).await; + } } } } } /// Process the next entry of the message stream for a certain chat -async fn try_process_next( +#[instrument(skip(shared), ret(level = "debug"))] +async fn process_next_update( shared: &SharedDependencies, chat_id: ChatId, -) -> Result, B::Error> { +) -> Result, B::Error> { + tracing::debug!("Processing next update"); let started = Instant::now(); - let (id, message) = match shared.backend.next_update(chat_id).await? { + let (update, message) = match shared.backend.next_update(chat_id).await? { NextUpdate::Ready { id, msg: next } => (id, next), NextUpdate::Skipped { id } => return Ok(ChatStatus::Processed(id)), NextUpdate::OutOfSync => return Ok(ChatStatus::OutOfSync), @@ -292,23 +265,16 @@ async fn try_process_next( // pass the message to the sender task let scheduled = ScheduledMessage { chat_id, + update, message, - update: id, }; let (oneshot_tx, oneshot_rx) = oneshot::channel(); - - if shared - .sender_tx - .send((scheduled, oneshot_tx)) - .await - .is_err() - { - return Ok(ChatStatus::ShuttingDown); - } + _ = shared.sender_tx.send((scheduled, oneshot_tx)).await; match oneshot_rx.await { Ok((r, true)) => { // message has been sent, apply a delay for rate limiting + tracing::debug!("Applying delay for rate limiting"); sleep_until(started + delay(chat_id)).await; r } @@ -377,6 +343,7 @@ impl<'a, B: Backend, Fut, F: Fn(&'a SharedDependencies, ChatId) -> Fut> fn trigger_chat(&mut self, chat_id: ChatId) { match self.states.entry(chat_id) { Entry::Occupied(mut entry) => { + tracing::debug!("Triggered chat {chat_id} already running"); entry.get_mut().triggered_while_running = true; } Entry::Vacant(entry) => { @@ -389,6 +356,10 @@ impl<'a, B: Backend, Fut, F: Fn(&'a SharedDependencies, ChatId) -> Fut> /// triggers all active chats after a new message has arrived fn on_message_scheduled(&mut self, id: B::UpdateId, active_chats: Vec) { + tracing::info!( + active_chats = active_chats.len(), + "Latest scheduled message: {id:?}" + ); self.latest_entry_id = Some(id); for chat_id in active_chats { @@ -396,13 +367,17 @@ impl<'a, B: Backend, Fut, F: Fn(&'a SharedDependencies, ChatId) -> Fut> } } - fn on_processing_finished(&mut self, chat_id: ChatId, result: Result, B::Error>) { + fn on_processing_finished( + &mut self, + chat_id: ChatId, + result: Result, B::Error>, + ) { let restart = self .states .remove(&chat_id) .map(|s| s.triggered_while_running) .unwrap_or_else(|| { - log::warn!("Unexpectedly missing state"); + tracing::warn!(chat_id, "ProcessingState is missing unexpectedly"); true // restart task to be on the safe site }); match result { @@ -425,7 +400,7 @@ impl<'a, B: Backend, Fut, F: Fn(&'a SharedDependencies, ChatId) -> Fut> } Ok(ChatStatus::MigratedTo(chat_id)) => self.trigger_chat(chat_id), Ok(ChatStatus::ShuttingDown) => (), - Err(e) => log::error!("{e}"), + Err(e) => tracing::error!(error=%e, "Processing chat failed"), } } } @@ -446,7 +421,7 @@ async fn broadcast_task(backend: impl Backend, mut shutdown_rx: mpsc::Receiver return, signal = shutdown_rx.recv() => match signal { - Some(ShutdownSignal::Soft) => soft_shutdown = true, - Some(ShutdownSignal::Hard) | None => break + Some(ShutdownSignal::Soft) => { + tracing::info!("Received soft shutdown signal"); + soft_shutdown = true; + } + Some(ShutdownSignal::Hard) => { + tracing::info!("Received hard shutdown signal"); + break; + } + None => { + tracing::warn!("Shutdown channel closed unexpectedly"); + break; + } }, item = updates.next(), if !updates.is_terminated() => { if let Some((id,active_chats)) = item { manager.on_message_scheduled(id, active_chats) } else { + tracing::info!("Scheduled messages stream is terminated, doing soft shutdown"); soft_shutdown = true; } }, @@ -480,13 +466,13 @@ async fn broadcast_task(backend: impl Backend, mut shutdown_rx: mpsc::Receiver, - handle: Fuse>, + handle: JoinHandle<()>, } impl Broadcaster { pub fn new(backend: impl Backend) -> Self { let (shutdown_tx, shutdown_rx) = mpsc::channel(2); - let handle = tokio::spawn(broadcast_task(backend, shutdown_rx)).fuse(); + let handle = tokio::spawn(broadcast_task(backend, shutdown_rx)); Self { shutdown_tx, handle, @@ -496,7 +482,7 @@ impl Broadcaster { pub async fn soft_shutdown(&mut self) { _ = self.shutdown_tx.send(ShutdownSignal::Soft).await; - if !self.handle.is_terminated() { + if !self.handle.is_finished() { _ = (&mut self.handle).await; } } @@ -504,7 +490,7 @@ impl Broadcaster { pub async fn hard_shutdown(self) { _ = self.shutdown_tx.send(ShutdownSignal::Hard).await; - if !self.handle.is_terminated() { + if !self.handle.is_finished() { _ = self.handle.await; } } diff --git a/bot-utils/src/command.rs b/bot-utils/src/command.rs index 6ce997c..97519e3 100644 --- a/bot-utils/src/command.rs +++ b/bot-utils/src/command.rs @@ -15,7 +15,7 @@ impl CommandParser { let pattern = if let Some(username) = username { &format!("^/([a-z0-9_]+)(?:@({}))?(?:\\s+(.*))?$", escape(username)) } else { - log::warn!("Bot has no username!"); + tracing::warn!("No username was given!"); "^/([a-z0-9_]+)(?:@([a-z0-9_]+))?(?:\\s+(.*))?$" }; diff --git a/bot-utils/src/lib.rs b/bot-utils/src/lib.rs index 4a9f587..0b941de 100644 --- a/bot-utils/src/lib.rs +++ b/bot-utils/src/lib.rs @@ -1,5 +1,50 @@ +use frankenstein::types::ChatMember; + pub mod broadcasting; pub mod command; +pub mod response; pub mod updates; +#[macro_export] +macro_rules! respond { + (@param $m:expr; maybe_reply_parameters group) => {if $m.chat.id < 0{ + let p = ::frankenstein::types::ReplyParameters::builder().message_id($m.message_id).build(); + Some(p) + } else { + None + }}; + (@param $m:expr; reply_parameters always) => { + ::frankenstein::types::ReplyParameters::builder().message_id($m.message_id).build() + }; + + (@param $m:expr; $p:ident) => {$p}; + (@param $m:expr; $p:ident $v:expr) => {$v}; + ($bot:expr, $message:expr $(,$p:ident $(= $v:expr)?)* $(,)? ) => {{ + let thread_id = $message + .is_topic_message + .unwrap_or(false) + .then_some($message.message_thread_id) + .flatten(); + let params = ::frankenstein::methods::SendMessageParams::builder() + .chat_id($message.chat.id) + .maybe_message_thread_id(thread_id) + $(.$p($crate::respond!(@param $message;$p $($v)?)))* + .build(); + + async move { + ::frankenstein::AsyncTelegramApi::send_message($bot, ¶ms).await.map(|_|()) + } + }}; +} + pub type ChatId = i64; + +pub fn can_send_messages(c: &ChatMember) -> bool { + match c { + ChatMember::Administrator(member) => member.can_post_messages.unwrap_or(true), + ChatMember::Restricted(member) => member.can_send_messages, + ChatMember::Left(_) => false, + ChatMember::Kicked(_) => false, + _ => true, + } +} diff --git a/bot-utils/src/response.rs b/bot-utils/src/response.rs new file mode 100644 index 0000000..16fb079 --- /dev/null +++ b/bot-utils/src/response.rs @@ -0,0 +1,75 @@ +use std::time::Duration; + +use frankenstein::Error; +use frankenstein::response::{ErrorResponse, ResponseParameters}; + +#[derive(Debug)] +pub enum RequestError { + InvalidToken, + ChatMigrated(i64), + BotBlocked, + RetryAfter(Duration), + ClientError, + Other, +} + +/// error messages that imply we're not allowed to send messages +/// to this chat in the future. +const TELEGRAM_ERRORS: [&str; 14] = [ + "Bad Request: CHAT_WRITE_FORBIDDEN", + "Bad Request: TOPIC_CLOSED", + "Bad Request: chat not found", + "Bad Request: have no rights to send a message", + "Bad Request: not enough rights to send text messages to the chat", + "Bad Request: need administrator rights in the channel chat", + "Forbidden: bot is not a member of the channel chat", + "Forbidden: bot is not a member of the supergroup chat", + "Forbidden: bot was blocked by the user", + "Forbidden: bot was kicked from the channel chat", + "Forbidden: bot was kicked from the group chat", + "Forbidden: bot was kicked from the supergroup chat", + "Forbidden: the group chat was deleted", + "Forbidden: user is deactivated", +]; + +pub fn map_error(e: &frankenstein::Error) -> RequestError { + let Error::Api(api_error) = e else { + return RequestError::Other; + }; + + match api_error { + ErrorResponse { + error_code: 401 | 404, + .. + } => RequestError::InvalidToken, + + ErrorResponse { + parameters: + Some(ResponseParameters { + migrate_to_chat_id: Some(new_chat_id), + .. + }), + .. + } => RequestError::ChatMigrated(*new_chat_id), + + ErrorResponse { description, .. } if TELEGRAM_ERRORS.contains(&description.as_str()) => { + RequestError::BotBlocked + } + + ErrorResponse { + parameters: + Some(ResponseParameters { + retry_after: Some(secs), + .. + }), + .. + } => RequestError::RetryAfter(Duration::from_secs(*secs as u64)), + + ErrorResponse { + error_code: 400..=499, + .. + } => RequestError::ClientError, + + _ => RequestError::Other, + } +} diff --git a/bot-utils/src/updates.rs b/bot-utils/src/updates.rs index c20e499..ccf8480 100644 --- a/bot-utils/src/updates.rs +++ b/bot-utils/src/updates.rs @@ -8,18 +8,20 @@ use frankenstein::methods::GetUpdatesParams; use frankenstein::types::{ AllowedUpdate, CallbackQuery, ChatMemberUpdated, MaybeInaccessibleMessage, Message, }; -use frankenstein::updates::UpdateContent; +use frankenstein::updates::{Update, UpdateContent}; use futures_util::FutureExt; use tokio::select; use tokio::sync::{Mutex, oneshot}; use tokio::task::JoinSet; use tokio::time::sleep; +use tracing::Instrument; const CLEANUP_PERIOD: Duration = Duration::from_secs(300); +type Mutexes = HashMap>>; #[allow(unused_variables)] pub trait UpdateHandler: Clone + Send + 'static { - fn handle_message(self, message: Message) -> impl Future + Send { + fn handle_message(self, message: Box) -> impl Future + Send { async {} } @@ -27,12 +29,12 @@ pub trait UpdateHandler: Clone + Send + 'static { async {} } - fn handle_callback_query(self, update: CallbackQuery) -> impl Future + Send { + fn handle_callback_query(self, update: Box) -> impl Future + Send { async {} } } -fn cleanup(last_cleanup: &mut Instant, mutexes: &mut HashMap>>) { +fn cleanup(last_cleanup: &mut Instant, mutexes: &mut Mutexes) { let now = Instant::now(); if now - *last_cleanup < CLEANUP_PERIOD { @@ -44,6 +46,74 @@ fn cleanup(last_cleanup: &mut Instant, mutexes: &mut HashMap *last_cleanup = now; } +fn handle_update( + handler: &impl UpdateHandler, + mutexes: &mut Mutexes, + join_set: &mut JoinSet<()>, + update: Update, +) { + let chat = match &update.content { + UpdateContent::Message(msg) => &*msg.chat, + UpdateContent::MyChatMember(member) => &member.chat, + UpdateContent::CallbackQuery(query) => match &query.message { + Some(MaybeInaccessibleMessage::InaccessibleMessage(m)) => &m.chat, + Some(MaybeInaccessibleMessage::Message(m)) => &m.chat, + None => { + tracing::warn!( + id = update.update_id, + from = query.from.id, + "Received callback query without message" + ); + return; + } + }, + _ => { + tracing::warn!(id = update.update_id, "Received unsupported update"); + return; + } + }; + + let span = tracing::error_span!("update", id = update.update_id, chat = chat.id).entered(); + + let mutex = mutexes + .get(&chat.id) + .and_then(|weak| weak.upgrade()) + .unwrap_or_else(|| { + let mutex = Default::default(); + mutexes.insert(chat.id, Arc::downgrade(&mutex)); + mutex + }); + + let handler = handler.clone(); + let mut acquiring = Box::pin(mutex.lock_owned()); + + // to ensure correct order, it's necessary to poll the future + // once now (to enqueue it in the mutex' fifo queue) + let guard = acquiring.as_mut().now_or_never(); + tracing::trace!(immediately = guard.is_some(), "Acquiring chat mutex"); + + let fut = async move { + let _guard = if let Some(guard) = guard { + guard + } else { + acquiring.await + }; + + tracing::trace!("Start handling update"); + + match update.content { + UpdateContent::Message(msg) => handler.handle_message(msg).await, + UpdateContent::MyChatMember(msg) => handler.handle_my_chat_member(msg).await, + UpdateContent::CallbackQuery(q) => { + handler.handle_callback_query(q).await; + } + _ => tracing::warn!("Unreachable code reached!"), + } + }; + + join_set.spawn(fut.instrument(span.exit())); +} + /// Gets new incoming messages and calls `handler` on them, while ensuring that no messages /// from the same chat are processed in parallel. pub async fn handle_updates>( @@ -52,7 +122,7 @@ pub async fn handle_updates>( allowed_updates: Vec, mut shutdown: oneshot::Receiver<()>, ) { - let mut mutexes: HashMap>> = HashMap::new(); + let mut mutexes = Mutexes::new(); let mut last_cleanup = Instant::now(); let mut join_set = JoinSet::new(); @@ -74,64 +144,11 @@ pub async fn handle_updates>( marked_seen = updates.result.is_empty(); for update in updates.result { params.offset = Some(update.update_id as i64 + 1); - - let chat = match &update.content { - UpdateContent::Message(msg) => &*msg.chat, - UpdateContent::MyChatMember(member) => &member.chat, - UpdateContent::CallbackQuery(query) => match &query.message { - Some(MaybeInaccessibleMessage::InaccessibleMessage(m)) => &m.chat, - Some(MaybeInaccessibleMessage::Message(m)) => &m.chat, - None => { - log::warn!("Unsupported!"); - continue; - } - }, - _ => { - log::warn!("Received unsupported update: {:?}", update.content); - continue; - } - }; - - let mutex = mutexes - .get(&chat.id) - .and_then(|weak| weak.upgrade()) - .unwrap_or_else(|| { - let mutex = Default::default(); - mutexes.insert(chat.id, Arc::downgrade(&mutex)); - mutex - }); - - let handler = handler.clone(); - let mut acquiring = Box::pin(mutex.lock_owned()); - - // to ensure correct order, it's necessary to poll the future - // once now (to enqueue it in the mutex' fifo queue) - let guard = acquiring.as_mut().now_or_never(); - - let fut = async move { - let guard = if let Some(guard) = guard { - guard - } else { - acquiring.await - }; - - match update.content { - UpdateContent::Message(msg) => handler.handle_message(msg).await, - UpdateContent::MyChatMember(msg) => { - handler.handle_my_chat_member(msg).await - } - UpdateContent::CallbackQuery(q) => { - handler.handle_callback_query(q).await; - } - _ => log::warn!("Unreachable code reached!"), - } - drop(guard) - }; - join_set.spawn(fut); + handle_update(&handler, &mut mutexes, &mut join_set, update); } } Err(e) => { - log::error!("Error retrieving updates: {}", e); + tracing::error!(error = %e, "Error retrieving updates"); sleep(Duration::from_secs(5)).await; } } @@ -145,7 +162,7 @@ pub async fn handle_updates>( params.limit = Some(1); if let Err(e) = bot.get_updates(¶ms).await { - log::error!("Error marking messages as seen: {}", e); + tracing::error!(error = %e, "Error marking messages as seen"); } } diff --git a/src/allris/html.rs b/src/allris/html.rs index 9ec4209..eb76427 100644 --- a/src/allris/html.rs +++ b/src/allris/html.rs @@ -64,7 +64,7 @@ pub async fn scrape_website(client: &Client, url: &Url) -> Result { pub struct ArcMessageHandler(Arc); impl UpdateHandler for ArcMessageHandler { - async fn handle_message(self, message: Message) { + async fn handle_message(self, message: Box) { HandleMessage { message: &message, inner: &self.0, @@ -461,25 +459,21 @@ impl UpdateHandler for ArcMessageHandler { } async fn handle_my_chat_member(self, update: ChatMemberUpdated) { - let can_send_messages = match update.new_chat_member { - ChatMember::Administrator(member) => member.can_post_messages.unwrap_or(true), - ChatMember::Restricted(member) => member.can_send_messages, - ChatMember::Left(_) => false, - ChatMember::Kicked(_) => false, - _ => true, - }; + let can_send_messages = bot_utils::can_send_messages(&update.new_chat_member); if !can_send_messages { + let chat_id = update.chat.id; + let delete_chat = async { - self.0.database.remove_subscription(update.chat.id).await?; - self.0.database.remove_dialogue(update.chat.id).await?; + self.0.database.remove_subscription(chat_id).await?; + self.0.database.remove_dialogue(chat_id).await?; HandlerResult::Ok(()) }; if let Err(e) = delete_chat.await { - log::error!("Unable to delete chat {}: {e}", update.chat.id) + log::error!("Unable to delete chat {chat_id}: {e}") } else { - log::info!("Chat was deleted!"); + log::info!("Chat {chat_id} was deleted!"); } } } diff --git a/src/main.rs b/src/main.rs index 0bc1bad..780dc6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ use clap::Parser; use database::DatabaseConnection; use redis::{ConnectionInfo, IntoConnectionInfo}; use tokio::sync::oneshot; +use tracing_subscriber::EnvFilter; use url::Url; use crate::allris::AllrisUrl; @@ -110,19 +111,24 @@ fn parse_owner_username(mut input: &str) -> Result { fn init_logging(args: &Args) { let log_level = match (args.quiet, args.verbose) { - (true, _) => log::LevelFilter::Off, - (_, 0) => log::LevelFilter::Error, - (_, 1) => log::LevelFilter::Warn, - (_, 2) => log::LevelFilter::Info, - (_, 3) => log::LevelFilter::Debug, - _ => log::LevelFilter::Trace, + (true, _) => "off", + (_, 0) => "error", + (_, 1) => "warn", + (_, 2) => "info", + (_, 3) => "debug", + _ => "trace", }; - env_logger::Builder::from_default_env() - .filter_level(log_level) - .filter_module("scraper", log::LevelFilter::Off) - .filter_module("selectors", log::LevelFilter::Off) - .filter_module("html5ever", log::LevelFilter::Off) + // Build the subscriber with filtering and formatting + let filter = EnvFilter::builder() + .parse(format!( + "{log_level},scraper=off,selectors=off,html5ever=off,h2=warn,hyper_util=warn" + )) + .unwrap(); + + tracing_subscriber::fmt() + .with_env_filter(filter) + .with_target(true) .init(); } diff --git a/telegram-message-builder/Cargo.toml b/telegram-message-builder/Cargo.toml index 756b57f..1c7be98 100644 --- a/telegram-message-builder/Cargo.toml +++ b/telegram-message-builder/Cargo.toml @@ -6,5 +6,5 @@ edition = "2024" license = "MIT OR Apache-2.0" [dependencies] -frankenstein = "0.40.0" +frankenstein = "0.41.0" telegram-message-builder-macro = { path = "../telegram-message-builder-macro" } diff --git a/telegram-message-builder/src/lib.rs b/telegram-message-builder/src/lib.rs index 1ab2918..1d10fa1 100644 --- a/telegram-message-builder/src/lib.rs +++ b/telegram-message-builder/src/lib.rs @@ -534,7 +534,7 @@ mod tests { use super::{concat, *}; - fn get_entity(entities: &Vec) -> &MessageEntity { + fn get_entity(entities: &[MessageEntity]) -> &MessageEntity { entities.first().expect("expected at least one entity") }