diff --git a/Cargo.lock b/Cargo.lock index 0881763..7da89c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,21 +29,27 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - [[package]] name = "allocator-api2" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[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 = "aquamarine" version = "0.1.12" @@ -98,9 +104,9 @@ checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" [[package]] name = "bytes" @@ -125,11 +131,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", "num-traits", + "wasm-bindgen", + "windows-targets 0.52.0", ] [[package]] @@ -202,6 +213,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dptree" version = "0.3.0" @@ -213,9 +230,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "encoding_rs" @@ -226,19 +243,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -457,20 +461,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hh" version = "0.1.0" dependencies = [ + "chrono", + "dotenv", "log", - "pretty_env_logger", "rusqlite", "teloxide", + "thiserror", "tokio", ] @@ -508,12 +520,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.28" @@ -551,6 +557,29 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "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 = "ident_case" version = "1.0.1" @@ -569,9 +598,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.0" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2a4f498956c7723dc280afc6a37d0dec50b39a29e232c6187ce4503703e8c2" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown", @@ -583,17 +612,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "itertools" version = "0.9.0" @@ -611,9 +629,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -626,9 +644,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libsqlite3-sys" @@ -636,6 +654,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" dependencies = [ + "cc", "pkg-config", "vcpkg", ] @@ -686,9 +705,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -730,9 +749,9 @@ checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91" [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -869,19 +888,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" - -[[package]] -name = "pretty_env_logger" -version = "0.5.0" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" -dependencies = [ - "env_logger", - "log", -] +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "proc-macro-error" @@ -943,40 +952,11 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ "base64", "bytes", @@ -997,9 +977,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -1044,9 +1026,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.4.2", "errno", @@ -1055,6 +1037,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + [[package]] name = "ryu" version = "1.0.16" @@ -1127,9 +1118,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.112" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -1222,6 +1213,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -1273,6 +1270,7 @@ dependencies = [ "serde_json", "serde_with_macros", "teloxide-core", + "teloxide-macros", "thiserror", "tokio", "tokio-stream", @@ -1312,41 +1310,43 @@ dependencies = [ ] [[package]] -name = "tempfile" -version = "3.9.0" +name = "teloxide-macros" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "0f1d653b093dba5e44cada57a516f572167df37b8a619443e59c8c517bb6d804" dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.52.0", + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "termcolor" -version = "1.4.1" +name = "tempfile" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ - "winapi-util", + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", @@ -1544,9 +1544,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1554,9 +1554,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", @@ -1569,9 +1569,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -1581,9 +1581,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1591,9 +1591,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", @@ -1604,15 +1604,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-streams" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" dependencies = [ "futures-util", "js-sys", @@ -1623,45 +1623,23 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" 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-util" -version = "0.1.6" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "winapi", + "windows-targets 0.52.0", ] -[[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-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index e97ef35..8f922fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,17 +2,15 @@ name = "hh" version = "0.1.0" edition = "2021" -authors = ["github.com/DmitroPodolsky", "github.com/geekenji"] -description = "Centralized platform to manage and access your university homework information." -license = "MIT" -repository = "github.com/seadclub/hh.git" readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] log = "0.4.20" -pretty_env_logger = "0.5.0" -rusqlite = "0.30.0" -teloxide = "0.12.2" +rusqlite = { version = "0.30.0", features = ["bundled"] } +teloxide = { version = "0.12.2", features = ["macros"] } tokio = { version = "1.36.0", features = ["full"] } +dotenv = "0.15.0" +thiserror = "1.0.56" +chrono = "0.4.34" diff --git a/src/commands.rs b/src/commands.rs new file mode 100644 index 0000000..f3b28db --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,43 @@ +use crate::models::{State, Command}; +use crate::telegram::basic_methods::*; +use teloxide::dispatching::dialogue::InMemStorage; +use teloxide::dispatching::{dialogue, DpHandlerDescription}; +use teloxide::dptree; +use teloxide::dptree::{case, Handler}; +use teloxide::prelude::*; + + +pub fn schema() -> Handler<'static, DependencyMap, crate::errors::Result<()>, DpHandlerDescription> +{ + let command_handler = teloxide::filter_command::() + .branch( + case![State::Start] + .branch(case![Command::Help].endpoint(help)) + .branch(case![Command::Add].endpoint(add)), + ) + .branch(case![Command::Cancel].endpoint(cancel)); + + let callback_query_handler = Update::filter_callback_query().branch( + case![State::ReceiveProductChoice].endpoint(receive_add_button), + ); + + // let callback_query_handler = Update::filter_message() + // .branch(case![State::GetEmail { phone_number }].endpoint(get_email)) + // .branch(case![State::GetAge { phone_number }].endpoint(get_age)) + // .branch(case![State::GetWeightAndHeight { phone_number }].endpoint(get_height_and_weight)); + + let message_handler = Update::filter_message() + .branch(command_handler) + // .branch(case![State::GetPhoneNumber].endpoint(get_number)) + // .branch(case![State::HomeTrainingMenu { phone_number }].endpoint(home_training_menu)) + // .branch(case![State::GymTrainingMenu { phone_number }].endpoint(gym_training_menu)) + .branch(case![State::CreateCategorie].endpoint(send_categorie)) + .branch(case![State::AddTaskName { categorie }].endpoint(send_taskname)) + .branch(case![State::AddDescription { categorie, taskname }].endpoint(send_description)) + .branch(case![State::CreateTask { categorie, taskname, description }].endpoint(send_deadline)) + .branch(dptree::endpoint(invalid_state)); + + + dialogue::enter::, State, _>().branch(message_handler).branch(callback_query_handler) + //State::Start - initial state +} \ No newline at end of file diff --git a/src/db.rs b/src/db.rs index 0474038..920e54b 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,4 +1,6 @@ -use rusqlite::Connection; +use rusqlite::{Connection, Error}; + +use crate::models::MyDialogue; pub fn create_db() { let conn = Connection::open("your_database.db").expect("Failed to open database"); @@ -33,4 +35,71 @@ pub fn create_db() { ).expect("Failed to create homework_hub table"); log::info!("created database successfully!"); -} \ No newline at end of file +} + +pub fn select_all_categories() -> Result, Error> { + let conn = Connection::open("your_database.db")?; + + let mut stmt = conn.prepare("SELECT name FROM category")?; + + let category_iter = stmt.query_map([], |row| { + Ok(row.get(0)?) + })?; + + let mut categories = Vec::new(); + + for name in category_iter { + categories.push(name?); + } + + Ok(categories) +} + +pub fn insert_user(msg: MyDialogue) -> Result<(), Error> { + let conn = Connection::open("your_database.db")?; + + let mut stmt = conn.prepare("SELECT COUNT(*) FROM users WHERE id = ?")?; + let user_exists: i64 = stmt.query_row([msg.chat_id().to_string()], |row| row.get(0))?; + + if user_exists == 0 { + conn.execute("INSERT INTO users(id) VALUES (?)", [&msg.chat_id().to_string()])?; + } else { + + } + + Ok(()) +} + +pub fn insert_category(name: &str) -> Result<(), Error> { + let conn = Connection::open("your_database.db")?; + + conn.execute( + "INSERT INTO category (name) VALUES (?)", + &[name], + )?; + + Ok(()) +} + +pub fn select_categorie(name: &str) -> Result { + let conn = Connection::open("your_database.db")?; + + let category_id: i32 = conn.query_row( + "SELECT id FROM category WHERE name = ?", + &[name], + |row| row.get(0) + )?; + + Ok(category_id) +} + +pub fn insert_homework(name: &str, desc: &str, deadline: &str, category_id: &i32, msg: MyDialogue) -> Result<(), Error> { + let conn = Connection::open("your_database.db")?; + + conn.execute( + "INSERT INTO homework_hub (name, desc, deadline, category_id, user_id) VALUES (?, ?, ?, ?, ?)", + &[name, desc, deadline, &category_id.to_string(), &msg.chat_id().to_string()], + )?; + + Ok(()) +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..8fb7ae4 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,18 @@ +#[allow(clippy::enum_variant_names)] +#[derive(Debug, thiserror::Error)] +pub enum Errors { + #[error(transparent)] + EnvError(#[from] dotenv::Error), + + #[error(transparent)] + TeloxideError(#[from] teloxide::RequestError), + + #[error(transparent)] + InMemStorageError(#[from] teloxide::dispatching::dialogue::InMemStorageError), + + + #[error(transparent)] + ParseIntError(#[from] std::num::ParseIntError), +} + +pub type Result = std::result::Result; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c42a9c0..c62e65a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,32 +1,35 @@ -pub mod bot; +pub mod telegram; pub mod db; - +use crate::errors::Result; +use crate::commands::schema; +use crate::models::State; +use dotenv::dotenv; +use std::sync::Arc; use db::create_db; -use bot::*; -use teloxide::{dispatching::dialogue::InMemStorage, prelude::*}; +use teloxide::dispatching::dialogue::InMemStorage; +use teloxide::prelude::*; + +mod models; +mod commands; +mod errors; #[tokio::main] -async fn main() { +async fn main() -> Result<()> { + dotenv().ok(); log::info!("Starting dialogue bot..."); create_db(); - pretty_env_logger::init(); - let bot = Bot::from_env(); + let bot = Bot::new(dotenv::var("TELOXIDE_TOKEN")?); + let state = Arc::new(State::Start); - Dispatcher::builder( - bot, - Update::filter_message() - .enter_dialogue::, State>() - .branch(dptree::case![State::Start].endpoint(start)) - .branch(dptree::case![State::ReceiveFullName].endpoint(receive_full_name)) - .branch(dptree::case![State::ReceiveAge { full_name }].endpoint(receive_age)) - .branch( - dptree::case![State::ReceiveLocation { full_name, age }].endpoint(receive_location), - ), - ) - .dependencies(dptree::deps![InMemStorage::::new()]) + Dispatcher::builder(bot, schema()) + .dependencies(dptree::deps![ + InMemStorage::::new(), + Arc::clone(&state) + ]) .enable_ctrlc_handler() .build() .dispatch() .await; + Ok(()) } diff --git a/src/models.rs b/src/models.rs index e69de29..5f90a16 100644 --- a/src/models.rs +++ b/src/models.rs @@ -0,0 +1,32 @@ + +use teloxide::dispatching::dialogue::InMemStorage; +use teloxide::prelude::Dialogue; +use teloxide::utils::command::BotCommands; + +pub type MyDialogue = Dialogue>; + +/// These commands are supported: +#[derive(BotCommands, Clone)] +#[command( + rename_rule = "lowercase", + description = "These commands are supported:" +)] +pub enum Command { + #[command(description = "display this text.")] + Help, + #[command(description = "cancel the purchase procedure.")] + Cancel, + #[command(description = "create new hometask")] + Add, +} + +#[derive(Clone, Default)] +pub enum State { + #[default] + Start, + ReceiveProductChoice, + CreateCategorie, + AddTaskName { categorie: String }, + AddDescription { categorie: String, taskname: String }, + CreateTask { categorie: String, taskname: String, description: String }, +} diff --git a/src/telegram/basic_methods.rs b/src/telegram/basic_methods.rs new file mode 100644 index 0000000..2a87e7b --- /dev/null +++ b/src/telegram/basic_methods.rs @@ -0,0 +1,214 @@ + +use crate::models::Command; +use crate::models::{MyDialogue, State}; +use crate::db::{select_all_categories, insert_category, select_categorie, insert_homework, insert_user}; +use teloxide::prelude::*; +use teloxide::requests::Requester; +use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup}; +use teloxide::utils::command::BotCommands; +use chrono::NaiveDate; +// use crate::utils::check_deadline; // Commented out as it's causing an error +use teloxide::Bot; + +pub async fn help(bot: Bot, msg: Message) -> crate::errors::Result<()> { + bot.send_message(msg.chat.id, Command::descriptions().to_string()) + .await?; + Ok(()) +} + +pub async fn cancel(bot: Bot, dialogue: MyDialogue, msg: Message) -> crate::errors::Result<()> { + bot.send_message(msg.chat.id, "Cancelling the dialogue.") + .await?; + dialogue.exit().await?; + Ok(()) +} + +pub async fn invalid_state(bot: Bot, msg: Message) -> crate::errors::Result<()> { + bot.send_message( + msg.chat.id, + "Я тебе не розумію, подивись будь-ласка на команду /help", + ) + .await?; + Ok(()) +} + +pub async fn add(bot: Bot, dialogue: MyDialogue, msg: Message) -> crate::errors::Result<()> { + let categories = select_all_categories().unwrap(); + let create_row = InlineKeyboardButton::callback("create categorie", "create"); + let mut products = categories + .iter() + .map(|product| vec![InlineKeyboardButton::callback(product.to_string(), product.to_string())]) + .collect::>(); + + + if categories.len() <= 4 { + products.push(vec![create_row]); + bot.send_message(msg.chat.id, "Select a product:") + .reply_markup(InlineKeyboardMarkup::new(products)) + .await?; + + dialogue.update(State::ReceiveProductChoice).await?; + return Ok(()); + } else { + let mut products = categories[..4] + .iter() + .map(|product| vec![InlineKeyboardButton::callback(product.to_string(), product.to_string())]) + .collect::>(); + + let additional_row = ["next"] + .iter() + .map(|&product| InlineKeyboardButton::callback(product.to_string(), "next_2")) + .collect(); + + products.push(additional_row); + products.push(vec![create_row]); + + bot.send_message(msg.chat.id, "Select a product:") + .reply_markup(InlineKeyboardMarkup::new(products)) + .await?; + + dialogue.update(State::ReceiveProductChoice).await?; + } + + // let additional_row = ["next", "previous"] + // .iter() + // .map(|&product| InlineKeyboardButton::callback(product.to_string(), product.to_string())) + // .collect(); + Ok(()) +} + +pub async fn receive_add_button( + bot: Bot, + dialogue: MyDialogue, + q: CallbackQuery, +) -> crate::errors::Result<()> { + insert_user(dialogue.clone()).unwrap(); + if let Some(product) = &q.data { + if product == "create" { + bot.send_message( + dialogue.chat_id(), + "Enter the name of the new product:", + ) + .await?; + dialogue.update(State::CreateCategorie).await?; + } else if product.starts_with("next") || product.starts_with("previous") { + let page = product.chars().last().unwrap().to_digit(10).unwrap() as usize; + let create_row = InlineKeyboardButton::callback("create categorie", "create"); + let mut products = pages(page); + products.push(vec![create_row]); + bot.send_message( + dialogue.chat_id(), + "Select a product:", + ) + .reply_markup(InlineKeyboardMarkup::new(products)) + .await?; + } else { + bot.send_message( + dialogue.chat_id(), + "send task name:", + ) + .await?; + dialogue.update(State::AddTaskName { categorie: product.to_string() }).await?; + } + } + + Ok(()) +} + + +pub async fn send_categorie(bot: Bot, dialogue: MyDialogue, msg: Message) -> crate::errors::Result<()> { + insert_category(&msg.text().unwrap()).unwrap(); + bot.send_message( + dialogue.chat_id(), + "send task name:", + ) + .await?; + dialogue.update(State::AddTaskName { categorie: msg.text().unwrap().to_string() }).await?; + + Ok(()) +} + +pub async fn send_taskname(bot: Bot, dialogue: MyDialogue, msg: Message, categorie: String) -> crate::errors::Result<()> { + bot.send_message( + dialogue.chat_id(), + "send description:", + ) + .await?; + dialogue.update(State::AddDescription { categorie: categorie, taskname: msg.text().unwrap().to_string() }).await?; + Ok(()) +} + +pub async fn send_description(bot: Bot, dialogue: MyDialogue, msg: Message, (categorie, taskname) : (String, String)) -> crate::errors::Result<()> { + bot.send_message( + dialogue.chat_id(), + "send deadline(example: 2023-04-12):", + ) + .await?; + dialogue.update(State::CreateTask { categorie: categorie, taskname: taskname, description: msg.text().unwrap().to_string() }).await?; + Ok(()) +} + +pub async fn send_deadline(bot: Bot, dialogue: MyDialogue, msg: Message, (categorie, taskname, description) : (String, String, String)) -> crate::errors::Result<()> { + if check_deadline(&msg.text().unwrap()) { + insert_homework(&taskname, &description, &msg.text().unwrap(), &select_categorie(&categorie).unwrap(), dialogue.clone()).unwrap(); + bot.send_message( + dialogue.chat_id(), + "Task has been created successfully!", + ) + .await?; + dialogue.exit().await?; + } else { + bot.send_message( + dialogue.chat_id(), + "Invalid deadline format. Please enter the deadline in the format: YYYY-MM-DD", + ) + .await?; + } + Ok(()) +} + +pub fn check_deadline(deadline: &str) -> bool { + let date = NaiveDate::parse_from_str(deadline, "%Y-%m-%d"); + match date { + Ok(_) => true, + Err(_) => false, + } +} + +pub fn pages(page: usize) -> Vec> { + let categories = select_all_categories().unwrap(); + let additional_row: Vec = ["next", "previous"] + .iter() + .map(|&product| { + let callback_data = match product { + "next" => format!("next_{}", page + 1), + "previous" => format!("previous_{}", page - 1), + _ => panic!("Unknown product type"), + }; + InlineKeyboardButton::callback(product.to_string(), callback_data) + }) + .collect(); + + if categories.len() <= page * 4 { + let mut products = categories[((page - 1) * 4)..] + .iter() + .map(|product| vec![InlineKeyboardButton::callback(product.to_string(), product.to_string())]) + .collect::>(); + products.push(vec![additional_row[1].clone()]); + return products; + } else if page == 1 { + let mut products = categories[..4] + .iter() + .map(|product| vec![InlineKeyboardButton::callback(product.to_string(), product.to_string())]) + .collect::>(); + products.push(vec![additional_row[0].clone()]); + return products; + } else { + let mut products = categories[((page - 1) * 4)..(page * 4)] + .iter() + .map(|product| vec![InlineKeyboardButton::callback(product.to_string(), product.to_string())]) + .collect::>(); + products.push(additional_row); + return products; + } +} diff --git a/src/telegram/mod.rs b/src/telegram/mod.rs index e69de29..e679bea 100644 --- a/src/telegram/mod.rs +++ b/src/telegram/mod.rs @@ -0,0 +1 @@ +pub mod basic_methods; \ No newline at end of file