From 33f92f9ea00d9659950fed8ee4895ee8d3b1847a Mon Sep 17 00:00:00 2001 From: p0lunin Date: Wed, 24 Jun 2020 20:43:21 +0300 Subject: [PATCH] updated admin_command example --- examples/admin_bot/src/main.rs | 152 ++++++++++++++------------------- 1 file changed, 64 insertions(+), 88 deletions(-) diff --git a/examples/admin_bot/src/main.rs b/examples/admin_bot/src/main.rs index 6cc82d62..022e6af9 100644 --- a/examples/admin_bot/src/main.rs +++ b/examples/admin_bot/src/main.rs @@ -1,4 +1,4 @@ -// TODO: simplify this and use typed command variants (see https://github.com/teloxide/teloxide/issues/152). +use std::str::FromStr; use teloxide::{ prelude::*, types::ChatPermissions, utils::command::BotCommand, @@ -18,82 +18,68 @@ use futures::future; #[derive(BotCommand)] #[command( rename = "lowercase", - description = "Use commands in format /%command% %num% %unit%" + description = "Use commands in format /%command% %num% %unit%", + parse_with = "split" )] enum Command { #[command(description = "kick user from chat.")] Kick, #[command(description = "ban user in chat.")] - Ban, + Ban { + time: u32, + unit: UnitOfTime, + }, #[command(description = "mute user in chat.")] - Mute, - + Mute { + time: u32, + unit: UnitOfTime, + }, Help, } +enum UnitOfTime { + Seconds, + Minutes, + Hours, +} + +impl FromStr for UnitOfTime { + type Err = &'static str; + fn from_str(s: &str) -> Result::Err> { + match s { + "h" | "hours" => Ok(UnitOfTime::Hours), + "m" | "minutes" => Ok(UnitOfTime::Minutes), + "s" | "seconds" => Ok(UnitOfTime::Seconds), + _ => Err("Allowed units: h, m, s"), + } + } +} + // Calculates time of user restriction. -fn calc_restrict_time(num: i32, unit: &str) -> Result { +fn calc_restrict_time(time: u32, unit: UnitOfTime) -> u32 { match unit { - "h" | "hours" => Ok(num * 3600), - "m" | "minutes" => Ok(num * 60), - "s" | "seconds" => Ok(num), - _ => Err("Allowed units: h, m, s"), + UnitOfTime::Hours => time * 3600, + UnitOfTime::Minutes => time * 60, + UnitOfTime::Seconds => time, } } -// Parse arguments after a command. -fn parse_args(args: &[String]) -> Result<(i32, &str), &str> { - let num = match args.get(0) { - Some(s) => s, - None => return Err("Use command in format /%command% %num% %unit%"), - }; - let unit = match args.get(1) { - Some(s) => s, - None => return Err("Use command in format /%command% %num% %unit%"), - }; - - match num.parse::() { - Ok(n) => Ok((n, unit)), - Err(_) => Err("input positive number!"), - } -} - -// Parse arguments into a user restriction duration. -fn parse_time_restrict(args: &[String]) -> Result { - let (num, unit) = parse_args(args)?; - calc_restrict_time(num, unit) -} - type Cx = DispatcherHandlerCx; // Mute a user with a replied message. -async fn mute_user(cx: &Cx, args: &[String]) -> ResponseResult<()> { +async fn mute_user(cx: &Cx, time: u32) -> ResponseResult<()> { match cx.update.reply_to_message() { - Some(msg1) => match parse_time_restrict(args) { - // Mute user temporarily... - Ok(time) => { - cx.bot - .restrict_chat_member( - cx.update.chat_id(), - msg1.from().expect("Must be MessageKind::Common").id, - ChatPermissions::default(), - ) - .until_date(cx.update.date + time) - .send() - .await?; - } - // ...or permanently - Err(_) => { - cx.bot - .restrict_chat_member( - cx.update.chat_id(), - msg1.from().unwrap().id, - ChatPermissions::default(), - ) - .send() - .await?; - } - }, + Some(msg1) => { + cx.bot + .restrict_chat_member( + cx.update.chat_id(), + msg1.from().expect("Must be MessageKind::Common").id, + ChatPermissions::default(), + ) + .until_date(cx.update.date + time as i32) + .send() + .await?; + } None => { cx.reply_to("Use this command in reply to another message") .send() @@ -123,31 +109,18 @@ async fn kick_user(cx: &Cx) -> ResponseResult<()> { } // Ban a user with replied message. -async fn ban_user(cx: &Cx, args: &[String]) -> ResponseResult<()> { +async fn ban_user(cx: &Cx, time: u32) -> ResponseResult<()> { match cx.update.reply_to_message() { - Some(message) => match parse_time_restrict(args) { - // Mute user temporarily... - Ok(time) => { - cx.bot - .kick_chat_member( - cx.update.chat_id(), - message.from().expect("Must be MessageKind::Common").id, - ) - .until_date(cx.update.date + time) - .send() - .await?; - } - // ...or permanently - Err(_) => { - cx.bot - .kick_chat_member( - cx.update.chat_id(), - message.from().unwrap().id, - ) - .send() - .await?; - } - }, + Some(message) => { + cx.bot + .kick_chat_member( + cx.update.chat_id(), + message.from().expect("Must be MessageKind::Common").id, + ) + .until_date(cx.update.date + time as i32) + .send() + .await?; + } None => { cx.reply_to("Use this command in a reply to another message!") .send() @@ -160,15 +133,18 @@ async fn ban_user(cx: &Cx, args: &[String]) -> ResponseResult<()> { async fn action( cx: DispatcherHandlerCx, command: Command, - args: &[String], ) -> ResponseResult<()> { match command { Command::Help => { cx.answer(Command::descriptions()).send().await.map(|_| ())? } Command::Kick => kick_user(&cx).await?, - Command::Ban => ban_user(&cx, args).await?, - Command::Mute => mute_user(&cx, args).await?, + Command::Ban { time, unit } => { + ban_user(&cx, calc_restrict_time(time, unit)).await? + } + Command::Mute { time, unit } => { + mute_user(&cx, calc_restrict_time(time, unit)).await? + } }; Ok(()) @@ -181,8 +157,8 @@ async fn handle_commands(rx: DispatcherHandlerRx) { // Only iterate through commands in a proper format: .commands::(panic!("Insert here your bot's name")) // Execute all incoming commands concurrently: - .for_each_concurrent(None, |(cx, command, args)| async move { - action(cx, command, &args).await.log_on_error().await; + .for_each_concurrent(None, |(cx, command)| async move { + action(cx, command).await.log_on_error().await; }) .await; }