refactor/feat: add xkcd.ru, for-loop -> iter

This commit is contained in:
DarkCat09 2024-11-27 17:35:34 +04:00
parent b98dd28fcd
commit 0e6e6a14fd
Signed by: DarkCat09
GPG key ID: BD3CE9B65916CD82

View file

@ -7,6 +7,8 @@ use tokio::signal::unix::{signal, SignalKind};
const BOT_URL: &str = "https://api.telegram.org/bot"; const BOT_URL: &str = "https://api.telegram.org/bot";
/// Command to search for in a message text /// Command to search for in a message text
const COMMAND: &str = "/xkcd"; const COMMAND: &str = "/xkcd";
/// Length of the command substring
const CMD_LEN: usize = COMMAND.len();
/// Long polling timeout in seconds /// Long polling timeout in seconds
const POLL_TIMEOUT: &str = "300"; const POLL_TIMEOUT: &str = "300";
/// Update types to receive (filtered out on tg backend) /// Update types to receive (filtered out on tg backend)
@ -58,11 +60,13 @@ struct TgChat {
// is_forum: bool, // is_forum: bool,
} }
/// XKCD.com API comic info schema /// XKCD API comic info schema
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct XkcdInfo { struct XkcdInfo {
alt: String, #[serde(alias = "text")] // xkcd.ru
img: String, alt: String, // xkcd.com
#[serde(alias = "image")] // xkcd.ru
img: String, // xkcd.com
} }
#[tokio::main] #[tokio::main]
@ -122,30 +126,43 @@ async fn handler(cfg: &Config, s: &mut State) -> Result<(), reqwest::Error> {
.await? .await?
.result; .result;
for u in &mut updates { updates
let Some(mut msg) = u.message.take() else { .iter_mut()
continue; .filter_map(|u| {
}; u.message.take().and_then(|mut msg| {
msg.text.take().and_then(|text| {
let Some(text) = msg.text.take() else { // starts with our command
continue; if text.get(..CMD_LEN)? == COMMAND
}; // check space or @ after cmd name
// to ensure that our command is
if !text.starts_with(COMMAND) { // not a part of any other cmd
continue; && [" ", "@"].contains(&text.get(CMD_LEN..CMD_LEN + 1)?)
{
let mut args = text.split_whitespace();
args.next(); // skip command name
match args.next()? {
"ru" => {
let comic_id = args.next()?.parse::<u16>().ok()?;
Some((msg, format!("https://xkcd.ru/{}/?json=true", comic_id)))
} }
"en" => {
let Some(comic_id) = text let comic_id = args.next()?.parse::<u16>().ok()?;
.split_whitespace() Some((msg, format!("https://xkcd.com/{}/info.0.json", comic_id)))
.skip(1)
.next()
.and_then(|id| id.parse::<u16>().ok())
else {
continue;
};
tokio::spawn(send_comic(cfg.clone(), msg, comic_id));
} }
comic_id => {
let comic_id = comic_id.parse::<u16>().ok()?;
Some((msg, format!("https://xkcd.com/{}/info.0.json", comic_id)))
}
}
} else {
None
}
})
})
})
.for_each(|(msg, url)| {
tokio::spawn(send_comic(cfg.clone(), msg, url));
});
if let Some(u) = updates.last() { if let Some(u) = updates.last() {
s.offset = u.update_id + 1; s.offset = u.update_id + 1;
@ -154,14 +171,8 @@ async fn handler(cfg: &Config, s: &mut State) -> Result<(), reqwest::Error> {
Ok(()) Ok(())
} }
async fn send_comic(cfg: Config, msg: TgMessage, comic_id: u16) -> Result<(), reqwest::Error> { async fn send_comic(cfg: Config, msg: TgMessage, url: String) -> Result<(), reqwest::Error> {
let info = cfg let info = cfg.client.get(url).send().await?.json::<XkcdInfo>().await?;
.client
.get(format!("https://xkcd.com/{}/info.0.json", comic_id))
.send()
.await?
.json::<XkcdInfo>()
.await?;
cfg.client cfg.client
.post((*cfg.send_url).clone()) .post((*cfg.send_url).clone())