Compare commits

..

18 Commits

Author SHA1 Message Date
doryan c387c0497a feat(help): add help to the ban command 2024-08-21 23:11:47 +04:00
doryan 1044f7a434 feat(ver): change version number 2024-08-21 23:10:54 +04:00
doryan 20b1e78aa3 uhm... 2024-08-21 20:58:34 +04:00
doryan d45ebcc682 feat(imports): format imports 2024-08-21 20:58:21 +04:00
doryan f41e012f8e refactor: add append_command macro 2024-08-21 20:57:43 +04:00
doryan e333e401f3 feat(fn): all_admin_member is slice 2024-08-21 20:56:45 +04:00
doryan 352514d2b0 refactor: format code 2024-08-21 20:56:11 +04:00
doryan 46183842bd fix(on reply): prevent unmute action with REPLY 2024-08-21 20:55:28 +04:00
doryan 1bcbb3d456 refactor: rename file
dice.rs -> dice_handler.rs
2024-08-21 20:52:08 +04:00
doryan b557bf5832 feat(imports): format imports 2024-08-21 20:50:38 +04:00
doryan 311187b6eb refactor(bot): dice and command endpoints; feat(ban): add ban endpoint; and etc. 2024-07-09 23:05:29 +04:00
doryan 3fda2620e3 feat(attributes): add #[allow(dead_code)] for target user and #[derive(Clone)] for handler_entity 2024-07-09 23:03:49 +04:00
doryan cca1b86772 refactor(folder name): rename from 'handlers' to 'endpoints' 2024-07-09 23:01:33 +04:00
doryan 7576859907 refactor(bot actions): move bot actions from src/handlers to src/ 2024-07-09 23:00:01 +04:00
doryan ec2ff44e36 refactor(utils): sort, rename and refactor utils 2024-07-09 22:57:37 +04:00
doryan e0a5e3a0bb feat(ban): add ban command help info 2024-07-09 22:56:36 +04:00
doryan 8928a21e1e fix(spell): remove stupid spelling mistake 2024-07-09 22:20:05 +04:00
doryan be6c68dcf2 feat(ban): add ban command help info 2024-07-09 22:18:16 +04:00
41 changed files with 372 additions and 312 deletions

View File

@ -1,10 +1,11 @@
[profile.release] [profile.release]
opt-level = 3 opt-level = 3
lto = "fat"
overflow-checks = false overflow-checks = false
[package] [package]
name = "dorya" name = "dorya"
version = "0.1.0" version = "0.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,5 +1,6 @@
use telers::{ use telers::{
event::{telegram::HandlerResult, EventReturn}, event::{telegram::HandlerResult, EventReturn},
methods::BanChatMember,
Bot, Bot,
}; };
@ -10,7 +11,7 @@ use crate::{
enums::target_user::TargetUser, enums::target_user::TargetUser,
structs::handler_entity::{ExtractedEntityData, HandlerEntity}, structs::handler_entity::{ExtractedEntityData, HandlerEntity},
}, },
utils::telegram::{ban_member::ban_chat_member, try_do::try_restrict}, utils::telegram::try_do::try_restrict,
}; };
pub async fn ban_member( pub async fn ban_member(
@ -21,24 +22,14 @@ pub async fn ban_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 = match user.get_id() {
Some(id) => id,
None => {
sender_builder
.text("Нет ID или ответа на сообщение пользователя.")
.reply_to(message.id())
.build()
.send(&bot)
.await
.unwrap();
return Ok(EventReturn::Cancel);
}
};
sleep(DurationSleep::from_millis(delay)).await; sleep(DurationSleep::from_millis(delay)).await;
let callback = || async { ban_chat_member(&bot, user_id, chat_id).await }; let user_id: i64 = user.get_id().unwrap();
let callback = || async { bot.send(BanChatMember::new(chat_id, user_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())

View File

@ -12,8 +12,8 @@ use crate::{
TimeValues, TimeValues,
}, },
utils::{ utils::{
general::get_duration::{get_duration, ExtractedDuration}, general::get_expiration_time::{get_expiration_time, ExtractedDuration},
telegram::{restrict::restrict, try_do::try_restrict}, telegram::{rights_control::restrict, try_do::try_restrict},
}, },
}; };
@ -29,7 +29,7 @@ pub async fn mute_member(
sleep(Duration::from_millis(time.1)).await; sleep(Duration::from_millis(time.1)).await;
let (unmute_date, postfix, mute_duration): ExtractedDuration = get_duration(time); let (unmute_date, postfix, mute_duration): ExtractedDuration = get_expiration_time(time);
let demote_args: (&Bot, i64, i64) = (&bot, user_id, chat_id); let demote_args: (&Bot, i64, i64) = (&bot, user_id, chat_id);
let callback = || async { restrict(&bot, user_id, unmute_date, chat_id).await }; let callback = || async { restrict(&bot, user_id, unmute_date, chat_id).await };

View File

@ -16,7 +16,18 @@ pub async fn unmute_member(
) -> HandlerResult { ) -> HandlerResult {
let (bot, message, sender_builder): ExtractedEntityData = handler_entity.extract(); let (bot, message, sender_builder): ExtractedEntityData = handler_entity.extract();
let user_id: i64 = user.get_id().unwrap(); let user_id: i64;
if let Some(id) = user.get_id() {
user_id = id;
} else {
sender_builder
.build()
.send(&bot)
.await?;
return Ok(EventReturn::Cancel);
}
let default_member_permissions = ChatPermissions::all() let default_member_permissions = ChatPermissions::all()
.can_change_info(false) .can_change_info(false)
@ -32,6 +43,7 @@ pub async fn unmute_member(
.build() .build()
.send(&bot) .send(&bot)
.await?; .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();
@ -41,8 +53,8 @@ pub async fn unmute_member(
.text(format!("С пользователя {muted_user_name} снят мут.")) .text(format!("С пользователя {muted_user_name} снят мут."))
.build() .build()
.send(&bot) .send(&bot)
.await .await?;
.unwrap();
Ok(EventReturn::Finish) Ok(EventReturn::Finish)
} }
} }

View File

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

View File

@ -2,6 +2,7 @@
<code>/mute {ID | REPLY} &lt;DURATION&gt; [TIME METRIC]</code> - выдаёт мут на заданное время; <code>/mute {ID | REPLY} &lt;DURATION&gt; [TIME METRIC]</code> - выдаёт мут на заданное время;
<code>/unmute {ID | REPLY}</code> - снимает мут; <code>/unmute {ID | REPLY}</code> - снимает мут;
<code>/ban {ID | REPLY}</code> - банит;
Для более подробного описания, введите команды без аргументов. Для более подробного описания, введите команды без аргументов.

View File

@ -3,6 +3,7 @@ use std::include_str;
pub mod files { pub mod files {
use super::*; use super::*;
pub const BAN_COMMAND_HELP: &str = include_str!("ban_command_help.html");
pub const HELP_COMMAND_TEXT: &str = include_str!("help_command.html"); pub const HELP_COMMAND_TEXT: &str = include_str!("help_command.html");
pub const PRIVACY_COMMAND_TEXT: &str = include_str!("privacy_command.html"); pub const PRIVACY_COMMAND_TEXT: &str = include_str!("privacy_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

@ -1 +1 @@
В боте <strong>Gluon v.0.1</strong> ни где не предусмотрено хранение данных о пользователе. В боте <strong>Gluon v.0.2</strong> не предусмотрено хранение данных о пользователе.

View File

@ -0,0 +1,51 @@
use telers::{
event::{
EventReturn,
telegram::HandlerResult
},
filters::CommandObject,
types::Message,
Bot
};
use crate::{
assets::files::BAN_COMMAND_HELP, actions::ban::ban_member,
types::{
enums::target_user::TargetUser,
structs::handler_entity::HandlerEntity
},
utils::{
general::cast_boxed_array::cast_boxed,
telegram::{
args_parsers::get_user,
data_getters::get_chat_data,
senders::send_html
}
}
};
pub async fn ban(bot: Bot, message: Message, command: CommandObject) -> HandlerResult {
let args: Vec<&'static str> = cast_boxed(command.args);
let (chat_id, mut handler_entity): (i64, HandlerEntity) = get_chat_data(&bot, &message);
let target_user: TargetUser = get_user(
handler_entity.clone(),
args.first().copied(),
&mut 0,
);
if args.is_empty() && !target_user.exist(){
send_html(bot, message, BAN_COMMAND_HELP).await?;
return Ok(EventReturn::Cancel);
}
handler_entity
.message_sender_builder
.set_text("Нет ID или ответа на сообщение пользователя.");
ban_member(handler_entity, chat_id, target_user, 0).await?;
Ok(EventReturn::Finish)
}

View File

@ -0,0 +1,16 @@
use telers::{event::telegram::HandlerResult, types::Message, Bot};
use crate::{
assets::files::{HELP_COMMAND_TEXT, PRIVACY_COMMAND_TEXT},
utils::telegram::senders::send_html,
};
#[inline]
pub async fn help(bot: Bot, msg: Message) -> HandlerResult {
send_html(bot, msg, HELP_COMMAND_TEXT).await
}
#[inline]
pub async fn privacy(bot: Bot, msg: Message) -> HandlerResult {
send_html(bot, msg, PRIVACY_COMMAND_TEXT).await
}

View File

@ -1,3 +1,4 @@
pub mod info_commands_template; pub mod ban_command;
pub mod info_commands;
pub mod mute_command; pub mod mute_command;
pub mod unmute_command; pub mod unmute_command;

View File

@ -0,0 +1,85 @@
use telers::{
event::{telegram::HandlerResult, EventReturn},
filters::CommandObject,
types::Message,
Bot,
};
use crate::{
assets::files::MUTE_COMMAND_HELP,
actions::mute::mute_member,
types::{
enums::{
target_user::TargetUser,
time_metrics::TimeMetrics
},
structs::handler_entity::HandlerEntity,
},
utils::{
general::cast_boxed_array::cast_boxed,
telegram::{
args_parsers::get_user,
data_getters::get_chat_data,
senders::send_html
},
},
};
pub async fn mute(bot: Bot, message: Message, command: CommandObject) -> HandlerResult {
let (chat_id, mut handler_entity): (i64, HandlerEntity) = get_chat_data(&bot, &message);
let args: Vec<&'static str> = cast_boxed(command.args);
let mut duration_argument_position = 0usize;
let target_user: TargetUser = get_user(
handler_entity.clone(),
args.first().copied(),
&mut duration_argument_position,
);
if args.is_empty() && !target_user.exist(){
send_html(bot, message, MUTE_COMMAND_HELP).await?;
return Ok(EventReturn::Cancel);
}
handler_entity
.message_sender_builder
.set_text("Нет ID или ответа на сообщение пользователя.");
match args.get(duration_argument_position).cloned() {
Some(duration_str) => {
let metric = args
.get(duration_argument_position + 1)
.cloned()
.unwrap_or("d");
if let Ok(duration) = duration_str.parse::<i64>() {
let mute_duration = TimeMetrics::from(metric, duration);
mute_member(handler_entity, chat_id, target_user, (mute_duration, 0)).await?;
} else {
handler_entity
.message_sender_builder
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
}
None => {
handler_entity
.message_sender_builder
.text("Не указана длительность мута.")
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
}
Ok(EventReturn::Finish)
}

View File

@ -0,0 +1,38 @@
use telers::{
event::{telegram::HandlerResult, EventReturn},
filters::CommandObject,
types::Message,
Bot,
};
use crate::{
actions::unmute::unmute_member,
assets::files::UNMUTE_COMMAND_HELP,
types::{enums::target_user::TargetUser, structs::handler_entity::HandlerEntity},
utils::{
general::cast_boxed_array::cast_boxed,
telegram::{args_parsers::get_user, data_getters::get_chat_data, senders::send_html},
},
};
pub async fn unmute(bot: Bot, message: Message, command: CommandObject) -> HandlerResult {
let (chat_id, mut handler_entity): (i64, HandlerEntity) = get_chat_data(&bot, &message);
let args: Vec<&'static str> = cast_boxed(command.args);
let target_user: TargetUser = get_user(handler_entity.clone(), args.first().copied(), &mut 0);
if args.is_empty() && !target_user.exist() {
send_html(bot, message, UNMUTE_COMMAND_HELP).await?;
return Ok(EventReturn::Cancel);
}
handler_entity
.message_sender_builder
.set_text("Нет ID или ответа на сообщение пользователя.");
unmute_member(handler_entity, chat_id, target_user).await?;
Ok(EventReturn::Finish)
}

View File

@ -5,7 +5,7 @@ use telers::{
}; };
use crate::{ use crate::{
handlers::actions::{ban::ban_member, mute::mute_member}, actions::{ban::ban_member, mute::mute_member},
types::{ types::{
enums::{target_user::TargetUser, time_metrics::TimeMetrics}, enums::{target_user::TargetUser, time_metrics::TimeMetrics},
structs::{handler_entity::HandlerEntity, message_sender::MessageSender}, structs::{handler_entity::HandlerEntity, message_sender::MessageSender},
@ -19,22 +19,15 @@ pub async fn dice_handler(bot: Bot, message: Message) -> HandlerResult {
let (chat_id, dice): (i64, Dice) = (message.chat().id(), message.dice().unwrap().clone()); let (chat_id, dice): (i64, Dice) = (message.chat().id(), message.dice().unwrap().clone());
let sender = MessageSender::builder(chat_id); let sender = MessageSender::builder(chat_id);
let handler_entity: HandlerEntity = HandlerEntity::new(bot, message, sender); let mut handler_entity = 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::Reply(handler_entity.message_reciever.clone());
if !target.exist() {
handler_entity handler_entity
.message_sender_builder .message_sender_builder
.text("Нет ответа на сообщение пользователя.") .set_text("Нет ответа на сообщение пользователя.");
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
match emoji { match emoji {
"🎲" => { "🎲" => {
@ -53,14 +46,7 @@ pub async fn dice_handler(bot: Bot, message: Message) -> HandlerResult {
.await?; .await?;
} }
} }
_ => { _ => ()
handler_entity
.message_sender_builder
.text("Эмодзи не имеет привязанных действий.")
.build()
.send(&handler_entity.bot_instance)
.await?;
}
} }
Ok(EventReturn::Finish) Ok(EventReturn::Finish)

View File

@ -0,0 +1 @@
pub mod dice_handler;

2
src/endpoints/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod commands;
pub mod dice;

View File

@ -1,97 +0,0 @@
use telers::{
enums::ParseMode,
event::{telegram::HandlerResult, EventReturn},
filters::CommandObject,
types::Message,
Bot,
};
use crate::{
assets::files::MUTE_COMMAND_HELP,
handlers::actions::mute::mute_member,
types::{
enums::{target_user::TargetUser, time_metrics::TimeMetrics},
structs::{handler_entity::HandlerEntity, message_sender::MessageSender},
},
utils::general::parse_boxed_array::parse_boxed,
};
pub async fn mute(bot: Bot, message: Message, command: CommandObject) -> HandlerResult {
let args: Vec<&'static str> = parse_boxed(command.args);
let (message_id, chat_id): (i64, i64) = (message.id(), message.chat().id());
let sender = MessageSender::builder(chat_id).reply_to(message_id);
let mut handler_entity: HandlerEntity = HandlerEntity::new(bot, message, sender);
let mut duration_argument_position: usize = 0;
let target_user: TargetUser = match (
handler_entity.message_reciever.reply_to_message(),
args.first(),
) {
(Some(msg), _) => TargetUser::CurrentMessage(msg.clone()),
(None, Some(raw_id)) => {
duration_argument_position += 1;
if let Ok(id) = raw_id.parse::<i64>() {
TargetUser::Id(id)
} else {
handler_entity
.message_sender_builder
.text("Нет ID или ответа на сообщение пользователя.")
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
}
(None, None) => {
handler_entity
.message_sender_builder
.text(MUTE_COMMAND_HELP)
.parse_mode(ParseMode::HTML)
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
};
handler_entity
.message_sender_builder
.set_text("Не указана длительность мута.");
match args.get(duration_argument_position).cloned() {
Some(duration_str) => {
let metric = args
.get(duration_argument_position + 1)
.cloned()
.unwrap_or("d");
if let Ok(duration) = duration_str.parse::<i64>() {
let mute_duration = TimeMetrics::from(metric, duration);
mute_member(handler_entity, chat_id, target_user, (mute_duration, 0)).await?;
} else {
handler_entity
.message_sender_builder
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
}
None => {
handler_entity
.message_sender_builder
.build()
.send(&handler_entity.bot_instance)
.await?;
return Ok(EventReturn::Cancel);
}
}
Ok(EventReturn::Finish)
}

View File

@ -1,62 +0,0 @@
use telers::{
enums::ParseMode,
event::{telegram::HandlerResult, EventReturn},
filters::CommandObject,
types::Message,
Bot,
};
use crate::{
assets::files::UNMUTE_COMMAND_HELP,
handlers::actions::unmute::unmute_member,
types::{
enums::target_user::TargetUser,
structs::{handler_entity::HandlerEntity, message_sender::MessageSender},
},
utils::general::parse_boxed_array::parse_boxed,
};
pub async fn unmute(bot: Bot, message: Message, command: CommandObject) -> HandlerResult {
let args: Vec<&'static str> = parse_boxed(command.args);
let (message_id, chat_id): (i64, i64) = (message.id(), message.chat().id());
let sender = MessageSender::builder(chat_id).reply_to(message_id);
let mut handler_entity: HandlerEntity = HandlerEntity::new(bot, message, sender);
match args.first().cloned() {
Some(raw_id) => {
handler_entity
.message_sender_builder
.set_text("Нет ID или ответа на сообщение пользователя.");
if let Ok(parsed_id) = raw_id.parse::<i64>() {
let on_id: TargetUser = TargetUser::Id(parsed_id);
unmute_member(handler_entity, chat_id, on_id).await?;
} else {
handler_entity
.message_sender_builder
.build()
.send(&handler_entity.bot_instance)
.await
.unwrap();
}
}
None => {
if handler_entity.message_reciever.reply_to_message().is_none() {
handler_entity
.message_sender_builder
.text(UNMUTE_COMMAND_HELP)
.parse_mode(ParseMode::HTML)
.build()
.send(&handler_entity.bot_instance)
.await
.unwrap();
} else {
let on_reply = TargetUser::Reply(handler_entity.message_reciever.clone());
unmute_member(handler_entity, chat_id, on_reply).await?;
}
}
}
Ok(EventReturn::Finish)
}

View File

@ -1 +0,0 @@
pub mod dice;

View File

@ -1,3 +0,0 @@
pub mod actions;
pub mod command_handlers;
pub mod dice_handler;

View File

@ -4,10 +4,10 @@ use telers::{
enums::ContentType, enums::ContentType,
event::ToServiceProvider, event::ToServiceProvider,
filters::{content_type::ContentType as CT, Command}, filters::{content_type::ContentType as CT, Command},
types::Message,
Bot, Dispatcher, Router, Bot, Dispatcher, Router,
}; };
mod actions;
mod assets; mod assets;
mod middlewares; mod middlewares;
mod types; mod types;
@ -15,14 +15,15 @@ mod utils;
use middlewares::admin_check_middleware::AdminCheck; use middlewares::admin_check_middleware::AdminCheck;
use assets::files::{HELP_COMMAND_TEXT, PRIVACY_COMMAND_TEXT}; mod endpoints;
use endpoints::{
mod handlers; commands::{
use handlers::{ ban_command::ban,
command_handlers::{ info_commands::{help, privacy},
info_commands_template::send_info, mute_command::mute, unmute_command::unmute, mute_command::mute,
unmute_command::unmute,
}, },
dice_handler::dice::dice_handler, dice::dice_handler::dice_handler,
}; };
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -45,6 +46,16 @@ fn logs() {
); );
} }
macro_rules! append_command {
($branch:expr, $($command:expr), *) => {
$($branch
.message
.register($command)
.filter(Command::one(stringify!($command)));
)*
}
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
logs(); logs();
@ -69,31 +80,8 @@ async fn main() {
let mut admin_commands = Router::new("admin_commands"); let mut admin_commands = Router::new("admin_commands");
let mut default_commands = Router::new("default_commands"); let mut default_commands = Router::new("default_commands");
let help = append_command!(default_commands, help, privacy);
|bot: Bot, msg: Message| async { send_info(bot, msg, HELP_COMMAND_TEXT).await }; append_command!(admin_commands, unmute, mute, ban);
let privacy =
|bot: Bot, msg: Message| async { send_info(bot, msg, PRIVACY_COMMAND_TEXT).await };
default_commands
.message
.register(help)
.filter(Command::one("help"));
default_commands
.message
.register(privacy)
.filter(Command::one("privacy"));
admin_commands
.message
.register(unmute)
.filter(Command::one("unmute"));
admin_commands
.message
.register(mute)
.filter(Command::one("mute"));
admin_commands admin_commands
.message .message
@ -115,7 +103,7 @@ async fn main() {
.unwrap(); .unwrap();
} }
Err(error) => { Err(error) => {
println!("Error text: {:?}", error); eprintln!("Error text: {:?}", error);
} }
} }
} }

View File

@ -9,7 +9,7 @@ use anyhow::Error as Reject;
use crate::{ use crate::{
types::structs::message_sender::MessageSender, types::structs::message_sender::MessageSender,
utils::telegram::{admin_check::is_admin, get_all_admins::get_all_admins}, utils::telegram::{admin_check::is_admin, data_getters::get_all_admins},
}; };
#[derive(Default)] #[derive(Default)]

View File

@ -15,6 +15,7 @@ pub enum TargetUser {
} }
impl TargetUser { impl TargetUser {
#[allow(dead_code)]
pub fn exist(&self) -> bool { pub fn exist(&self) -> bool {
match self { match self {
Self::Id(_id) => true, Self::Id(_id) => true,
@ -44,6 +45,7 @@ impl TargetUser {
Self::None => None, Self::None => None,
} }
} }
pub async fn get_user_name(&self, bot: &Bot, msg: &Message) -> Option<String> { pub async fn get_user_name(&self, bot: &Bot, msg: &Message) -> Option<String> {
match self { match self {
Self::Id(id) => { Self::Id(id) => {

View File

@ -27,6 +27,7 @@ impl TimeMetrics {
_ => Self::Days(duration), _ => Self::Days(duration),
} }
} }
pub fn extract(self) -> i64 { pub fn extract(self) -> i64 {
match self { match self {
Self::Minutes(min) => min, Self::Minutes(min) => min,
@ -36,6 +37,7 @@ impl TimeMetrics {
Self::Mounths(mon) => mon, Self::Mounths(mon) => mon,
} }
} }
pub fn get_word_declensions(self) -> (impl Into<String>, impl Into<String>, impl Into<String>) { pub fn get_word_declensions(self) -> (impl Into<String>, impl Into<String>, impl Into<String>) {
match self { match self {
Self::Minutes(_) => ("минута", "минуты", "минут"), Self::Minutes(_) => ("минута", "минуты", "минут"),

View File

@ -3,6 +3,7 @@ use telers::{types::Message, Bot};
pub type ExtractedEntityData = (Bot, Message, MessageSenderBuilder); pub type ExtractedEntityData = (Bot, Message, MessageSenderBuilder);
#[derive(Clone)]
pub struct HandlerEntity { pub struct HandlerEntity {
pub bot_instance: Bot, pub bot_instance: Bot,
pub message_reciever: Message, pub message_reciever: Message,

View File

@ -0,0 +1,11 @@
pub fn cast_box<'a>(boxed: Box<str>) -> &'a str {
unsafe { &*Box::into_raw(boxed) }
}
#[allow(clippy::boxed_local)]
pub fn cast_boxed<'a>(boxed_array: Box<[Box<str>]>) -> Vec<&'a str> {
boxed_array
.iter()
.map(|arg| cast_box(arg.to_owned()))
.collect()
}

View File

@ -3,7 +3,7 @@ use chrono::{Duration, Local, NaiveDateTime};
use crate::types::{enums::time_metrics::TimeMetrics, TimeValues}; use crate::types::{enums::time_metrics::TimeMetrics, TimeValues};
#[inline] #[inline]
pub fn unrestrict_date(duration: TimeValues) -> NaiveDateTime { pub fn expiration_date(duration: TimeValues) -> NaiveDateTime {
let mute_duration = match duration.0 { let mute_duration = match duration.0 {
TimeMetrics::Minutes(min) => Duration::minutes(min), TimeMetrics::Minutes(min) => Duration::minutes(min),
TimeMetrics::Hours(hrs) => Duration::hours(hrs), TimeMetrics::Hours(hrs) => Duration::hours(hrs),

View File

@ -4,13 +4,13 @@ use crate::types::{
structs::countable_time::CountableTime, traits::countable_interface::ICountable, TimeValues, structs::countable_time::CountableTime, traits::countable_interface::ICountable, TimeValues,
}; };
use super::unrestrict_date::unrestrict_date; use super::expiration_date::expiration_date;
pub type ExtractedDuration = (NaiveDateTime, String, i64); pub type ExtractedDuration = (NaiveDateTime, String, i64);
pub fn get_duration(time: TimeValues) -> ExtractedDuration { pub fn get_expiration_time(time: TimeValues) -> ExtractedDuration {
let time_duration = time.0.extract(); let time_duration = time.0.extract();
let unmute_date = unrestrict_date(time); let unmute_date = expiration_date(time);
let postfix = CountableTime::from_value(time_duration) let postfix = CountableTime::from_value(time_duration)
.get_postfix(time.0) .get_postfix(time.0)
.unwrap(); .unwrap();

View File

@ -1,3 +1,3 @@
pub mod get_duration; pub mod expiration_date;
pub mod parse_boxed_array; pub mod get_expiration_time;
pub mod unrestrict_date; pub mod cast_boxed_array;

View File

@ -1,11 +0,0 @@
pub fn parse_box<'a>(boxed: Box<str>) -> &'a str {
unsafe { &*Box::into_raw(boxed) }
}
#[allow(clippy::boxed_local)]
pub fn parse_boxed<'a>(boxed_array: Box<[Box<str>]>) -> Vec<&'a str> {
boxed_array
.iter()
.map(|arg| parse_box(arg.to_owned()))
.collect()
}

View File

@ -1,6 +1,6 @@
use telers::types::chat_member::ChatMember; use telers::types::chat_member::ChatMember;
pub fn is_admin(all_admin_members: &Vec<ChatMember>, user_id: i64) -> bool { pub fn is_admin(all_admin_members: &[ChatMember], user_id: i64) -> bool {
all_admin_members all_admin_members
.iter() .iter()
.any(|admin: &ChatMember| match admin { .any(|admin: &ChatMember| match admin {
@ -9,10 +9,7 @@ pub fn is_admin(all_admin_members: &Vec<ChatMember>, user_id: i64) -> bool {
&& admin.can_change_info && admin.can_change_info
&& admin.can_delete_messages && admin.can_delete_messages
&& admin.can_promote_members && admin.can_promote_members
&& admin.can_manage_chat
&& admin.can_restrict_members && admin.can_restrict_members
&& admin.can_invite_users
&& admin.can_manage_topics.unwrap()
} }
ChatMember::Owner(owner) => owner.user.id == user_id, ChatMember::Owner(owner) => owner.user.id == user_id,
_ => false, _ => false,

View File

@ -0,0 +1,28 @@
use crate::types::{
enums::target_user::TargetUser,
structs::handler_entity::HandlerEntity
};
pub fn get_user(
handler_entity: HandlerEntity,
arg: Option<&str>,
arg_pos: &mut usize,
) -> TargetUser {
match (
handler_entity.message_reciever.reply_to_message(),
arg,
) {
(Some(msg), _) => TargetUser::CurrentMessage(msg.clone()),
(None, Some(raw_id)) => {
*arg_pos += 1;
if let Ok(id) = raw_id.parse::<i64>() {
TargetUser::Id(id)
} else {
TargetUser::None
}
}
(None, None) => {
TargetUser::None
}
}
}

View File

@ -1,6 +0,0 @@
use telers::{errors::session::ErrorKind, methods::BanChatMember, Bot};
#[inline]
pub async fn ban_chat_member(bot: &Bot, chat_id: i64, user_id: i64) -> Result<bool, ErrorKind> {
bot.send(BanChatMember::new(chat_id, user_id)).await
}

View File

@ -0,0 +1,22 @@
use telers::{
methods::GetChatAdministrators,
types::{ChatMember, Message},
Bot,
errors::SessionErrorKind
};
use crate::types::structs::{handler_entity::HandlerEntity, message_sender::MessageSender};
pub fn get_chat_data(bot: &Bot, message: &Message) -> (i64, HandlerEntity) {
let (message_id, chat_id): (i64, i64) = (message.id(), message.chat().id());
let sender = MessageSender::builder(chat_id).reply_to(message_id);
let handler_entity: HandlerEntity = HandlerEntity::new(bot.clone(), message.clone(), sender);
(chat_id, handler_entity)
}
#[inline]
pub async fn get_all_admins(bot: &Bot, chat_id: i64) -> Result<Vec<ChatMember>, SessionErrorKind> {
bot.send(GetChatAdministrators::new(chat_id))
.await
}

View File

@ -1,21 +0,0 @@
use telers::{errors::session::ErrorKind, methods::promote_chat_member::PromoteChatMember, Bot};
#[inline]
pub async fn demote_user(bot: &Bot, user_id: i64, chat_id: i64) -> Result<bool, ErrorKind> {
bot.send(
PromoteChatMember::new(chat_id, user_id)
.can_manage_topics(false)
.can_pin_messages(false)
.can_invite_users(false)
.can_change_info(false)
.can_promote_members(false)
.can_restrict_members(false)
.can_manage_voice_chats(false)
.can_delete_messages(false)
.can_edit_messages(false)
.can_post_messages(false)
.can_manage_chat(false)
.is_anonymous(false),
)
.await
}

View File

@ -1,7 +0,0 @@
use telers::{errors::SessionErrorKind, methods::get_chat_administrators, types::ChatMember, Bot};
#[inline]
pub async fn get_all_admins(bot: &Bot, chat_id: i64) -> Result<Vec<ChatMember>, SessionErrorKind> {
bot.send(get_chat_administrators::GetChatAdministrators::new(chat_id))
.await
}

View File

@ -1,6 +1,6 @@
pub mod admin_check; pub mod admin_check;
pub mod ban_member; pub mod args_parsers;
pub mod demote; pub mod data_getters;
pub mod get_all_admins; pub mod rights_control;
pub mod restrict; pub mod senders;
pub mod try_do; pub mod try_do;

View File

@ -31,3 +31,23 @@ pub async fn restrict(
) )
.await .await
} }
#[inline]
pub async fn demote_user(bot: &Bot, user_id: i64, chat_id: i64) -> Result<bool, ErrorKind> {
bot.send(
PromoteChatMember::new(chat_id, user_id)
.can_manage_topics(false)
.can_pin_messages(false)
.can_invite_users(false)
.can_change_info(false)
.can_promote_members(false)
.can_restrict_members(false)
.can_manage_voice_chats(false)
.can_delete_messages(false)
.can_edit_messages(false)
.can_post_messages(false)
.can_manage_chat(false)
.is_anonymous(false),
)
.await
}

View File

@ -1,19 +1,22 @@
use telers::{ use telers::{
enums::parse_mode::ParseMode, event::{
event::{telegram::HandlerResult, EventReturn}, telegram::HandlerResult,
EventReturn
},
enums::ParseMode,
types::Message, types::Message,
Bot, Bot
}; };
use crate::types::structs::message_sender::MessageSender; use crate::types::structs::message_sender::MessageSender;
pub async fn send_info(bot: Bot, message: Message, info_text: &'static str) -> HandlerResult { pub async fn send_html(bot: Bot, message: Message, info_text: &str) -> HandlerResult {
MessageSender::builder(message.chat().id()) MessageSender::builder(message.chat().id())
.text(info_text) .text(info_text)
.parse_mode(ParseMode::HTML) .parse_mode(ParseMode::HTML)
.build() .build()
.send(&bot) .send(&bot)
.await .await?;
.unwrap();
Ok(EventReturn::Finish) Ok(EventReturn::Finish)
} }

View File

@ -3,7 +3,7 @@ use telers::{errors::SessionErrorKind as ErrorKind, event::EventReturn, types::C
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::{admin_check::is_admin, data_getters::get_all_admins, rights_control::demote_user};
const DEMOTE_FAILURE_MESSAGE: &str = "Команда не может быть выполнена: \ const DEMOTE_FAILURE_MESSAGE: &str = "Команда не может быть выполнена: \
не удалось удалить административные привилегии пользователя."; не удалось удалить административные привилегии пользователя.";