clean warnings and add tests
This commit is contained in:
		
							parent
							
								
									baf7ba2ffb
								
							
						
					
					
						commit
						91f6c5f9f9
					
				| @ -1,6 +1,4 @@ | |||||||
| use crate::database; | use crate::database; | ||||||
| use sqlite::{Error, State}; |  | ||||||
| 
 |  | ||||||
| pub struct Database { | pub struct Database { | ||||||
|     ins_connection: &'static database::DB_CONNECTION, //Mutex<Box<sqlite::Connection>>,
 |     ins_connection: &'static database::DB_CONNECTION, //Mutex<Box<sqlite::Connection>>,
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,9 +4,7 @@ use std::error::Error; | |||||||
| use std::fmt; | use std::fmt; | ||||||
| 
 | 
 | ||||||
| pub fn check_media(msg: Message) -> bool { | pub fn check_media(msg: Message) -> bool { | ||||||
|     check_gif(msg.clone()) || |     check_gif(msg.clone()) || check_stiker(msg.clone()) || check_photo(msg.clone()) | ||||||
|     check_stiker(msg.clone()) || |  | ||||||
|     check_photo(msg.clone()) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn check_stiker(msg: Message) -> bool { | pub fn check_stiker(msg: Message) -> bool { | ||||||
| @ -15,7 +13,7 @@ pub fn check_stiker(msg: Message) -> bool { | |||||||
|         None => return false, |         None => return false, | ||||||
|     }; |     }; | ||||||
|     let db = database::Database::get_database(); |     let db = database::Database::get_database(); | ||||||
|     db.media_is_banned(stiker.unique_id.as_str(),database::T_STIKER) |     db.media_is_banned(stiker.unique_id.as_str(), database::T_STIKER) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn check_gif(msg: Message) -> bool { | pub fn check_gif(msg: Message) -> bool { | ||||||
| @ -24,7 +22,7 @@ pub fn check_gif(msg: Message) -> bool { | |||||||
|         None => return false, |         None => return false, | ||||||
|     }; |     }; | ||||||
|     let db = database::Database::get_database(); |     let db = database::Database::get_database(); | ||||||
|     db.media_is_banned(gif.unique_id.as_str(),database::T_GIF) |     db.media_is_banned(gif.unique_id.as_str(), database::T_GIF) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn check_photo(msg: Message) -> bool { | pub fn check_photo(msg: Message) -> bool { | ||||||
| @ -32,30 +30,27 @@ pub fn check_photo(msg: Message) -> bool { | |||||||
|         Some(s) => { |         Some(s) => { | ||||||
|             let db = database::Database::get_database(); |             let db = database::Database::get_database(); | ||||||
|             for p in s { |             for p in s { | ||||||
|                 if db.media_is_banned(p.file.unique_id.as_str(),database::T_PHOTO) { |                 if db.media_is_banned(p.file.unique_id.as_str(), database::T_PHOTO) { | ||||||
|                     return true; |                     return true; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             false |             false | ||||||
|         }, |         } | ||||||
|         None => false, |         None => false, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub async fn ban_media( | pub async fn ban_media(msg: Message, bot: Bot) -> anyhow::Result<()> { | ||||||
|     msg: Message, |  | ||||||
|     bot: Bot, |  | ||||||
| ) -> anyhow::Result<()>{ |  | ||||||
|     if !is_admin(msg.clone(), bot).await { |     if !is_admin(msg.clone(), bot).await { | ||||||
|         return get_error("No tienes permiso para hacer esto"); |         return get_error("No tienes permiso para hacer esto"); | ||||||
|     } |     } | ||||||
|     match msg.reply_to_message() { |     match msg.reply_to_message() { | ||||||
|         Some(s) => { |         Some(s) => { | ||||||
|             insert_ban_stiker((*s).clone()); |             _ = insert_ban_stiker((*s).clone()); | ||||||
|             insert_ban_gif((*s).clone()); |             _ = insert_ban_gif((*s).clone()); | ||||||
|             insert_ban_photo((*s).clone()); |             _ = insert_ban_photo((*s).clone()); | ||||||
|             Ok(()) |             Ok(()) | ||||||
|         }, |         } | ||||||
|         None => get_error("No has seleccionado nada"), |         None => get_error("No has seleccionado nada"), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -64,15 +59,15 @@ fn insert_ban_stiker(msg: Message) -> anyhow::Result<()> { | |||||||
|     match msg.sticker() { |     match msg.sticker() { | ||||||
|         Some(s) => { |         Some(s) => { | ||||||
|             let db = database::Database::get_database(); |             let db = database::Database::get_database(); | ||||||
|             match db.add_media(s.file.unique_id.as_str(), |             match db.add_media( | ||||||
|                                 msg.chat.id.to_string().as_str(), |                 s.file.unique_id.as_str(), | ||||||
|                                 database::T_STIKER) |                 msg.chat.id.to_string().as_str(), | ||||||
|                 { |                 database::T_STIKER, | ||||||
|                     true => Ok(()), |             ) { | ||||||
|                     false => get_error("Stiker ya quemado"), |                 true => Ok(()), | ||||||
|                 } |                 false => get_error("Stiker ya quemado"), | ||||||
| 
 |             } | ||||||
|         }, |         } | ||||||
|         None => Ok(()), |         None => Ok(()), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -81,15 +76,15 @@ fn insert_ban_gif(msg: Message) -> anyhow::Result<()> { | |||||||
|     match msg.animation() { |     match msg.animation() { | ||||||
|         Some(s) => { |         Some(s) => { | ||||||
|             let db = database::Database::get_database(); |             let db = database::Database::get_database(); | ||||||
|             match db.add_media(s.file.unique_id.as_str(), |             match db.add_media( | ||||||
|                                 msg.chat.id.to_string().as_str(), |                 s.file.unique_id.as_str(), | ||||||
|                                 database::T_GIF) |                 msg.chat.id.to_string().as_str(), | ||||||
|                 { |                 database::T_GIF, | ||||||
|                     true => Ok(()), |             ) { | ||||||
|                     false => get_error("Gif ya quemado"), |                 true => Ok(()), | ||||||
|                 } |                 false => get_error("Gif ya quemado"), | ||||||
| 
 |             } | ||||||
|         }, |         } | ||||||
|         None => Ok(()), |         None => Ok(()), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -98,23 +93,28 @@ fn insert_ban_photo(msg: Message) -> anyhow::Result<()> { | |||||||
|     match msg.photo() { |     match msg.photo() { | ||||||
|         Some(s) => { |         Some(s) => { | ||||||
|             let db = database::Database::get_database(); |             let db = database::Database::get_database(); | ||||||
|             for p in s{ |             for p in s { | ||||||
|                 match db.add_media(p.file.unique_id.as_str(), |                 match db.add_media( | ||||||
|                                 msg.chat.id.to_string().as_str(), |                     p.file.unique_id.as_str(), | ||||||
|                                 database::T_PHOTO) |                     msg.chat.id.to_string().as_str(), | ||||||
|                 { |                     database::T_PHOTO, | ||||||
|                     true => {}, |                 ) { | ||||||
|  |                     true => {} | ||||||
|                     false => return get_error("Foto ya quemado"), |                     false => return get_error("Foto ya quemado"), | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }, |         } | ||||||
|         None => {}, |         None => {} | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async fn is_admin(msg: Message, bot: Bot)->bool{ | async fn is_admin(msg: Message, bot: Bot) -> bool { | ||||||
|     match bot.get_chat_member(msg.chat.id, msg.from().unwrap().id).send().await { |     match bot | ||||||
|  |         .get_chat_member(msg.chat.id, msg.from().unwrap().id) | ||||||
|  |         .send() | ||||||
|  |         .await | ||||||
|  |     { | ||||||
|         Ok(k) => k.kind.is_privileged(), |         Ok(k) => k.kind.is_privileged(), | ||||||
|         Err(_e) => false, |         Err(_e) => false, | ||||||
|     } |     } | ||||||
| @ -133,7 +133,8 @@ impl fmt::Display for ErrorBanStiker { | |||||||
| 
 | 
 | ||||||
| impl Error for ErrorBanStiker {} | impl Error for ErrorBanStiker {} | ||||||
| 
 | 
 | ||||||
| fn get_error(msg: &str)-> anyhow::Result<()> { | fn get_error(msg: &str) -> anyhow::Result<()> { | ||||||
|     Err(anyhow::Error::new(ErrorBanStiker{message: String::from(msg),})) |     Err(anyhow::Error::new(ErrorBanStiker { | ||||||
| } 
 |         message: String::from(msg), | ||||||
| 
 |     })) | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,9 +1,5 @@ | |||||||
| #[cfg(test)] |  | ||||||
| use mockall::{automock, mock, predicate::*}; |  | ||||||
| use once_cell::sync::Lazy; |  | ||||||
| use std::collections::LinkedList; | use std::collections::LinkedList; | ||||||
| use std::fs; | use std::fs; | ||||||
| use std::sync::Mutex; |  | ||||||
| use std::sync::RwLock; | use std::sync::RwLock; | ||||||
| 
 | 
 | ||||||
| #[cfg(not(debug_assertions))] | #[cfg(not(debug_assertions))] | ||||||
| @ -16,12 +12,7 @@ const ALLOW_PATH: &str = "allow_users"; | |||||||
| #[cfg(debug_assertions)] | #[cfg(debug_assertions)] | ||||||
| const POLE_PATH: &str = "allow_pole"; | const POLE_PATH: &str = "allow_pole"; | ||||||
| 
 | 
 | ||||||
| static mut LIST_IDS: Lazy<Mutex<LinkedList<String>>> = | #[cfg(not(test))] | ||||||
|     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))); |  | ||||||
| 
 |  | ||||||
| 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"); |     let content = fs::read_to_string(path).expect("Something went wrong reading the file"); | ||||||
|     content |     content | ||||||
| @ -31,12 +22,22 @@ fn read_ids<'a>(path: &str) -> LinkedList<String> { | |||||||
|         .collect::<LinkedList<String>>() |         .collect::<LinkedList<String>>() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | fn read_ids<'a>(path: &str) -> LinkedList<String> { | ||||||
|  |     let mut ret = LinkedList::new(); | ||||||
|  |     ret.push_front("id_1".to_string()); | ||||||
|  |     ret.push_front("id_2".to_string()); | ||||||
|  |     if !path.eq(POLE_PATH) { | ||||||
|  |         ret.push_front("id_3".to_string()); | ||||||
|  |     } | ||||||
|  |     ret | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub struct GroupPermissions { | pub struct GroupPermissions { | ||||||
|     aproved_groups: RwLock<LinkedList<String>>, |     aproved_groups: RwLock<LinkedList<String>>, | ||||||
|     party_groups: RwLock<LinkedList<String>>, |     party_groups: RwLock<LinkedList<String>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg_attr(test, automock)] |  | ||||||
| impl GroupPermissions { | impl GroupPermissions { | ||||||
|     pub fn new() -> Self { |     pub fn new() -> Self { | ||||||
|         Self { |         Self { | ||||||
| @ -54,20 +55,16 @@ impl GroupPermissions { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn compare(id: &String) -> bool { | #[test] | ||||||
|     let ret: bool; | pub fn test_compare() { | ||||||
|     unsafe { |     let gp = GroupPermissions::new(); | ||||||
|         ret = LIST_IDS.lock().unwrap().contains(id); |     assert_eq!(true, gp.compare(&"id_3".to_string())); | ||||||
|         log::info!("{}", id); |     assert_eq!(false, gp.compare(&"id_4".to_string())); | ||||||
|     } |  | ||||||
|     ret |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn compare_pole(id: &String) -> bool { | #[test] | ||||||
|     let ret: bool; | pub fn test_compare_pole() { | ||||||
|     unsafe { |     let gp = GroupPermissions::new(); | ||||||
|         ret = LIST_POLE_IDS.lock().unwrap().contains(id); |     assert_eq!(true, gp.compar_party(&"id_2".to_string())); | ||||||
|         log::info!("{}", id); |     assert_eq!(false, gp.compar_party(&"id_3".to_string())); | ||||||
|     } |  | ||||||
|     ret |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,19 +2,19 @@ use lazy_static::lazy_static; | |||||||
| use std::sync::Mutex; | use std::sync::Mutex; | ||||||
| 
 | 
 | ||||||
| #[cfg(not(debug_assertions))] | #[cfg(not(debug_assertions))] | ||||||
| const db_path : &str ="/opt/mini_admin_bot/data.db"; | const DB_PATH: &str = "/opt/mini_admin_bot/data.db"; | ||||||
| 
 | 
 | ||||||
| #[cfg(debug_assertions)] | #[cfg(debug_assertions)] | ||||||
| const db_path : &str ="polesDB"; | const DB_PATH: &str = "polesDB"; | ||||||
| 
 | 
 | ||||||
| #[cfg(not(test))] | #[cfg(not(test))] | ||||||
| lazy_static! { | lazy_static! { | ||||||
|     pub static ref DB_CONNECTION : Mutex<Box<sqlite::Connection>> = |     pub static ref DB_CONNECTION: Mutex<Box<sqlite::Connection>> = | ||||||
|         Mutex::new(Box::new(sqlite::open(db_path).unwrap())); |         Mutex::new(Box::new(sqlite::open(DB_PATH).unwrap())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| lazy_static! { | lazy_static! { | ||||||
|     pub static ref DB_CONNECTION : Mutex<Box<sqlite::Connection>> = |     pub static ref DB_CONNECTION: Mutex<Box<sqlite::Connection>> = | ||||||
|         Mutex::new(Box::new(sqlite::open("polesDBTest").unwrap())); |         Mutex::new(Box::new(sqlite::open("polesDBTest").unwrap())); | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -6,7 +6,7 @@ pub mod check_permissions; | |||||||
| mod database; | mod database; | ||||||
| mod filter_files; | mod filter_files; | ||||||
| mod pole_dialogue; | mod pole_dialogue; | ||||||
| mod rewrite_links; | pub mod rewrite_links; | ||||||
| mod spoiler_mangas; | mod spoiler_mangas; | ||||||
| mod telegram_utils; | mod telegram_utils; | ||||||
| 
 | 
 | ||||||
| @ -39,7 +39,6 @@ pub async fn run() { | |||||||
|     let permissions = Arc::new(check_permissions::GroupPermissions::new()); |     let permissions = Arc::new(check_permissions::GroupPermissions::new()); | ||||||
|     let p1 = Arc::clone(&permissions); |     let p1 = Arc::clone(&permissions); | ||||||
|     let p2 = Arc::clone(&permissions); |     let p2 = Arc::clone(&permissions); | ||||||
|     //Command::repl(bot.clone(), answer).await;
 |  | ||||||
|     let handler = Update::filter_message() |     let handler = Update::filter_message() | ||||||
|         .branch( |         .branch( | ||||||
|             dptree::filter(move |msg: Message| !p1.compare(&msg.chat.id.to_string())).endpoint( |             dptree::filter(move |msg: Message| !p1.compare(&msg.chat.id.to_string())).endpoint( | ||||||
| @ -72,14 +71,12 @@ pub async fn run() { | |||||||
|                     Ok(()) |                     Ok(()) | ||||||
|                 }), |                 }), | ||||||
|         ) |         ) | ||||||
|         /* |  | ||||||
|         Now is useless because the group doesn't make any spoiler |  | ||||||
|         .branch( |         .branch( | ||||||
|             dptree::filter(move |msg: Message| { |             dptree::filter(move |msg: Message| { | ||||||
|                 (is_photo(msg.clone()) && p2.compar_party(&msg.chat.id.to_string())) |                 is_photo(msg.clone()) && p2.compar_party(&msg.chat.id.to_string()) | ||||||
|             }) |             }) | ||||||
|             .endpoint(|msg: Message, bot: Bot| spoiler_mangas::check_image(msg, bot)), |             .endpoint(|msg: Message, bot: Bot| spoiler_mangas::check_image(msg, bot)), | ||||||
|         )*/ |         ) | ||||||
|         .branch( |         .branch( | ||||||
|             dptree::filter(move |msg: Message| filter_files::analyce_name::check_file(msg.clone())) |             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)), |                 .endpoint(|msg: Message, bot: Bot| filter_files::action::take_actions(msg, bot)), | ||||||
| @ -131,21 +128,21 @@ fn is_media(msg: Message) -> bool { | |||||||
| 
 | 
 | ||||||
| fn is_stiker(msg: Message) -> bool { | fn is_stiker(msg: Message) -> bool { | ||||||
|     match msg.sticker() { |     match msg.sticker() { | ||||||
|         Some(s) => true, |         Some(_) => true, | ||||||
|         None => false, |         None => false, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn is_gif(msg: Message) -> bool { | fn is_gif(msg: Message) -> bool { | ||||||
|     match msg.animation() { |     match msg.animation() { | ||||||
|         Some(s) => true, |         Some(_) => true, | ||||||
|         None => false, |         None => false, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn is_photo(msg: Message) -> bool { | fn is_photo(msg: Message) -> bool { | ||||||
|     match msg.photo() { |     match msg.photo() { | ||||||
|         Some(s) => true, |         Some(_) => true, | ||||||
|         None => false, |         None => false, | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ use sqlite::{Error, State}; | |||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| fn drop_all(con: &sqlite::Connection) -> bool { | fn drop_all(con: &sqlite::Connection) -> bool { | ||||||
|     let mut result: bool; |     let result: bool; | ||||||
|     match con.execute( |     match con.execute( | ||||||
|         " |         " | ||||||
|                 DROP TABLE IF EXISTS poles; |                 DROP TABLE IF EXISTS poles; | ||||||
| @ -188,7 +188,7 @@ impl<'a> DatabasePole { | |||||||
|             .unwrap(); |             .unwrap(); | ||||||
|         statement.bind((1, group_id)).unwrap(); |         statement.bind((1, group_id)).unwrap(); | ||||||
|         let mut ret = Vec::new(); |         let mut ret = Vec::new(); | ||||||
|         for i in 1..10 { |         for _ in 1..10 { | ||||||
|             match statement.next().unwrap() { |             match statement.next().unwrap() { | ||||||
|                 State::Row => ret.push(( |                 State::Row => ret.push(( | ||||||
|                     statement.read::<i64, _>(0).unwrap(), |                     statement.read::<i64, _>(0).unwrap(), | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ fn do_fail(group_id: &str, user_id: &str, user_name: &str) { | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn check_user_points(msg: &teloxide::prelude::Message, rw: Rewards) -> bool { | fn check_user_points(msg: &Message, rw: Rewards) -> bool { | ||||||
|     let data: database::DatabasePole = database::DatabasePole::get_database(); |     let data: database::DatabasePole = database::DatabasePole::get_database(); | ||||||
|     let ret = data.check_user_pole( |     let ret = data.check_user_pole( | ||||||
|         &msg.chat.id.to_string(), |         &msg.chat.id.to_string(), | ||||||
| @ -75,7 +75,7 @@ enum Rewards { | |||||||
|     FAIL = 1, |     FAIL = 1, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn check_group_points(msg: &teloxide::prelude::Message, rw: Rewards) -> bool { | fn check_group_points(msg: &Message, rw: Rewards) -> bool { | ||||||
|     let data: database::DatabasePole = database::DatabasePole::get_database(); |     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 { |     match rw { | ||||||
| @ -86,7 +86,7 @@ fn check_group_points(msg: &teloxide::prelude::Message, rw: Rewards) -> bool { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub async fn exe_pole(msg: Message, bot: Bot) -> anyhow::Result<()> { | pub async fn exe_pole(msg: Message, bot: Bot) -> anyhow::Result<()> { | ||||||
|     let text_lower = match msg.text() { |     let _text_lower = match msg.text() { | ||||||
|         Some(t) => t.to_lowercase(), |         Some(t) => t.to_lowercase(), | ||||||
|         None => return Ok(()), |         None => return Ok(()), | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -2,17 +2,19 @@ use phf::phf_map; | |||||||
| 
 | 
 | ||||||
| use curl::easy::Easy; | use curl::easy::Easy; | ||||||
| 
 | 
 | ||||||
| static URLS: phf::Map<&'static str, &'static str> = phf_map! { | static URLS: phf::Map<&'static str, (&'static str, bool)> = phf_map! { | ||||||
|     "www.tiktok.com" => "vxtiktok.com", |     "www.tiktok.com" => ("vxtiktok.com", false), | ||||||
|     "vm.tiktok.com" => "vxtiktok.com", |     "vm.tiktok.com" => ("vxtiktok.com", true), | ||||||
|     "lite.tiktok.com" => "vxtiktok.com", |     "vt.tiktok.com" => ("vxtiktok.com", true), | ||||||
|     "https://x.com" => "https://fxtwitter.com", |     "lite.tiktok.com" => ("vxtiktok.com", true), | ||||||
|     "https://twitter.com" => "https://fxtwitter.com", |     "www.instagram.com" => ("ddinstagram.com", false), | ||||||
|  |     "https://x.com" => ("https://fxtwitter.com", false), | ||||||
|  |     "https://twitter.com" => ("https://fxtwitter.com",false), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub fn filter_string(url: String, domain: String) -> Option<String> { | pub fn filter_string(url: String, domain: String) -> Option<String> { | ||||||
|     let ret = match URLS.get(domain.as_str()) { |     let ret = match URLS.get(domain.as_str()) { | ||||||
|         Some(fixed_domain) => url.replacen(domain.as_str(),fixed_domain,1), |         Some(fixed_domain) => url.replacen(domain.as_str(), fixed_domain.0, 1), | ||||||
|         None => return None, |         None => return None, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @ -22,19 +24,10 @@ pub fn filter_string(url: String, domain: String) -> Option<String> { | |||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn get_domain(url: String) -> Option<String> { |  | ||||||
|     for domain in URLS.keys() { |  | ||||||
|         if url.contains(domain) { |  | ||||||
|             return Some(String::from(*domain)) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     None |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub fn check_domains(text: String) -> bool { | pub fn check_domains(text: String) -> bool { | ||||||
|     for domain in URLS.keys() { |     for domain in URLS.keys() { | ||||||
|         if text.contains(domain) { |         if text.contains(domain) { | ||||||
|             return true |             return true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     false |     false | ||||||
| @ -44,14 +37,14 @@ pub fn get_domain_from_text(text: String) -> (String, String) { | |||||||
|     for word in text.split(' ') { |     for word in text.split(' ') { | ||||||
|         for domain in URLS.keys() { |         for domain in URLS.keys() { | ||||||
|             if word.contains(domain) { |             if word.contains(domain) { | ||||||
|                 if String::from(*domain).contains("vm.tiktok.com") || String::from(*domain).contains("lite.tiktok.com") { |                 if URLS[domain].1 { | ||||||
|                     let url = match get_tiktok_redirection(String::from(word)) { |                     let url = match get_tiktok_redirection(String::from(word)) { | ||||||
|                         Ok(furl) => furl, |                         Ok(furl) => furl, | ||||||
|                         Err(_e) => String::from(word), |                         Err(_e) => String::from(word), | ||||||
|                     }; |                     }; | ||||||
|                     return (String::from(url), String::from("www.tiktok.com")) |                     return (String::from(url), String::from("www.tiktok.com")); | ||||||
|                 } |                 } | ||||||
|                 return (String::from(word), String::from(*domain)) |                 return (String::from(word), String::from(*domain)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -67,3 +60,37 @@ fn get_tiktok_redirection(url: String) -> Result<String, curl::Error> { | |||||||
|         None => url, |         None => url, | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #[test] | ||||||
|  | fn test_check_domains() { | ||||||
|  |     assert_eq!( | ||||||
|  |         true, | ||||||
|  |         check_domains("https://vm.tiktok.com/ZGeouHd2t/".to_string()) | ||||||
|  |     ); | ||||||
|  |     assert_eq!( | ||||||
|  |         false, | ||||||
|  |         check_domains("https://randomwebsite.com".to_string()) | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[test] | ||||||
|  | fn test_rewrite_clean_tiktok() { | ||||||
|  |     let domain = get_domain_from_text( | ||||||
|  |         "https://www.tiktok.com/@kramkang/video/7417808362957589778".to_string(), | ||||||
|  |     ); | ||||||
|  |     assert_eq!(domain.1, "www.tiktok.com"); | ||||||
|  |     assert_eq!( | ||||||
|  |         domain.0, | ||||||
|  |         "https://www.tiktok.com/@kramkang/video/7417808362957589778" | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[test] | ||||||
|  | fn test_rewrite_refered_tiktok() { | ||||||
|  |     let url_and_domain = get_domain_from_text("https://vm.tiktok.com/ZGeouHd2t/".to_string()); | ||||||
|  |     let domain = filter_string(url_and_domain.0, url_and_domain.1); | ||||||
|  |     assert_eq!( | ||||||
|  |         domain, | ||||||
|  |         Some("https://vxtiktok.com/@/video/7417808362957589778".to_string()) | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,39 +1,39 @@ | |||||||
|  | use crate::telegram_utils::*; | ||||||
|  | use image::{DynamicImage, GenericImageView}; | ||||||
|  | use std::io::Cursor; | ||||||
| use teloxide::prelude::*; | use teloxide::prelude::*; | ||||||
| use teloxide::{ | use teloxide::{ | ||||||
|     net::Download, |     net::Download, | ||||||
|     requests::{Requester,MultipartRequest}, |  | ||||||
|     types::{MessageEntity, MessageEntityKind}, |  | ||||||
|     payloads::SendPhoto, |     payloads::SendPhoto, | ||||||
|  |     requests::{MultipartRequest, Requester}, | ||||||
|  |     types::{MessageEntity, MessageEntityKind}, | ||||||
|     Bot, |     Bot, | ||||||
| }; | }; | ||||||
| use image::{DynamicImage,GenericImageView}; |  | ||||||
| use std::io::Cursor; |  | ||||||
| use tokio::io::BufStream; | use tokio::io::BufStream; | ||||||
| use crate::telegram_utils::*; |  | ||||||
| 
 | 
 | ||||||
| const TOLERANCE: i16 = 10; | const TOLERANCE: i16 = 10; | ||||||
| const PERCENT_ACEPTANCE: u8 = 5; | const PERCENT_ACEPTANCE: u8 = 5; | ||||||
| const WHITE : u8 = 160; | const WHITE: u8 = 160; | ||||||
| const WHITE_ACEPTANCE: u8 = 40; | const WHITE_ACEPTANCE: u8 = 40; | ||||||
| 
 | 
 | ||||||
| fn check_percent(img: DynamicImage) -> (u8,u8) { | fn check_percent(img: DynamicImage) -> (u8, u8) { | ||||||
|     let mut cont = 0; |     let mut cont = 0; | ||||||
|     let mut cont_wite = 0; |     let mut cont_wite = 0; | ||||||
|     for pixel in img.pixels() { |     for pixel in img.pixels() { | ||||||
|         let diference_rg:i16 = (pixel.2[0] as i16 - pixel.2[1] as i16).abs(); |         let diference_rg: i16 = (pixel.2[0] as i16 - pixel.2[1] as i16).abs(); | ||||||
|         let diference_gb:i16 = (pixel.2[1] as i16 - pixel.2[2] as i16).abs(); |         let diference_gb: i16 = (pixel.2[1] as i16 - pixel.2[2] as i16).abs(); | ||||||
|         let diference_br:i16 = (pixel.2[0] as i16 - pixel.2[2] as i16).abs(); |         let diference_br: i16 = (pixel.2[0] as i16 - pixel.2[2] as i16).abs(); | ||||||
|         let diference_pixel = diference_rg + diference_gb + diference_br; |         let diference_pixel = diference_rg + diference_gb + diference_br; | ||||||
|         if pixel.2[0] > WHITE && pixel.2[1] > WHITE && pixel.2[2] > WHITE { |         if pixel.2[0] > WHITE && pixel.2[1] > WHITE && pixel.2[2] > WHITE { | ||||||
|             cont_wite+=1 |             cont_wite += 1 | ||||||
|         } |         } | ||||||
|         if diference_pixel > TOLERANCE { |         if diference_pixel > TOLERANCE { | ||||||
|             cont += 1; |             cont += 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     let percent = ((cont as f64 /(img.width() * img.height()) as f64)*100.0) as u8; |     let percent = ((cont as f64 / (img.width() * img.height()) as f64) * 100.0) as u8; | ||||||
|     let white = ((cont_wite as f64 /(img.width() * img.height()) as f64)*100.0) as u8; |     let white = ((cont_wite as f64 / (img.width() * img.height()) as f64) * 100.0) as u8; | ||||||
|     (percent,white) |     (percent, white) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn generate_from(msg: &Message, append_text: bool) -> String { | fn generate_from(msg: &Message, append_text: bool) -> String { | ||||||
| @ -45,42 +45,58 @@ fn generate_from(msg: &Message, append_text: bool) -> String { | |||||||
|     msg_from |     msg_from | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn append_text(new_msg: MultipartRequest<SendPhoto>, old_msg: Message) -> MultipartRequest<SendPhoto> { | pub fn append_text( | ||||||
|  |     new_msg: MultipartRequest<SendPhoto>, | ||||||
|  |     old_msg: Message, | ||||||
|  | ) -> MultipartRequest<SendPhoto> { | ||||||
|     let msg_from; |     let msg_from; | ||||||
|     match old_msg.caption() { |     match old_msg.caption() { | ||||||
|         Some(caption) => { |         Some(caption) => { | ||||||
|             msg_from = generate_from(&old_msg, true); |             msg_from = generate_from(&old_msg, true); | ||||||
|             let from_offset = msg_from.encode_utf16().count(); |             let from_offset = msg_from.encode_utf16().count(); | ||||||
|             //new_msg.caption(caption).caption_entities(generate_entity_spoiler(caption.len())).has_spoiler(true)
 |             //new_msg.caption(caption).caption_entities(generate_entity_spoiler(caption.len())).has_spoiler(true)
 | ||||||
|             new_msg.caption(msg_from + caption).caption_entities(generate_captions(old_msg.caption_entities().unwrap().to_vec(),caption.encode_utf16().count(), from_offset)) |             new_msg | ||||||
|         }, |                 .caption(msg_from + caption) | ||||||
|  |                 .caption_entities(generate_captions( | ||||||
|  |                     old_msg.caption_entities().unwrap().to_vec(), | ||||||
|  |                     caption.encode_utf16().count(), | ||||||
|  |                     from_offset, | ||||||
|  |                 )) | ||||||
|  |         } | ||||||
|         None => { |         None => { | ||||||
|             msg_from = generate_from(&old_msg, false); |             msg_from = generate_from(&old_msg, false); | ||||||
|             new_msg.caption(msg_from) |             new_msg.caption(msg_from) | ||||||
|         }, |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn generate_captions(captions: Vec<MessageEntity>, len: usize, offset: usize) -> Vec<MessageEntity> { | pub fn generate_captions( | ||||||
|  |     captions: Vec<MessageEntity>, | ||||||
|  |     len: usize, | ||||||
|  |     offset: usize, | ||||||
|  | ) -> Vec<MessageEntity> { | ||||||
|     let mut ret = Vec::new(); |     let mut ret = Vec::new(); | ||||||
|     let mut last_hole = 0; |     let mut last_hole = 0; | ||||||
|     for mut cap in captions { |     for mut cap in captions { | ||||||
|         match cap.kind { |         match cap.kind { | ||||||
|             MessageEntityKind::TextMention { user: ref User } => { |             MessageEntityKind::TextMention { user: ref _user } => { | ||||||
|                 if cap.offset == 0 { |                 if cap.offset == 0 { | ||||||
|                     last_hole = cap.length; |                     last_hole = cap.length; | ||||||
|                 }else if cap.offset >= last_hole { |                 } else if cap.offset >= last_hole { | ||||||
|                     ret.push(MessageEntity::spoiler(last_hole+offset,cap.offset-last_hole)); |                     ret.push(MessageEntity::spoiler( | ||||||
|  |                         last_hole + offset, | ||||||
|  |                         cap.offset - last_hole, | ||||||
|  |                     )); | ||||||
|                     last_hole = cap.offset + cap.length; |                     last_hole = cap.offset + cap.length; | ||||||
|                 } |                 } | ||||||
|                 cap.offset += offset; |                 cap.offset += offset; | ||||||
|                 ret.push(cap.clone()); |                 ret.push(cap.clone()); | ||||||
|             }, |             } | ||||||
|             _ => continue, |             _ => continue, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if last_hole < len { |     if last_hole < len { | ||||||
|         ret.push(MessageEntity::spoiler(last_hole+offset,len - last_hole)); |         ret.push(MessageEntity::spoiler(last_hole + offset, len - last_hole)); | ||||||
|     } |     } | ||||||
|     ret |     ret | ||||||
| } | } | ||||||
| @ -89,7 +105,7 @@ pub async fn check_image(msg: Message, bot: Bot) -> anyhow::Result<()> { | |||||||
|         Some(s) => { |         Some(s) => { | ||||||
|             let mut percent = 0; |             let mut percent = 0; | ||||||
|             let mut white = 0; |             let mut white = 0; | ||||||
|             let mut id : Option<(String, u32)> = None; |             let mut id: Option<(String, u32)> = None; | ||||||
|             let mut failed = true; |             let mut failed = true; | ||||||
|             for p in s { |             for p in s { | ||||||
|                 let file = bot.get_file(p.file.id.clone()).await?; |                 let file = bot.get_file(p.file.id.clone()).await?; | ||||||
| @ -112,30 +128,34 @@ pub async fn check_image(msg: Message, bot: Bot) -> anyhow::Result<()> { | |||||||
|                                     } else { |                                     } else { | ||||||
|                                         Some(i) |                                         Some(i) | ||||||
|                                     } |                                     } | ||||||
|                                 }, |                                 } | ||||||
|                                 None => Some((p.clone().file.id, p.clone().width)), |                                 None => Some((p.clone().file.id, p.clone().width)), | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }, |                     } | ||||||
|                     Err(_e) => continue, |                     Err(_e) => continue, | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if !failed && percent < PERCENT_ACEPTANCE && white > WHITE_ACEPTANCE { |             if !failed && percent < PERCENT_ACEPTANCE && white > WHITE_ACEPTANCE { | ||||||
|                 bot.delete_message(msg.chat.id, msg.id).await?; |                 bot.delete_message(msg.chat.id, msg.id).await?; | ||||||
|                 let response = match id { |                 let response = match id { | ||||||
|                     Some(i) => bot.send_photo(msg.chat.id, teloxide::types::InputFile::file_id(i.0)).has_spoiler(true), |                     Some(i) => bot | ||||||
|                     None => { |                         .send_photo(msg.chat.id, teloxide::types::InputFile::file_id(i.0)) | ||||||
|                         match msg.photo().unwrap().iter().max_by_key(|p| p.width) { |                         .has_spoiler(true), | ||||||
|                             Some(f) => bot.send_photo(msg.chat.id, teloxide::types::InputFile::file_id(f.file.id.clone())).has_spoiler(true), |                     None => match msg.photo().unwrap().iter().max_by_key(|p| p.width) { | ||||||
|                             None => return Ok(()), |                         Some(f) => bot | ||||||
|                         } |                             .send_photo( | ||||||
|  |                                 msg.chat.id, | ||||||
|  |                                 teloxide::types::InputFile::file_id(f.file.id.clone()), | ||||||
|  |                             ) | ||||||
|  |                             .has_spoiler(true), | ||||||
|  |                         None => return Ok(()), | ||||||
|                     }, |                     }, | ||||||
|                 }; |                 }; | ||||||
|                 append_text(response, msg).await?; |                 append_text(response, msg).await?; | ||||||
|             } |             } | ||||||
|             Ok(()) |             Ok(()) | ||||||
|         }, |         } | ||||||
|         None => Ok(()), |         None => Ok(()), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -1,6 +0,0 @@ | |||||||
| use mini_admin_bot::ban_stiker; |  | ||||||
| 
 |  | ||||||
| #[test] |  | ||||||
| pub fn db_media_is_banned() { |  | ||||||
|     assert_eq!(0, 0); |  | ||||||
| } |  | ||||||
							
								
								
									
										1
									
								
								tests/mocks/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/mocks/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | pub mod teloxide_mocks; | ||||||
							
								
								
									
										54
									
								
								tests/mocks/teloxide_mocks.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tests/mocks/teloxide_mocks.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | use chrono::DateTime; | ||||||
|  | use teloxide::types::{ | ||||||
|  |     Chat, ChatId, ChatKind, ChatPublic, MediaKind::Text, MediaText, Message, MessageCommon, | ||||||
|  |     MessageId, MessageKind::Common, PublicChatGroup, PublicChatKind::Group, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | pub fn generate_msg_mock(text: &str) -> Message { | ||||||
|  |     let chat_id = ChatId { 0: 0 }; | ||||||
|  |     let public_chat_kind = Group(PublicChatGroup { permissions: None }); | ||||||
|  |     let chat_kind = ChatKind::Public(ChatPublic { | ||||||
|  |         title: None, | ||||||
|  |         kind: public_chat_kind, | ||||||
|  |         description: None, | ||||||
|  |         invite_link: None, | ||||||
|  |         has_protected_content: None, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     let chat = Chat { | ||||||
|  |         has_aggressive_anti_spam_enabled: false, | ||||||
|  |         has_hidden_members: false, | ||||||
|  |         id: chat_id, | ||||||
|  |         pinned_message: None, | ||||||
|  |         photo: None, | ||||||
|  |         message_auto_delete_time: None, | ||||||
|  |         kind: chat_kind, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let media_kind = Text(MediaText { | ||||||
|  |         text: text.to_string(), | ||||||
|  |         entities: Vec::new(), | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     let message_kind = Common(MessageCommon { | ||||||
|  |         from: None, | ||||||
|  |         sender_chat: None, | ||||||
|  |         author_signature: None, | ||||||
|  |         forward: None, | ||||||
|  |         reply_to_message: None, | ||||||
|  |         edit_date: None, | ||||||
|  |         media_kind, | ||||||
|  |         reply_markup: None, | ||||||
|  |         is_topic_message: false, | ||||||
|  |         is_automatic_forward: false, | ||||||
|  |         has_protected_content: false, | ||||||
|  |     }); | ||||||
|  |     Message { | ||||||
|  |         chat, | ||||||
|  |         via_bot: None, | ||||||
|  |         thread_id: None, | ||||||
|  |         kind: message_kind, | ||||||
|  |         date: DateTime::from_timestamp_nanos(0), | ||||||
|  |         id: MessageId { 0: 0 }, | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,12 +0,0 @@ | |||||||
| 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")); |  | ||||||
| } |  | ||||||
							
								
								
									
										19
									
								
								tests/test_links_to_rewrite.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/test_links_to_rewrite.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | use mini_admin_bot::rewrite_links; | ||||||
|  | 
 | ||||||
|  | mod mocks; | ||||||
|  | #[test] | ||||||
|  | pub fn test_contain_links() { | ||||||
|  |     assert_eq!( | ||||||
|  |         false, | ||||||
|  |         rewrite_links::check_contain_links::contain_links( | ||||||
|  |             mocks::teloxide_mocks::generate_msg_mock("hola") | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     assert_eq!( | ||||||
|  |         true, | ||||||
|  |         rewrite_links::check_contain_links::contain_links( | ||||||
|  |             mocks::teloxide_mocks::generate_msg_mock("https://x.com") | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user