use crate::{Context, Error};
use poise::serenity_prelude as serenity;
use serde::Deserialize;
use std::collections::HashMap;
#[derive(Deserialize)]
pub struct PonyResponse {
pub pony: Pony,
}
#[allow(non_snake_case)]
#[derive(Deserialize)]
pub struct Pony {
pub id: u64,
pub derpiId: Option<u64>,
pub tags: Vec<String>,
pub sourceURL: Option<String>,
pub height: u64,
pub width: u64,
pub aspectRatio: f64,
pub mimeType: String,
pub originalFormat: String,
pub representations: PonyRepresentation,
}
#[allow(non_snake_case)]
#[derive(Deserialize)]
pub struct PonyRepresentation {
pub full: String,
pub tall: String,
pub large: String,
pub medium: String,
pub small: String,
pub thumb: String,
pub thumbSmall: String,
pub thumbTiny: String,
}
/// Retrieves a random SFW pony image
#[poise::command(slash_command, prefix_command)]
pub async fn randpony(ctx: Context<'_>) -> Result<(), Error> {
let response_msg = ctx
.say("Fetching a random pony image, please wait!")
.await?;
let res = reqwest::get("https://theponyapi.com/api/v1/pony/random")
.await?
.json::<PonyResponse>()
.await?;
match response_msg.unwrap().message().await {
Ok(mut msg) => {
msg.edit(&ctx.discord(), |m| {
m.content("");
m.embed(|e| {
e.title("Pony!");
e.image(res.pony.representations.full.clone());
let res_tags = get_tags_as_string(res.pony.tags);
e.field("Tags", format!("{:?}", res_tags), true);
e.field("Image URL", res.pony.representations.full.clone(), true);
if let Some(url) = res.pony.sourceURL {
e.field("Source", url, true);
} else {
e.field("Source", "None found", true);
}
e.footer(|f| f.text(format!("Pony ID: {}", res.pony.id)))
})
})
.await?;
}
Err(_) => {
ctx.say("Error editing message").await?;
}
};
Ok(())
}
/// Get a random pony image based on a set of tags
///
/// Usage:
/// ~tpony <tags>
/// Example:
/// ~tpony twilight sparkle,fluttershy
#[poise::command(slash_command, prefix_command)]
pub async fn tpony(
ctx: Context<'_>,
#[description = "List of tags"]
#[rest]
tags: String,
) -> Result<(), Error> {
let response_msg = ctx
.say(format!(
"Fetching pony image based on tags: {:?}",
tags.clone()
))
.await?;
let res =
reqwest::get(format!("https://theponyapi.com/api/v1/pony/random?q={}", tags).as_str())
.await?
.json::<PonyResponse>()
.await?;
match response_msg.unwrap().message().await {
Ok(mut msg) => {
msg.edit(&ctx.discord(), |m| {
m.content("");
m.embed(|e| {
e.title("Pony!");
e.image(res.pony.representations.full.clone());
let res_tags = get_tags_as_string(res.pony.tags);
e.field("Tags", format!("{:?}", res_tags), true);
e.field("Image URL", res.pony.representations.full.clone(), true);
if let Some(url) = res.pony.sourceURL {
e.field("Source", url, true);
} else {
e.field("Source", "None found", true);
}
e.footer(|f| f.text(format!("Pony ID: {}", res.pony.id)))
})
})
.await?;
}
Err(e) => {
ctx.say("Error editing message").await?;
}
};
Ok(())
}
/// Gets a specific pony based on the ID
///
/// Usage:
/// /ponybyid <id>
#[poise::command(slash_command, prefix_command)]
pub async fn ponybyid(
ctx: Context<'_>,
#[description = "The ID to search for"] id: String,
) -> Result<(), Error> {
let response_msg = ctx
.say(format!("Fetching pony based on id: {}", id))
.await?;
let res = match reqwest::get(format!("https://theponyapi.com/api/v1/pony/id/{}", id).as_str())
.await
{
Ok(r) => r.json::<PonyResponse>().await?,
Err(_) => {
response_msg.unwrap().message().await.unwrap().edit(ctx.discord(), |m| {
m.content("There was an error fetching that pony, please double-check your ID and try again.")
}).await?;
return Ok(());
}
};
match response_msg.unwrap().message().await {
Ok(mut msg) => {
msg.edit(&ctx.discord(), |m| {
m.content("");
m.embed(|e| {
e.title("Pony!");
e.image(res.pony.representations.full.clone());
let res_tags = get_tags_as_string(res.pony.tags);
e.field("Tags", format!("{:?}", res_tags), true);
if let Some(url) = res.pony.sourceURL {
e.field("Source", url, true);
} else {
e.field("Source", "None found", true);
}
e.footer(|f| f.text(format!("Pony ID: {}", res.pony.id)))
})
})
.await?
}
Err(e) => {
ctx.say("Could not edit message").await?;
}
};
Ok(())
}
fn get_tags_as_string(tags: Vec<String>) -> String {
let mut response = String::from(tags.get(0).unwrap());
for (i, s) in tags.iter().enumerate() {
if i > 0 {
response.push_str(format!(", {}", s).as_str());
} else {
continue;
}
}
response
}