dispatching_features/
dispatching_features.rs1use rand::Rng;
5
6use teloxide::{
7 dispatching::HandlerExt, prelude::*, sugar::request::RequestReplyExt, types::Dice,
8 utils::command::BotCommands,
9};
10
11#[tokio::main]
12async fn main() {
13 pretty_env_logger::init();
14 log::info!("Starting dispatching features bot...");
15
16 let bot = Bot::from_env();
17
18 let parameters = ConfigParameters {
19 bot_maintainer: UserId(0), maintainer_username: None,
21 };
22
23 let handler = Update::filter_message()
24 .branch(
27 dptree::entry()
28 .filter_command::<SimpleCommand>()
30 .endpoint(simple_commands_handler),
32 )
33 .branch(
34 dptree::filter(|cfg: ConfigParameters, msg: Message| {
36 msg.from.map(|user| user.id == cfg.bot_maintainer).unwrap_or_default()
37 })
38 .filter_command::<MaintainerCommands>()
39 .endpoint(|msg: Message, bot: Bot, cmd: MaintainerCommands| async move {
40 match cmd {
41 MaintainerCommands::Rand { from, to } => {
42 let mut rng = rand::rngs::OsRng;
43 let value: u64 = rng.gen_range(from..=to);
44
45 bot.send_message(msg.chat.id, value.to_string()).await?;
46 Ok(())
47 }
48 }
49 }),
50 )
51 .branch(
52 dptree::filter(|msg: Message| msg.chat.is_group() || msg.chat.is_supergroup())
54 .branch(
55 dptree::entry().filter_mention_command::<GroupCommand>().endpoint(
60 |bot: Bot, msg: Message, cmd: GroupCommand| async move {
61 match cmd {
62 GroupCommand::Repeat { text } => {
63 bot.send_message(msg.chat.id, format!("You said: {text}"))
64 .await?;
65 Ok(())
66 }
67 }
68 },
69 ),
70 )
71 .branch(
72 dptree::endpoint(|msg: Message, bot: Bot| async move {
74 log::info!("Received a message from a group chat.");
75 bot.send_message(msg.chat.id, "This is a group chat.").await?;
76 respond(())
77 }),
78 ),
79 )
80 .branch(
81 Message::filter_dice().endpoint(|bot: Bot, msg: Message, dice: Dice| async move {
84 bot.send_message(msg.chat.id, format!("Dice value: {}", dice.value))
85 .reply_to(msg)
86 .await?;
87 Ok(())
88 }),
89 );
90
91 Dispatcher::builder(bot, handler)
92 .dependencies(dptree::deps![parameters])
96 .default_handler(|upd| async move {
98 log::warn!("Unhandled update: {upd:?}");
99 })
100 .error_handler(LoggingErrorHandler::with_custom_text(
102 "An error has occurred in the dispatcher",
103 ))
104 .enable_ctrlc_handler()
105 .build()
106 .dispatch()
107 .await;
108}
109
110#[derive(Clone)]
111struct ConfigParameters {
112 bot_maintainer: UserId,
113 maintainer_username: Option<String>,
114}
115
116#[derive(BotCommands, Clone)]
118#[command(rename_rule = "lowercase")]
119enum SimpleCommand {
120 Help,
122 Maintainer,
124 MyId,
126}
127
128#[derive(BotCommands, Clone)]
130#[command(rename_rule = "lowercase")]
131enum MaintainerCommands {
132 #[command(parse_with = "split")]
134 Rand { from: u64, to: u64 },
135}
136
137#[derive(BotCommands, Clone)]
139#[command(rename_rule = "lowercase")]
140enum GroupCommand {
141 Repeat { text: String },
143}
144
145async fn simple_commands_handler(
146 cfg: ConfigParameters,
147 bot: Bot,
148 me: teloxide::types::Me,
149 msg: Message,
150 cmd: SimpleCommand,
151) -> Result<(), teloxide::RequestError> {
152 let text = match cmd {
153 SimpleCommand::Help => {
154 if msg.from.unwrap().id == cfg.bot_maintainer {
155 format!(
156 "{}\n\n{}",
157 SimpleCommand::descriptions(),
158 MaintainerCommands::descriptions()
159 )
160 } else if msg.chat.is_group() || msg.chat.is_supergroup() {
161 SimpleCommand::descriptions().username_from_me(&me).to_string()
162 } else {
163 SimpleCommand::descriptions().to_string()
164 }
165 }
166 SimpleCommand::Maintainer => {
167 if msg.from.as_ref().unwrap().id == cfg.bot_maintainer {
168 "Maintainer is you!".into()
169 } else if let Some(username) = cfg.maintainer_username {
170 format!("Maintainer is @{username}")
171 } else {
172 format!("Maintainer ID is {}", cfg.bot_maintainer)
173 }
174 }
175 SimpleCommand::MyId => {
176 format!("{}", msg.from.unwrap().id)
177 }
178 };
179
180 bot.send_message(msg.chat.id, text).await?;
181
182 Ok(())
183}