diff --git a/youmubot-core/src/fun/images.rs b/youmubot-core/src/fun/images.rs index 39f6b6f..cfa4aa8 100644 --- a/youmubot-core/src/fun/images.rs +++ b/youmubot-core/src/fun/images.rs @@ -48,19 +48,43 @@ async fn message_command( rating: Rating, ) -> CommandResult { let tags = args.remains().unwrap_or("touhou"); - let image = get_image( + let images = get_image( ctx.data.read().await.get::().unwrap(), rating, tags, ) .await?; - match image { - None => msg.reply(&ctx, "🖼️ No image found...\n💡 Tip: In danbooru, character names follow Japanese standards (last name before first name), so **Hakurei Reimu** might give you an image while **Reimu Hakurei** won't.").await, - Some(url) => msg.reply( - &ctx, - format!("🖼️ Here's the image you requested!\n\n{}", url), - ).await, - }?; + if images.is_empty() { + msg.reply(&ctx, "🖼️ No image found...\n💡 Tip: In danbooru, character names follow Japanese standards (last name before first name), so **Hakurei Reimu** might give you an image while **Reimu Hakurei** won't.").await?; + return Ok(()); + } + let images = std::sync::Arc::new(images); + paginate_fn( + move |page, ctx, msg: &mut Message| { + let images = images.clone(); + Box::pin(async move { + let page = page as usize; + if page >= images.len() { + Ok(false) + } else { + msg.edit(ctx, |f| { + f.content(format!( + "[🖼️ **{}/{}**] Here's the image you requested!\n\n{}", page + 1, + images.len(), + images[page] + )) + }) + .await + .map(|_| true) + .map_err(|e| e.into()) + } + }) + }, + ctx, + msg.channel_id, + std::time::Duration::from_secs(120), + ) + .await?; Ok(()) } @@ -69,7 +93,7 @@ async fn get_image( client: &::Value, rating: Rating, tags: &str, -) -> Result, Error> { +) -> Result, Error> { // Fix the tags: change whitespaces to + let tags = tags.split_whitespace().collect::>().join("_"); let req = client @@ -78,19 +102,21 @@ async fn get_image( rating.to_string(), tags )) - .query(&[("limit", "1"), ("random", "true")]) + .query(&[("limit", "50"), ("random", "true")]) .build()?; println!("{:?}", req.url()); let response: Vec = client.execute(req).await?.json().await?; Ok(response .into_iter() - .next() - .map(|v| format!("https://danbooru.donmai.us/posts/{}", v.id))) + .filter_map(|v| { + v.id.map(|id| format!("https://danbooru.donmai.us/posts/{}", id)) + }) + .collect()) } #[derive(Deserialize, Debug)] struct PostResponse { - id: u64, + id: Option, } #[derive(Copy, Clone, Debug)]