From 40d05cb2412205968df23af334a20506cd2fe861 Mon Sep 17 00:00:00 2001 From: RA <70325462+RAprogramm@users.noreply.github.com> Date: Fri, 12 Sep 2025 13:05:58 +0700 Subject: [PATCH 1/3] feat: add teloxide error mapping --- CHANGELOG.md | 5 + Cargo.lock | 478 +++++++++++++++++++++++++++-- Cargo.toml | 4 +- README.md | 7 +- src/convert.rs | 5 + src/convert/telegram_webapp_sdk.rs | 3 + src/convert/teloxide.rs | 86 ++++++ src/lib.rs | 1 + 8 files changed, 566 insertions(+), 23 deletions(-) create mode 100644 src/convert/teloxide.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a47f16..945b6d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [0.3.5] - 2025-09-12 +### Added +- Conversion from `teloxide_core::RequestError` into `AppError` (feature `teloxide`). + ## [0.3.4] - 2025-09-12 ### Added - `ErrorResponse::with_retry_after_duration` helper for specifying retry advice via `Duration`. @@ -99,6 +103,7 @@ All notable changes to this project will be documented in this file. - **MSRV:** 1.89 - **No unsafe:** the crate forbids `unsafe`. +[0.3.5]: https://github.com/RAprogramm/masterror/releases/tag/v0.3.5 [0.3.4]: https://github.com/RAprogramm/masterror/releases/tag/v0.3.4 [0.3.3]: https://github.com/RAprogramm/masterror/releases/tag/v0.3.3 [0.3.2]: https://github.com/RAprogramm/masterror/releases/tag/v0.3.2 diff --git a/Cargo.lock b/Cargo.lock index 88c3414..b93a727 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ dependencies = [ "bitflags", "bytes", "bytestring", - "derive_more", + "derive_more 2.0.1", "encoding_rs", "foldhash", "futures-core", @@ -143,7 +143,7 @@ dependencies = [ "bytes", "bytestring", "cfg-if", - "derive_more", + "derive_more 2.0.1", "encoding_rs", "foldhash", "futures-core", @@ -208,6 +208,15 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "arraydeque" version = "0.5.1" @@ -351,6 +360,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "bytemuck" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" + [[package]] name = "byteorder" version = "1.5.0" @@ -372,12 +387,34 @@ dependencies = [ "bytes", ] +[[package]] +name = "cc" +version = "1.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link 0.2.0", +] + [[package]] name = "combine" version = "4.6.7" @@ -452,6 +489,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -587,6 +630,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", + "serde", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", ] [[package]] @@ -595,7 +648,19 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" dependencies = [ - "derive_more-impl", + "derive_more-impl 2.0.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] @@ -648,6 +713,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "ed25519" version = "2.2.3" @@ -696,6 +767,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erasable" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437cfb75878119ed8265685c41a115724eae43fb7cc5a0bf0e4ecc3b803af1c4" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "erased-serde" version = "0.4.6" @@ -734,6 +815,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + [[package]] name = "flume" version = "0.11.1" @@ -766,6 +853,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -810,6 +912,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -828,8 +941,10 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -877,6 +992,12 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1050,6 +1171,30 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" version = "2.0.0" @@ -1169,6 +1314,17 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.11.1" @@ -1335,7 +1491,7 @@ dependencies = [ [[package]] name = "masterror" -version = "0.3.4" +version = "0.3.5" dependencies = [ "actix-web", "axum", @@ -1347,6 +1503,7 @@ dependencies = [ "serde_json", "sqlx", "telegram-webapp-sdk", + "teloxide-core", "thiserror", "tokio", "tracing", @@ -1354,18 +1511,6 @@ dependencies = [ "validator", ] -[[package]] -name = "masterror" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e7c3a243a6f697e05d0b971c22d0ac029b9080c20b2bbc5f4a3f43ea6024a60" -dependencies = [ - "http 1.3.1", - "serde", - "thiserror", - "tracing", -] - [[package]] name = "matchit" version = "0.8.4" @@ -1394,6 +1539,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1614,6 +1769,26 @@ dependencies = [ "sha2", ] +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -1708,6 +1883,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psm" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" +dependencies = [ + "cc", +] + [[package]] name = "quote" version = "1.0.40" @@ -1782,6 +1966,15 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rc-box" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897fecc9fac6febd4408f9e935e86df739b0023b625e610e0357535b9c8adad0" +dependencies = [ + "erasable", +] + [[package]] name = "redis" version = "0.32.5" @@ -1806,6 +1999,26 @@ dependencies = [ "bitflags", ] +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "regex" version = "1.11.2" @@ -1850,6 +2063,7 @@ dependencies = [ "base64 0.22.1", "bytes", "futures-core", + "futures-util", "http 1.3.1", "http-body", "http-body-util", @@ -1857,6 +2071,7 @@ dependencies = [ "hyper-util", "js-sys", "log", + "mime_guess", "percent-encoding", "pin-project-lite", "serde", @@ -1864,15 +2079,26 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-util", "tower", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", ] +[[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +dependencies = [ + "bytemuck", +] + [[package]] name = "ron" version = "0.8.1" @@ -1942,6 +2168,30 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2039,6 +2289,38 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.11.1", + "schemars 0.9.0", + "schemars 1.0.4", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2061,6 +2343,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.6" @@ -2165,7 +2453,7 @@ dependencies = [ "futures-util", "hashbrown 0.15.5", "hashlink", - "indexmap", + "indexmap 2.11.1", "log", "memchr", "once_cell", @@ -2320,6 +2608,19 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "stacker" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + [[package]] name = "stringprep" version = "0.1.5" @@ -2374,6 +2675,18 @@ dependencies = [ "syn", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + +[[package]] +name = "takecell" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e" + [[package]] name = "telegram-webapp-sdk" version = "0.1.0" @@ -2384,7 +2697,7 @@ dependencies = [ "hex", "hmac-sha256", "js-sys", - "masterror 0.3", + "masterror 0.3.3", "once_cell", "percent-encoding", "serde", @@ -2397,6 +2710,38 @@ dependencies = [ "web-sys", ] +[[package]] +name = "teloxide-core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7a34ca8e971fa892e633858c07547fe138ef4a02e4a4eaa1d35e517d6e0bc4" +dependencies = [ + "bitflags", + "bytes", + "chrono", + "derive_more 1.0.0", + "either", + "futures", + "log", + "mime", + "once_cell", + "pin-project", + "rc-box", + "reqwest", + "rgb", + "serde", + "serde_json", + "serde_with", + "stacker", + "take_mut", + "takecell", + "thiserror", + "tokio", + "tokio-util", + "url", + "uuid", +] + [[package]] name = "thiserror" version = "2.0.16" @@ -2657,6 +3002,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-bidi" version = "0.3.18" @@ -2720,7 +3071,7 @@ version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" dependencies = [ - "indexmap", + "indexmap 2.11.1", "serde", "serde_json", "utoipa-gen", @@ -2737,6 +3088,17 @@ dependencies = [ "syn", ] +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "validator" version = "0.20.0" @@ -2890,6 +3252,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.78" @@ -2910,6 +3285,71 @@ dependencies = [ "wasite", ] +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index ff5a601..675e797 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "masterror" -version = "0.3.4" +version = "0.3.5" rust-version = "1.89" edition = "2024" description = "Application error types and response mapping" @@ -24,6 +24,7 @@ config = ["dep:config"] # config::ConfigError -> AppError multipart = ["axum"] tokio = ["dep:tokio"] reqwest = ["dep:reqwest"] +teloxide = ["dep:teloxide-core"] telegram-webapp-sdk = ["dep:telegram-webapp-sdk"] turnkey = [] @@ -55,6 +56,7 @@ config = { version = "0.15", optional = true } utoipa = { version = "5.3", optional = true } tokio = { version = "1", optional = true, features = ["time"] } reqwest = { version = "0.12", optional = true, default-features = false } +teloxide-core = { version = "0.13", optional = true, default-features = false } telegram-webapp-sdk = { git = "https://github.com/RAprogramm/telegram-webapp-sdk", rev = "0c5a1d557e1cefe2b37a190c9359be05fe48d41a", optional = true } [dev-dependencies] diff --git a/README.md b/README.md index 1153e60..70f8525 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ masterror = { version = "0.3", default-features = false } # or with features: # masterror = { version = "0.3", features = [ # "axum", "actix", "serde_json", "openapi", -# "sqlx", "reqwest", "redis", "validator", "config", "tokio" +# "sqlx", "reqwest", "redis", "validator", "config", "tokio", "teloxide" # ] } ~~~ @@ -58,7 +58,7 @@ masterror = { version = "0.3", default-features = false } # with Axum/Actix + JSON + integrations # masterror = { version = "0.3", features = [ # "axum", "actix", "serde_json", "openapi", -# "sqlx", "reqwest", "redis", "validator", "config", "tokio" +# "sqlx", "reqwest", "redis", "validator", "config", "tokio", "teloxide" # ] } ~~~ @@ -173,7 +173,7 @@ utoipa = "5" - `actix` — ResponseError/Responder - `openapi` — utoipa schema - `serde_json` — JSON details -- `sqlx`, `redis`, `reqwest`, `validator`, `config`, `tokio`, `multipart`, `telegram-webapp-sdk` +- `sqlx`, `redis`, `reqwest`, `validator`, `config`, `tokio`, `multipart`, `teloxide`, `telegram-webapp-sdk` - `turnkey` — domain taxonomy and conversions for Turnkey errors @@ -190,6 +190,7 @@ utoipa = "5" - `validator::ValidationErrors` → Validation - `config::ConfigError` → Config - `tokio::time::error::Elapsed` → Timeout +- `teloxide_core::RequestError` → RateLimited/Network/ExternalApi/Deserialization/Internal - `telegram_webapp_sdk::utils::validate_init_data::ValidationError` → TelegramAuth diff --git a/src/convert.rs b/src/convert.rs index 52f8c42..eb0d6d3 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -26,6 +26,7 @@ //! manually) //! - `sqlx`: database driver errors //! - `tokio`: timeouts from `tokio::time::error::Elapsed` +//! - `teloxide`: Telegram request errors //! - `validator`: input DTO validation errors //! //! ## Design notes @@ -113,6 +114,10 @@ mod tokio; #[cfg_attr(docsrs, doc(cfg(feature = "validator")))] mod validator; +#[cfg(feature = "teloxide")] +#[cfg_attr(docsrs, doc(cfg(feature = "teloxide")))] +mod teloxide; + #[cfg(feature = "telegram-webapp-sdk")] #[cfg_attr(docsrs, doc(cfg(feature = "telegram-webapp-sdk")))] mod telegram_webapp_sdk; diff --git a/src/convert/telegram_webapp_sdk.rs b/src/convert/telegram_webapp_sdk.rs index 0d85ae8..944e5aa 100644 --- a/src/convert/telegram_webapp_sdk.rs +++ b/src/convert/telegram_webapp_sdk.rs @@ -73,6 +73,9 @@ mod tests { assert!(matches!(app.kind, AppErrorKind::TelegramAuth)); assert_eq!(app.message.as_deref(), Some(msg.as_str())); } + } + + #[test] fn validation_error_maps_to_telegram_auth() { let err: AppError = ValidationError::SignatureMismatch.into(); assert!(matches!(err.kind, AppErrorKind::TelegramAuth)); diff --git a/src/convert/teloxide.rs b/src/convert/teloxide.rs new file mode 100644 index 0000000..6e30032 --- /dev/null +++ b/src/convert/teloxide.rs @@ -0,0 +1,86 @@ +//! Conversion from [`teloxide_core::RequestError`] into [`AppError`]. +//! +//! Enabled with the `teloxide` feature flag. +//! +//! ## Mapping +//! +//! - [`RequestError::Api`] or [`RequestError::MigrateToChatId`] → +//! `AppErrorKind::ExternalApi` +//! - [`RequestError::RetryAfter`] → `AppErrorKind::RateLimited` +//! - [`RequestError::Network`] → `AppErrorKind::Network` +//! - [`RequestError::InvalidJson`] → `AppErrorKind::Deserialization` +//! - [`RequestError::Io`] → `AppErrorKind::Internal` +//! +//! The original error string is preserved in the `message` for observability. +//! +//! ## Example +//! +//! ```rust,ignore +//! use masterror::{AppError, AppErrorKind}; +//! use teloxide_core::{errors::ApiError, RequestError, types::Seconds}; +//! use std::{io, sync::Arc}; +//! +//! fn map(err: RequestError) -> AppError { err.into() } +//! +//! let err = RequestError::RetryAfter(Seconds::from_seconds(1)); +//! let app_err = map(err); +//! assert!(matches!(app_err.kind, AppErrorKind::RateLimited)); +//! ``` +#[cfg(feature = "teloxide")] +use teloxide_core::RequestError; + +#[cfg(feature = "teloxide")] +use crate::AppError; + +#[cfg(feature = "teloxide")] +#[cfg_attr(docsrs, doc(cfg(feature = "teloxide")))] +impl From for AppError { + fn from(err: RequestError) -> Self { + match err { + RequestError::Api(api) => AppError::external_api(format!("Telegram API error: {api}")), + RequestError::MigrateToChatId(id) => { + AppError::external_api(format!("Group migrated to {id}")) + } + RequestError::RetryAfter(secs) => { + AppError::rate_limited(format!("Retry after {secs}")) + } + RequestError::Network(e) => AppError::network(format!("Network error: {e}")), + RequestError::InvalidJson { + source, .. + } => AppError::deserialization(format!("Invalid Telegram JSON: {source}")), + RequestError::Io(e) => AppError::internal(format!("I/O error: {e}")) + } + } +} + +#[cfg(all(test, feature = "teloxide"))] +mod tests { + use std::{io, sync::Arc}; + + use teloxide_core::{errors::ApiError, types::Seconds}; + + use super::*; + use crate::AppErrorKind; + + #[test] + fn api_maps_to_external_api() { + let err = RequestError::Api(ApiError::BotBlocked); + let app_err: AppError = err.into(); + assert!(matches!(app_err.kind, AppErrorKind::ExternalApi)); + } + + #[test] + fn retry_after_maps_to_rate_limited() { + let err = RequestError::RetryAfter(Seconds::from_seconds(5)); + let app_err: AppError = err.into(); + assert!(matches!(app_err.kind, AppErrorKind::RateLimited)); + } + + #[test] + fn io_maps_to_internal() { + let io_err = Arc::new(io::Error::other("disk")); + let err = RequestError::Io(io_err); + let app_err: AppError = err.into(); + assert!(matches!(app_err.kind, AppErrorKind::Internal)); + } +} diff --git a/src/lib.rs b/src/lib.rs index de3cb9a..7139b39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ //! - `config` — `From` mapping //! - `tokio` — `From` mapping //! - `reqwest` — `From` mapping +//! - `teloxide` — `From` mapping //! - `telegram-webapp-sdk` — //! `From` //! mapping From 661ccd1ad012f49a1dc85529d459dcf9e52ab3b9 Mon Sep 17 00:00:00 2001 From: RAprogramm Date: Fri, 12 Sep 2025 13:32:09 +0700 Subject: [PATCH 2/3] prepare v0.3.5 --- Cargo.toml | 4 ++-- src/convert/telegram_webapp_sdk.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 675e797..5431131 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,13 @@ keywords = ["error", "api", "framework"] [features] default = [] -axum = ["dep:axum", "dep:serde_json"] # IntoResponse + JSON body +axum = ["dep:axum", "dep:serde_json"] # IntoResponse + JSON body actix = ["dep:actix-web", "dep:serde_json"] sqlx = ["dep:sqlx"] redis = ["dep:redis"] validator = ["dep:validator"] serde_json = ["dep:serde_json"] -config = ["dep:config"] # config::ConfigError -> AppError +config = ["dep:config"] # config::ConfigError -> AppError multipart = ["axum"] tokio = ["dep:tokio"] reqwest = ["dep:reqwest"] diff --git a/src/convert/telegram_webapp_sdk.rs b/src/convert/telegram_webapp_sdk.rs index 944e5aa..252a089 100644 --- a/src/convert/telegram_webapp_sdk.rs +++ b/src/convert/telegram_webapp_sdk.rs @@ -18,10 +18,10 @@ //! //! ## Example //! -//! ```rust +//! '''rust //! # #[cfg(feature = "telegram-webapp-sdk")] //! # { -//! ```rust,ignore +//! '''rust,ignore //! use masterror::{AppError, AppErrorKind}; //! use telegram_webapp_sdk::utils::validate_init_data::ValidationError; //! @@ -33,7 +33,7 @@ //! assert!(matches!(e.kind, AppErrorKind::TelegramAuth)); //! assert_eq!(e.message.as_deref(), Some("signature mismatch")); //! # } -//! ``` +//! ''' #[cfg(feature = "telegram-webapp-sdk")] use telegram_webapp_sdk::utils::validate_init_data::ValidationError; From ab3a9d14323a83b499ed44cb8583250eead0ede0 Mon Sep 17 00:00:00 2001 From: RAprogramm Date: Fri, 12 Sep 2025 13:40:25 +0700 Subject: [PATCH 3/3] prepare v0.3.5 --- Cargo.lock | 7 ++++--- Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b93a727..f7c890c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2689,10 +2689,11 @@ checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e" [[package]] name = "telegram-webapp-sdk" -version = "0.1.0" -source = "git+https://github.com/RAprogramm/telegram-webapp-sdk?rev=0c5a1d557e1cefe2b37a190c9359be05fe48d41a#0c5a1d557e1cefe2b37a190c9359be05fe48d41a" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80632ebd5e273b42ddff5f444be5d6e2d7976a283008853a3b3af6a183f936e3" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "ed25519-dalek", "hex", "hmac-sha256", diff --git a/Cargo.toml b/Cargo.toml index 5431131..92ec6b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,11 +53,11 @@ sqlx = { version = "0.8", optional = true, default-features = false, features = redis = { version = "0.32", optional = true, default-features = false } validator = { version = "0.20", optional = true, features = ["derive"] } config = { version = "0.15", optional = true } -utoipa = { version = "5.3", optional = true } +utoipa = { version = "5.4", optional = true } tokio = { version = "1", optional = true, features = ["time"] } reqwest = { version = "0.12", optional = true, default-features = false } teloxide-core = { version = "0.13", optional = true, default-features = false } -telegram-webapp-sdk = { git = "https://github.com/RAprogramm/telegram-webapp-sdk", rev = "0c5a1d557e1cefe2b37a190c9359be05fe48d41a", optional = true } +telegram-webapp-sdk = { version = "0.1", optional = true } [dev-dependencies] serde_json = "1"