teloxide/examples/admin_bot/src/main.rs

148 lines
4.3 KiB
Rust
Raw Normal View History

use std::{convert::TryInto, error::Error, str::FromStr};
2020-02-13 19:26:06 +01:00
2021-03-05 22:24:10 +01:00
use teloxide::{prelude::*, utils::command::BotCommand};
2021-03-15 04:22:10 +01:00
use teloxide::types::ChatPermissions;
2020-02-11 20:35:22 +01:00
2020-02-13 19:11:56 +01:00
// Derive BotCommand to parse text with a command into this enumeration.
//
// 1. rename = "lowercase" turns all the commands into lowercase letters.
// 2. `description = "..."` specifies a text before all the commands.
//
// That is, you can just call Command::descriptions() to get a description of
// your commands in this format:
// %GENERAL-DESCRIPTION%
// %PREFIX%%COMMAND% - %DESCRIPTION%
2020-02-11 20:35:22 +01:00
#[derive(BotCommand)]
2020-02-13 18:23:22 +01:00
#[command(
rename = "lowercase",
2020-06-24 19:43:21 +02:00
description = "Use commands in format /%command% %num% %unit%",
parse_with = "split"
2020-02-13 18:23:22 +01:00
)]
2020-02-11 20:35:22 +01:00
enum Command {
#[command(description = "kick user from chat.")]
Kick,
#[command(description = "ban user in chat.")]
2020-06-24 19:43:21 +02:00
Ban {
time: u32,
unit: UnitOfTime,
},
2020-02-11 20:35:22 +01:00
#[command(description = "mute user in chat.")]
2020-06-24 19:43:21 +02:00
Mute {
time: u32,
unit: UnitOfTime,
},
2020-02-11 20:35:22 +01:00
Help,
}
2020-06-24 19:43:21 +02:00
enum UnitOfTime {
Seconds,
Minutes,
Hours,
2020-02-11 20:35:22 +01:00
}
2020-06-24 19:43:21 +02:00
impl FromStr for UnitOfTime {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
match s {
"h" | "hours" => Ok(UnitOfTime::Hours),
"m" | "minutes" => Ok(UnitOfTime::Minutes),
"s" | "seconds" => Ok(UnitOfTime::Seconds),
_ => Err("Allowed units: h, m, s"),
}
2020-02-11 20:35:22 +01:00
}
}
2020-06-24 19:43:21 +02:00
// Calculates time of user restriction.
fn calc_restrict_time(time: u32, unit: UnitOfTime) -> u32 {
match unit {
UnitOfTime::Hours => time * 3600,
UnitOfTime::Minutes => time * 60,
UnitOfTime::Seconds => time,
}
2020-02-11 20:35:22 +01:00
}
2021-03-05 22:24:10 +01:00
type Cx = UpdateWithCx<AutoSend<Bot>, Message>;
2020-02-13 19:11:56 +01:00
// Mute a user with a replied message.
async fn mute_user(cx: &Cx, time: u32) -> Result<(), Box<dyn Error + Send + Sync>> {
2020-02-18 23:54:41 +01:00
match cx.update.reply_to_message() {
2020-06-24 19:43:21 +02:00
Some(msg1) => {
2021-03-05 22:24:10 +01:00
cx.requester
2020-06-24 19:43:21 +02:00
.restrict_chat_member(
cx.update.chat_id(),
msg1.from().expect("Must be MessageKind::Common").id,
ChatPermissions::default(),
)
2021-03-05 22:24:10 +01:00
.until_date((cx.update.date + time as i32).try_into().unwrap())
2020-06-24 19:43:21 +02:00
.await?;
}
2020-02-13 16:42:24 +01:00
None => {
cx.reply_to("Use this command in reply to another message").send().await?;
2020-02-13 18:23:22 +01:00
}
2020-02-13 16:42:24 +01:00
}
Ok(())
}
2020-02-13 19:23:42 +01:00
// Kick a user with a replied message.
async fn kick_user(cx: &Cx) -> Result<(), Box<dyn Error + Send + Sync>> {
2020-02-18 23:54:41 +01:00
match cx.update.reply_to_message() {
2020-02-13 16:42:24 +01:00
Some(mes) => {
2020-02-13 19:23:42 +01:00
// bot.unban_chat_member can also kicks a user from a group chat.
2021-03-05 22:24:10 +01:00
cx.requester
.unban_chat_member(cx.update.chat_id(), mes.from().unwrap().id)
.send()
.await?;
2020-02-13 18:23:22 +01:00
}
2020-02-13 16:42:24 +01:00
None => {
cx.reply_to("Use this command in reply to another message").send().await?;
2020-02-13 16:42:24 +01:00
}
}
Ok(())
}
2020-02-13 19:11:56 +01:00
// Ban a user with replied message.
async fn ban_user(cx: &Cx, time: u32) -> Result<(), Box<dyn Error + Send + Sync>> {
2020-02-18 23:54:41 +01:00
match cx.update.reply_to_message() {
2020-06-24 19:43:21 +02:00
Some(message) => {
2021-03-05 22:24:10 +01:00
cx.requester
2020-06-24 19:43:21 +02:00
.kick_chat_member(
cx.update.chat_id(),
message.from().expect("Must be MessageKind::Common").id,
)
2021-03-05 22:24:10 +01:00
.until_date((cx.update.date + time as i32).try_into().unwrap())
2020-06-24 19:43:21 +02:00
.await?;
}
2020-02-13 16:42:24 +01:00
None => {
cx.reply_to("Use this command in a reply to another message!").send().await?;
2020-02-13 18:23:22 +01:00
}
2020-02-13 16:42:24 +01:00
}
Ok(())
}
async fn action(cx: Cx, command: Command) -> Result<(), Box<dyn Error + Send + Sync>> {
2020-02-18 23:54:41 +01:00
match command {
Command::Help => cx.answer(Command::descriptions()).send().await.map(|_| ())?,
2020-02-18 23:54:41 +01:00
Command::Kick => kick_user(&cx).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?,
2020-02-18 23:54:41 +01:00
};
2020-02-11 20:35:22 +01:00
Ok(())
}
#[tokio::main]
async fn main() {
2020-02-18 23:54:41 +01:00
run().await;
}
async fn run() {
2020-02-13 18:23:22 +01:00
teloxide::enable_logging!();
log::info!("Starting admin_bot...");
2020-02-13 18:23:22 +01:00
2021-03-05 22:24:10 +01:00
let bot = Bot::from_env().auto_send();
2020-02-13 18:23:22 +01:00
2020-08-02 06:11:09 +02:00
let bot_name: String = panic!("Your bot's name here");
teloxide::commands_repl(bot, bot_name, action).await;
2020-02-11 20:35:22 +01:00
}