use teloxide::prelude::*; use teloxide::{ net::Download, requests::{Requester,MultipartRequest}, types::{MessageEntity, MessageEntityKind}, payloads::SendPhoto, Bot, }; use image::{DynamicImage,GenericImageView}; use std::io::Cursor; use tokio::io::BufStream; use crate::telegram_utils::*; const TOLERANCE: i16 = 10; const PERCENT_ACEPTANCE: u8 = 5; const WHITE : u8 = 160; const WHITE_ACEPTANCE: u8 = 40; fn check_percent(img: DynamicImage) -> (u8,u8) { let mut cont = 0; let mut cont_wite = 0; for pixel in img.pixels() { 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_br:i16 = (pixel.2[0] as i16 - pixel.2[2] as i16).abs(); let diference_pixel = diference_rg + diference_gb + diference_br; if pixel.2[0] > WHITE && pixel.2[1] > WHITE && pixel.2[2] > WHITE { cont_wite+=1 } if diference_pixel > TOLERANCE { cont += 1; } } 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; (percent,white) } pub fn append_text(new_msg: MultipartRequest, old_msg: Message) -> MultipartRequest { match old_msg.caption() { Some(caption) => { let mut msg_from = get_alias(&old_msg); msg_from.push_str(": "); msg_from = String::from("Mensaje de ") + &msg_from; 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(msg_from + caption).caption_entities(generate_captions(old_msg.caption_entities().unwrap().to_vec(),caption.encode_utf16().count(), from_offset)) }, None => new_msg, } } pub fn generate_captions(captions: Vec, len: usize, offset: usize) -> Vec { let mut ret = Vec::new(); let mut last_hole = 0; for mut cap in captions { match cap.kind { MessageEntityKind::TextMention { user: ref User } => { if cap.offset == 0 { last_hole = cap.length; }else if cap.offset >= last_hole { ret.push(MessageEntity::spoiler(last_hole+offset,cap.offset-last_hole)); last_hole = cap.offset + cap.length; } cap.offset += offset; ret.push(cap.clone()); }, _ => continue, } } if last_hole < len { ret.push(MessageEntity::spoiler(last_hole+offset,len - last_hole)); } ret } pub async fn check_image(msg: Message, bot: Bot) -> anyhow::Result<()> { match msg.photo() { Some(s) => { let mut percent = 0; let mut white = 0; let mut id : Option<(String, u32)> = None; let mut failed = true; for p in s { let file = bot.get_file(p.file.id.clone()).await?; let empty_memory: Vec = Vec::new(); let cursor = Cursor::new(empty_memory); let mut reader = BufStream::new(cursor); bot.download_file(&file.path, &mut reader).await?; let raw = reader.into_inner().into_inner().leak(); match image::load_from_memory(raw) { Ok(img) => { failed = false; let img_percent = check_percent(img); if img_percent.0 >= percent { percent = img_percent.0; white = img_percent.1; id = match id { Some(i) => { if i.1 > p.width { Some((p.clone().file.id, p.clone().width)) } else { Some(i) } }, None => Some((p.clone().file.id, p.clone().width)), } } }, Err(_e) => continue, } } if !failed && percent < PERCENT_ACEPTANCE && white > WHITE_ACEPTANCE { bot.delete_message(msg.chat.id, msg.id).await?; let response = match id { Some(i) => bot.send_photo(msg.chat.id, teloxide::types::InputFile::file_id(i.0)).has_spoiler(true), None => { match msg.photo().unwrap().iter().max_by_key(|p| p.width) { 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?; } Ok(()) }, None => Ok(()), } }