Compare commits

..

3 Commits

15 changed files with 57 additions and 83 deletions

View File

@ -1,12 +1,10 @@
<b>Команды (для админов)</b> <b>Команды (для админов)</b>
<code>/mute {ID | REPLY} &lt;DURATION&gt; [TIME METRIC]</code> - выдаёт мут на заданное время; <em>/mute {ID | REPLY} &lt;DURATION&gt; [TIME METRIC]</em> - выдаёт мут на заданное время;
<code>/unmute {ID | REPLY}</code> - снимает мут; <em>/unmute {ID | REPLY}</em> - снимает мут;
Для более подробного описания, введите команды без аргументов.
<b>Эмодзи (для админов)</b> <b>Эмодзи (для админов)</b>
🎲 - выдаёт мут пользователю на случайно заданное время (от 1 до 6 дней); 🎲 - выдаёт мут участнику чата на случайно заданное время (от 1 до 6 дней);
🎰 - выдаёт мут пользователю на случайно заданное время (от 1 до 63 дней), в случае джекпота участник отправляется в бан. 🎰 - выдаёт мут участнику чата на случайно заданное время (от 1 до 63 дней), в случае джекпота участник отправляется в бан.

View File

@ -1,7 +1,5 @@
use std::include_str;
pub mod files { pub mod files {
use super::*; use std::include_str;
pub const HELP_COMMAND_TEXT: &str = include_str!("help_command.html"); pub const HELP_COMMAND_TEXT: &str = include_str!("help_command.html");
pub const MUTE_COMMAND_HELP: &str = include_str!("mute_command_help.html"); pub const MUTE_COMMAND_HELP: &str = include_str!("mute_command_help.html");

View File

@ -2,11 +2,8 @@
<b>Выдаёт мут.</b> <b>Выдаёт мут.</b>
Использовать при ответе на сообщение или указать ID пользователя. <b><em>1. ID | REPLY.</em></b> ID участника чата, или ответ на его сообщение;
<b><em>1. ID | REPLY.</em></b> ID или ответ на сообщение пользователя;
<b><em>2. DURATION.</em></b> Продолжительность мута (DURATION &gt; 0); <b><em>2. DURATION.</em></b> Продолжительность мута (DURATION &gt; 0);
<b><em>3. TIME METRIC.</em></b> Временная метрика. Измеряется в минутах/часах/днях/неделях/месяцах. По умолчанию применяется в днях. <b><em>3. TIME METRIC.</em></b> Временная метрика. Измеряется в минутах/часах/днях/неделях/месяцах. По-умолчанию, применяется в днях.
<b><u>Команда доступна только администраторам.</u></b>
Команда доступна только администраторам.

View File

@ -1,8 +1,7 @@
<code>/unmute {ID | REPLY}</code> <code>/unmute {ID | REPLY}</code>
<b>Cнимает мут с пользователя.</b> <b>Cнимает мут.</b>
<b><em>1. ID | REPLY.</em></b> ID или ответ на сообщение пользователя. <b><em>1. ID | REPLY</em></b> ID участника чата, или ответ на его сообщение.
<b><u>Команда доступна только администраторам.</u></b>
Команда доступна только администраторам.

View File

@ -25,7 +25,7 @@ pub async fn ban_member(
Some(id) => id, Some(id) => id,
None => { None => {
sender_builder sender_builder
.text("Нет ID или ответа на сообщение пользователя.") .text("Ответьте на сообщение участника чата, которого вы хотите забанить")
.reply_to(message.id()) .reply_to(message.id())
.build() .build()
.send(&bot) .send(&bot)
@ -39,19 +39,21 @@ pub async fn ban_member(
let callback = || async { ban_chat_member(&bot, user_id, chat_id).await }; let callback = || async { ban_chat_member(&bot, user_id, chat_id).await };
let demote_args: (&Bot, i64, i64) = (&bot, user_id, chat_id); let demote_args: (&Bot, i64, i64) = (&bot, user_id, chat_id);
sender_builder.set_text("Невозможно забанить пользователя."); sender_builder
.set_text("Невозможно забанить участника чата, демотните своими силами и попробуйте снова");
if try_restrict(callback, demote_args, sender_builder.clone().build()) if try_restrict(callback, demote_args, sender_builder.clone().build())
.await .await
.is_err() .is_err()
{ {
sender_builder.build().send(&bot).await?;
Ok(EventReturn::Cancel) Ok(EventReturn::Cancel)
} else { } else {
let banned_user_name: String = user.get_user_name(&bot, &message).await.unwrap(); let banned_user_name: String = user.get_user_name(&bot, &message).await.unwrap();
sender_builder sender_builder
.reply_to(message.id()) .reply_to(message.id())
.text(format!("Пользователь {banned_user_name} забанен.")) .text(format!("Пользователь {} забанен.", banned_user_name))
.build() .build()
.send(&bot) .send(&bot)
.await?; .await?;

View File

@ -25,7 +25,19 @@ pub async fn mute_member(
) -> HandlerResult { ) -> HandlerResult {
let (bot, message, mut sender_builder): ExtractedEntityData = handler_entity.extract(); let (bot, message, mut sender_builder): ExtractedEntityData = handler_entity.extract();
let user_id: i64 = user.get_id().unwrap(); let user_id: i64 = match user.get_id() {
Some(id) => id,
None => {
sender_builder
.text("Ответьте на сообщение участника чата, которого вы хотите замьютить")
.reply_to(message.id())
.build()
.send(&bot)
.await
.unwrap();
return Ok(EventReturn::Cancel);
}
};
sleep(Duration::from_millis(time.1)).await; sleep(Duration::from_millis(time.1)).await;
@ -34,12 +46,13 @@ pub async fn mute_member(
let callback = || async { restrict(&bot, user_id, unmute_date, chat_id).await }; let callback = || async { restrict(&bot, user_id, unmute_date, chat_id).await };
sender_builder.set_text("Невозможно выдать мут."); sender_builder.set_text("Невозможно замьютить участника чата, демотните и попробуйте снова");
if try_restrict(callback, demote_args, sender_builder.clone().build()) if try_restrict(callback, demote_args, sender_builder.clone().build())
.await .await
.is_err() .is_err()
{ {
sender_builder.build().send(&bot).await?;
Ok(EventReturn::Cancel) Ok(EventReturn::Cancel)
} else { } else {
let muted_user_name: String = user.get_user_name(&bot, &message).await.unwrap(); let muted_user_name: String = user.get_user_name(&bot, &message).await.unwrap();
@ -47,7 +60,8 @@ pub async fn mute_member(
sender_builder sender_builder
.reply_to(message.id()) .reply_to(message.id())
.text(format!( .text(format!(
"Пользователю {muted_user_name} выдан мут на {mute_duration} {postfix}." "Пользователь {} замьючен на {:?} {}.",
muted_user_name, mute_duration, postfix
)) ))
.build() .build()
.send(&bot) .send(&bot)

View File

@ -28,7 +28,9 @@ pub async fn unmute_member(
if let Err(error) = bot.send(bot_action).await { if let Err(error) = bot.send(bot_action).await {
sender_builder sender_builder
.text(format!("Невозможно снять мут с пользователя: {error:?}.")) .text(format!(
"Невозможно снять мьют с участника чата по причине: {error:?}"
))
.build() .build()
.send(&bot) .send(&bot)
.await?; .await?;
@ -38,7 +40,7 @@ pub async fn unmute_member(
sender_builder sender_builder
.reply_to(message.id()) .reply_to(message.id())
.text(format!("С пользователя {muted_user_name} снят мут.")) .text(format!("С пользователя {} был снят мьют.", muted_user_name))
.build() .build()
.send(&bot) .send(&bot)
.await .await

View File

@ -35,9 +35,8 @@ pub async fn mute(bot: Bot, message: Message, command: CommandObject) -> Handler
if let Ok(id) = raw_id.parse::<i64>() { if let Ok(id) = raw_id.parse::<i64>() {
TargetUser::Id(id) TargetUser::Id(id)
} else { } else {
handler_entity handler_entity.message_sender_builder
.message_sender_builder .text("Ответьте на сообщение или укажите первым аргументом ID человека, которого вы хотите замьютить")
.text("Нет ID или ответа на сообщение пользователя.")
.build() .build()
.send(&handler_entity.bot_instance) .send(&handler_entity.bot_instance)
.await?; .await?;
@ -60,7 +59,7 @@ pub async fn mute(bot: Bot, message: Message, command: CommandObject) -> Handler
handler_entity handler_entity
.message_sender_builder .message_sender_builder
.set_text("Не указана длительность мута."); .set_text("Укажите число, характеризующее длительность мьюта.");
match args.get(duration_argument_position).cloned() { match args.get(duration_argument_position).cloned() {
Some(duration_str) => { Some(duration_str) => {

View File

@ -27,7 +27,7 @@ pub async fn unmute(bot: Bot, message: Message, command: CommandObject) -> Handl
Some(raw_id) => { Some(raw_id) => {
handler_entity handler_entity
.message_sender_builder .message_sender_builder
.set_text("Нет ID или ответа на сообщение пользователя."); .set_text("Укажите id пользователя, с которого вы хотите снять мьют");
if let Ok(parsed_id) = raw_id.parse::<i64>() { if let Ok(parsed_id) = raw_id.parse::<i64>() {
let on_id: TargetUser = TargetUser::Id(parsed_id); let on_id: TargetUser = TargetUser::Id(parsed_id);

View File

@ -22,20 +22,8 @@ pub async fn dice_handler(bot: Bot, message: Message) -> HandlerResult {
let handler_entity: HandlerEntity = HandlerEntity::new(bot, message, sender); let handler_entity: HandlerEntity = HandlerEntity::new(bot, message, sender);
let (mute_time, emoji): (TimeMetrics, &str) = (TimeMetrics::Days(dice.value), &dice.emoji); let (mute_time, emoji): (TimeMetrics, &str) = (TimeMetrics::Days(dice.value), &dice.emoji);
let target: TargetUser = TargetUser::Reply(handler_entity.message_reciever.clone()); let target: TargetUser = TargetUser::Reply(handler_entity.message_reciever.clone());
if !target.exist() {
handler_entity
.message_sender_builder
.text("Нет ответа на сообщение пользователя.")
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
match emoji { match emoji {
"🎲" => { "🎲" => {
mute_member(handler_entity, chat_id, target, (mute_time, DICE_DELAY_MS)).await?; mute_member(handler_entity, chat_id, target, (mute_time, DICE_DELAY_MS)).await?;
@ -56,7 +44,7 @@ pub async fn dice_handler(bot: Bot, message: Message) -> HandlerResult {
_ => { _ => {
handler_entity handler_entity
.message_sender_builder .message_sender_builder
.text("Эмодзи не имеет привязанных действий.") .text("Такой эмодзи не имеет привязки к какому либо действию бота.")
.build() .build()
.send(&handler_entity.bot_instance) .send(&handler_entity.bot_instance)
.await?; .await?;

View File

@ -30,12 +30,13 @@ impl InnerMiddleware for AdminCheck {
let chat_id: i64 = message.chat_id().unwrap(); let chat_id: i64 = message.chat_id().unwrap();
if is_admin(&admins_list, message.from().unwrap().id) { if is_admin(&admins_list, message.from().unwrap()) {
let response = next(request).await?; let response = next(request).await?;
return Ok(response); return Ok(response);
} else { } else {
println!("lol");
MessageSender::builder(chat_id) MessageSender::builder(chat_id)
.text("Недостаточно прав для использования данной команды.") .text("У ваc нет прав администратора, чтобы использовать эту команду.")
.build() .build()
.send(&bot) .send(&bot)
.await .await

View File

@ -15,21 +15,6 @@ pub enum TargetUser {
} }
impl TargetUser { impl TargetUser {
pub fn exist(&self) -> bool {
match self {
Self::Id(_id) => true,
Self::Reply(msg) => {
if let Some(replied_msg) = msg.reply_to_message() {
return replied_msg.from().map(|user| user.id).is_some();
} else {
false
}
}
Self::CurrentMessage(msg) => msg.from().map(|user| user.id).is_some(),
Self::None => false,
}
}
pub fn get_id(&self) -> Option<i64> { pub fn get_id(&self) -> Option<i64> {
match self { match self {
Self::Id(id) => Some(*id), Self::Id(id) => Some(*id),

View File

@ -21,7 +21,7 @@ impl TimeMetrics {
"w" | "weeks" | "week" | "недель" | "недели" | "неделя" | "н" => { "w" | "weeks" | "week" | "недель" | "недели" | "неделя" | "н" => {
Self::Weeks(duration) Self::Weeks(duration)
} }
"m" | "months" | "month" | "месяц" | "месяца" | "месяцев" | "мес" => { "m" | "mounths" | "mounth" | "месяц" | "месяца" | "месяцев" | "мес" => {
Self::Mounths(duration) Self::Mounths(duration)
} }
_ => Self::Days(duration), _ => Self::Days(duration),

View File

@ -1,11 +1,11 @@
use telers::types::chat_member::ChatMember; use telers::types::{chat_member::ChatMember, User};
pub fn is_admin(all_admin_members: &Vec<ChatMember>, user_id: i64) -> bool { pub fn is_admin(all_admin_members: &Vec<ChatMember>, user: &User) -> bool {
all_admin_members all_admin_members
.iter() .iter()
.any(|admin: &ChatMember| match admin { .any(|admin: &ChatMember| match admin {
ChatMember::Administrator(admin) => admin.user.id == user_id, ChatMember::Administrator(admin) => &admin.user == user,
ChatMember::Owner(owner) => owner.user.id == user_id, ChatMember::Owner(owner) => &owner.user == user,
_ => false, _ => false,
}) })
} }

View File

@ -1,12 +1,15 @@
use telers::{errors::SessionErrorKind as ErrorKind, event::EventReturn, types::ChatMember, Bot}; use telers::{errors::SessionErrorKind as ErrorKind, event::EventReturn, Bot};
use crate::types::structs::message_sender::MessageSender; use crate::types::structs::message_sender::MessageSender;
use std::future::Future; use std::future::Future;
use super::{admin_check::is_admin, demote::demote_user, get_all_admins::get_all_admins}; use super::demote::demote_user;
const DEMOTE_FAILURE_MESSAGE: &str = "Команда не может быть выполнена: \ const DEMOTE_FAILURE_MESSAGE: &str = "\
не удалось удалить административные привилегии пользователя."; Нельзя выдать ограничение пользователю, т.к. невозможно демотнуть \
участника посредством бота, если ему выдан админ при помощи других \
админов или владельца чата.\
";
pub async fn try_restrict<F, R>( pub async fn try_restrict<F, R>(
future_callback: F, future_callback: F,
@ -19,18 +22,6 @@ where
{ {
let (bot, user_id, chat_id): (&Bot, i64, i64) = demote_args; let (bot, user_id, chat_id): (&Bot, i64, i64) = demote_args;
let admins: Vec<ChatMember> = get_all_admins(bot, chat_id).await.unwrap();
if is_admin(&admins, user_id) {
MessageSender::builder(chat_id)
.text("Нельзя применить эту команду на пользователе/бота, имеющего привелегии администратора.")
.build()
.send(bot)
.await
.unwrap();
return Err(EventReturn::Cancel);
}
if future_callback().await.is_err() { if future_callback().await.is_err() {
if demote_user(bot, user_id, chat_id).await.is_err() { if demote_user(bot, user_id, chat_id).await.is_err() {
MessageSender::builder(chat_id) MessageSender::builder(chat_id)