diff --git a/.gitignore b/.gitignore index 6abfe1b..81213c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ /target /.direnv +/db +/.env +/result +/telegram-exporter-arx +/channels.json diff --git a/Cargo.lock b/Cargo.lock index 50637cc..66544cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,6 +59,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.2" @@ -71,6 +77,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.10.1" @@ -88,9 +100,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34e221e91c7eb5e8315b5c9cf1a61670938c0626451f954a51693ed44b37f45" +checksum = "c8d458d63f0f0f482c8da9b7c8b76c21bd885a02056cc94c6404d861ca2b8206" dependencies = [ "smallvec", "target-lexicon", @@ -115,12 +127,59 @@ dependencies = [ "windows-link", ] +[[package]] +name = "console" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.1", + "windows-sys 0.60.2", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossterm" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "darling" version = "0.20.11" @@ -142,7 +201,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.106", ] [[package]] @@ -153,7 +212,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -187,6 +246,35 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dotenv_codegen" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56966279c10e4f8ee8c22123a15ed74e7c8150b658b26c619c53f4a56eb4a8aa" +dependencies = [ + "dotenv_codegen_implementation", + "proc-macro-hack", +] + +[[package]] +name = "dotenv_codegen_implementation" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e737a3522cd45f6adc19b644ce43ef53e1e9045f2d2de425c1f468abd4cf33" +dependencies = [ + "dotenv", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -199,12 +287,29 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "libz-sys", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -226,6 +331,24 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -319,13 +442,43 @@ dependencies = [ "serde", ] +[[package]] +name = "indicatif" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" +dependencies = [ + "console", + "portable-atomic", + "unicode-width 0.2.1", + "unit-prefix", + "web-time", +] + +[[package]] +name = "inquire" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a" +dependencies = [ + "bitflags 2.9.2", + "crossterm", + "dyn-clone", + "fuzzy-matcher", + "fxhash", + "newline-converter", + "once_cell", + "unicode-segmentation", + "unicode-width 0.1.14", +] + [[package]] name = "io-uring" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "bitflags", + "bitflags 2.9.2", "cfg-if", "libc", ] @@ -358,10 +511,21 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags", + "bitflags 2.9.2", "libc", ] +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "lock_api" version = "0.4.13" @@ -393,6 +557,18 @@ dependencies = [ "adler2", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "mio" version = "1.0.4" @@ -404,6 +580,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "newline-converter" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -475,12 +660,24 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" version = "1.0.101" @@ -505,7 +702,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags", + "bitflags 2.9.2", ] [[package]] @@ -536,7 +733,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -604,14 +801,14 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -657,7 +854,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -666,6 +863,27 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio 0.8.11", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.6" @@ -703,6 +921,17 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.106" @@ -770,7 +999,13 @@ checksum = "87cbdfae498e57fb48d380fff8eb5c9c98d4497c998f6de0d30d5d6b12f5358b" name = "telegram-exporter" version = "0.1.0" dependencies = [ + "dotenv_codegen", "dotenvy", + "flate2", + "indicatif", + "inquire", + "serde", + "serde_json", "tdlib-rs", "tokio", ] @@ -792,7 +1027,16 @@ checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", ] [[package]] @@ -836,7 +1080,7 @@ dependencies = [ "bytes", "io-uring", "libc", - "mio", + "mio 1.0.4", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -854,7 +1098,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -897,6 +1141,36 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + +[[package]] +name = "unit-prefix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.0" @@ -931,7 +1205,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.106", "wasm-bindgen-shared", ] @@ -953,7 +1227,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -967,6 +1241,38 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[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.2" @@ -988,7 +1294,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -999,7 +1305,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1026,6 +1332,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -1044,6 +1359,21 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -1077,6 +1407,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -1089,6 +1425,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -1101,6 +1443,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1125,6 +1473,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -1137,6 +1491,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -1149,6 +1509,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -1161,6 +1527,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1175,9 +1547,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 98fab42..eeb3f24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,13 @@ version = "0.1.0" edition = "2024" [dependencies] +dotenv_codegen = "0.15.0" dotenvy = "0.15.7" +flate2 = { version = "1.1.2", features = ["zlib"] } +indicatif = "0.18.0" +inquire = "0.7.5" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.143" tdlib-rs = { version = "1.1.0", features = ["pkg-config"] } tokio = { version = "1.47.1", features = ["full"] } @@ -13,3 +19,10 @@ tdlib-rs = { version = "1.1.0", features = ["pkg-config"] } [package.metadata.system-deps] tdjson = "1.8.29" + +[profile.release] +codegen-units = 1 +lto = true +opt-level = "z" +strip = true +panic = "abort" diff --git a/flake.lock b/flake.lock index 3285909..a533c4f 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "crane": { "locked": { - "lastModified": 1748970125, - "narHash": "sha256-UDyigbDGv8fvs9aS95yzFfOKkEjx1LO3PL3DsKopohA=", + "lastModified": 1755993354, + "narHash": "sha256-FCRRAzSaL/+umLIm3RU3O/+fJ2ssaPHseI2SSFL8yZU=", "owner": "ipetkov", "repo": "crane", - "rev": "323b5746d89e04b22554b061522dfce9e4c49b18", + "rev": "25bd41b24426c7734278c2ff02e53258851db914", "type": "github" }, "original": { @@ -35,11 +35,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1748929857, - "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", + "lastModified": 1756125398, + "narHash": "sha256-XexyKZpf46cMiO5Vbj+dWSAXOnr285GHsMch8FBoHbc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4", + "rev": "3b9f00d7a7bf68acd4c4abb9d43695afb04e03a5", "type": "github" }, "original": { @@ -81,11 +81,11 @@ ] }, "locked": { - "lastModified": 1749091064, - "narHash": "sha256-TGtYjzRX0sueFhwYsnNNFF5TTKnpnloznpIghLzxeXo=", + "lastModified": 1756175826, + "narHash": "sha256-cQNnntKWve+vnqo6pGGXl4NFT4dgnMKXl4+bpwLELvU=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "12419593ce78f2e8e1e89a373c6515885e218acb", + "rev": "d137b47bde8a6783b961db81254013b454eab46a", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index a3ae48e..ef6caec 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,19 @@ pkgs = import nixpkgs { inherit system; overlays = [ + (final: prev: { + tdlib = prev.tdlib.overrideAttrs (_: { + version = "1.8.29"; + src = prev.fetchFromGitHub { + owner = "tdlib"; + repo = "td"; + rev = "af69dd4397b6dc1bf23ba0fd0bf429fcba6454f6"; + hash = "sha256-2RhKSxy0AvuA74LHI86pqUxv9oJZ+ZxxDe4TPI5UYxE="; + # hash = "sha256-mbhxuJjrV3nC8Ja7N0WWF9ByHovJLmoLLuuzoU4khjU="; + }; + + }); + }) (import rust-overlay) ]; }; @@ -48,29 +61,33 @@ ]; } ); - src = craneLib.cleanCargoSource ./.; + src = lib.cleanSourceWith { + src = ./.; + filter = ( + path: type: (craneLib.filterCargoSources path type) || (builtins.match ".*/\.env$" path != null) + ); + name = "source"; + }; commonArgs = { inherit src; strictDeps = true; + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + buildInputs = with pkgs; [ + tdlib + openssl + ]; }; cargoArtifacts = craneLib.buildDepsOnly commonArgs; - individualCrateArgs = commonArgs // { - inherit cargoArtifacts; - inherit (craneLib.crateNameFromCargoToml { inherit src; }) version; - }; - - fileSetForCrate = - crate: - lib.fileset.toSource { - root = ./.; - fileset = lib.fileset.unions [ - ./Cargo.toml - ./Cargo.lock - ]; - }; server = craneLib.buildPackage ( - individualCrateArgs + commonArgs // { + inherit cargoArtifacts; + inherit (craneLib.crateNameFromCargoToml { inherit src; }) version; + postInstall = '' + ${pkgs.upx}/bin/upx --lzma --best $out/bin/telegram-exporter + ''; } ); in @@ -81,6 +98,8 @@ config = (import ./process-compose.nix { inherit pkgs; }); modules = [ ]; }; + default = server; + inherit server; }; devShells.default = craneLib.devShell { diff --git a/src/main.rs b/src/main.rs index 33a5791..b8f52e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,8 +6,16 @@ use std::{ }, }; +use dotenv_codegen::dotenv; +use flate2::write::ZlibEncoder; +use indicatif::{ProgressBar, ProgressStyle}; +use inquire::{Password, Text, validator::StringValidator}; +use serde::{Deserialize, Serialize}; use tdlib_rs::{ - enums::{self, AuthorizationState, Update, User}, + enums::{ + self, AuthorizationState, Chat, ChatPhoto, Chats, Supergroup, SupergroupFullInfo, Update, + User, + }, functions, }; use tokio::sync::mpsc::{self, Receiver, Sender}; @@ -18,10 +26,36 @@ async fn handle_update(update: Update, auth_tx: &Sender) { auth_tx.send(state.authorization_state).await.unwrap(); } _ => { - println!("Received update: {:?}", update); + // println!("Received update: {:?}", update); } } } +#[derive(Debug, Clone)] +struct NumberValidator; +impl NumberValidator { + fn new() -> Self { + Self + } +} +impl StringValidator for NumberValidator { + fn validate( + &self, + input: &str, + ) -> Result { + if input + .chars() + .all(|c| c.is_ascii_digit() || c == '+' || c == '-') + && input.len() >= 4 + { + Ok(inquire::validator::Validation::Valid) + } else { + Ok(inquire::validator::Validation::Invalid( + "Please enter a valid phone number.".into(), + )) + } + } +} + fn ask_user(string: &str) -> String { println!("{string}"); let mut input = String::new(); @@ -38,15 +72,15 @@ async fn handle_authorization_state( AuthorizationState::WaitTdlibParameters => { let response = functions::set_tdlib_parameters( false, - "get_me_db".into(), + "db".into(), String::new(), String::new(), false, false, false, false, - env::var("API_ID").unwrap().parse().unwrap(), - env::var("API_HASH").unwrap().into(), + dotenv!("APP_ID").parse().unwrap(), + dotenv!("APP_HASH").into(), "en".into(), "Desktop".into(), String::new(), @@ -60,9 +94,16 @@ async fn handle_authorization_state( } } AuthorizationState::WaitPhoneNumber => loop { - let input = ask_user("Enter your phone number (include the country calling code):"); + // let input = ask_user("Enter your phone number (include the country calling code):"); + let number = + Text::new("Enter your phone number (include the country calling code):") + .with_initial_value("+") + .with_validator(NumberValidator::new()) + .prompt() + .unwrap(); + let response = - functions::set_authentication_phone_number(input, None, client_id).await; + functions::set_authentication_phone_number(number, None, client_id).await; match response { Ok(_) => break, Err(e) => println!("{}", e.message), @@ -99,7 +140,9 @@ async fn handle_authorization_state( } AuthorizationState::WaitCode(_) => loop { - let input = ask_user("Enter the verification code:"); + let input = Text::new("Enter the authentication code you received:") + .prompt() + .unwrap(); let response = functions::check_authentication_code(input, client_id).await; match response { Ok(_) => break, @@ -115,7 +158,11 @@ async fn handle_authorization_state( .unwrap(); } AuthorizationState::WaitPassword(_x) => { - let password = ask_user("Please enter password: "); + let password = Password::new("Please enter your password:") + .with_display_mode(inquire::PasswordDisplayMode::Masked) + .without_confirmation() + .prompt() + .unwrap(); functions::check_authentication_password(password, client_id) .await .unwrap(); @@ -135,6 +182,37 @@ async fn handle_authorization_state( auth_rx } +#[derive(Debug, Serialize, Deserialize)] +struct ChannelInfo { + id: i64, + name: String, + description: String, + minithumbnail: Option, + member_count: i32, + linked_chat_id: i64, + invite_link: Option, + usernames: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +struct ChannelInviteLink { + invite_link: String, + name: String, + is_primary: bool, + is_revoked: bool, +} +#[derive(Debug, Serialize, Deserialize)] +struct ChannelUsernameInfo { + active: Vec, + inactive: Vec, + editable: String, +} + +#[derive(Debug, Serialize, Deserialize)] +struct TotalData { + total: usize, + channels: Vec, +} #[tokio::main] async fn main() { @@ -158,7 +236,7 @@ async fn main() { } }); - functions::set_log_verbosity_level(2, client_id) + functions::set_log_verbosity_level(0, client_id) .await .unwrap(); @@ -167,14 +245,94 @@ async fn main() { // Run the get_me() method to get user information let User::User(me) = functions::get_me(client_id).await.unwrap(); - println!("Hi, I'm {}", me.first_name); + println!("logged in as {}", me.first_name); + + let chats = functions::get_chats(None, i32::MAX, client_id) + .await + .unwrap(); + let Chats::Chats(chats) = chats; + // println!("I have {} chats", chats.chat_ids.len()); + let chat_ids = chats + .chat_ids + .iter() + .filter_map(|f| { + f.to_string() + .strip_prefix("-100") + .and_then(|s| s.parse::().ok()) + .map(|a| (a, *f)) + }) + .collect::>(); + println!( + "{} total chats {} of which are channels", + chats.chat_ids.len(), + chat_ids.len() + ); + println!("Fetching channel info..."); + let mut chat_vec = vec![]; + let progress = ProgressBar::new(chat_ids.len() as u64); + progress.set_style( + ProgressStyle::with_template( + "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})", + ) + .unwrap() + .progress_chars("#>-"), + ); + + for (chat_id, chat_id_origin) in chat_ids { + let sgfi = functions::get_supergroup_full_info(chat_id, client_id) + .await + .unwrap(); + let sg = functions::get_supergroup(chat_id, client_id).await.unwrap(); + let chat = functions::get_chat(chat_id_origin, client_id) + .await + .unwrap(); + let Supergroup::Supergroup(sg) = sg; + let Chat::Chat(chat) = chat; + let SupergroupFullInfo::SupergroupFullInfo(sgfi) = sgfi; + let photo = sgfi.photo.and_then(|p| p.minithumbnail); + let channel_info = ChannelInfo { + id: chat_id_origin, + name: chat.title, + description: sgfi.description, + member_count: sgfi.member_count, + linked_chat_id: sgfi.linked_chat_id, + invite_link: sgfi.invite_link.map(|il| ChannelInviteLink { + invite_link: il.invite_link, + name: il.name, + is_primary: il.is_primary, + is_revoked: il.is_revoked, + }), + minithumbnail: photo.map(|p| p.data), + usernames: sg.usernames.map(|u| ChannelUsernameInfo { + active: u.active_usernames, + inactive: u.disabled_usernames, + editable: u.editable_username, + }), + }; + chat_vec.push(channel_info); + progress.inc(1); + } + println!("Fetched info for {} channels", chat_vec.len()); + let data = TotalData { + total: chats.chat_ids.len(), + channels: chat_vec, + }; + progress.finish_and_clear(); + let data = serde_json::to_string_pretty(&data).unwrap(); + let mut encoder = ZlibEncoder::new(Vec::new(), flate2::Compression::best()); + std::io::copy(&mut data.as_bytes(), &mut encoder).unwrap(); + let compressed_data = encoder.finish().unwrap(); + std::fs::write("channels.json", &compressed_data).unwrap(); + println!("Written to channels.json, {} bytes", compressed_data.len()); // Tell the client to close functions::close(client_id).await.unwrap(); + println!("Client closed"); // Handle the authorization state to wait for the "Closed" state handle_authorization_state(client_id, auth_rx, run_flag.clone()).await; // Wait for the previously spawned task to end the execution handle.await.unwrap(); + println!("Exiting..."); }