Refactoring, minor fixes in karma handler (multiple messages)

This commit is contained in:
Nefrace 2022-10-17 01:34:22 +03:00
parent 379c161c3b
commit 759dc374ea
7 changed files with 159 additions and 128 deletions

7
Cargo.lock generated
View File

@ -157,6 +157,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]] [[package]]
name = "dptree" name = "dptree"
version = "0.3.0" version = "0.3.0"
@ -347,6 +353,7 @@ dependencies = [
name = "godette" name = "godette"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dotenv",
"lazy_static", "lazy_static",
"log", "log",
"pretty_env_logger", "pretty_env_logger",

View File

@ -12,3 +12,4 @@ pretty_env_logger = "0.4"
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] } tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
lazy_static = "1.4.0" lazy_static = "1.4.0"
url = "2.3.1" url = "2.3.1"
dotenv = "0.15.0"

View File

@ -1,17 +1,18 @@
use teloxide::{ use teloxide::{dispatching::DpHandlerDescription, prelude::*, RequestError};
prelude::*,
types::{InlineKeyboardButton, InlineKeyboardMarkup},
};
pub mod commands; pub mod commands;
mod dispatchers;
mod handlers; mod handlers;
mod utils; mod utils;
use commands::{AdminCommand, Command};
use url::Url;
use utils::get_text_or_empty;
pub struct Godette { pub struct Godette {
pub bot: Bot, pub bot: Bot,
pub triggers: Vec<Trigger>,
}
pub struct Trigger {
pub words: Vec<String>,
pub callback: fn(&Bot, &Message) -> ResponseResult<()>,
} }
pub struct KarmaTrigger { pub struct KarmaTrigger {
@ -31,87 +32,36 @@ impl Godette {
pub fn new() -> Godette { pub fn new() -> Godette {
Godette { Godette {
bot: Bot::from_env(), bot: Bot::from_env(),
triggers: vec![],
} }
} }
pub async fn commands_dispatcher(bot: Bot, msg: Message, cmd: Command) -> ResponseResult<()> { pub fn create_handler(
match cmd { &self,
Command::Help => handlers::show_help(bot, msg).await?, ) -> Handler<'static, DependencyMap, Result<(), RequestError>, DpHandlerDescription> {
Command::Me(quote) => handlers::me(bot, msg, quote).await?, Update::filter_message()
}; // User commands
Ok(()) .branch(
} dptree::entry()
.filter_command::<commands::Command>()
pub async fn admin_dispatcher(bot: Bot, msg: Message, cmd: AdminCommand) -> ResponseResult<()> { .endpoint(Godette::commands_dispatcher),
let mut is_admin = true; )
if msg.chat.is_group() || msg.chat.is_supergroup() { // Admin commands
let sender = msg.from().unwrap(); .branch(
let admins = bot.get_chat_administrators(msg.chat.id).await?; dptree::entry()
is_admin = admins.iter().any(|member| member.user.id == sender.id); .filter_command::<commands::AdminCommand>()
} .endpoint(Godette::admin_dispatcher),
if !is_admin { )
return Ok(()); // Replies
} // .branch(Message::filter_reply_to_message().endpoint(Godette::reply_dispatcher))
match cmd { // Messages
AdminCommand::HelpAdmin => handlers::show_adminhelp(bot, msg).await?, .branch(
AdminCommand::Say(quote) => handlers::say(bot, msg, quote).await?, dptree::filter(|msg: Message| {
AdminCommand::Warn(reason) => handlers::warn(bot, msg, reason).await?, msg.from()
AdminCommand::Unwarn => handlers::unwarn(bot, msg).await?, .map(|user| user.id == UserId(60441930))
}; .unwrap_or_default()
Ok(()) })
} .endpoint(Godette::message_dispatcher),
)
pub async fn message_dispatcher(bot: Bot, msg: Message) -> ResponseResult<()> {
// Checking if it's a reply
let reply = msg.reply_to_message();
match reply {
Some(reply) => {
Godette::reply_dispatcher(bot.clone(), msg.clone(), reply.to_owned()).await?
}
None => (),
};
let text = utils::get_text_or_empty(&msg).to_lowercase();
match text.find("оффтоп") {
Some(_) => {
bot.send_message(msg.chat.id, "Вот вам ссылка на оффтоп")
.reply_to_message_id(msg.id)
.reply_markup(Godette::make_offtop_keyboard())
.await?;
}
None => (),
}
Ok(())
}
pub async fn reply_dispatcher(bot: Bot, msg: Message, reply: Message) -> ResponseResult<()> {
let triggers = vec![
KarmaTrigger::new("спс", 1),
KarmaTrigger::new("спасибо", 1),
KarmaTrigger::new("+", 1),
KarmaTrigger::new("благодарю", 1),
KarmaTrigger::new("пасиб", 1),
KarmaTrigger::new("-", -1),
KarmaTrigger::new("👍", 1),
KarmaTrigger::new("👎", -1),
];
let text = get_text_or_empty(&msg);
println!("{:?}", text);
for trigger in triggers {
match text.to_lowercase().find(&trigger.text) {
Some(_id) => {
println!("It's a thanks!");
return handlers::karma(&bot, &msg, &reply, trigger.value).await;
}
None => (),
}
}
Ok(())
}
fn make_offtop_keyboard() -> InlineKeyboardMarkup {
let link = Url::parse("https://t.me/Godot_Engine_Offtop").unwrap();
let button = InlineKeyboardButton::url("Godot Engine оффтоп чат".to_owned(), link);
return InlineKeyboardMarkup::new(vec![[button]]);
} }
} }

View File

@ -0,0 +1,58 @@
use teloxide::prelude::*;
use super::{handlers, utils, Godette, KarmaTrigger, Trigger};
use crate::commands::{AdminCommand, Command};
impl Godette {
pub async fn commands_dispatcher(bot: Bot, msg: Message, cmd: Command) -> ResponseResult<()> {
match cmd {
Command::Help => handlers::show_help(bot, msg).await?,
Command::Me(quote) => handlers::me(bot, msg, quote).await?,
};
Ok(())
}
pub async fn admin_dispatcher(bot: Bot, msg: Message, cmd: AdminCommand) -> ResponseResult<()> {
let mut is_admin = true;
if msg.chat.is_group() || msg.chat.is_supergroup() {
let sender = msg.from().unwrap();
let admins = bot.get_chat_administrators(msg.chat.id).await?;
is_admin = admins.iter().any(|member| member.user.id == sender.id);
}
if !is_admin {
return Ok(());
}
match cmd {
AdminCommand::HelpAdmin => handlers::show_adminhelp(bot, msg).await?,
AdminCommand::Say(quote) => handlers::say(bot, msg, quote).await?,
AdminCommand::Warn(reason) => handlers::warn(bot, msg, reason).await?,
AdminCommand::Unwarn => handlers::unwarn(bot, msg).await?,
};
Ok(())
}
pub async fn message_dispatcher(bot: Bot, msg: Message) -> ResponseResult<()> {
// Checking if it's a reply and send it to Reply dispatcher
let reply = msg.reply_to_message();
match reply {
Some(reply) => {
Godette::reply_dispatcher(bot.clone(), msg.clone(), reply.to_owned()).await?
}
None => (),
};
let text = utils::get_text_or_empty(&msg).to_lowercase();
match text.find("оффтоп") {
Some(_) => handlers::offtop(&bot, &msg).await?,
None => (),
}
Ok(())
}
pub async fn reply_dispatcher(bot: Bot, msg: Message, reply: Message) -> ResponseResult<()> {
let text = utils::get_text_or_empty(&msg);
handlers::karma(&bot, &msg, &reply, &text).await?;
Ok(())
}
}

View File

@ -8,6 +8,8 @@ use teloxide::{
use crate::commands::{AdminCommand, Command}; use crate::commands::{AdminCommand, Command};
use super::{utils, KarmaTrigger};
pub async fn show_help(bot: Bot, msg: Message) -> ResponseResult<Message> { pub async fn show_help(bot: Bot, msg: Message) -> ResponseResult<Message> {
bot.send_message(msg.chat.id, Command::descriptions().to_string()) bot.send_message(msg.chat.id, Command::descriptions().to_string())
.await .await
@ -67,10 +69,23 @@ pub async fn unwarn(bot: Bot, msg: Message) -> ResponseResult<Message> {
.await .await
} }
pub async fn karma(bot: &Bot, msg: &Message, reply: &Message, change: i8) -> ResponseResult<()> { pub async fn karma(bot: &Bot, msg: &Message, reply: &Message, text: &String) -> ResponseResult<()> {
let triggers = vec![
KarmaTrigger::new("спс", 1),
KarmaTrigger::new("спасибо", 1),
KarmaTrigger::new("+", 1),
KarmaTrigger::new("благодарю", 1),
KarmaTrigger::new("пасиб", 1),
KarmaTrigger::new("-", -1),
KarmaTrigger::new("👍", 1),
KarmaTrigger::new("👎", -1),
];
for trigger in triggers {
match text.to_lowercase().find(&trigger.text) {
Some(_id) => {
let giver = msg.from().unwrap(); let giver = msg.from().unwrap();
let reciever = reply.from().unwrap(); let reciever = reply.from().unwrap();
let change_text = match change { let change_text = match trigger.value {
1 => "повысил", 1 => "повысил",
-1 => "понизил", -1 => "понизил",
_ => "изменил", _ => "изменил",
@ -84,5 +99,18 @@ pub async fn karma(bot: &Bot, msg: &Message, reply: &Message, change: i8) -> Res
bot.send_message(msg.chat.id, text) bot.send_message(msg.chat.id, text)
.parse_mode(MarkdownV2) .parse_mode(MarkdownV2)
.await?; .await?;
return Ok(());
}
None => (),
}
}
Ok(())
}
pub async fn offtop(bot: &Bot, msg: &Message) -> ResponseResult<()> {
bot.send_message(msg.chat.id, "Вот вам ссылка на оффтоп")
.reply_to_message_id(msg.id)
.reply_markup(utils::make_offtop_keyboard())
.await?;
Ok(()) Ok(())
} }

View File

@ -1,7 +1,14 @@
use teloxide::types::Message; use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup, Message};
use url::Url;
pub fn get_text_or_empty(msg: &Message) -> String { pub fn get_text_or_empty(msg: &Message) -> String {
msg.text() msg.text()
.unwrap_or(msg.caption().unwrap_or("")) .unwrap_or(msg.caption().unwrap_or(""))
.to_string() .to_string()
} }
pub fn make_offtop_keyboard() -> InlineKeyboardMarkup {
let link = Url::parse("https://t.me/Godot_Engine_Offtop").unwrap();
let button = InlineKeyboardButton::url("Godot Engine оффтоп чат".to_owned(), link);
return InlineKeyboardMarkup::new(vec![[button]]);
}

View File

@ -5,35 +5,15 @@ use teloxide::prelude::*;
use godette::commands; use godette::commands;
use godette::Godette; use godette::Godette;
use dotenv::dotenv;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
dotenv().ok();
pretty_env_logger::init(); pretty_env_logger::init();
let bot = Godette::new(); let bot = Godette::new();
let handler = Update::filter_message() let handler = bot.create_handler();
// User commands
.branch(
dptree::entry()
.filter_command::<commands::Command>()
.endpoint(Godette::commands_dispatcher),
)
// Admin commands
.branch(
dptree::entry()
.filter_command::<commands::AdminCommand>()
.endpoint(Godette::admin_dispatcher),
)
// Replies
// .branch(Message::filter_reply_to_message().endpoint(Godette::reply_dispatcher))
// Messages
.branch(
dptree::filter(|msg: Message| {
msg.from()
.map(|user| user.id == UserId(60441930))
.unwrap_or_default()
})
.endpoint(Godette::message_dispatcher),
);
Dispatcher::builder(bot.bot, handler) Dispatcher::builder(bot.bot, handler)
.default_handler(|upd| async move { .default_handler(|upd| async move {
log::warn!("Unhandled update: {:?}", upd); log::warn!("Unhandled update: {:?}", upd);