1use crate::snowflake::Snowflake;
2use crate::TitanString;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Deserialize, Serialize)]
7pub struct User<'a> {
8 pub id: Snowflake,
10 pub username: TitanString<'a>,
12 pub discriminator: TitanString<'a>,
14 #[serde(default)]
16 pub global_name: Option<TitanString<'a>>,
17 #[serde(default)]
19 pub avatar: Option<TitanString<'a>>,
20 #[serde(default)]
22 pub bot: bool,
23 #[serde(default)]
25 pub system: bool,
26 #[serde(default)]
28 pub mfa_enabled: Option<bool>,
29 #[serde(default)]
31 pub banner: Option<TitanString<'a>>,
32 #[serde(default)]
34 pub accent_color: Option<u32>,
35 #[serde(default)]
37 pub locale: Option<TitanString<'a>>,
38 #[serde(default)]
40 pub verified: Option<bool>,
41 #[serde(default)]
43 pub email: Option<TitanString<'a>>,
44 #[serde(default)]
46 pub flags: Option<u64>,
47 #[serde(default)]
49 pub premium_type: Option<u8>,
50 #[serde(default)]
52 pub public_flags: Option<u64>,
53 #[serde(default)]
55 pub avatar_decoration_data: Option<crate::json::Value>,
56}
57
58impl<'a> User<'a> {
59 pub fn avatar_url(&self) -> Option<String> {
61 self.avatar.as_ref().map(|hash| {
62 let ext = if hash.starts_with("a_") { "gif" } else { "png" };
63 format!(
64 "https://cdn.discordapp.com/avatars/{}/{}.{}",
65 self.id, hash, ext
66 )
67 })
68 }
69
70 pub fn default_avatar_url(&self) -> String {
72 let index = if self.discriminator == "0" {
73 (self.id.0 >> 22) % 6
74 } else {
75 self.discriminator.parse::<u64>().unwrap_or(0) % 5
76 };
77 format!("https://cdn.discordapp.com/embed/avatars/{}.png", index)
78 }
79
80 pub fn face(&self) -> String {
82 self.avatar_url()
83 .unwrap_or_else(|| self.default_avatar_url())
84 }
85}
86
87impl<'a> crate::Mention for User<'a> {
88 fn mention(&self) -> String {
89 format!("<@{}>", self.id.0)
90 }
91}
92
93#[derive(Debug, Clone, Deserialize, Serialize)]
95pub struct PartialUser {
96 pub id: Snowflake,
97}
98
99#[derive(Debug, Clone, Deserialize, Serialize)]
101pub struct ClientStatus {
102 #[serde(default)]
103 pub desktop: Option<String>,
104 #[serde(default)]
105 pub mobile: Option<String>,
106 #[serde(default)]
107 pub web: Option<String>,
108}
109
110#[derive(Debug, Clone, Deserialize, Serialize)]
112pub struct PresenceUpdateEvent {
113 pub user: PartialUser,
114 #[serde(default)]
115 pub guild_id: Option<Snowflake>,
116 pub status: String,
117 #[serde(default)]
118 pub activities: Vec<crate::json::Value>,
119 #[serde(default)]
120 pub client_status: Option<ClientStatus>,
121}