Allow multiple image outputs on !image/!nsfw

This commit is contained in:
Natsu Kagami 2021-01-16 02:25:47 +09:00
parent 8d4c3e01d8
commit 0cbf74fb82
Signed by: nki
GPG key ID: 7306B3D3C3AD6E51

View file

@ -48,19 +48,43 @@ async fn message_command(
rating: Rating, rating: Rating,
) -> CommandResult { ) -> CommandResult {
let tags = args.remains().unwrap_or("touhou"); let tags = args.remains().unwrap_or("touhou");
let image = get_image( let images = get_image(
ctx.data.read().await.get::<HTTPClient>().unwrap(), ctx.data.read().await.get::<HTTPClient>().unwrap(),
rating, rating,
tags, tags,
) )
.await?; .await?;
match image { if images.is_empty() {
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, 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( return Ok(());
&ctx, }
format!("🖼️ Here's the image you requested!\n\n{}", url), let images = std::sync::Arc::new(images);
).await, 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(()) Ok(())
} }
@ -69,7 +93,7 @@ async fn get_image(
client: &<HTTPClient as TypeMapKey>::Value, client: &<HTTPClient as TypeMapKey>::Value,
rating: Rating, rating: Rating,
tags: &str, tags: &str,
) -> Result<Option<String>, Error> { ) -> Result<Vec<String>, Error> {
// Fix the tags: change whitespaces to + // Fix the tags: change whitespaces to +
let tags = tags.split_whitespace().collect::<Vec<_>>().join("_"); let tags = tags.split_whitespace().collect::<Vec<_>>().join("_");
let req = client let req = client
@ -78,19 +102,21 @@ async fn get_image(
rating.to_string(), rating.to_string(),
tags tags
)) ))
.query(&[("limit", "1"), ("random", "true")]) .query(&[("limit", "50"), ("random", "true")])
.build()?; .build()?;
println!("{:?}", req.url()); println!("{:?}", req.url());
let response: Vec<PostResponse> = client.execute(req).await?.json().await?; let response: Vec<PostResponse> = client.execute(req).await?.json().await?;
Ok(response Ok(response
.into_iter() .into_iter()
.next() .filter_map(|v| {
.map(|v| format!("https://danbooru.donmai.us/posts/{}", v.id))) v.id.map(|id| format!("https://danbooru.donmai.us/posts/{}", id))
})
.collect())
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
struct PostResponse { struct PostResponse {
id: u64, id: Option<u64>,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]