reinit git
This commit is contained in:
commit
7ec67cb6e4
|
@ -0,0 +1,16 @@
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
.env
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "dorya"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.86"
|
||||||
|
async-trait = "0.1.80"
|
||||||
|
chrono = "0.4.38"
|
||||||
|
dashmap = "5.5.3"
|
||||||
|
dotenvy = "0.15.7"
|
||||||
|
futures = "0.3.30"
|
||||||
|
telers = "1.0.0-alpha.18"
|
||||||
|
tokio = { version="1.37.0", features=["rt-multi-thread"] }
|
||||||
|
tracing = "0.1.40"
|
||||||
|
tracing-subscriber = {version="0.3.18", features=["env-filter"]}
|
|
@ -0,0 +1,64 @@
|
||||||
|
use telers::{
|
||||||
|
event::{telegram::HandlerResult, EventReturn},
|
||||||
|
types::{Message, User},
|
||||||
|
Bot,
|
||||||
|
};
|
||||||
|
|
||||||
|
use tokio::time::{sleep, Duration as DurationSleep};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
types::structs::{bot_entity::BotEntity, message_sender::MessageSender},
|
||||||
|
utils::telegram::try_do_action::try_restrict,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::utils::telegram::ban_member::ban_chat_member;
|
||||||
|
|
||||||
|
pub async fn ban(bot_entity: BotEntity, delay: u64) -> HandlerResult {
|
||||||
|
let (bot, message, sender): (Bot, Message, MessageSender) = (
|
||||||
|
bot_entity.bot_instance,
|
||||||
|
bot_entity.receive_message,
|
||||||
|
bot_entity.message_sender,
|
||||||
|
);
|
||||||
|
|
||||||
|
let reply_to: Message;
|
||||||
|
let chat_id: i64 = message.chat().id();
|
||||||
|
|
||||||
|
if let Some(msg) = message.reply_to_message() {
|
||||||
|
reply_to = msg.clone();
|
||||||
|
} else {
|
||||||
|
sender
|
||||||
|
.reply_to(message.id())
|
||||||
|
.text("Ответьте на сообщение, чтобы забанить.")
|
||||||
|
.send(&bot)
|
||||||
|
.await?;
|
||||||
|
return Ok(EventReturn::Cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_data: &User = reply_to.from().unwrap();
|
||||||
|
let user_id: i64 = user_data.id;
|
||||||
|
|
||||||
|
sleep(DurationSleep::from_millis(delay)).await;
|
||||||
|
|
||||||
|
let future = || async { ban_chat_member(&bot, user_id, chat_id).await };
|
||||||
|
let demote_args: (&Bot, i64, i64) = (&bot, user_id, chat_id);
|
||||||
|
let failure_sender: MessageSender = sender
|
||||||
|
.clone()
|
||||||
|
.text("Невозможно забанить участника чата, демотните и попробуйте снова");
|
||||||
|
|
||||||
|
if try_restrict(future, demote_args, failure_sender)
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
Ok(EventReturn::Cancel)
|
||||||
|
} else {
|
||||||
|
let banned_user_name: String = reply_to.from().unwrap().clone().username.unwrap();
|
||||||
|
|
||||||
|
sender
|
||||||
|
.reply_to(message.id())
|
||||||
|
.text(format!("Пользователь {} забанен.", banned_user_name))
|
||||||
|
.send(&bot)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(EventReturn::Finish)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod ban;
|
||||||
|
pub mod mute;
|
|
@ -0,0 +1,80 @@
|
||||||
|
use futures::stream::futures_unordered;
|
||||||
|
use telers::{
|
||||||
|
event::{telegram::HandlerResult, EventReturn},
|
||||||
|
types::{Message, User},
|
||||||
|
Bot,
|
||||||
|
};
|
||||||
|
|
||||||
|
use tokio::time::{sleep, Duration as DurationSleep};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
types::{
|
||||||
|
enums::time_metrics::TimeMetrics,
|
||||||
|
structs::{
|
||||||
|
bot_entity::BotEntity, countable_time::CountableTime, message_sender::MessageSender,
|
||||||
|
},
|
||||||
|
traits::countable_interface::ICountable,
|
||||||
|
},
|
||||||
|
utils::telegram::try_do_action::try_restrict,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::utils::{general::unrestrict_date::unrestrict_date, telegram::restrict::restrict};
|
||||||
|
|
||||||
|
pub async fn mute(bot_entity: BotEntity, values: (TimeMetrics, u64)) -> HandlerResult {
|
||||||
|
let (bot, message, sender): (Bot, Message, MessageSender) = (
|
||||||
|
bot_entity.bot_instance,
|
||||||
|
bot_entity.receive_message,
|
||||||
|
bot_entity.message_sender,
|
||||||
|
);
|
||||||
|
|
||||||
|
let reply_to: Message;
|
||||||
|
let chat_id: i64 = message.chat().id();
|
||||||
|
|
||||||
|
if let Some(msg) = message.reply_to_message() {
|
||||||
|
reply_to = msg.clone();
|
||||||
|
} else {
|
||||||
|
sender
|
||||||
|
.reply_to(message.id())
|
||||||
|
.text("Ответьте на сообщение, чтобы замьютить.")
|
||||||
|
.send(&bot)
|
||||||
|
.await?;
|
||||||
|
return Ok(EventReturn::Cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_data: &User = reply_to.from().unwrap();
|
||||||
|
let user_id: i64 = user_data.id;
|
||||||
|
|
||||||
|
sleep(DurationSleep::from_millis(values.1)).await;
|
||||||
|
|
||||||
|
let time_duration = values.0.extract();
|
||||||
|
let unmute_date = unrestrict_date(time_duration);
|
||||||
|
let postfix = CountableTime::from_value(time_duration)
|
||||||
|
.get_postfix(values.0)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let future = || async { restrict(&bot, user_id, unmute_date, chat_id).await };
|
||||||
|
let demote_args: (&Bot, i64, i64) = (&bot, user_id, chat_id);
|
||||||
|
let failure_sender: MessageSender = sender
|
||||||
|
.clone()
|
||||||
|
.text("Невозможно замьютить участника чата, демотните и попробуйте снова");
|
||||||
|
|
||||||
|
if try_restrict(future, demote_args, failure_sender)
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
Ok(EventReturn::Cancel)
|
||||||
|
} else {
|
||||||
|
let muted_user_name = reply_to.from().unwrap().clone().username.unwrap();
|
||||||
|
|
||||||
|
sender
|
||||||
|
.reply_to(message.id())
|
||||||
|
.text(format!(
|
||||||
|
"Пользователь {} замьючен на {:?} {}.",
|
||||||
|
muted_user_name, time_duration, postfix
|
||||||
|
))
|
||||||
|
.send(&bot)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(EventReturn::Finish)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
use telers::{
|
||||||
|
event::{telegram::HandlerResult, EventReturn},
|
||||||
|
types::Message,
|
||||||
|
Bot,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::types::structs::message_sender::MessageSender;
|
||||||
|
|
||||||
|
const HELP_TEXT: &str = "\
|
||||||
|
/help - помощь по боту.\n\
|
||||||
|
/unmute - снимает с человека мьют, нужно ответить на сообщение, чтобы команда сработала (\
|
||||||
|
только для админов).\n\
|
||||||
|
🎲 - выдаёт мут, для этого нужно отправить ТОЛЬКО эмодзи в ответ на сообщение участника. \
|
||||||
|
чата, которого вы хотите замьютить (только для админов).\n\
|
||||||
|
🎰 - выдаёт бан в случае джекпота, напротив, мьют, всё так же кидайте этот эмодзи в ответ \
|
||||||
|
на сообщение участника чата, которого вы хотите замьютить/забанить (только для админов).";
|
||||||
|
|
||||||
|
pub async fn help(bot: Bot, message: Message) -> HandlerResult {
|
||||||
|
println!("hi");
|
||||||
|
MessageSender::new(message.chat().id())
|
||||||
|
.text(HELP_TEXT)
|
||||||
|
.send(&bot)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Ok(EventReturn::Finish)
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod help;
|
||||||
|
pub mod unmute;
|
|
@ -0,0 +1,60 @@
|
||||||
|
use telers::{
|
||||||
|
event::{telegram::HandlerResult, EventReturn},
|
||||||
|
filters::CommandObject,
|
||||||
|
methods::RestrictChatMember,
|
||||||
|
types::User,
|
||||||
|
types::{ChatPermissions, Message},
|
||||||
|
Bot,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::types::structs::message_sender::MessageSender;
|
||||||
|
|
||||||
|
pub async fn unmute(bot: Bot, message: Message, command: CommandObject) -> HandlerResult {
|
||||||
|
let sender = MessageSender::new(message.chat().id());
|
||||||
|
|
||||||
|
let reply_to: Message;
|
||||||
|
let chat_id: i64 = message.chat().id();
|
||||||
|
|
||||||
|
if let Some(msg) = message.reply_to_message() {
|
||||||
|
reply_to = msg.clone();
|
||||||
|
} else {
|
||||||
|
sender
|
||||||
|
.reply_to(message.id())
|
||||||
|
.text("Ответьте на сообщение, чтобы замьютить.")
|
||||||
|
.send(&bot)
|
||||||
|
.await?;
|
||||||
|
return Ok(EventReturn::Cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_data: &User = reply_to.from().unwrap();
|
||||||
|
let user_id: i64 = user_data.id;
|
||||||
|
|
||||||
|
let default_member_permissions = ChatPermissions::all()
|
||||||
|
.can_change_info(false)
|
||||||
|
.can_manage_topics(false)
|
||||||
|
.can_invite_users(false)
|
||||||
|
.can_pin_messages(false);
|
||||||
|
|
||||||
|
let bot_action = RestrictChatMember::new(chat_id, user_id, default_member_permissions);
|
||||||
|
|
||||||
|
let username = reply_to.from().unwrap().clone().username.unwrap();
|
||||||
|
|
||||||
|
if let Err(error) = bot.send(bot_action).await {
|
||||||
|
sender
|
||||||
|
.text(format!(
|
||||||
|
"Невозможно снять мьют с участника чата по причине: {error:?}"
|
||||||
|
))
|
||||||
|
.send(&bot)
|
||||||
|
.await?;
|
||||||
|
return Ok(EventReturn::Cancel);
|
||||||
|
} else {
|
||||||
|
sender
|
||||||
|
.reply_to(message.id())
|
||||||
|
.text(format!("С пользователя {} был снят мьут.", username))
|
||||||
|
.send(&bot)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(EventReturn::Finish)
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod endpoints;
|
|
@ -0,0 +1,50 @@
|
||||||
|
use telers::{
|
||||||
|
event::{telegram::HandlerResult, EventReturn},
|
||||||
|
types::{Dice, Message},
|
||||||
|
Bot,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
handlers::actions::{ban::ban, mute::mute},
|
||||||
|
types::{
|
||||||
|
enums::time_metrics::TimeMetrics,
|
||||||
|
structs::{bot_entity::BotEntity, message_sender::MessageSender},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
let bot_entity: BotEntity = BotEntity {
|
||||||
|
bot_instance: bot,
|
||||||
|
receive_message: message,
|
||||||
|
message_sender: MessageSender::new(chat_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let (mute_time, emoji): (TimeMetrics, &str) = (TimeMetrics::Days(dice.value), &dice.emoji);
|
||||||
|
|
||||||
|
match emoji {
|
||||||
|
"🎲" => {
|
||||||
|
mute(bot_entity, (mute_time, DICE_DELAY_MS)).await?;
|
||||||
|
}
|
||||||
|
"🎰" => {
|
||||||
|
if dice.value == 64 {
|
||||||
|
ban(bot_entity, CASINO_DELAY_MS).await?;
|
||||||
|
} else {
|
||||||
|
mute(bot_entity, (mute_time, CASINO_DELAY_MS)).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
bot_entity
|
||||||
|
.message_sender
|
||||||
|
.text("Такой эмодзи не имеет привязки к какому либо действию бота.")
|
||||||
|
.send(&bot_entity.bot_instance)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(EventReturn::Finish)
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod dice;
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod actions;
|
||||||
|
pub mod commands_handler;
|
||||||
|
pub mod dice_handler;
|
|
@ -0,0 +1,83 @@
|
||||||
|
use dotenvy::dotenv;
|
||||||
|
use telers::{
|
||||||
|
enums::ContentType,
|
||||||
|
event::ToServiceProvider,
|
||||||
|
filters::{content_type::ContentType as CT, Command},
|
||||||
|
Bot, Dispatcher, Router,
|
||||||
|
};
|
||||||
|
|
||||||
|
use tracing_subscriber::{fmt, layer::SubscriberExt as _, util::SubscriberInitExt as _, EnvFilter};
|
||||||
|
|
||||||
|
mod middlewares;
|
||||||
|
mod types;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use middlewares::admin_check_middleware::AdminCheck;
|
||||||
|
|
||||||
|
mod handlers;
|
||||||
|
use handlers::{
|
||||||
|
commands_handler::endpoints::{help::help, unmute::unmute},
|
||||||
|
dice_handler::dice::dice_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(fmt::layer())
|
||||||
|
.with(EnvFilter::from_env("RUST_LOG"))
|
||||||
|
.init();
|
||||||
|
|
||||||
|
dotenv().ok();
|
||||||
|
|
||||||
|
let token_result = dotenvy::var("TOKEN");
|
||||||
|
match token_result {
|
||||||
|
Ok(token) => {
|
||||||
|
let bot = Bot::new(token);
|
||||||
|
|
||||||
|
let mut route = Router::new("main");
|
||||||
|
|
||||||
|
let mut dice = Router::new("dice");
|
||||||
|
|
||||||
|
dice.message
|
||||||
|
.register(dice_handler)
|
||||||
|
.filter(CT::one(ContentType::Dice));
|
||||||
|
|
||||||
|
dice.message.inner_middlewares.register(AdminCheck {});
|
||||||
|
|
||||||
|
let mut command = Router::new("commands");
|
||||||
|
let mut admin_commands = Router::new("admin_commands");
|
||||||
|
let mut default_commands = Router::new("default_commands");
|
||||||
|
|
||||||
|
admin_commands
|
||||||
|
.message
|
||||||
|
.register(unmute)
|
||||||
|
.filter(Command::one("unmute"));
|
||||||
|
|
||||||
|
admin_commands
|
||||||
|
.message
|
||||||
|
.inner_middlewares
|
||||||
|
.register(AdminCheck {});
|
||||||
|
|
||||||
|
default_commands
|
||||||
|
.message
|
||||||
|
.register(help)
|
||||||
|
.filter(Command::one("help"));
|
||||||
|
|
||||||
|
command.include(admin_commands).include(default_commands);
|
||||||
|
|
||||||
|
route.include(dice).include(command);
|
||||||
|
|
||||||
|
let dispatcher = Dispatcher::builder().main_router(route).bot(bot).build();
|
||||||
|
|
||||||
|
dispatcher
|
||||||
|
.to_service_provider_default()
|
||||||
|
.unwrap()
|
||||||
|
.run_polling()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
println!("Error text: {:?}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use telers::{
|
||||||
|
errors::{EventErrorKind, HandlerError},
|
||||||
|
event::telegram::{HandlerRequest, HandlerResponse},
|
||||||
|
middlewares::{InnerMiddleware, Next},
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Error as Reject;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
types::structs::message_sender::MessageSender,
|
||||||
|
utils::telegram::{admin_check::is_admin, get_all_admins::get_all_admins},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct AdminCheck {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl InnerMiddleware for AdminCheck {
|
||||||
|
async fn call(
|
||||||
|
&self,
|
||||||
|
request: HandlerRequest,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<HandlerResponse, EventErrorKind> {
|
||||||
|
let (bot, message) = (request.clone().bot, request.clone().update);
|
||||||
|
|
||||||
|
let admins_list = get_all_admins(&bot, message.chat().unwrap().id())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let chat_id: i64 = message.chat_id().unwrap();
|
||||||
|
|
||||||
|
if is_admin(&admins_list, message.from().unwrap()) {
|
||||||
|
let response = next(request).await?;
|
||||||
|
return Ok(response);
|
||||||
|
} else {
|
||||||
|
MessageSender::new(chat_id)
|
||||||
|
.text("У вам нет прав администратора, чтобы использовать эту команду.")
|
||||||
|
.send(&bot)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return Err(EventErrorKind::Handler(HandlerError::new(Reject::msg(
|
||||||
|
"User isn't admin.".to_string(),
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod admin_check_middleware;
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod time_metrics;
|
|
@ -0,0 +1,30 @@
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum TimeMetrics {
|
||||||
|
Minutes(i64),
|
||||||
|
Hours(i64),
|
||||||
|
Days(i64),
|
||||||
|
Weeks(i64),
|
||||||
|
Mounths(i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeMetrics {
|
||||||
|
pub fn extract(self) -> i64 {
|
||||||
|
match self {
|
||||||
|
Self::Minutes(min) => min,
|
||||||
|
Self::Hours(hrs) => hrs,
|
||||||
|
Self::Days(day) => day,
|
||||||
|
Self::Weeks(wks) => wks,
|
||||||
|
Self::Mounths(mon) => mon,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_word_declensions(self) -> (impl Into<String>, impl Into<String>, impl Into<String>) {
|
||||||
|
match self {
|
||||||
|
Self::Minutes(_) => ("минута", "минуты", "минут"),
|
||||||
|
Self::Hours(_) => ("час", "часов", "часов"),
|
||||||
|
Self::Days(_) => ("день", "дня", "дней"),
|
||||||
|
Self::Weeks(_) => ("неделя", "недели", "недель"),
|
||||||
|
Self::Mounths(_) => ("месяц", "месяца", "месяцев"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod enums;
|
||||||
|
pub mod structs;
|
||||||
|
pub mod traits;
|
|
@ -0,0 +1,8 @@
|
||||||
|
use crate::types::structs::message_sender::MessageSender;
|
||||||
|
use telers::{types::Message, Bot};
|
||||||
|
|
||||||
|
pub struct BotEntity {
|
||||||
|
pub bot_instance: Bot,
|
||||||
|
pub receive_message: Message,
|
||||||
|
pub message_sender: MessageSender,
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
use crate::types::{enums::time_metrics::TimeMetrics, traits::countable_interface::ICountable};
|
||||||
|
|
||||||
|
pub struct CountableTime(i64, i64);
|
||||||
|
|
||||||
|
impl ICountable<(i64, i64), TimeMetrics> for CountableTime {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_value(value: i64) -> Self {
|
||||||
|
Self((value / 10) % 10, value % 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_values(&self) -> (i64, i64) {
|
||||||
|
(self.0, self.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_values(&self, value: i64) -> Self {
|
||||||
|
Self((value / 10) % 10, value % 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_postfix(&self, metrics: TimeMetrics) -> Option<String> {
|
||||||
|
let all_word_declensions = metrics.get_word_declensions();
|
||||||
|
let (first, second, third): (String, String, String) = (
|
||||||
|
all_word_declensions.0.into(),
|
||||||
|
all_word_declensions.1.into(),
|
||||||
|
all_word_declensions.2.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
match self.get_values() {
|
||||||
|
(0, 1) | (2..=9, 1) => Some(first),
|
||||||
|
(0, 2..=4) | (2..=9, 2..=4) => Some(second),
|
||||||
|
(0..=9, 0) | (0, 5..=9) | (1, 0..=9) | (2..=9, 5..=9) => Some(third),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
use core::convert::Into;
|
||||||
|
use telers::{
|
||||||
|
errors::session::ErrorKind,
|
||||||
|
methods::SendMessage,
|
||||||
|
types::{Message, ReplyParameters},
|
||||||
|
Bot,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MessageSender {
|
||||||
|
chat_id: i64,
|
||||||
|
send_message: SendMessage,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageSender {
|
||||||
|
pub fn new(group_id: i64) -> Self {
|
||||||
|
Self {
|
||||||
|
chat_id: group_id,
|
||||||
|
send_message: SendMessage::new(group_id, ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn group_id(mut self, val: i64) -> Self {
|
||||||
|
self.chat_id = val;
|
||||||
|
self.send_message = self.send_message.clone().chat_id(val);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn text(mut self, val: impl Into<String>) -> Self {
|
||||||
|
self.send_message = self.send_message.clone().text(val);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn disable_notification(mut self, val: bool) -> Self {
|
||||||
|
self.send_message = self.send_message.clone().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.clone().reply_parameters(reply);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub async fn send(self, bot: &Bot) -> Result<Message, ErrorKind> {
|
||||||
|
bot.send(self.send_message).await
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod bot_entity;
|
||||||
|
pub mod countable_time;
|
||||||
|
pub mod message_sender;
|
|
@ -0,0 +1,12 @@
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub trait ICountable<T, M> {
|
||||||
|
fn new() -> Self;
|
||||||
|
|
||||||
|
fn from_value(value: i64) -> Self;
|
||||||
|
|
||||||
|
fn set_values(&self, value: i64) -> Self;
|
||||||
|
|
||||||
|
fn get_values(&self) -> T;
|
||||||
|
|
||||||
|
fn get_postfix(&self, metrics: M) -> Option<String>;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod countable_interface;
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod unrestrict_date;
|
|
@ -0,0 +1,5 @@
|
||||||
|
use chrono::{Duration, Local, NaiveDateTime};
|
||||||
|
|
||||||
|
pub fn unrestrict_date(days: i64) -> NaiveDateTime {
|
||||||
|
Local::now().naive_utc() + Duration::days(days)
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod general;
|
||||||
|
pub mod telegram;
|
|
@ -0,0 +1,11 @@
|
||||||
|
use telers::types::{chat_member::ChatMember, User};
|
||||||
|
|
||||||
|
pub fn is_admin(all_admin_members: &Vec<ChatMember>, user: &User) -> bool {
|
||||||
|
all_admin_members
|
||||||
|
.iter()
|
||||||
|
.any(|admin: &ChatMember| match admin {
|
||||||
|
ChatMember::Administrator(admin) => &admin.user == user,
|
||||||
|
ChatMember::Owner(owner) => &owner.user == user,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
use telers::{errors::session::ErrorKind, methods::BanChatMember, Bot};
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
use telers::{errors::session::ErrorKind, methods::promote_chat_member::PromoteChatMember, Bot};
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
use telers::{errors::SessionErrorKind, methods::get_chat_administrators, types::ChatMember, Bot};
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
pub mod admin_check;
|
||||||
|
pub mod ban_member;
|
||||||
|
pub mod demote;
|
||||||
|
pub mod get_all_admins;
|
||||||
|
pub mod restrict;
|
||||||
|
pub mod try_do_action;
|
|
@ -0,0 +1,32 @@
|
||||||
|
use chrono::NaiveDateTime;
|
||||||
|
use telers::{errors::session::ErrorKind, methods::*, types::ChatPermissions, Bot};
|
||||||
|
|
||||||
|
pub async fn restrict(
|
||||||
|
bot: &Bot,
|
||||||
|
user_id: i64,
|
||||||
|
duration: NaiveDateTime,
|
||||||
|
chat_id: i64,
|
||||||
|
) -> Result<bool, ErrorKind> {
|
||||||
|
bot.send(
|
||||||
|
restrict_chat_member::RestrictChatMember::new(
|
||||||
|
chat_id,
|
||||||
|
user_id,
|
||||||
|
ChatPermissions::new()
|
||||||
|
.can_send_photos(false)
|
||||||
|
.can_send_polls(false)
|
||||||
|
.can_send_audios(false)
|
||||||
|
.can_send_videos(false)
|
||||||
|
.can_change_info(false)
|
||||||
|
.can_invite_users(false)
|
||||||
|
.can_send_other_messages(false)
|
||||||
|
.can_pin_messages(false)
|
||||||
|
.can_send_messages(false)
|
||||||
|
.can_send_voice_notes(false)
|
||||||
|
.can_send_video_notes(false)
|
||||||
|
.can_send_documents(false)
|
||||||
|
.can_manage_topics(false),
|
||||||
|
)
|
||||||
|
.until_date(duration.and_utc().timestamp()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
use telers::{errors::SessionErrorKind as ErrorKind, event::EventReturn, Bot};
|
||||||
|
|
||||||
|
use crate::types::structs::message_sender::MessageSender;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
use super::demote::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;
|
||||||
|
|
||||||
|
if future_callback().await.is_err() {
|
||||||
|
if demote_user(bot, user_id, chat_id).await.is_err() {
|
||||||
|
MessageSender::new(chat_id)
|
||||||
|
.text(DEMOTE_FAILURE_MESSAGE)
|
||||||
|
.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(())
|
||||||
|
}
|
Loading…
Reference in New Issue