refactor: clippy warnings

This commit is contained in:
Kristofers Solo 2025-10-28 17:04:25 +02:00
parent 5dfc82508b
commit fee8178ad2
Signed by: kristoferssolo
GPG Key ID: 8687F2D3EEE6F0ED
5 changed files with 47 additions and 45 deletions

View File

@ -13,6 +13,11 @@ pub enum Command {
Curse,
}
/// Handle a command from the user.
///
/// # Errors
///
/// Returns a Teloxide error if the message fails to send.
pub async fn answer(bot: Bot, msg: Message, cmd: Command) -> ResponseResult<()> {
match cmd {
Command::Help => {

View File

@ -58,11 +58,6 @@ async fn run_command_in_tempdir(cmd: &str, args: &[&str]) -> Result<DownloadResu
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
if stderr.is_empty() {
return Err(Error::Other(format!("{cmd} failed: {stderr}")));
}
let err = match cmd {
"yt-dlp" => Error::ytdlp_failed(stderr),
_ => Error::Other(format!("{cmd} failed: {stderr}")),
@ -241,19 +236,16 @@ pub async fn process_download_result(
}
// deterministic ordering
media_items.sort_by(|(p1, _), (p2, _)| p1.cmp(p2));
media_items.sort_by_key(|(_, k)| match k {
MediaKind::Video => 0,
MediaKind::Image => 1,
MediaKind::Unknown => 2,
});
info!(media_items = media_items.len(), "Sending media to chat");
// prefer video over image
if let Some((path, MediaKind::Video)) = media_items.iter().find(|(_, k)| *k == MediaKind::Video)
{
return send_media_from_path(bot, chat_id, path.clone(), MediaKind::Video).await;
}
if let Some((path, MediaKind::Image)) = media_items.iter().find(|(_, k)| *k == MediaKind::Image)
{
return send_media_from_path(bot, chat_id, path.clone(), MediaKind::Image).await;
if let Some((path, kind)) = media_items.first() {
return send_media_from_path(bot, chat_id, path.clone(), *kind).await;
}
Err(Error::NoMediaFound)

View File

@ -7,26 +7,28 @@ use std::{pin::Pin, sync::Arc};
use teloxide::{Bot, types::ChatId};
use tracing::info;
type DownloadFn = fn(&str) -> Pin<Box<dyn Future<Output = Result<DownloadResult>> + Send>>;
#[derive(Debug, Clone)]
pub struct Handler {
name: &'static str,
regex: Regex,
handler_fn: fn(&str) -> Pin<Box<dyn Future<Output = Result<DownloadResult>> + Send>>,
func: DownloadFn,
}
impl Handler {
#[must_use]
/// Create a new handler with a regex pattern and download function.
///
/// # Errors
///
/// Returns `RegexError` if the regex pattern is invalid.
pub fn new(
name: &'static str,
regex_pattern: &'static str,
handler_fn: fn(&str) -> Pin<Box<dyn Future<Output = Result<DownloadResult>> + Send>>,
func: DownloadFn,
) -> std::result::Result<Self, RegexError> {
let regex = Regex::new(regex_pattern)?;
Ok(Self {
name,
regex,
handler_fn,
})
Ok(Self { name, regex, func })
}
#[inline]
@ -35,16 +37,22 @@ impl Handler {
self.name
}
/// Extract a URL matching this handler's regex pattern.
#[must_use]
pub fn try_extract(&self, text: &str) -> Option<String> {
pub fn try_extract<'a>(&self, text: &'a str) -> Option<&'a str> {
self.regex
.captures(text)
.and_then(|c| c.get(0).map(|m| m.as_str().to_owned()))
.and_then(|c| c.get(0).map(|m| m.as_str()))
}
pub async fn handle(&self, bot: &Bot, chat_id: ChatId, url: String) -> Result<()> {
/// Handle a URL by downloading and sending the media.
///
/// # Errors
///
/// Returns `Error` if download or media processing fails.
pub async fn handle(&self, bot: &Bot, chat_id: ChatId, url: &str) -> Result<()> {
info!(handler = %self.name(), url = %url, "handling url");
let dr = (self.handler_fn)(&url).await?;
let dr = (self.func)(url).await?;
process_download_result(bot, chat_id, dr).await
}
}

View File

@ -30,10 +30,9 @@ async fn main() -> color_eyre::Result<()> {
// Command::repl(bot.clone(), answer).await;
teloxide::repl(bot.clone(), move |bot: Bot, msg: Message| {
// clone the handlers vector into the closure
let handlers = handlers.clone();
async move {
process_message(&bot, &msg, &handlers);
process_message(&bot, &msg, &handlers).await;
respond(())
}
})
@ -42,26 +41,20 @@ async fn main() -> color_eyre::Result<()> {
Ok(())
}
fn process_message(bot: &Bot, msg: &Message, handlers: &[Handler]) {
async fn process_message(bot: &Bot, msg: &Message, handlers: &[Handler]) {
let Some(text) = msg.text() else {
return;
};
for handler in handlers {
if let Some(url) = handler.try_extract(text) {
handle_extracted_content(bot.clone(), msg.chat.id, handler.clone(), url);
break;
if let Err(err) = handler.handle(bot, msg.chat.id, url).await {
error!(%err, "handler failed");
let _ = bot
.send_message(msg.chat.id, "Failed to fetch media, you foking donkey.")
.await;
}
return;
}
}
}
fn handle_extracted_content(bot: Bot, chat: ChatId, handler: Handler, url: String) {
tokio::spawn(async move {
if let Err(err) = handler.handle(&bot, chat, url).await {
error!(%err, "handler failed");
let _ = bot
.send_message(chat, "Failed to fetch media, you foking donkey.")
.await;
}
});
}

View File

@ -121,8 +121,12 @@ pub async fn send_media_from_path(
if let Some(cap) = caption_opt {
request = request.caption(cap);
}
if let Ok(message) = request.await {
info!(message_id = message.id.to_string(), "{} sent", kind);
match request.await {
Ok(message) => info!(message_id = message.id.to_string(), "{} sent", kind),
Err(e) => {
error!("Failed to send {}: {e}", kind.to_str());
return Err(Error::Teloxide(e));
}
}
}};
}