jensmemesclient/cli/src/commands/search.rs

84 lines
2.1 KiB
Rust
Raw Normal View History

use anyhow::{Context, Result};
2020-12-06 14:57:14 +01:00
use log::info;
use std::io::Write;
2020-12-05 22:20:08 +01:00
2021-05-27 18:01:30 +02:00
use crate::{
table::{self, AsTableRow},
util,
};
use jm_client_core::JMClient;
2020-12-05 22:20:08 +01:00
2020-12-21 23:06:50 +01:00
pub async fn run(
2021-05-27 18:01:30 +02:00
client: &JMClient,
2020-12-21 23:06:50 +01:00
query: String,
user: Option<String>,
category: Option<String>,
firsturl: bool,
cat: bool,
2020-12-21 23:06:50 +01:00
) -> Result<()> {
let (memes, ..) = tokio::try_join!(
2021-05-27 18:01:30 +02:00
async { client.get_memes().await.map_err(|e| e.into()) },
2020-12-21 23:06:50 +01:00
async {
if let Some(u) = user.as_ref() {
2021-05-27 18:01:30 +02:00
util::assert_user_exists(client, u).await
2020-12-21 23:06:50 +01:00
} else {
Ok(())
}
},
async {
if let Some(c) = category.as_ref() {
2021-05-27 18:01:30 +02:00
util::assert_category_exists(client, c).await
2020-12-21 23:06:50 +01:00
} else {
Ok(())
}
}
)?;
2020-12-05 22:20:08 +01:00
let mut matches = vec![];
2020-12-06 14:57:14 +01:00
info!("Starting search with query '{}'", query);
2020-12-21 23:06:50 +01:00
2021-05-27 18:01:30 +02:00
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 {
2020-12-06 14:57:14 +01:00
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);
2020-12-05 22:20:08 +01:00
matches.push((meme, score));
}
}
2020-12-05 22:31:02 +01:00
matches.sort_by(|a, b| b.1.cmp(&a.1));
let res = match (firsturl, cat) {
(false, false) => {
let mut table = table::list_table();
2020-12-05 22:20:08 +01:00
for m in matches {
2021-05-27 18:01:30 +02:00
table.add_row(m.0.as_table_row());
}
table.render().into_bytes()
},
2020-12-05 22:20:08 +01:00
(true, _) => matches
.first()
.context("No matches found")?
.0
.link
.clone()
.into_bytes(),
(_, true) => {
let url = &matches.first().context("No results found")?.0.link;
2021-05-27 18:01:30 +02:00
client.http.get(url).send().await?.bytes().await?.to_vec()
},
};
2020-12-05 22:20:08 +01:00
let stdout = std::io::stdout();
let mut handle = stdout.lock();
handle.write_all(&res)?;
2020-12-05 22:20:08 +01:00
Ok(())
}