REFACTOR!: remove a lot of bad code + structures, remake command args parser, and etc.

This commit is contained in:
doryan 2025-04-10 00:46:50 +04:00
parent d3d13b32c9
commit dd306b7000
28 changed files with 250 additions and 423 deletions

View File

@ -4,7 +4,7 @@ lto = "fat"
overflow-checks = false
[package]
name = "dorya"
name = "gluon"
version = "0.2.0"
edition = "2021"

View File

@ -8,91 +8,39 @@ use telers::{
};
use crate::{
actions::{ban::ban_member, mute::mute_member, unmute::unmute_member},
assets::files::{BAN_COMMAND_HELP, MUTE_COMMAND_HELP, UNMUTE_COMMAND_HELP},
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},
},
assets::files::{BAN_COMMAND_HELP, MUTE_COMMAND_HELP, UNBAN_COMMAND_HELP, UNMUTE_COMMAND_HELP},
utils::telegram::{args_parser::parse_args, senders::send_html},
};
pub async fn admin_command_endpoint(
#[allow(unused)]
const USER_ID_NOT_FOUND: &str = "Для выполнение команды нужно знать ID пользователя, или ввести команду и выполнить её, ответив на сообщение пользователя";
#[allow(unused)]
const COMMAND_EXECUTION_REJECTED: &str = "Выполнение данной команды невозможно, поскольку пользователю были выданы права администратора модераторами или основателем";
pub async fn admin_commands_endpoint(
bot: Bot,
message: Message,
command: CommandObject,
command_object: CommandObject,
) -> HandlerResult {
let command_type: &str = command.command.deref();
let (command_type, args) = (command_object.command.deref(), command_object.args.deref());
let args: Vec<&'static str> = cast_boxed(command.args);
let chat_id = message.chat().id();
let (chat_id, mut handler_entity): (i64, HandlerEntity) = get_chat_data(&bot, &message);
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() {
if let Some(_args) = parse_args(args, &message, command_type) {
match command_type {
"ban" | "unban" | "mute" | "unmute" => todo!(),
_ => unreachable!(),
};
} else {
let help_txt = match command_type {
"ban" => BAN_COMMAND_HELP,
"mute" => MUTE_COMMAND_HELP,
"unban" => UNBAN_COMMAND_HELP,
"unmute" => UNMUTE_COMMAND_HELP,
_ => "Такой команды не существует.",
_ => unreachable!(),
};
send_html(bot, message, help_txt).await?;
return Ok(EventReturn::Cancel);
send_html(&bot, chat_id, help_txt).await?;
}
handler_entity
.message_sender_builder
.set_text("Нет ID или ответа на сообщение пользователя.");
match command_type {
"ban" => ban_member(handler_entity, chat_id, target_user, 0).await?,
"mute" => 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);
}
},
"unmute" => unmute_member(handler_entity, chat_id, target_user).await?,
_ => EventReturn::Finish,
};
Ok(EventReturn::Finish)
}

View File

@ -1,6 +1,11 @@
use std::ops::Deref;
use telers::{event::telegram::HandlerResult, filters::CommandObject, types::Message, Bot};
use telers::{
event::{telegram::HandlerResult, EventReturn},
filters::CommandObject,
types::Message,
Bot,
};
use crate::{
assets::files::{HELP_COMMAND_TEXT, PRIVACY_COMMAND_TEXT},
@ -10,12 +15,13 @@ use crate::{
#[inline]
pub async fn info_commands_endpoint(
bot: Bot,
msg: Message,
command: CommandObject,
message: Message,
command_object: CommandObject,
) -> HandlerResult {
match command.command.deref() {
"help" => send_html(bot, msg, HELP_COMMAND_TEXT).await,
"privacy" => send_html(bot, msg, PRIVACY_COMMAND_TEXT).await,
_ => Ok(telers::event::EventReturn::Cancel),
let chat_id = message.chat().id();
match command_object.command.deref() {
"help" => send_html(&bot, chat_id, HELP_COMMAND_TEXT).await,
"privacy" => send_html(&bot, chat_id, PRIVACY_COMMAND_TEXT).await,
_ => Ok(EventReturn::Cancel),
}
}

View File

@ -1,2 +1,5 @@
pub mod admin_commands;
pub mod info_commands;
mod admin_commands;
mod info_commands;
pub use admin_commands::*;
pub use info_commands::*;

View File

@ -1,48 +1,43 @@
use std::time::Duration;
use telers::{
event::{telegram::HandlerResult, EventReturn},
types::{Dice, Message},
Bot,
};
use tokio::time::sleep;
use crate::{
actions::{ban::ban_member, mute::mute_member},
types::{
enums::{target_user::TargetUser, time_metrics::TimeMetrics},
structs::{handler_entity::HandlerEntity, message_sender::MessageSender},
},
types::enums::{target_user::TargetUser, time_metrics::TimeDuration},
utils::telegram::args_parser::Argument,
};
const DICE_DELAY_MS: u64 = 4000u64;
const CASINO_DELAY_MS: u64 = 1500u64;
pub async fn dice_handler(bot: Bot, message: Message) -> HandlerResult {
let (chat_id, dice): (i64, Dice) = (message.chat().id(), message.dice().unwrap().clone());
pub async fn dice_handler(_bot: Bot, message: Message) -> HandlerResult {
let (_chat_id, dice): (i64, Dice) = (message.chat().id(), message.dice().unwrap().clone());
let sender = MessageSender::builder(chat_id);
let handler_entity = HandlerEntity::new(bot, message, sender);
let (mute_time, emoji): (TimeDuration, &str) = (TimeDuration::Days(dice.value), &dice.emoji);
let (mute_time, emoji): (TimeMetrics, &str) = (TimeMetrics::Days(dice.value), &dice.emoji);
let target = TargetUser::Reply(handler_entity.message_reciever.clone());
let target_user = TargetUser::Reply(message.clone());
let _args = [Argument::User(target_user), Argument::Time(mute_time)];
match emoji {
"🎲" => {
mute_member(handler_entity, chat_id, target, (mute_time, DICE_DELAY_MS)).await?;
sleep(Duration::from_millis(DICE_DELAY_MS)).await;
todo!()
}
"🎰" => {
if dice.value == 64 {
ban_member(handler_entity, chat_id, target, CASINO_DELAY_MS).await?;
sleep(Duration::from_millis(CASINO_DELAY_MS)).await;
todo!()
} else {
mute_member(
handler_entity,
chat_id,
target,
(mute_time, CASINO_DELAY_MS),
)
.await?;
sleep(Duration::from_millis(CASINO_DELAY_MS)).await;
todo!()
}
}
_ => ()
_ => (),
}
Ok(EventReturn::Finish)

View File

@ -1 +1,3 @@
pub mod dice_handler;
mod dice_handler;
pub use dice_handler::*;

View File

@ -7,7 +7,6 @@ use telers::{
Bot, Dispatcher, Router,
};
mod actions;
mod assets;
mod handlers;
mod middlewares;
@ -17,8 +16,8 @@ mod utils;
use middlewares::admin_check_middleware::AdminCheck;
use handlers::{
commands::{admin_commands::admin_command_endpoint, info_commands::info_commands_endpoint},
dice::dice_handler::dice_handler,
commands::{admin_commands_endpoint, info_commands_endpoint},
dice::dice_handler,
};
#[cfg(debug_assertions)]
@ -65,7 +64,14 @@ async fn main() {
let mut default_commands = Router::new("default_commands");
create_handler!(default_commands, info_commands_endpoint, help, privacy);
create_handler!(admin_commands, admin_command_endpoint, mute, unmute, ban);
create_handler!(
admin_commands,
admin_commands_endpoint,
ban,
unban,
mute,
unmute
);
admin_commands
.message

View File

@ -2,6 +2,7 @@ use async_trait::async_trait;
use telers::{
errors::{EventErrorKind, HandlerError},
event::telegram::HandlerResponse,
methods::SendMessage,
middlewares::{InnerMiddleware, Next},
types::Message,
Request,
@ -9,10 +10,7 @@ use telers::{
use anyhow::Error as Reject;
use crate::{
types::structs::message_sender::MessageSender,
utils::telegram::{admin_check::is_admin, data_getters::get_all_admins},
};
use crate::utils::telegram::{admin_check::is_admin, data_getters::get_all_admins};
#[derive(Default)]
pub struct AdminCheck {}
@ -20,16 +18,23 @@ pub struct AdminCheck {}
#[async_trait]
impl InnerMiddleware for AdminCheck {
async fn call(&self, request: Request, next: Next) -> Result<HandlerResponse, EventErrorKind> {
let (bot, message) = (request.clone().bot, request.clone().update);
let (bot, message) = (request.bot.clone(), request.update.clone());
let is_replying_dice: Option<Message> = match message.kind().message().unwrap() {
Message::Dice(dice) => dice.reply_to_message.clone(),
_ => None,
};
let admins_list = get_all_admins(&bot, message.chat().unwrap().id())
.await
.unwrap();
let chat = match message.chat() {
Some(chat) => chat,
None => {
return Err(EventErrorKind::Handler(HandlerError::from_display(
"Chat not found",
)))
}
};
let admins_list = get_all_admins(&bot, chat.id()).await.unwrap();
let chat_id: i64 = message.chat_id().unwrap();
@ -38,12 +43,12 @@ impl InnerMiddleware for AdminCheck {
return Ok(response);
} else {
if is_replying_dice.is_some() {
MessageSender::builder(chat_id)
.text("Недостаточно прав для использования данной команды.")
.build()
.send(&bot)
.await
.unwrap();
bot.send(SendMessage::new(
chat_id,
"Недостаточно прав для использования данной команды.",
))
.await
.ok();
}
return Err(EventErrorKind::Handler(HandlerError::new(Reject::msg(

View File

@ -14,6 +14,15 @@ pub enum TargetUser {
None,
}
impl From<Option<i64>> for TargetUser {
fn from(value: Option<i64>) -> Self {
match value {
Some(id) => TargetUser::Id(id),
None => TargetUser::None,
}
}
}
impl TargetUser {
#[allow(dead_code)]
pub fn exist(&self) -> bool {
@ -21,10 +30,9 @@ impl TargetUser {
Self::Id(_id) => true,
Self::Reply(msg) => {
if let Some(replied_msg) = msg.reply_to_message() {
replied_msg.from().map(|user| user.id).is_some()
} else {
false
return replied_msg.from().map(|user| user.id).is_some();
}
false
}
Self::CurrentMessage(msg) => msg.from().map(|user| user.id).is_some(),
Self::None => false,
@ -36,10 +44,9 @@ impl TargetUser {
Self::Id(id) => Some(*id),
Self::Reply(msg) => {
if let Some(replied_msg) = msg.reply_to_message() {
replied_msg.from().map(|user| user.id)
} else {
None
return replied_msg.from().map(|user| user.id);
}
None
}
Self::CurrentMessage(msg) => msg.from().map(|user| user.id),
Self::None => None,
@ -53,31 +60,28 @@ impl TargetUser {
bot.send(GetChatMember::new(msg.chat().id(), *id)).await;
if let Ok(member_kind) = get_chat_member_result {
match member_kind {
return match member_kind {
ChatMember::Owner(member) => member.user.username,
ChatMember::Administrator(member) => member.user.username,
ChatMember::Member(member) => member.user.username,
ChatMember::Restricted(member) => member.user.username,
ChatMember::Left(member) => member.user.username,
ChatMember::Banned(member) => member.user.username,
}
} else {
None
};
}
None
}
Self::Reply(msg) => {
if let Some(replied_msg) = msg.reply_to_message() {
replied_msg.from().unwrap().username.clone()
} else {
None
return replied_msg.from().unwrap().username.clone();
}
None
}
Self::CurrentMessage(msg) => {
if let Some(replied_msg) = msg.from() {
replied_msg.username.clone()
} else {
None
return replied_msg.username.clone();
}
None
}
Self::None => None,
}

View File

@ -1,6 +1,6 @@
#[allow(dead_code)]
#[derive(Debug, Copy, Clone)]
pub enum TimeMetrics {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum TimeDuration {
Minutes(i64),
Hours(i64),
Days(i64),
@ -8,23 +8,23 @@ pub enum TimeMetrics {
Mounths(i64),
}
impl TimeMetrics {
pub fn from(metric: impl Into<&'static str>, duration: i64) -> Self {
impl<'a> TimeDuration {
pub fn from(metric: impl Into<&'a str>, duration: i64) -> Option<Self> {
match metric.into() {
"m" | "min" | "minutes" | "minute" | "минута" | "минуты" | "минут" | "мин" | "м" => {
Self::Minutes(duration)
Some(Self::Minutes(duration))
}
"h" | "hours" | "hour" | "час" | "часов" | "ч" => Self::Hours(duration),
"h" | "hours" | "hour" | "час" | "часов" | "ч" => Some(Self::Hours(duration)),
"d" | "days" | "day" | "день" | "дня" | "дней" | "д" => {
Self::Days(duration)
Some(Self::Days(duration))
}
"w" | "weeks" | "week" | "недель" | "недели" | "неделя" | "н" => {
Self::Weeks(duration)
Some(Self::Weeks(duration))
}
"M" | "months" | "month" | "месяц" | "месяца" | "месяцев" | "мес" | "М" => {
Self::Mounths(duration)
Some(Self::Mounths(duration))
}
_ => Self::Days(duration),
_ => None,
}
}

View File

@ -1,7 +1,3 @@
use enums::time_metrics::TimeMetrics;
pub mod enums;
pub mod structs;
pub mod traits;
pub type TimeValues = (TimeMetrics, u64);

View File

@ -1,8 +1,8 @@
use crate::types::{enums::time_metrics::TimeMetrics, traits::countable_interface::ICountable};
use crate::types::{enums::time_metrics::TimeDuration, traits::countable_interface::ICountable};
pub struct CountableTime(i64, i64);
impl ICountable<(i64, i64), TimeMetrics> for CountableTime {
impl ICountable<(i64, i64), TimeDuration> for CountableTime {
#[inline]
fn new() -> Self {
Self(0, 0)
@ -23,7 +23,7 @@ impl ICountable<(i64, i64), TimeMetrics> for CountableTime {
Self((value / 10) % 10, value % 10)
}
fn get_postfix(&self, metrics: TimeMetrics) -> Option<String> {
fn get_postfix(&self, metrics: TimeDuration) -> Option<String> {
let all_word_declensions = metrics.get_word_declensions();
let (first, second, third): (String, String, String) = (
all_word_declensions.0.into(),

View File

@ -1,29 +0,0 @@
use crate::types::structs::message_sender::MessageSenderBuilder;
use telers::{types::Message, Bot};
pub type ExtractedEntityData = (Bot, Message, MessageSenderBuilder);
#[derive(Clone)]
pub struct HandlerEntity {
pub bot_instance: Bot,
pub message_reciever: Message,
pub message_sender_builder: MessageSenderBuilder,
}
impl HandlerEntity {
pub fn new(bot: Bot, msg: Message, msg_builder: MessageSenderBuilder) -> Self {
Self {
bot_instance: bot,
message_reciever: msg,
message_sender_builder: msg_builder,
}
}
#[inline]
pub fn extract(self) -> ExtractedEntityData {
(
self.bot_instance,
self.message_reciever,
self.message_sender_builder,
)
}
}

View File

@ -1,81 +0,0 @@
use core::convert::Into;
use telers::{
enums::ParseMode,
errors::session::ErrorKind,
methods::SendMessage,
types::{Message, ReplyParameters},
Bot,
};
#[derive(Clone, Debug)]
pub struct MessageSender {
message: SendMessage,
}
impl MessageSender {
pub fn builder(group_id: i64) -> MessageSenderBuilder {
MessageSenderBuilder {
chat_id: group_id,
send_message: SendMessage::new(group_id, ""),
}
}
pub async fn send(self, bot: &Bot) -> Result<Message, ErrorKind> {
bot.send(self.message).await
}
}
#[derive(Clone, Debug)]
pub struct MessageSenderBuilder {
chat_id: i64,
send_message: SendMessage,
}
#[allow(dead_code)]
impl MessageSenderBuilder {
pub fn parse_mode(mut self, parse_mode: ParseMode) -> Self {
self.send_message = self.send_message.parse_mode(parse_mode);
self
}
pub fn group_id(mut self, val: i64) -> Self {
self.chat_id = val;
self.send_message = self.send_message.chat_id(val);
self
}
pub fn text(mut self, val: impl Into<String>) -> Self {
self.send_message = self.send_message.text(val);
self
}
pub fn disable_notification(mut self, val: bool) -> Self {
self.send_message = self.send_message.disable_notification(val);
self
}
pub fn reply_to(mut self, msg_id: i64) -> Self {
let reply = ReplyParameters::new(msg_id).chat_id(self.chat_id);
self.send_message = self.send_message.reply_parameters(reply);
self
}
pub fn set_parse_mode(&mut self, parse_mode: ParseMode) {
self.send_message = self.send_message.clone().parse_mode(parse_mode);
}
pub fn set_group_id(&mut self, val: i64) {
self.chat_id = val;
self.send_message = self.send_message.clone().chat_id(val);
}
pub fn set_text(&mut self, val: impl Into<String>) {
self.send_message = self.send_message.clone().text(val);
}
pub fn set_disable_notification(&mut self, val: bool) {
self.send_message = self.send_message.clone().disable_notification(val);
}
pub fn set_reply_to(&mut self, msg_id: i64) {
let reply = ReplyParameters::new(msg_id).chat_id(self.chat_id);
self.send_message = self.send_message.clone().reply_parameters(reply);
}
pub fn build(self) -> MessageSender {
MessageSender {
message: self.send_message,
}
}
}

View File

@ -1,3 +1 @@
pub mod countable_time;
pub mod handler_entity;
pub mod message_sender;

View File

@ -1,11 +0,0 @@
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

@ -1,15 +0,0 @@
use chrono::{Duration, Local, NaiveDateTime};
use crate::types::{enums::time_metrics::TimeMetrics, TimeValues};
#[inline]
pub fn expiration_date(duration: TimeValues) -> NaiveDateTime {
let mute_duration = match duration.0 {
TimeMetrics::Minutes(min) => Duration::minutes(min),
TimeMetrics::Hours(hrs) => Duration::hours(hrs),
TimeMetrics::Days(day) => Duration::days(day),
TimeMetrics::Weeks(wks) => Duration::weeks(wks),
TimeMetrics::Mounths(mon) => Duration::weeks(mon * 4),
};
Local::now().naive_utc() + mute_duration
}

View File

@ -1,18 +1,29 @@
use chrono::NaiveDateTime;
use crate::types::{
structs::countable_time::CountableTime, traits::countable_interface::ICountable, TimeValues,
enums::time_metrics::TimeDuration, structs::countable_time::CountableTime,
traits::countable_interface::ICountable,
};
use super::expiration_date::expiration_date;
use chrono::{Duration, Local, NaiveDateTime};
pub type ExtractedDuration = (NaiveDateTime, String, i64);
pub fn get_expiration_time(time: TimeValues) -> ExtractedDuration {
let time_duration = time.0.extract();
let unmute_date = expiration_date(time);
#[inline]
pub fn get_expiration_date(duration: TimeDuration) -> NaiveDateTime {
let mute_duration = match duration {
TimeDuration::Minutes(min) => Duration::minutes(min),
TimeDuration::Hours(hrs) => Duration::hours(hrs),
TimeDuration::Days(day) => Duration::days(day),
TimeDuration::Weeks(wks) => Duration::weeks(wks),
TimeDuration::Mounths(mon) => Duration::weeks(mon * 4),
};
Local::now().naive_utc() + mute_duration
}
pub fn get_expiration_time(time: TimeDuration) -> ExtractedDuration {
let time_duration = time.extract();
let unmute_date = get_expiration_date(time);
let postfix = CountableTime::from_value(time_duration)
.get_postfix(time.0)
.get_postfix(time)
.unwrap();
(unmute_date, postfix, time_duration)

View File

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

View File

@ -1,11 +1,10 @@
#[macro_export]
macro_rules! create_handler {
($branch:expr, $command:expr) => {
$($branch
$branch
.message
.register($command)
.filter(Command::one(stringify!($command)));
)*
};
($branch:expr, $command:expr, $($endpoint:expr), *) => {
$branch

View File

@ -0,0 +1,66 @@
use std::{collections::VecDeque, ops::Deref};
use telers::types::Message;
use crate::types::enums::{target_user::TargetUser, time_metrics::TimeDuration};
#[derive(Debug)]
pub enum Argument {
User(TargetUser),
Time(TimeDuration),
Reason(String),
}
pub fn parse_args(
args: &[Box<str>],
message: &Message,
command_type: &str,
) -> Option<Vec<Argument>> {
if args.is_empty() && message.reply_to_message().is_none() {
return None;
}
let mut raw_args: VecDeque<&str> = args.iter().map(|arg| arg.deref()).collect();
let mut parsed_args: Vec<Argument> = Vec::new();
let user_id = match message.reply_to_message() {
Some(reply_message) => TargetUser::from(reply_message.from_id()),
None => match raw_args.pop_front() {
Some(arg) => TargetUser::from(arg.parse::<i64>().ok()),
None => TargetUser::default(),
},
};
parsed_args.push(Argument::User(user_id));
match command_type {
"mute" | "tban" => 'raw_time_parsing: {
let time = match raw_args.pop_front() {
Some(raw_time) => raw_time.parse::<i64>().unwrap_or(0),
None => break 'raw_time_parsing,
};
if time == 0 {
break 'raw_time_parsing;
}
if let Some(raw_time_metric) = raw_args.pop_front() {
let time_metric = match TimeDuration::from(raw_time_metric, time) {
Some(metric) => metric,
None => TimeDuration::Days(time),
};
parsed_args.push(Argument::Time(time_metric));
};
}
_ => {}
}
if !raw_args.is_empty() {
let reason = raw_args.iter().fold(String::new(), |acc, v| acc + v + " ");
parsed_args.push(Argument::Reason(reason.trim_end().to_string()));
}
Some(parsed_args)
}

View File

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

View File

@ -9,7 +9,7 @@ pub async fn restrict(
chat_id: i64,
) -> Result<bool, ErrorKind> {
bot.send(
restrict_chat_member::RestrictChatMember::new(
RestrictChatMember::new(
chat_id,
user_id,
ChatPermissions::new()

View File

@ -1,6 +1,6 @@
pub mod admin_check;
pub mod args_parsers;
pub mod args_parser;
pub mod data_getters;
pub mod rights_control;
pub mod member_rights;
pub mod senders;
pub mod try_do;
pub mod try_admin_action;

View File

@ -1,21 +1,12 @@
use telers::{
event::{
telegram::HandlerResult,
EventReturn
},
enums::ParseMode,
types::Message,
Bot
enums::ParseMode,
event::{telegram::HandlerResult, EventReturn},
methods::SendMessage,
Bot,
};
use crate::types::structs::message_sender::MessageSender;
pub async fn send_html(bot: Bot, message: Message, info_text: &str) -> HandlerResult {
MessageSender::builder(message.chat().id())
.text(info_text)
.parse_mode(ParseMode::HTML)
.build()
.send(&bot)
pub async fn send_html(bot: &Bot, chat_id: i64, text: &str) -> HandlerResult {
bot.send(SendMessage::new(chat_id, text).parse_mode(ParseMode::HTML))
.await?;
Ok(EventReturn::Finish)

View File

@ -0,0 +1,31 @@
use telers::{
errors::{HandlerError, SessionErrorKind},
event::simple::HandlerResult,
methods::SendMessage,
Bot,
};
use super::member_rights::demote_user;
const DEMOTE_ERROR: &str = "Невозможно снять привелегий администратора в силу того, что права были выданы одним из администраторов или основателем";
pub async fn try_admin_action<F>(
callback: F,
bot: &Bot,
chat_id: i64,
user_id: i64,
) -> HandlerResult
where
F: Copy + AsyncFnOnce(i64) -> Result<bool, SessionErrorKind>,
{
if callback(user_id).await.is_err() {
if demote_user(bot, user_id, chat_id).await.is_err() {
bot.send(SendMessage::new(chat_id, DEMOTE_ERROR)).await?;
return Err(HandlerError::from_display("DemoteFailure"));
} else {
callback(user_id).await;
}
}
Ok(())
}

View File

@ -1,52 +0,0 @@
use telers::{errors::SessionErrorKind as ErrorKind, event::EventReturn, types::ChatMember, Bot};
use crate::types::structs::message_sender::MessageSender;
use std::future::Future;
use super::{admin_check::is_admin, data_getters::get_all_admins, rights_control::demote_user};
const DEMOTE_FAILURE_MESSAGE: &str = "Команда не может быть выполнена: \
не удалось удалить административные привилегии пользователя.";
pub async fn try_restrict<F, R>(
future_callback: F,
demote_args: (&Bot, i64, i64),
failure_sender: MessageSender,
) -> Result<(), EventReturn>
where
R: Future<Output = Result<bool, ErrorKind>>,
F: Copy + Fn() -> R,
{
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 demote_user(bot, user_id, chat_id).await.is_err() {
MessageSender::builder(chat_id)
.text(DEMOTE_FAILURE_MESSAGE)
.build()
.send(bot)
.await
.unwrap();
return Err(EventReturn::Cancel);
}
if future_callback().await.is_err() {
failure_sender.send(bot).await.unwrap();
return Err(EventReturn::Cancel);
}
}
Ok(())
}