linkleaner/src/deamp/mod.rs

63 lines
2.0 KiB
Rust

mod model;
use crate::{message::TryReplyMessage, utils::get_urls_from_message};
use model::AMPResponse;
use reqwest::Url;
use std::{error::Error, str::FromStr};
use teloxide::{prelude::Requester, types::Message, utils::html::link, Bot};
use tracing::debug;
const BASE_URL: &str = "https://www.amputatorbot.com/api/v1/convert?gac=true&md=3&q=";
fn deserialize_amp_response(text: &str) -> Result<AMPResponse, serde_json::Error> {
serde_json::from_str(text)
}
pub async fn handler(
bot: Bot,
message: Message,
) -> Result<(), Box<dyn Error + Sync + Send + 'static>> {
if let Some(text) = message.text()
&& let Some(user) = message.from()
{
let mut text = String::from_str(text)?;
let urls = get_urls_from_message(&message);
debug!(?urls);
for url in &urls {
let resp = reqwest::get(&format!("{BASE_URL}{url}"))
.await?
.text()
.await?;
debug!(?resp, "{url}");
let resp = deserialize_amp_response(&resp)?;
if let AMPResponse::Success(ok) = resp {
text = text.replace(url, &ok[0].canonical.url);
} else {
return Ok(());
}
}
let text = format!("{}: {}", link(user.url().as_str(), &user.full_name()), text);
let _del = bot.delete_message(message.chat.id, message.id).await;
bot.try_reply(message, text).await?;
}
Ok(())
}
// The dptree handler requires this to be a move
#[allow(clippy::needless_pass_by_value)]
pub fn is_amp(msg: Message) -> bool {
let urls = get_urls_from_message(&msg);
if urls.is_empty() {
return false;
}
urls.iter().flat_map(|url| Url::parse(url)).any(|url| {
if let Some(mut segments) = url.path_segments()
&& let Some(host) = url.host_str()
{
segments.any(|x| x == "amp") || host.ends_with(".cdn.ampproject.org")
} else {
false
}
})
}