#![allow(unused)]
use reqwest;
use image::codecs::png;
use std::io::Cursor;
mod builder;
pub use builder::DicebearBuilder;
pub mod exports {
pub use image::{self, DynamicImage, GenericImageView, ImageReader};
}
pub async fn generate_from_builder(builder:DicebearBuilder) -> Result<exports::DynamicImage, Box<dyn std::error::Error>> {
return generate(builder.avatar_style, builder.seed, builder.size, builder.flip, builder.options).await;
}
pub async fn generate_url_from_builder(format:String, builder:DicebearBuilder) -> Result<String, Box<dyn std::error::Error>> {
return generate_url(format, builder.avatar_style, builder.seed, builder.size, builder.flip, builder.options).await;
}
pub async fn generate_url(
format: String,
avatar_style: String,
seed: Option<String>,
size: String,
flip: Option<bool>,
options: Option<Vec<String>>,
) -> Result<String, Box<dyn std::error::Error>> {
let flip_str = bool::to_string(&flip.unwrap_or(false));
let url = format!(
"https://api.dicebear.com/9.x/{}/{}?seed={}&size={}&flip={}&{}",
avatar_style,
format,
seed.unwrap_or(String::from("")),
size,
flip_str,
options
.map(|v| v.join("&"))
.unwrap_or_else(|| String::from("")),
);
Ok(String::from(url))
}
pub async fn generate(
avatar_style: String,
seed: Option<String>,
size: String,
flip: Option<bool>,
options: Option<Vec<String>>
) -> Result<exports::DynamicImage, Box<dyn std::error::Error>> {
let url = generate_url(
String::from("png"),
avatar_style,
seed,
size,
flip,
options,
).await;
let response = reqwest::get(&url.unwrap())
.await;
match response {
Ok(png_img) => {
if png_img.status().is_success() {
let img = exports::image::ImageReader::new(Cursor::new(png_img.bytes().await?))
.with_guessed_format()?
.decode()?;
Ok(img)
} else {
Err("could not fetch the image, mismatched style?".into())
}
}
Err(e) => Err(Box::new(e)),
}
}
#[cfg(test)]
mod tests {
use image::GenericImageView;
use super::*;
use tokio;
#[tokio::test]
async fn get_bottts_image() {
let result = generate(
String::from("bottts"),
Some(String::from("dunno")),
String::from("256"),
Some(true),
None,
).await;
let img = result.unwrap();
assert!(img.dimensions().0 == 256, "bottts: width is wrong for unknown reasons! aborting!");
assert!(img.dimensions().1 == 256, "bottts: height is wrong for unknown reasons! aborting!");
}
#[tokio::test]
async fn get_thumbs_image() {
let result = generate(
String::from("thumbs"),
Some(String::from("teesh3rt")),
String::from("128"),
Some(false),
None,
).await;
let img = result.unwrap();
assert!(img.dimensions().0 == 128, "thumbs: width is wrong for unknown reasons! aborting!");
assert!(img.dimensions().1 == 128, "thumbs: height is wrong for unknown reasons! aborting!");
}
#[tokio::test]
async fn test_url() {
let url = generate_url(
String::from("png"),
String::from("thumbs"),
Some(String::from("user0")),
String::from("64"),
Some(false),
None
).await.unwrap();
assert!(
url == "https://api.dicebear.com/9.x/thumbs/png?seed=user0&size=64&flip=false&",
"url did not match. generated url: {url}"
);
}
}