From 6d7024f7ddba0c235c635099a53d8ba0c5e4658c Mon Sep 17 00:00:00 2001 From: doryan04 Date: Mon, 4 Mar 2024 23:09:59 +0400 Subject: [PATCH] improved architecture --- .env | 2 + Cargo.lock | 178 +++++++++++++++++++++++++ Cargo.toml | 9 +- src/handlers/decorators.rs | 20 +++ src/handlers/main_handler.rs | 102 +++++--------- src/handlers/main_handler_endpoints.rs | 84 ++++++++++++ src/main.rs | 27 ++-- src/utils/is_admin.rs | 3 - 8 files changed, 336 insertions(+), 89 deletions(-) create mode 100644 .env create mode 100644 src/handlers/decorators.rs create mode 100644 src/handlers/main_handler_endpoints.rs diff --git a/.env b/.env new file mode 100644 index 0000000..dead0eb --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +BOT_TOKEN=6941223962:AAG4SVKKlUOPlgJTINLfxtD09duB_YSkHOw +URL_WEBHOOK=https://api.telegram.org/bot6941223962:AAG4SVKKlUOPlgJTINLfxtD09duB_YSkHOw/sendMessage?chat_id=-1001753166710&message_thread_id= \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2f58f53..20d4801 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,12 +54,72 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -209,12 +269,20 @@ name = "doryan-facker" version = "0.1.0" dependencies = [ "chrono", + "dotenv", "log", "pretty_env_logger", "teloxide", "tokio", + "url", ] +[[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" @@ -479,6 +547,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -648,6 +722,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.7.1" @@ -836,6 +916,12 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "pretty_env_logger" version = "0.5.0" @@ -888,6 +974,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "rc-box" version = "1.2.0" @@ -1006,6 +1122,12 @@ dependencies = [ "base64", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.16" @@ -1087,6 +1209,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1213,6 +1345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c63345cf32a8850ebddcdd769dc2d5193d5e231262d5dada264b79da01a664da" dependencies = [ "aquamarine", + "axum", "bytes", "derive_more", "dptree", @@ -1220,6 +1353,7 @@ dependencies = [ "log", "mime", "pin-project", + "rand", "serde", "serde_json", "serde_with_macros", @@ -1229,6 +1363,8 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", + "tower", + "tower-http", "url", ] @@ -1395,6 +1531,47 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags 1.3.2", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -1407,6 +1584,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] diff --git a/Cargo.toml b/Cargo.toml index 47260c5..24d8baf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -teloxide = { version = "0.12", features = ["macros"] } +teloxide = { version = "0.12.2", features = ["macros", "webhooks", "webhooks-axum"] } log = "0.4" pretty_env_logger = "0.5.0" tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] } -chrono = "0.4.34" \ No newline at end of file +chrono = "0.4.34" +url = "2.5.0" +dotenv = "0.15.0" + +[env] +BOT_TOKEN = "6941223962:AAG4SVKKlUOPlgJTINLfxtD09duB_YSkHOw" diff --git a/src/handlers/decorators.rs b/src/handlers/decorators.rs new file mode 100644 index 0000000..e735ff8 --- /dev/null +++ b/src/handlers/decorators.rs @@ -0,0 +1,20 @@ +#[path="../utils/is_admin.rs"] +mod is_admin; + +pub mod decorators { + use super::*; + + use std::future::Future; + use is_admin::is_admin::is_admin_check; + use teloxide::{Bot, types::Message, requests::Requester}; + + pub async fn admin_access(bot: Bot, msg: Message, callback: impl Future){ + if is_admin_check(&msg, &bot).await { + callback.await; + } else { + bot.send_message(msg.chat.id, "Команда доступна только администраторам") + .await + .unwrap(); + } + } +} \ No newline at end of file diff --git a/src/handlers/main_handler.rs b/src/handlers/main_handler.rs index 9f69550..f843c58 100644 --- a/src/handlers/main_handler.rs +++ b/src/handlers/main_handler.rs @@ -1,73 +1,39 @@ -pub mod main_handler { - use std::future::Future; - use teloxide::Bot; - use teloxide::types::Message; - use crate::ban::ban::ban_user; - use crate::mute::mute::mute_user; - use crate::unmute::unmute::unmute; - use teloxide::requests::Requester; - use teloxide::prelude::ResponseResult; - use teloxide::utils::command::BotCommands; - use crate::commands::enum_commands::Commands; - use crate::is_admin::is_admin::is_admin_check; +use teloxide::{Bot, types::Message}; +use std::{future::Future, error::Error}; - async fn admin_command(bot: Bot, msg: Message, callback: impl Future){ - if is_admin_check(&msg, &bot).await { - callback.await; - } - } +#[path="../enums/commands.rs"] +mod commands; +#[path= "main_handler_endpoints.rs"] +mod main_handler_endpoints; - pub async fn handler(bot: Bot, msg: Message, commands: Commands) -> ResponseResult<()> { - let chat_id = msg.chat.id; +use main_handler_endpoints::main_handler_endpoints::*; - match commands { - Commands::Facker => { - bot.send_message(msg.chat.id, Commands::descriptions().to_string()).await?; - }, - Commands::Tribunal(reason) => { - let reason_result = if reason.is_empty() { None } else { Some(reason) }; - admin_command(bot.clone(), msg.clone(), ban_user( - msg.reply_to_message(), - reason_result, - &bot, - chat_id, - )).await; - }, - Commands::DemocracyMute(multiplier, time) => { - if let 1i32..=10i32 = multiplier{ - admin_command(bot.clone(), msg.clone(), mute_user( - msg.clone().reply_to_message(), - multiplier, - time.to_string(), - &bot, - chat_id, - )).await; - } else if let 10i32..=i32::MAX = multiplier{ - bot.send_message( - msg.chat.id, - "Вы ввели слишком большой множитель, пожалуйста, \ - выберите множитель из промежутка [1; 10]" - ).await - .expect("Вы ввели слишком большой множитель, пожалуйста, \ - выберите множитель из промежутка [1; 10]"); - } else { - bot.send_message( - msg.chat.id, - "Вы ввели нулевой или отрицательный множитель, пожалуйста, \ - выберите множитель из промежутка [1; 10]" - ).await - .expect("Вы ввели нулевой или отрицательный множитель, пожалуйста, \ - выберите множитель из промежутка [1; 10]"); - } - } - Commands::DemocracyUnmute => { - admin_command(bot.clone(), msg.clone(), unmute( - msg.clone().reply_to_message(), - &bot, - chat_id, - )).await; - } - }; - Ok(()) +pub mod main_handler{ + + use std::error::Error; + use super::{*, commands::enum_commands::Commands}; + use teloxide::{dptree::case, filter_command, types::Update, dispatching::{Dispatcher, UpdateFilterExt}}; + + pub async fn main_handler_spawn(bot: Bot) -> () { + let command_handler = filter_command::>>() + .branch(case![Commands::Facker].endpoint(facker)) + .branch( + case![Commands::DemocracyMute(multiplier, time_type)] + .endpoint(|bot : Bot, msg : Message, args : (i32, String)| async move { + democracy_mute(bot, msg, args.0, args.1).await + })) + .branch(case![Commands::DemocracyUnmute].endpoint(democracy_unmute)) + .branch(case![Commands::Tribunal(reason)] + .endpoint(|bot : Bot, msg : Message, args| async move { + tribunal(bot, msg, args).await + })); + + let message_handler = Update::filter_message() + .branch(command_handler); + + Dispatcher::builder(bot, message_handler) + .build() + .dispatch() + .await; } } \ No newline at end of file diff --git a/src/handlers/main_handler_endpoints.rs b/src/handlers/main_handler_endpoints.rs new file mode 100644 index 0000000..102fe3f --- /dev/null +++ b/src/handlers/main_handler_endpoints.rs @@ -0,0 +1,84 @@ +use teloxide::{Bot, types::Message}; +use std::{future::Future, error::Error}; + +#[path="../bot_functions/ban.rs"] +mod ban; +#[path="../bot_functions/mute.rs"] +mod mute; +#[path="../bot_functions/unmute.rs"] +mod unmute; +#[path="../enums/commands.rs"] +mod commands; +#[path= "decorators.rs"] +mod decorators; + +pub mod main_handler_endpoints { + use super::*; + + use super::ban::ban::ban_user; + use super::mute::mute::mute_user; + use super::unmute::unmute::unmute; + use super::commands::enum_commands::Commands; + use super::decorators::decorators::admin_access; + use teloxide::{requests::Requester, utils::command::BotCommands}; + + pub(crate) type CommandHandleResult = Result<(), Box>; + + pub(crate) async fn facker(bot : Bot, msg : Message) -> CommandHandleResult { + bot.send_message(msg.chat.id, Commands::descriptions().to_string()).await?; + Ok(()) + } + + pub(crate) async fn democracy_unmute(bot : Bot, msg : Message) -> CommandHandleResult { + admin_access(bot.clone(), msg.clone(), unmute( + msg.clone().reply_to_message(), + &bot, + msg.chat.id, + )).await; + Ok(()) + } + + pub(crate) async fn democracy_mute( + bot : Bot, + msg : Message, + multiplier : i32, + time : String + ) -> CommandHandleResult { + if let 1i32..=10i32 = multiplier{ + admin_access(bot.clone(), msg.clone(), mute_user( + msg.clone().reply_to_message(), + multiplier, + time.to_string(), + &bot, + msg.chat.id, + )).await; + } else if let 10i32..=i32::MAX = multiplier{ + let except_text = "Вы ввели слишком большой множитель, пожалуйста, \ + выберите множитель из промежутка [1; 10]"; + + bot.send_message(msg.chat.id, except_text) + .await + .expect(except_text); + } else { + let except_text = "Вы ввели нулевой или отрицательный множитель, пожалуйста, \ + выберите множитель из промежутка [1; 10]"; + + bot.send_message(msg.chat.id, except_text) + .await + .expect(except_text); + } + Ok(()) + } + + pub(crate) async fn tribunal(bot : Bot, msg : Message, reason : String) -> CommandHandleResult { + let reason_result = if reason.is_empty() { None } else { Some(reason) }; + admin_access(bot.clone(), msg.clone(), ban_user( + msg.reply_to_message(), + reason_result, + &bot, + msg.chat.id, + )).await; + Ok(()) + } + +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1744260..5ae25af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,21 @@ -use teloxide::prelude::*; -use crate::commands::enum_commands::Commands; -use crate::main_handler::main_handler::handler; +use std::env; +use dotenv::dotenv; +use std::error::Error; +use teloxide::{prelude::*}; +use teloxide::error_handlers::ErrorHandler; -#[path="bot_functions/ban.rs"] -mod ban; -#[path="bot_functions/mute.rs"] -mod mute; -#[path="bot_functions/unmute.rs"] -mod unmute; -#[path="utils/is_admin.rs"] -mod is_admin; -#[path="enums/commands.rs"] -mod commands; #[path="handlers/main_handler.rs"] mod main_handler; #[tokio::main] async fn main() { + pretty_env_logger::init(); - log::info!("Starting throw dice bot..."); + dotenv().ok(); - let bot = Bot::new("6941223962:AAG4SVKKlUOPlgJTINLfxtD09duB_YSkHOw".to_string()); + let token = env::var("BOT_TOKEN").unwrap(); + let bot = Bot::new(token); + + main_handler::main_handler::main_handler_spawn(bot).await; - Commands::repl(bot, handler).await; } diff --git a/src/utils/is_admin.rs b/src/utils/is_admin.rs index f8c4c50..69b5532 100644 --- a/src/utils/is_admin.rs +++ b/src/utils/is_admin.rs @@ -20,9 +20,6 @@ pub mod is_admin{ if chat_member.is_administrator() || chat_member.is_owner() { return true; } else { - bot.send_message(message.chat.id, "Команда доступна только администраторам") - .await - .unwrap(); return false; } }