jensmemesclient/cli/src/commands/search.rs

81 lines
2.1 KiB
Rust

use anyhow::{Context, Result};
use log::info;
use std::io::Write;
use crate::{
table::{list_table, JMTableEntry, TableExt},
util,
};
use libjens::{api::Meme, JMClient};
pub async fn run(
client: &JMClient,
query: String,
user: Option<String>,
category: Option<String>,
firsturl: bool,
cat: bool,
) -> Result<()> {
let (memes, ..) = tokio::try_join!(
async { client.get_memes().await.map_err(|e| e.into()) },
async {
if let Some(u) = user.as_ref() {
util::assert_user_exists(client, u).await
} else {
Ok(())
}
},
async {
if let Some(c) = category.as_ref() {
util::assert_category_exists(client, c).await
} else {
Ok(())
}
}
)?;
let mut matches = vec![];
info!("Starting search with query '{}'", query);
let memes = memes
.iter()
.filter(|m| category.as_ref().map(|c| &m.category == c).unwrap_or(true))
.filter(|m| user.as_ref().map(|u| &m.user == u).unwrap_or(true));
for meme in memes {
let file_name = meme.file_name()?;
if let Some(score) = fuzzy_matcher::clangd::fuzzy_match(file_name, &query) {
info!("Found matching meme '{}' with score {}", file_name, score);
matches.push((meme, score));
}
}
matches.sort_by(|a, b| b.1.cmp(&a.1));
let res = match (firsturl, cat) {
(false, false) => list_table()
.type_header::<Meme>()
.add_rows(matches.into_iter().map(|(m, _)| JMTableEntry(m.clone())))
.to_string()
.into_bytes(),
(true, _) => matches
.first()
.context("No matches found")?
.0
.link
.clone()
.into_bytes(),
(_, true) => {
let url = &matches.first().context("No results found")?.0.link;
client.http.get(url).send().await?.bytes().await?.to_vec()
},
};
let stdout = std::io::stdout();
let mut handle = stdout.lock();
handle.write_all(&res)?;
Ok(())
}