use super::*;
#[derive(Args, Clone)]
pub struct SearchArgs {
pub query: String,
#[arg(long)]
pub detailed: bool,
#[command(flatten)]
pub filter: SearchFilter,
}
#[derive(Args, Clone, Debug)]
pub struct SearchFilter {
#[arg(long)]
pub author: Option<String>,
#[arg(long)]
pub source: Option<String>,
#[arg(long)]
pub before: Option<String>,
}
pub async fn search<I: UserInteraction>(
interaction: &mut I,
search_args: SearchArgs,
) -> Result<()> {
let SearchArgs { query, detailed, filter } = search_args;
let mut papers = Query::text(&query).execute(&mut interaction.learner().database).await?;
if let Some(author) = &filter.author {
let author_papers =
Query::by_author(author).execute(&mut interaction.learner().database).await?;
papers.retain(|p| author_papers.contains(p));
}
if let Some(source) = &filter.source {
papers.retain(|p| p.source == *source);
}
if let Some(date_str) = &filter.before {
let date = parse_date(date_str)?;
papers.retain(|p| p.publication_date < date);
}
interaction.reply(ResponseContent::Info(&format!("Searching for: {}", query)))?;
if papers.is_empty() {
interaction.reply(ResponseContent::Info("No papers found matching all criteria"))
} else {
if detailed {
for paper in papers.iter() {
interaction.reply(ResponseContent::Paper(paper))?;
}
} else {
interaction.reply(ResponseContent::Papers(&papers))?;
}
Ok(())
}
}