use crate::{
endpoints,
error::{InvalidUrl, Result},
};
use snafu::ResultExt;
use std::collections::HashMap;
use url::Url;
#[derive(Clone, Debug)]
struct Widget(u64, HashMap<&'static str, String>, bool);
impl Widget {
fn build(self) -> Result<String> {
let widget_uri = if self.2 {
endpoints::png_widget(self.0)
} else {
endpoints::widget(self.0)
};
let params = self.1.into_iter().map(|(k, v)| (k, v)).collect::<Vec<_>>();
let url = Url::parse_with_params(&widget_uri, params)
.with_context(|| InvalidUrl { uri: widget_uri })?;
Ok(url.into_string())
}
fn insert(&mut self, k: &'static str, v: impl Into<String>) -> &mut Self {
self._insert(k, v.into())
}
fn _insert(&mut self, k: &'static str, v: String) -> &mut Self {
self.1.insert(k, v);
self
}
}
#[derive(Clone, Debug)]
pub struct LargeWidget(Widget);
impl LargeWidget {
pub fn new(bot_id: u64) -> Self {
Self(Widget(bot_id, HashMap::new(), false))
}
pub fn build(self) -> Result<String> {
self.0.build()
}
pub fn top_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("topcolor", value);
self
}
pub fn middle_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("middlecolor", value);
self
}
pub fn username_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("usernamecolor", value);
self
}
pub fn certified_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("certifiedcolor", value);
self
}
pub fn data_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("datacolor", value);
self
}
pub fn label_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("labelcolor", value);
self
}
pub fn png(&mut self, value: bool) -> &mut Self {
(self.0).2 = value;
self
}
}
#[derive(Clone, Debug)]
pub struct SmallWidget(Widget);
impl SmallWidget {
pub fn new(bot_id: u64) -> Self {
Self(Widget(bot_id, HashMap::new(), false))
}
pub fn build(self) -> Result<String> {
self.0.build()
}
pub fn avatar_background(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("avatarbg", value);
self
}
pub fn left_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("leftcolor", value);
self
}
pub fn left_text_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("lefttextcolor", value);
self
}
pub fn right_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("rightcolor", value);
self
}
pub fn right_text_color(&mut self, value: impl Into<String>) -> &mut Self {
self.0.insert("righttextcolor", value);
self
}
pub fn png(&mut self, value: bool) -> &mut Self {
(self.0).2 = value;
self
}
}
#[cfg(test)]
mod tests {
use super::{LargeWidget, SmallWidget};
use crate::Result;
#[test]
fn test_small_widget() -> Result<()> {
let mut widget = SmallWidget::new(1);
widget
.avatar_background("00FF00")
.left_color("FF0000")
.left_text_color("FFFFFF")
.right_color("0F0F0F")
.right_text_color("F0F0F0")
.png(true);
let url = widget.build()?;
assert!(url.contains("avatarbg=00FF00"));
assert!(url.contains("lefttextcolor=FFFFFF"));
assert!(url.contains("leftcolor=FF0000"));
assert!(url.contains("rightcolor=0F0F0F"));
assert!(url.contains("righttextcolor=F0F0F0"));
assert!(url.starts_with("https://top.gg/api/widget/1.png?"));
Ok(())
}
#[test]
fn test_large_widget() -> Result<()> {
let mut widget = LargeWidget::new(1);
widget
.certified_color("FF0000")
.data_color("00FF00")
.label_color("0000FF")
.middle_color("FFF000")
.top_color("000FFF")
.username_color("AAAAAA");
let url = widget.build()?;
assert!(url.contains("certifiedcolor=FF0000"));
assert!(url.contains("datacolor=00FF00"));
assert!(url.contains("labelcolor=0000FF"));
assert!(url.contains("middlecolor=FFF000"));
assert!(url.contains("topcolor=000FFF"));
assert!(url.contains("usernamecolor=AAAAAA"));
assert!(url.starts_with("https://top.gg/api/widget/1.svg?"));
Ok(())
}
}