use chrono::{DateTime, Utc};
use serde::Deserialize;
use super::snowflake;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct UserBot {
#[serde(deserialize_with = "snowflake::as_string::deserialize")]
pub id: u64,
#[serde(deserialize_with = "snowflake::vec_as_string::deserialize")]
pub owners: Vec<u64>,
pub deleted: bool,
pub name: String,
pub avatar: Option<String>,
#[serde(rename = "short_desc")]
pub short_description: String,
pub lib: Option<String>,
pub prefix: String,
pub website: Option<String>,
#[serde(rename = "approved_at")]
pub approved_at: Option<DateTime<Utc>>,
pub monthly_votes: i64,
pub server_count: Option<i64>,
pub total_votes: i64,
pub monthly_votes_rank: i64,
pub server_count_rank: Option<i64>,
pub total_votes_rank: i64,
pub timestamp: Option<DateTime<Utc>>,
pub unix_timestamp: Option<String>,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct UserBotsResponse {
pub bots: Vec<UserBot>,
}
impl UserBotsResponse {
#[must_use]
pub fn count(&self) -> usize {
self.bots.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.bots.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &UserBot> {
self.bots.iter()
}
#[must_use]
pub fn total_monthly_votes(&self) -> i64 {
self.bots.iter().map(|b| b.monthly_votes).sum()
}
#[must_use]
pub fn total_votes(&self) -> i64 {
self.bots.iter().map(|b| b.total_votes).sum()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_user_bot_deserialization() {
let json = r#"{
"id": "461521980492087297",
"owners": ["205680187394752512"],
"deleted": false,
"name": "Shiro",
"avatar": "https://cdn.discordapp.com/avatars/461521980492087297/abc.png",
"short_desc": "A multipurpose bot",
"lib": "discord.js",
"prefix": "s!",
"website": "https://shirobot.org",
"approved_at": "2018-09-22T11:25:10.962Z",
"monthly_votes": 3,
"server_count": 17762,
"total_votes": 61387,
"monthly_votes_rank": 7556,
"server_count_rank": 501,
"total_votes_rank": 282,
"timestamp": "2024-10-28T18:00:00.000Z",
"unix_timestamp": "1730138400000"
}"#;
let bot: UserBot = serde_json::from_str(json).unwrap();
assert_eq!(bot.id, 461_521_980_492_087_297);
assert_eq!(bot.name, "Shiro");
assert_eq!(bot.owners.len(), 1);
assert_eq!(bot.owners[0], 205_680_187_394_752_512);
assert!(!bot.deleted);
assert_eq!(bot.server_count, Some(17762));
}
#[test]
fn test_user_bots_response_deserialization() {
let json = r#"{
"bots": [
{
"id": "461521980492087297",
"owners": ["205680187394752512"],
"deleted": false,
"name": "Shiro",
"short_desc": "A multipurpose bot",
"prefix": "s!",
"monthly_votes": 3,
"total_votes": 61387,
"monthly_votes_rank": 7556,
"total_votes_rank": 282
},
{
"id": "583807014896140293",
"owners": ["205680187394752512"],
"deleted": false,
"name": "TopStats",
"short_desc": "Statistics bot",
"prefix": "/",
"monthly_votes": 10,
"total_votes": 500,
"monthly_votes_rank": 5000,
"total_votes_rank": 4000
}
]
}"#;
let response: UserBotsResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.count(), 2);
assert!(!response.is_empty());
assert_eq!(response.total_monthly_votes(), 13);
assert_eq!(response.total_votes(), 61887);
}
#[test]
fn test_empty_user_bots_response() {
let response = UserBotsResponse { bots: vec![] };
assert!(response.is_empty());
assert_eq!(response.count(), 0);
assert_eq!(response.total_monthly_votes(), 0);
}
}