coc_rs/models/
clan.rs

1use serde::{Deserialize, Serialize};
2
3use crate::models::badge_urls::BadgeUrls;
4
5use super::{labels, leagues, location};
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
8#[serde(rename_all = "camelCase")]
9pub struct Clan {
10    pub tag: String,
11    pub name: String,
12    #[serde(rename = "type")]
13    pub privacy: Privacy,
14    pub description: Option<String>,
15    pub location: Option<location::Location>,
16    pub badge_urls: BadgeUrls,
17    pub clan_level: i8,
18    pub clan_points: i32,
19    pub clan_versus_points: i32,
20    pub required_trophies: i32,
21    pub war_frequency: WarFrequency,
22    pub war_win_streak: i32,
23    pub war_wins: i32,
24    pub war_ties: Option<i32>,
25    pub war_losses: Option<i32>,
26    pub is_war_log_public: bool,
27    pub war_league: leagues::WarLeague,
28    pub members: i32,
29    pub member_list: Option<Vec<ClanMember>>,
30    pub labels: Vec<labels::ClanLabel>,
31    pub required_versus_trophies: i32,
32    pub required_townhall_level: i8,
33    /// Unfortunately this isn't returned in the /clans endpoint, only for a specific clan so I'm
34    /// using an option for now
35    pub clan_capital: Option<ClanCapital>,
36    pub chat_language: Option<ChatLanguage>,
37}
38
39impl Clan {
40    #[must_use]
41    pub fn game_link(&self) -> String {
42        format!(
43            "https://link.clashofclans.com/en?action=OpenClanProfile&tag={}",
44            self.tag.replace('#', ""),
45        )
46    }
47    #[cfg(feature = "extra")]
48    pub fn clash_of_stats_link(&self) -> String {
49        format!("https://www.clashofstats.com/clans/{}/summary", self.tag.replace('#', ""))
50    }
51    #[cfg(feature = "extra")]
52    pub fn chocolate_clash_link(&self) -> String {
53        format!("https://cc.chocolateclash.com/cc_n/clan.php?tag={}", self.tag.replace('#', ""))
54    }
55}
56
57#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Clone, Copy, Ord)]
58pub enum Privacy {
59    #[serde(rename = "open")]
60    Open,
61    #[serde(rename = "inviteOnly")]
62    InviteOnly,
63    #[serde(rename = "closed")]
64    Closed,
65}
66
67impl Privacy {
68    #[must_use]
69    pub fn is_open(&self) -> bool {
70        self == &Self::Open
71    }
72    #[must_use]
73    pub fn is_invite_only(&self) -> bool {
74        self == &Self::InviteOnly
75    }
76    #[must_use]
77    pub fn is_closed(&self) -> bool {
78        self == &Self::Closed
79    }
80}
81
82impl ToString for Privacy {
83    fn to_string(&self) -> String {
84        match self {
85            Self::Open => "Anyone Can Join".to_string(),
86            Self::InviteOnly => "Invite Only".to_string(),
87            Self::Closed => "Closed".to_string(),
88        }
89    }
90}
91
92#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Clone, Copy, Ord)]
93pub enum WarFrequency {
94    #[serde(rename = "unknown")]
95    Unknown,
96    #[serde(rename = "always")]
97    Always,
98    #[serde(rename = "moreThanOncePerWeek")]
99    MoreThanOncePerWeek,
100    #[serde(rename = "oncePerWeek")]
101    OncePerWeek,
102    #[serde(rename = "lessThanOncePerWeek")]
103    LessThanOncePerWeek,
104    #[serde(rename = "never")]
105    Never,
106    #[serde(rename = "any")]
107    Any,
108}
109
110impl WarFrequency {
111    #[must_use]
112    pub fn is_unknown(&self) -> bool {
113        self == &Self::Unknown
114    }
115    #[must_use]
116    pub fn is_always(&self) -> bool {
117        self == &Self::Always
118    }
119    #[must_use]
120    pub fn is_more_than_once_per_week(&self) -> bool {
121        self == &Self::MoreThanOncePerWeek
122    }
123    #[must_use]
124    pub fn is_once_per_week(&self) -> bool {
125        self == &Self::OncePerWeek
126    }
127    #[must_use]
128    pub fn is_less_than_once_per_week(&self) -> bool {
129        self == &Self::LessThanOncePerWeek
130    }
131    #[must_use]
132    pub fn is_never(&self) -> bool {
133        self == &Self::Never
134    }
135    #[must_use]
136    pub fn is_any(&self) -> bool {
137        self == &Self::Any
138    }
139}
140
141impl ToString for WarFrequency {
142    fn to_string(&self) -> String {
143        match self {
144            Self::Unknown => "Not set".to_string(),
145            Self::Always => "Always".to_string(),
146            Self::MoreThanOncePerWeek => "Twice a week".to_string(),
147            Self::OncePerWeek => "Once a week".to_string(),
148            Self::LessThanOncePerWeek => "Rarely".to_string(),
149            Self::Never => "Never".to_string(),
150            Self::Any => "Any".to_string(),
151        }
152    }
153}
154
155#[derive(Debug, Serialize, Deserialize, Clone)]
156#[serde(rename_all = "camelCase")]
157pub struct ChatLanguage {
158    pub id: i32,
159    pub name: String,
160    pub language_code: String,
161}
162
163#[derive(Debug, Serialize, Deserialize, Clone)]
164#[serde(rename_all = "camelCase")]
165pub struct ClanMember {
166    pub tag: String,
167    pub name: String,
168    pub role: Role,
169    pub exp_level: i32,
170    pub league: leagues::League,
171    pub trophies: i32,
172    pub versus_trophies: i32,
173    pub clan_rank: i32,
174    pub previous_clan_rank: i32,
175    pub donations: i32,
176    pub donations_received: i32,
177}
178
179#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
180pub enum Role {
181    #[serde(rename = "notMember")]
182    NotMember,
183    #[serde(rename = "member")]
184    Member,
185    #[serde(rename = "admin")]
186    Elder,
187    #[serde(rename = "coLeader")]
188    CoLeader,
189    #[serde(rename = "leader")]
190    Leader,
191}
192
193impl Role {
194    #[must_use]
195    pub fn is_not_member(&self) -> bool {
196        self == &Self::NotMember
197    }
198    #[must_use]
199    pub fn is_member(&self) -> bool {
200        self == &Self::Member
201    }
202    #[must_use]
203    pub fn is_elder(&self) -> bool {
204        self == &Self::Elder
205    }
206    #[must_use]
207    pub fn is_co_leader(&self) -> bool {
208        self == &Self::CoLeader
209    }
210    #[must_use]
211    pub fn is_leader(&self) -> bool {
212        self == &Self::Leader
213    }
214}
215
216impl ToString for Role {
217    fn to_string(&self) -> String {
218        match self {
219            Self::NotMember => "Not Member".to_string(),
220            Self::Member => "Member".to_string(),
221            Self::Elder => "Elder".to_string(),
222            Self::CoLeader => "Co-Leader".to_string(),
223            Self::Leader => "Leader".to_string(),
224        }
225    }
226}
227
228#[derive(Debug, Serialize, Deserialize, Clone)]
229#[serde(rename_all = "camelCase")]
230pub struct ClanCapital {
231    capital_hall_level: Option<i8>,
232    districts: Option<Vec<District>>,
233}
234
235impl ClanCapital {
236    #[must_use]
237    pub fn capital_hall_level(&self) -> i8 {
238        self.capital_hall_level.unwrap_or_default()
239    }
240    #[must_use]
241    pub fn districts(&self) -> Vec<District> {
242        self.districts.clone().unwrap_or_default()
243    }
244}
245
246#[derive(Debug, Serialize, Deserialize, Clone)]
247#[serde(rename_all = "camelCase")]
248pub struct District {
249    pub id: i32,
250    pub name: String,
251    pub district_hall_level: i8,
252}