start the refactor
This commit is contained in:
parent
ae79359990
commit
baf7ba2ffb
123
Cargo.lock
generated
123
Cargo.lock
generated
@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
@ -53,6 +53,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.89"
|
||||
@ -412,6 +418,12 @@ dependencies = [
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||
|
||||
[[package]]
|
||||
name = "dptree"
|
||||
version = "0.3.0"
|
||||
@ -555,6 +567,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fragile"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619"
|
||||
|
||||
[[package]]
|
||||
name = "frunk"
|
||||
version = "0.4.3"
|
||||
@ -1125,6 +1143,31 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mini_admin_bot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"curl",
|
||||
"derive_more",
|
||||
"frunk",
|
||||
"frunk_core",
|
||||
"futures",
|
||||
"image",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mockall",
|
||||
"once_cell",
|
||||
"phf",
|
||||
"pretty_env_logger",
|
||||
"sqlite",
|
||||
"teloxide",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"turbojpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@ -1162,6 +1205,32 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockall"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"downcast",
|
||||
"fragile",
|
||||
"mockall_derive",
|
||||
"predicates",
|
||||
"predicates-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockall_derive"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.12"
|
||||
@ -1430,6 +1499,32 @@ dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "3.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"predicates-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates-core"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa"
|
||||
|
||||
[[package]]
|
||||
name = "predicates-tree"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c"
|
||||
dependencies = [
|
||||
"predicates-core",
|
||||
"termtree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_env_logger"
|
||||
version = "0.4.0"
|
||||
@ -2139,28 +2234,10 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test_bot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"curl",
|
||||
"derive_more",
|
||||
"frunk",
|
||||
"frunk_core",
|
||||
"futures",
|
||||
"image",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"once_cell",
|
||||
"phf",
|
||||
"pretty_env_logger",
|
||||
"sqlite",
|
||||
"teloxide",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"turbojpeg",
|
||||
]
|
||||
name = "termtree"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "test_bot"
|
||||
name = "mini_admin_bot"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
@ -9,7 +9,7 @@ teloxide = { version = "0.12", features = ["macros", "auto-send"] }
|
||||
futures = "0.3.5"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.4.0"
|
||||
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
|
||||
tokio = { version = "1.8", features = ["rt-multi-thread", "macros"] }
|
||||
tokio-stream = "0.1.8"
|
||||
derive_more = "0.99.9"
|
||||
frunk = "0.4"
|
||||
@ -24,6 +24,9 @@ turbojpeg = "*"
|
||||
phf = { version = "0.11", features = ["macros"] }
|
||||
curl = "*"
|
||||
|
||||
[dev-dependencies]
|
||||
mockall = "0.13.1"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
|
@ -1,8 +1,8 @@
|
||||
use sqlite::{State, Error};
|
||||
use crate::database;
|
||||
use sqlite::{Error, State};
|
||||
|
||||
pub struct Database {
|
||||
ins_connection: &'static database::DB_CONNECTION,//Mutex<Box<sqlite::Connection>>,
|
||||
ins_connection: &'static database::DB_CONNECTION, //Mutex<Box<sqlite::Connection>>,
|
||||
}
|
||||
|
||||
pub const T_STIKER: i64 = 1;
|
||||
@ -10,8 +10,8 @@ pub const T_GIF: i64 = 2;
|
||||
pub const T_PHOTO: i64 = 3;
|
||||
|
||||
impl<'a> Database {
|
||||
pub fn get_database()->Self{
|
||||
let ret = Self{
|
||||
pub fn get_database() -> Self {
|
||||
let ret = Self {
|
||||
ins_connection: &database::DB_CONNECTION,
|
||||
};
|
||||
ret.create_table();
|
||||
@ -34,8 +34,8 @@ impl<'a> Database {
|
||||
pub fn media_is_banned(&self, stiker_id: &str, media_type: i64) -> bool {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("SELECT id_stiker FROM bmedia WHERE id_stiker = ? and media_type=?")
|
||||
.unwrap();
|
||||
.prepare("SELECT id_stiker FROM bmedia WHERE id_stiker = ? and media_type=?")
|
||||
.unwrap();
|
||||
statement.bind((1, stiker_id)).unwrap();
|
||||
statement.bind((2, media_type)).unwrap();
|
||||
statement.next().unwrap();
|
||||
@ -45,17 +45,17 @@ impl<'a> Database {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_media(&self, stiker_id: &str, group_id: &str, media_type: i64)->bool{
|
||||
pub fn add_media(&self, stiker_id: &str, group_id: &str, media_type: i64) -> bool {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("INSERT INTO bmedia (id_stiker, id_group, media_type) VALUES (?,?,?)")
|
||||
.unwrap();
|
||||
.prepare("INSERT INTO bmedia (id_stiker, id_group, media_type) VALUES (?,?,?)")
|
||||
.unwrap();
|
||||
statement.bind((1, stiker_id)).unwrap();
|
||||
statement.bind((2, group_id)).unwrap();
|
||||
statement.bind((3, media_type)).unwrap();
|
||||
match statement.next(){
|
||||
Ok(_s)=>true,
|
||||
Err(_e)=>false,
|
||||
match statement.next() {
|
||||
Ok(_s) => true,
|
||||
Err(_e) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,45 @@
|
||||
use std::fs;
|
||||
#[cfg(test)]
|
||||
use mockall::{automock, mock, predicate::*};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::LinkedList;
|
||||
use std::fs;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::RwLock;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
const ALLOW_PATH : &str ="/opt/mini_admin_bot/allow_users";
|
||||
const ALLOW_PATH: &str = "/opt/mini_admin_bot/allow_users";
|
||||
#[cfg(not(debug_assertions))]
|
||||
const POLE_PATH : &str ="/opt/mini_admin_bot/allow_pole";
|
||||
const POLE_PATH: &str = "/opt/mini_admin_bot/allow_pole";
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const ALLOW_PATH : &str ="allow_users";
|
||||
const ALLOW_PATH: &str = "allow_users";
|
||||
#[cfg(debug_assertions)]
|
||||
const POLE_PATH : &str ="allow_pole";
|
||||
const POLE_PATH: &str = "allow_pole";
|
||||
|
||||
static mut LIST_IDS: Lazy<Mutex<LinkedList<String>>> = Lazy::new(|| Mutex::new(read_ids(ALLOW_PATH)));
|
||||
static mut LIST_IDS: Lazy<Mutex<LinkedList<String>>> =
|
||||
Lazy::new(|| Mutex::new(read_ids(ALLOW_PATH)));
|
||||
|
||||
static mut LIST_POLE_IDS: Lazy<Mutex<LinkedList<String>>> = Lazy::new(|| Mutex::new(read_ids(POLE_PATH)));
|
||||
static mut LIST_POLE_IDS: Lazy<Mutex<LinkedList<String>>> =
|
||||
Lazy::new(|| Mutex::new(read_ids(POLE_PATH)));
|
||||
|
||||
fn read_ids<'a>(path: &str)-> LinkedList<String> {
|
||||
fn read_ids<'a>(path: &str) -> LinkedList<String> {
|
||||
let content = fs::read_to_string(path).expect("Something went wrong reading the file");
|
||||
content.split('\n').into_iter().map(|item| format!("{}", item)).collect::<LinkedList<String>>()
|
||||
content
|
||||
.split('\n')
|
||||
.into_iter()
|
||||
.map(|item| format!("{}", item))
|
||||
.collect::<LinkedList<String>>()
|
||||
}
|
||||
|
||||
pub struct group_permissions {
|
||||
pub struct GroupPermissions {
|
||||
aproved_groups: RwLock<LinkedList<String>>,
|
||||
party_groups: RwLock<LinkedList<String>>,
|
||||
}
|
||||
|
||||
impl group_permissions {
|
||||
#[cfg_attr(test, automock)]
|
||||
impl GroupPermissions {
|
||||
pub fn new() -> Self {
|
||||
Self{
|
||||
Self {
|
||||
aproved_groups: RwLock::new(read_ids(ALLOW_PATH)),
|
||||
party_groups: RwLock::new(read_ids(POLE_PATH)),
|
||||
}
|
||||
@ -45,22 +54,20 @@ impl group_permissions {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare(id: &String) -> bool{
|
||||
pub fn compare(id: &String) -> bool {
|
||||
let ret: bool;
|
||||
unsafe {
|
||||
ret=LIST_IDS.lock().unwrap().contains(id);
|
||||
log::info!("{}",id);
|
||||
|
||||
ret = LIST_IDS.lock().unwrap().contains(id);
|
||||
log::info!("{}", id);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn compare_pole(id: &String) -> bool{
|
||||
pub fn compare_pole(id: &String) -> bool {
|
||||
let ret: bool;
|
||||
unsafe {
|
||||
ret=LIST_POLE_IDS.lock().unwrap().contains(id);
|
||||
log::info!("{}",id);
|
||||
|
||||
ret = LIST_POLE_IDS.lock().unwrap().contains(id);
|
||||
log::info!("{}", id);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
158
src/lib.rs
Normal file
158
src/lib.rs
Normal file
@ -0,0 +1,158 @@
|
||||
use chrono::Local;
|
||||
use std::sync::Arc;
|
||||
use teloxide::{prelude::*, utils::command::BotCommands};
|
||||
pub mod ban_stiker;
|
||||
pub mod check_permissions;
|
||||
mod database;
|
||||
mod filter_files;
|
||||
mod pole_dialogue;
|
||||
mod rewrite_links;
|
||||
mod spoiler_mangas;
|
||||
mod telegram_utils;
|
||||
|
||||
#[derive(BotCommands, Clone)]
|
||||
#[command(
|
||||
rename_rule = "lowercase",
|
||||
description = "These commands are supported:"
|
||||
)]
|
||||
enum Command {
|
||||
#[command(description = "ban a stiker")]
|
||||
Torquemada,
|
||||
#[command(description = "display this text.")]
|
||||
Help,
|
||||
#[command(description = "list pole points")]
|
||||
Top,
|
||||
#[command(description = "get the server time")]
|
||||
Time,
|
||||
}
|
||||
|
||||
/*#[tokio::main]
|
||||
async fn main() {
|
||||
run().await;
|
||||
}*/
|
||||
|
||||
pub async fn run() {
|
||||
//teloxide::enable_logging!();
|
||||
pretty_env_logger::init();
|
||||
log::info!("Starting bot");
|
||||
let bot = Bot::from_env();
|
||||
let permissions = Arc::new(check_permissions::GroupPermissions::new());
|
||||
let p1 = Arc::clone(&permissions);
|
||||
let p2 = Arc::clone(&permissions);
|
||||
//Command::repl(bot.clone(), answer).await;
|
||||
let handler = Update::filter_message()
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| !p1.compare(&msg.chat.id.to_string())).endpoint(
|
||||
|msg: Message, bot: Bot| async move {
|
||||
if !msg.chat.is_private() {
|
||||
println!("{}", msg.chat.id.0);
|
||||
bot.leave_chat(msg.chat.id).await?;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(|msg: Message| is_channel_user(msg)).endpoint(
|
||||
|msg: Message, bot: Bot| async move {
|
||||
bot.delete_message(msg.chat.id, msg.id).await?;
|
||||
Ok(())
|
||||
},
|
||||
),
|
||||
)
|
||||
.branch(
|
||||
Update::filter_message()
|
||||
.filter_command::<Command>()
|
||||
.endpoint(|msg: Message, bot: Bot, command: Command| answer(bot, msg, command)),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(|msg: Message| is_media(msg.clone()) && ban_stiker::check_media(msg))
|
||||
.endpoint(|msg: Message, bot: Bot| async move {
|
||||
bot.delete_message(msg.chat.id, msg.id).await?;
|
||||
Ok(())
|
||||
}),
|
||||
)
|
||||
/*
|
||||
Now is useless because the group doesn't make any spoiler
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| {
|
||||
(is_photo(msg.clone()) && p2.compar_party(&msg.chat.id.to_string()))
|
||||
})
|
||||
.endpoint(|msg: Message, bot: Bot| spoiler_mangas::check_image(msg, bot)),
|
||||
)*/
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| filter_files::analyce_name::check_file(msg.clone()))
|
||||
.endpoint(|msg: Message, bot: Bot| filter_files::action::take_actions(msg, bot)),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| {
|
||||
rewrite_links::check_contain_links::contain_links(msg.clone())
|
||||
})
|
||||
.endpoint(|msg: Message, bot: Bot| {
|
||||
rewrite_links::check_contain_links::fix_links(msg, bot)
|
||||
}),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| permissions.compar_party(&msg.chat.id.to_string()))
|
||||
.endpoint(|msg: Message, bot: Bot| pole_dialogue::exe_pole(msg, bot)),
|
||||
);
|
||||
Dispatcher::builder(bot, handler).build().dispatch().await;
|
||||
}
|
||||
|
||||
async fn answer(bot: Bot, msg: Message, command: Command) -> anyhow::Result<()> {
|
||||
match command {
|
||||
Command::Torquemada => match ban_stiker::ban_media(msg.clone(), bot.clone()).await {
|
||||
Ok(_o) => {
|
||||
bot.send_message(msg.chat.id, "Otro fichero que se va a la hoguera")
|
||||
.await?
|
||||
}
|
||||
Err(e) => bot.send_message(msg.chat.id, e.to_string()).await?,
|
||||
},
|
||||
Command::Help => {
|
||||
bot.send_message(msg.chat.id, Command::descriptions().to_string())
|
||||
.await?
|
||||
}
|
||||
Command::Top => pole_dialogue::get_top(msg, bot).await?,
|
||||
Command::Time => {
|
||||
bot.send_message(
|
||||
msg.chat.id,
|
||||
Local::now().format("%Y-%m-%d:%H:%M:%S").to_string(),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_media(msg: Message) -> bool {
|
||||
is_stiker(msg.clone()) || is_gif(msg.clone()) || is_photo(msg.clone())
|
||||
}
|
||||
|
||||
fn is_stiker(msg: Message) -> bool {
|
||||
match msg.sticker() {
|
||||
Some(s) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_gif(msg: Message) -> bool {
|
||||
match msg.animation() {
|
||||
Some(s) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_photo(msg: Message) -> bool {
|
||||
match msg.photo() {
|
||||
Some(s) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_channel_user(msg: Message) -> bool {
|
||||
match msg.from() {
|
||||
Some(u) => u.is_channel(),
|
||||
None => false,
|
||||
}
|
||||
}
|
156
src/main.rs
156
src/main.rs
@ -1,158 +1,4 @@
|
||||
use chrono::Local;
|
||||
use std::sync::Arc;
|
||||
use teloxide::{prelude::*, utils::command::BotCommands};
|
||||
mod ban_stiker;
|
||||
mod check_permissions;
|
||||
mod database;
|
||||
mod filter_files;
|
||||
mod pole_dialogue;
|
||||
mod rewrite_links;
|
||||
mod spoiler_mangas;
|
||||
mod telegram_utils;
|
||||
|
||||
#[derive(BotCommands, Clone)]
|
||||
#[command(
|
||||
rename_rule = "lowercase",
|
||||
description = "These commands are supported:"
|
||||
)]
|
||||
enum Command {
|
||||
#[command(description = "ban a stiker")]
|
||||
Torquemada,
|
||||
#[command(description = "display this text.")]
|
||||
Help,
|
||||
#[command(description = "list pole points")]
|
||||
Top,
|
||||
#[command(description = "get the server time")]
|
||||
Time,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
run().await;
|
||||
}
|
||||
|
||||
async fn run() {
|
||||
//teloxide::enable_logging!();
|
||||
pretty_env_logger::init();
|
||||
log::info!("Starting bot");
|
||||
let bot = Bot::from_env();
|
||||
let permissions = Arc::new(check_permissions::group_permissions::new());
|
||||
let p1 = Arc::clone(&permissions);
|
||||
let p2 = Arc::clone(&permissions);
|
||||
//Command::repl(bot.clone(), answer).await;
|
||||
let handler = Update::filter_message()
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| !p1.compare(&msg.chat.id.to_string())).endpoint(
|
||||
|msg: Message, bot: Bot| async move {
|
||||
if !msg.chat.is_private() {
|
||||
println!("{}", msg.chat.id.0);
|
||||
bot.leave_chat(msg.chat.id).await?;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(|msg: Message| is_channel_user(msg)).endpoint(
|
||||
|msg: Message, bot: Bot| async move {
|
||||
bot.delete_message(msg.chat.id, msg.id).await?;
|
||||
Ok(())
|
||||
},
|
||||
),
|
||||
)
|
||||
.branch(
|
||||
Update::filter_message()
|
||||
.filter_command::<Command>()
|
||||
.endpoint(|msg: Message, bot: Bot, command: Command| answer(bot, msg, command)),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(|msg: Message| is_media(msg.clone()) && ban_stiker::check_media(msg))
|
||||
.endpoint(|msg: Message, bot: Bot| async move {
|
||||
bot.delete_message(msg.chat.id, msg.id).await?;
|
||||
Ok(())
|
||||
}),
|
||||
)
|
||||
/*
|
||||
Now is useless because the group doesn't make any spoiler
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| {
|
||||
(is_photo(msg.clone()) && p2.compar_party(&msg.chat.id.to_string()))
|
||||
})
|
||||
.endpoint(|msg: Message, bot: Bot| spoiler_mangas::check_image(msg, bot)),
|
||||
)*/
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| filter_files::analyce_name::check_file(msg.clone()))
|
||||
.endpoint(|msg: Message, bot: Bot| filter_files::action::take_actions(msg, bot)),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| {
|
||||
rewrite_links::check_contain_links::contain_links(msg.clone())
|
||||
})
|
||||
.endpoint(|msg: Message, bot: Bot| {
|
||||
rewrite_links::check_contain_links::fix_links(msg, bot)
|
||||
}),
|
||||
)
|
||||
.branch(
|
||||
dptree::filter(move |msg: Message| permissions.compar_party(&msg.chat.id.to_string()))
|
||||
.endpoint(|msg: Message, bot: Bot| pole_dialogue::exe_pole(msg, bot)),
|
||||
);
|
||||
Dispatcher::builder(bot, handler).build().dispatch().await;
|
||||
}
|
||||
|
||||
async fn answer(bot: Bot, msg: Message, command: Command) -> anyhow::Result<()> {
|
||||
match command {
|
||||
Command::Torquemada => match ban_stiker::ban_media(msg.clone(), bot.clone()).await {
|
||||
Ok(_o) => {
|
||||
bot.send_message(msg.chat.id, "Otro fichero que se va a la hoguera")
|
||||
.await?
|
||||
}
|
||||
Err(e) => bot.send_message(msg.chat.id, e.to_string()).await?,
|
||||
},
|
||||
Command::Help => {
|
||||
bot.send_message(msg.chat.id, Command::descriptions().to_string())
|
||||
.await?
|
||||
}
|
||||
Command::Top => pole_dialogue::get_top(msg, bot).await?,
|
||||
Command::Time => {
|
||||
bot.send_message(
|
||||
msg.chat.id,
|
||||
Local::now().format("%Y-%m-%d:%H:%M:%S").to_string(),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_media(msg: Message) -> bool {
|
||||
is_stiker(msg.clone()) || is_gif(msg.clone()) || is_photo(msg.clone())
|
||||
}
|
||||
|
||||
fn is_stiker(msg: Message) -> bool {
|
||||
match msg.sticker() {
|
||||
Some(s) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_gif(msg: Message) -> bool {
|
||||
match msg.animation() {
|
||||
Some(s) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_photo(msg: Message) -> bool {
|
||||
match msg.photo() {
|
||||
Some(s) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_channel_user(msg: Message) -> bool {
|
||||
match msg.from() {
|
||||
Some(u) => u.is_channel(),
|
||||
None => false,
|
||||
}
|
||||
mini_admin_bot::run().await;
|
||||
}
|
||||
|
@ -1,38 +1,40 @@
|
||||
use sqlite::{State, Error};
|
||||
use crate::database;
|
||||
use sqlite::{Error, State};
|
||||
|
||||
#[cfg(test)]
|
||||
fn drop_all(con: &sqlite::Connection) -> bool {
|
||||
let mut result: bool;
|
||||
match con
|
||||
.execute(
|
||||
"
|
||||
match con.execute(
|
||||
"
|
||||
DROP TABLE IF EXISTS poles;
|
||||
",
|
||||
)
|
||||
{
|
||||
Ok(_a) => result = true,
|
||||
Err(e) => {log::error!("error drop pole {}",e);result = false},
|
||||
};
|
||||
) {
|
||||
Ok(_a) => result = true,
|
||||
Err(e) => {
|
||||
log::error!("error drop pole {}", e);
|
||||
result = false
|
||||
}
|
||||
};
|
||||
|
||||
match con
|
||||
.execute(
|
||||
"
|
||||
match con.execute(
|
||||
"
|
||||
DROP TABLE IF EXISTS last;
|
||||
",
|
||||
)
|
||||
{
|
||||
Ok(_a) => result && true,
|
||||
Err(e) => {log::error!("error drop last {}",e);result && false},
|
||||
) {
|
||||
Ok(_a) => result && true,
|
||||
Err(e) => {
|
||||
log::error!("error drop last {}", e);
|
||||
result && false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_databases(con: &sqlite::Connection) -> bool {
|
||||
return create_poles_database(con) && create_last_database(con)
|
||||
}
|
||||
return create_poles_database(con) && create_last_database(con);
|
||||
}
|
||||
|
||||
fn create_poles_database(con: &sqlite::Connection) -> bool {
|
||||
match con
|
||||
match con
|
||||
.execute(
|
||||
"
|
||||
CREATE TABLE IF NOT EXISTS poles (npole INTEGER, user TEXT, user_name TEXT, id_group TEXT, id INTEGER PRIMARY KEY AUTOINCREMENT);
|
||||
@ -42,10 +44,10 @@ fn create_poles_database(con: &sqlite::Connection) -> bool {
|
||||
Ok(_a) => return true,
|
||||
Err(e) => {log::error!("error pole {}",e);return false},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_last_database(con: &sqlite::Connection) -> bool {
|
||||
match con
|
||||
match con
|
||||
.execute(
|
||||
"
|
||||
CREATE TABLE IF NOT EXISTS last (date TEXT, id_group TEXT, user TEXT, points INTEGER, id INTEGER PRIMARY KEY AUTOINCREMENT);
|
||||
@ -55,18 +57,16 @@ fn create_last_database(con: &sqlite::Connection) -> bool {
|
||||
Ok(_a) => return true,
|
||||
Err(e) => {log::error!("error last {}",e);return false},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub struct DatabasePole {
|
||||
ins_connection: &'static database::DB_CONNECTION,//Mutex<Box<sqlite::Connection>>,
|
||||
}
|
||||
|
||||
impl<'a> DatabasePole{
|
||||
pub struct DatabasePole {
|
||||
ins_connection: &'static database::DB_CONNECTION, //Mutex<Box<sqlite::Connection>>,
|
||||
}
|
||||
|
||||
impl<'a> DatabasePole {
|
||||
#[cfg(not(test))]
|
||||
pub fn get_database()->Self{
|
||||
let ret = Self{
|
||||
pub fn get_database() -> Self {
|
||||
let ret = Self {
|
||||
ins_connection: &database::DB_CONNECTION,
|
||||
};
|
||||
let raw = &**ret.ins_connection.lock().unwrap();
|
||||
@ -76,9 +76,9 @@ impl<'a> DatabasePole{
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn get_database()->Self{
|
||||
let ret = Self{
|
||||
ins_connection: &DB_CONNECTION,
|
||||
pub fn get_database() -> Self {
|
||||
let ret = Self {
|
||||
ins_connection: &database::DB_CONNECTION,
|
||||
};
|
||||
let raw = &**ret.ins_connection.lock().unwrap();
|
||||
drop_all(raw);
|
||||
@ -87,50 +87,60 @@ impl<'a> DatabasePole{
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn last_pole(&self, group_id : &str) -> Result<String, Error>{
|
||||
pub fn last_pole(&self, group_id: &str) -> Result<String, Error> {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("SELECT date FROM last WHERE id_group = ? order by date desc")
|
||||
.unwrap();
|
||||
.prepare("SELECT date FROM last WHERE id_group = ? order by date desc")
|
||||
.unwrap();
|
||||
statement.bind((1, group_id)).unwrap();
|
||||
statement.next().unwrap();
|
||||
statement.read::<String, _>(0)
|
||||
}
|
||||
|
||||
pub fn write_points(&self, group_id : &str, user_id: &str, user_name: &str, date: &str, points: i64){
|
||||
pub fn write_points(
|
||||
&self,
|
||||
group_id: &str,
|
||||
user_id: &str,
|
||||
user_name: &str,
|
||||
date: &str,
|
||||
points: i64,
|
||||
) {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("SELECT npole FROM poles WHERE user = ? AND id_group = ?")
|
||||
.unwrap();
|
||||
.prepare("SELECT npole FROM poles WHERE user = ? AND id_group = ?")
|
||||
.unwrap();
|
||||
statement.bind((1, user_id)).unwrap();
|
||||
statement.bind((2, group_id)).unwrap();
|
||||
|
||||
match statement.next().unwrap() {
|
||||
State::Row => {
|
||||
let mut statement2 = builder
|
||||
.prepare("UPDATE poles SET npole=? WHERE user=? AND id_group=?")
|
||||
.unwrap();
|
||||
statement2.bind((1, statement.read::<i64, _>(0).unwrap()+points)).unwrap();
|
||||
.prepare("UPDATE poles SET npole=? WHERE user=? AND id_group=?")
|
||||
.unwrap();
|
||||
statement2
|
||||
.bind((1, statement.read::<i64, _>(0).unwrap() + points))
|
||||
.unwrap();
|
||||
statement2.bind((2, user_id)).unwrap();
|
||||
statement2.bind((3, group_id)).unwrap();
|
||||
statement2.next().unwrap();
|
||||
}
|
||||
State::Done => {
|
||||
let mut statement2 = builder
|
||||
.prepare("INSERT INTO poles (npole, user, user_name, id_group) VALUES (?,?,?,?)")
|
||||
.unwrap();
|
||||
.prepare(
|
||||
"INSERT INTO poles (npole, user, user_name, id_group) VALUES (?,?,?,?)",
|
||||
)
|
||||
.unwrap();
|
||||
statement2.bind((1, points)).unwrap();
|
||||
statement2.bind((2, user_id)).unwrap();
|
||||
statement2.bind((3, user_name)).unwrap();
|
||||
statement2.bind((4, group_id)).unwrap();
|
||||
statement2.next().unwrap();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let mut statement3 = builder
|
||||
.prepare("INSERT INTO last (date, id_group, user, points) VALUES (?,?,?,?)")
|
||||
.unwrap();
|
||||
.prepare("INSERT INTO last (date, id_group, user, points) VALUES (?,?,?,?)")
|
||||
.unwrap();
|
||||
statement3.bind((1, date)).unwrap();
|
||||
statement3.bind((2, group_id)).unwrap();
|
||||
statement3.bind((3, user_id)).unwrap();
|
||||
@ -141,11 +151,11 @@ impl<'a> DatabasePole{
|
||||
//}
|
||||
}
|
||||
|
||||
pub fn check_user_pole(&self, group_id : &str, user_id: &str, date: &str) -> i64{
|
||||
pub fn check_user_pole(&self, group_id: &str, user_id: &str, date: &str) -> i64 {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("SELECT points FROM last WHERE id_group = ? AND user = ? AND date = :date")
|
||||
.unwrap();
|
||||
.prepare("SELECT points FROM last WHERE id_group = ? AND user = ? AND date = :date")
|
||||
.unwrap();
|
||||
statement.bind((1, group_id)).unwrap();
|
||||
statement.bind((2, user_id)).unwrap();
|
||||
statement.bind((3, date)).unwrap();
|
||||
@ -155,11 +165,11 @@ impl<'a> DatabasePole{
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_group_points(&self, group_id : &str, date: &str) -> i64{
|
||||
pub fn check_group_points(&self, group_id: &str, date: &str) -> i64 {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("SELECT points FROM last WHERE id_group = ? AND date = ?")
|
||||
.unwrap();
|
||||
.prepare("SELECT points FROM last WHERE id_group = ? AND date = ?")
|
||||
.unwrap();
|
||||
statement.bind((1, group_id)).unwrap();
|
||||
statement.bind((2, date)).unwrap();
|
||||
let mut ret = 0;
|
||||
@ -169,27 +179,29 @@ impl<'a> DatabasePole{
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn get_top_users(&self, group_id : &str) -> Vec<(i64,String)>{
|
||||
pub fn get_top_users(&self, group_id: &str) -> Vec<(i64, String)> {
|
||||
let builder = self.ins_connection.lock().unwrap();
|
||||
let mut statement = builder
|
||||
.prepare("SELECT npole, user_name FROM poles where id_group=? order by npole desc limit 10")
|
||||
.unwrap();
|
||||
.prepare(
|
||||
"SELECT npole, user_name FROM poles where id_group=? order by npole desc limit 10",
|
||||
)
|
||||
.unwrap();
|
||||
statement.bind((1, group_id)).unwrap();
|
||||
let mut ret = Vec::new();
|
||||
for i in 1 .. 10 {
|
||||
for i in 1..10 {
|
||||
match statement.next().unwrap() {
|
||||
State::Row => ret.push((
|
||||
statement.read::<i64, _>(0).unwrap(),
|
||||
statement.read::<String, _>(1).unwrap()
|
||||
)),
|
||||
statement.read::<i64, _>(0).unwrap(),
|
||||
statement.read::<String, _>(1).unwrap(),
|
||||
)),
|
||||
State::Done => return ret,
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn write_points(){
|
||||
@ -207,3 +219,4 @@ fn last_pole(){
|
||||
data.write_points(group_id, "000", "2020-01-02", 3);
|
||||
assert_eq!("2020-01-02", data.last_pole(group_id).unwrap());
|
||||
}
|
||||
*/
|
||||
|
@ -1,17 +1,20 @@
|
||||
use teloxide::prelude::*;
|
||||
use chrono::Local;
|
||||
use std::ops::Add;
|
||||
use std::cmp::Ordering::Equal;
|
||||
use std::str;
|
||||
use crate::telegram_utils::*;
|
||||
use chrono::Local;
|
||||
use std::cmp::Ordering::Equal;
|
||||
use std::ops::Add;
|
||||
use std::str;
|
||||
use teloxide::prelude::*;
|
||||
mod database;
|
||||
|
||||
fn change_day(last_day: &str) -> bool{
|
||||
fn change_day(last_day: &str) -> bool {
|
||||
last_day.cmp(&get_actual_day()) != Equal
|
||||
}
|
||||
|
||||
fn get_actual_day() -> String {
|
||||
Local::now().add(chrono::TimeDelta::hours(2)).format("%Y-%m-%d").to_string()
|
||||
Local::now()
|
||||
.add(chrono::TimeDelta::hours(2))
|
||||
.format("%Y-%m-%d")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn check_pole(group_id: &str) -> bool {
|
||||
@ -23,26 +26,46 @@ fn check_pole(group_id: &str) -> bool {
|
||||
change_day(&slast_pole)
|
||||
}
|
||||
|
||||
fn do_pole(group_id: &str, user_id: &str, user_name: &str){
|
||||
fn do_pole(group_id: &str, user_id: &str, user_name: &str) {
|
||||
let data: database::DatabasePole = database::DatabasePole::get_database();
|
||||
data.write_points(group_id, user_id, user_name, &get_actual_day(),Rewards::POLE as i64);
|
||||
data.write_points(
|
||||
group_id,
|
||||
user_id,
|
||||
user_name,
|
||||
&get_actual_day(),
|
||||
Rewards::POLE as i64,
|
||||
);
|
||||
}
|
||||
|
||||
fn do_plata(group_id: &str, user_id: &str, user_name: &str){
|
||||
fn do_plata(group_id: &str, user_id: &str, user_name: &str) {
|
||||
let data: database::DatabasePole = database::DatabasePole::get_database();
|
||||
data.write_points(group_id, user_id, user_name, &get_actual_day(),Rewards::PLATA as i64);
|
||||
data.write_points(
|
||||
group_id,
|
||||
user_id,
|
||||
user_name,
|
||||
&get_actual_day(),
|
||||
Rewards::PLATA as i64,
|
||||
);
|
||||
}
|
||||
|
||||
fn do_fail(group_id: &str, user_id: &str, user_name: &str){
|
||||
fn do_fail(group_id: &str, user_id: &str, user_name: &str) {
|
||||
let data: database::DatabasePole = database::DatabasePole::get_database();
|
||||
data.write_points(group_id, user_id, user_name, &get_actual_day(),Rewards::FAIL as i64);
|
||||
data.write_points(
|
||||
group_id,
|
||||
user_id,
|
||||
user_name,
|
||||
&get_actual_day(),
|
||||
Rewards::FAIL as i64,
|
||||
);
|
||||
}
|
||||
|
||||
fn check_user_points(msg: &teloxide::prelude::Message, rw: Rewards) -> bool{
|
||||
fn check_user_points(msg: &teloxide::prelude::Message, rw: Rewards) -> bool {
|
||||
let data: database::DatabasePole = database::DatabasePole::get_database();
|
||||
let ret = data.check_user_pole(&msg.chat.id.to_string(),
|
||||
let ret = data.check_user_pole(
|
||||
&msg.chat.id.to_string(),
|
||||
&msg.from().unwrap().id.to_string(),
|
||||
&get_actual_day());
|
||||
&get_actual_day(),
|
||||
);
|
||||
check_group_points(msg, rw) && (ret == 0)
|
||||
}
|
||||
|
||||
@ -54,44 +77,52 @@ enum Rewards {
|
||||
|
||||
fn check_group_points(msg: &teloxide::prelude::Message, rw: Rewards) -> bool {
|
||||
let data: database::DatabasePole = database::DatabasePole::get_database();
|
||||
let ret = data.check_group_points(&msg.chat.id.to_string(),
|
||||
&get_actual_day());
|
||||
let ret = data.check_group_points(&msg.chat.id.to_string(), &get_actual_day());
|
||||
match rw {
|
||||
Rewards::PLATA => ret == (Rewards::POLE as i64),
|
||||
Rewards::FAIL => ret == (Rewards::PLATA as i64 + Rewards::POLE as i64),
|
||||
_=> false,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn exe_pole(
|
||||
msg: Message,
|
||||
bot: Bot,
|
||||
) -> anyhow::Result<()>{
|
||||
let text_lower = match msg.text(){
|
||||
pub async fn exe_pole(msg: Message, bot: Bot) -> anyhow::Result<()> {
|
||||
let text_lower = match msg.text() {
|
||||
Some(t) => t.to_lowercase(),
|
||||
None => return Ok(()),
|
||||
};
|
||||
if pole_conditions(msg.clone()){
|
||||
do_pole(&msg.chat.id.to_string(),
|
||||
if pole_conditions(msg.clone()) {
|
||||
do_pole(
|
||||
&msg.chat.id.to_string(),
|
||||
&*msg.from().unwrap().id.to_string(),
|
||||
&get_alias(&msg));
|
||||
bot.send_message(msg.chat.id, format!("{} ha hecho la pole",get_alias(&msg))).await?;
|
||||
&get_alias(&msg),
|
||||
);
|
||||
bot.send_message(msg.chat.id, format!("{} ha hecho la pole", get_alias(&msg)))
|
||||
.await?;
|
||||
} else if plata_conditions(msg.clone()) {
|
||||
do_plata(&msg.chat.id.to_string(),
|
||||
&*msg.from().unwrap().id.to_string(),
|
||||
&get_alias(&msg));
|
||||
bot.send_message(msg.chat.id, format!("{} ha hecho la plata", get_alias(&msg))).await?;
|
||||
do_plata(
|
||||
&msg.chat.id.to_string(),
|
||||
&*msg.from().unwrap().id.to_string(),
|
||||
&get_alias(&msg),
|
||||
);
|
||||
bot.send_message(
|
||||
msg.chat.id,
|
||||
format!("{} ha hecho la plata", get_alias(&msg)),
|
||||
)
|
||||
.await?;
|
||||
} else if bronce_conditions(msg.clone()) {
|
||||
do_fail(&msg.chat.id.to_string(),
|
||||
&*msg.from().unwrap().id.to_string(),
|
||||
&get_alias(&msg));
|
||||
bot.send_message(msg.chat.id, format!("{} buen fail", get_alias(&msg))).await?;
|
||||
do_fail(
|
||||
&msg.chat.id.to_string(),
|
||||
&*msg.from().unwrap().id.to_string(),
|
||||
&get_alias(&msg),
|
||||
);
|
||||
bot.send_message(msg.chat.id, format!("{} buen fail", get_alias(&msg)))
|
||||
.await?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn pole_conditions(msg: Message) -> bool{
|
||||
let text_lower = match msg.text(){
|
||||
fn pole_conditions(msg: Message) -> bool {
|
||||
let text_lower = match msg.text() {
|
||||
Some(t) => t.to_lowercase(),
|
||||
None => return false,
|
||||
};
|
||||
@ -103,21 +134,21 @@ fn pole_conditions(msg: Message) -> bool{
|
||||
false
|
||||
}
|
||||
|
||||
fn plata_conditions(msg: Message) -> bool{
|
||||
let text_lower = match msg.text(){
|
||||
fn plata_conditions(msg: Message) -> bool {
|
||||
let text_lower = match msg.text() {
|
||||
Some(t) => t.to_lowercase(),
|
||||
None => return false,
|
||||
};
|
||||
if text_lower.contains("plata") || text_lower.contains("subpole") {
|
||||
if check_user_points(&msg, Rewards::PLATA) {
|
||||
if check_user_points(&msg, Rewards::PLATA) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn bronce_conditions(msg: Message) -> bool{
|
||||
let text_lower = match msg.text(){
|
||||
fn bronce_conditions(msg: Message) -> bool {
|
||||
let text_lower = match msg.text() {
|
||||
Some(t) => t.to_lowercase(),
|
||||
None => return false,
|
||||
};
|
||||
@ -129,7 +160,7 @@ fn bronce_conditions(msg: Message) -> bool{
|
||||
false
|
||||
}
|
||||
|
||||
pub fn get_top(msg: Message, bot: Bot) -> <Bot as Requester>::SendMessage{
|
||||
pub fn get_top(msg: Message, bot: Bot) -> <Bot as Requester>::SendMessage {
|
||||
let db = database::DatabasePole::get_database();
|
||||
let top = db.get_top_users(&msg.chat.id.0.to_string());
|
||||
let mut repl = String::new();
|
||||
@ -139,11 +170,10 @@ pub fn get_top(msg: Message, bot: Bot) -> <Bot as Requester>::SendMessage{
|
||||
bot.send_message(msg.chat.id, format!("{}", repl))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/*#[cfg(test)]
|
||||
#[test]
|
||||
fn compare_dates(){
|
||||
assert_eq!(false, change_day("2020-01-01"));
|
||||
assert_eq!(true, change_day("3025-01-01"));
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
6
tests/ban_stiker.rs
Normal file
6
tests/ban_stiker.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use mini_admin_bot::ban_stiker;
|
||||
|
||||
#[test]
|
||||
pub fn db_media_is_banned() {
|
||||
assert_eq!(0, 0);
|
||||
}
|
12
tests/permissions.rs
Normal file
12
tests/permissions.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use mini_admin_bot::check_permissions;
|
||||
use mockall::{automock, mock, predicate::*};
|
||||
|
||||
#[test]
|
||||
fn test_permissions() {
|
||||
let mut mock = check_permissions::MockGroupPermissions::new();
|
||||
mock.expect_compare()
|
||||
.with("user_id")
|
||||
.times(1)
|
||||
.returning(true);
|
||||
assert_eq!(true, mock.compare("user_id"));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user