brawl_api/model/clubs.rs
1//! Models for the `/clubs/:tag` Brawl Stars API endpoint.
2//! Included by the feature `"clubs"`; removing that feature will disable the usage of this module.
3
4#[cfg(feature = "async")]
5use async_trait::async_trait;
6
7use serde::{self, Serialize, Deserialize};
8
9use crate::traits::{PropFetchable, FetchFrom, GetFetchProp};
10use crate::error::Result;
11
12#[cfg(feature = "async")]
13use crate::util::a_fetch_route;
14
15#[cfg(feature = "players")]
16use super::players::PlayerClub;
17use crate::http::Client;
18use crate::serde::{
19 serialize_smt_pointer, deserialize_number_from_string, deserialize_default_smt_pointer,
20 oxffffff_default,
21};
22use crate::http::routes::Route;
23use crate::util::{auto_hashtag, fetch_route};
24
25use std::fmt::{Display, Formatter};
26use crate::model::rankings::ClubRanking;
27use std::cmp::Ordering;
28
29pub use members::ClubMembers;
30
31/// The type of club (whether it's open, invite-only, or closed).
32#[non_exhaustive]
33#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub enum ClubType {
36 Open,
37 InviteOnly,
38 Closed,
39}
40
41impl Default for ClubType {
42 /// Defaults to [`ClubType::Open`] (new clubs start open).
43 ///
44 /// # Examples
45 ///
46 /// ```rust
47 /// use brawl_api::ClubType;
48 ///
49 /// assert_eq!(ClubType::default(), ClubType::Open);
50 /// ```
51 ///
52 /// [`ClubType::Open`]: ./enum.ClubType.html#variant.Open
53 fn default() -> ClubType { ClubType::Open }
54}
55
56impl Display for ClubType {
57 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
58 write!(
59 f, "{}",
60 match self {
61 ClubType::Open => "Open",
62 ClubType::InviteOnly => "InviteOnly",
63 ClubType::Closed => "Closed",
64 }
65 )
66 }
67}
68
69/// A struct representing a Brawl Stars club, with all of its data.
70/// Use [`Club::fetch`] to fetch one based on tag.
71///
72/// [`Club::fetch`]: ./struct.Club.html#method.fetch
73#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
74#[serde(rename_all = "camelCase")]
75pub struct Club {
76
77 /// The club's tag. **Note: this includes the initial '#'.**
78 #[serde(default)]
79 pub tag: String,
80
81 /// The club's name.
82 #[serde(default)]
83 pub name: String,
84
85 /// The club's description.
86 #[serde(default)]
87 pub description: Option<String>,
88
89 /// The club's trophies.
90 #[serde(default)]
91 pub trophies: usize,
92
93 /// The amount of trophies required to enter on this club, or 0 if it allows any amount.
94 #[serde(default)]
95 pub required_trophies: usize,
96
97 /// The members in this club, as a vector of [`ClubMember`] (note that the [`ClubMembers`]
98 /// struct is simply a smart pointer for `Vec<ClubMember>`).
99 ///
100 /// [`ClubMember`]: struct.ClubMember.html
101 /// [`ClubMembers`]: ./members/struct.ClubMembers.html
102 #[serde(default)]
103 #[serde(serialize_with="serialize_smt_pointer")]
104 #[serde(deserialize_with="deserialize_default_smt_pointer")]
105 pub members: ClubMembers, // Vec<ClubMember>,
106
107 /// The type of club (see [`ClubType`] docs).
108 ///
109 /// [`ClubType`]: ./enum.ClubType.html
110 #[serde(rename = "type")]
111 #[serde(default)]
112 pub club_type: ClubType
113}
114
115impl Default for Club {
116
117
118 /// Returns an instance of `Club` with initial values.
119 ///
120 /// # Examples
121 ///
122 /// ```rust
123 /// use brawl_api::{Club, ClubType, ClubMembers};
124 ///
125 /// assert_eq!(
126 /// Club::default(),
127 /// Club {
128 /// tag: String::from(""),
129 /// name: String::from(""),
130 /// description: None,
131 /// trophies: 0,
132 /// required_trophies: 0,
133 /// members: ClubMembers::default(),
134 /// club_type: ClubType::Open,
135 /// }
136 /// );
137 /// ```
138 fn default() -> Club {
139 Club {
140 tag: String::from(""),
141 name: String::from(""),
142 description: None,
143 trophies: 0,
144 required_trophies: 0,
145 members: ClubMembers::default(),
146 club_type: ClubType::Open,
147 }
148 }
149}
150
151impl GetFetchProp for Club {
152 type Property = str;
153
154 fn get_fetch_prop(&self) -> &str { &self.tag }
155
156 fn get_route(tag: &str) -> Route { Route::Club(auto_hashtag(tag)) }
157}
158
159#[cfg_attr(feature = "async", async_trait)]
160impl PropFetchable for Club {
161 type Property = str;
162
163 /// (Sync) Fetches a club from its tag.
164 ///
165 /// # Errors
166 ///
167 /// This function may error:
168 /// - While requesting (will return an [`Error::Request`]);
169 /// - After receiving a bad status code (API or other error - returns an [`Error::Status`]);
170 /// - After a ratelimit is indicated by the API, while also specifying when it is lifted ([`Error::Ratelimited`]);
171 /// - While parsing incoming JSON (will return an [`Error::Json`]).
172 ///
173 /// (All of those, of course, wrapped inside an `Err`.)
174 ///
175 /// # Examples
176 ///
177 /// ```rust,ignore
178 /// use brawl_api::{Client, Club, traits::*};
179 ///
180 /// # fn main() -> Result<(), Box<dyn ::std::error::Error>> {
181 /// let my_client = Client::new("my auth token");
182 /// let club = Club::fetch(&my_client, "#CLUBTAGHERE")?;
183 /// // now the data for the given club is available for use.
184 ///
185 /// # Ok(())
186 /// # }
187 /// ```
188 ///
189 /// [`Error::Request`]: error/enum.Error.html#variant.Request
190 /// [`Error::Status`]: error/enum.Error.html#variant.Status
191 /// [`Error::Ratelimited`]: error/enum.Error.html#variant.Ratelimited
192 /// [`Error::Json`]: error/enum.Error.html#variant.Json
193 fn fetch(client: &Client, tag: &str) -> Result<Club> {
194 let route = Club::get_route(tag);
195 let mut club = fetch_route::<Club>(client, &route)?;
196 club.members.tag = club.tag.clone();
197 Ok(club)
198 }
199
200 /// (Async) Fetches a club from its tag.
201 ///
202 /// # Errors
203 ///
204 /// This function may error:
205 /// - While requesting (will return an [`Error::Request`]);
206 /// - After receiving a bad status code (API or other error - returns an [`Error::Status`]);
207 /// - After a ratelimit is indicated by the API, while also specifying when it is lifted ([`Error::Ratelimited`]);
208 /// - While parsing incoming JSON (will return an [`Error::Json`]).
209 ///
210 /// (All of those, of course, wrapped inside an `Err`.)
211 ///
212 /// # Examples
213 ///
214 /// ```rust,ignore
215 /// use brawl_api::{Client, Club, traits::*};
216 ///
217 /// # async fn main() -> Result<(), Box<dyn ::std::error::Error>> {
218 /// let my_client = Client::new("my auth token");
219 /// let club = Club::a_fetch(&my_client, "#CLUBTAGHERE").await?;
220 /// // now the data for the given club is available for use.
221 ///
222 /// # Ok(())
223 /// # }
224 /// ```
225 ///
226 /// [`Error::Request`]: error/enum.Error.html#variant.Request
227 /// [`Error::Status`]: error/enum.Error.html#variant.Status
228 /// [`Error::Ratelimited`]: error/enum.Error.html#variant.Ratelimited
229 /// [`Error::Json`]: error/enum.Error.html#variant.Json
230 #[cfg(feature="async")]
231 async fn a_fetch(client: &Client, tag: &'async_trait str) -> Result<Club>
232 where Self: 'async_trait,
233 Self::Property: 'async_trait,
234 {
235 let route = Club::get_route(tag);
236 let mut club = a_fetch_route::<Club>(client, &route).await?;
237 club.members.tag = club.tag.clone();
238 Ok(club)
239 }
240}
241
242#[cfg_attr(feature = "async", async_trait)]
243#[cfg(feature = "players")]
244impl FetchFrom<PlayerClub> for Club {
245 /// (Sync) Fetches a `Club` using data from a [`PlayerClub`] object.
246 ///
247 /// [`PlayerClub`]: ../../players/player/struct.PlayerClub.html
248 fn fetch_from(client: &Client, p_club: &PlayerClub) -> Result<Club> {
249 Club::fetch(client, &p_club.tag)
250 }
251
252 /// (Async) Fetches a `Club` using data from a [`PlayerClub`] object.
253 ///
254 /// [`PlayerClub`]: ../../players/player/struct.PlayerClub.html
255 #[cfg(feature = "async")]
256 async fn a_fetch_from(client: &Client, p_club: &PlayerClub) -> Result<Club> {
257 Club::a_fetch(client, &p_club.tag).await
258 }
259}
260
261#[cfg_attr(feature = "async", async_trait)]
262#[cfg(feature = "rankings")]
263impl FetchFrom<ClubRanking> for Club {
264
265 /// (Sync) Fetches a `Club` using data from a [`ClubRanking`] object.
266 ///
267 /// [`ClubRanking`]: ../../rankings/clubs/struct.ClubRanking.html
268 fn fetch_from(client: &Client, c_ranking: &ClubRanking) -> Result<Club> {
269 Club::fetch(client, &c_ranking.tag)
270 }
271
272 /// (Async) Fetches a `Club` using data from a [`ClubRanking`] object.
273 ///
274 /// [`ClubRanking`]: ../../rankings/clubs/struct.ClubRanking.html
275 #[cfg(feature = "async")]
276 async fn a_fetch_from(client: &Client, c_ranking: &ClubRanking) -> Result<Club> {
277 Club::a_fetch(client, &c_ranking.tag).await
278 }
279}
280
281/// An enum representing a member's possible roles (See [`ClubMember`]).
282///
283/// [`ClubMember`]: ./struct.ClubMember.html
284#[non_exhaustive]
285#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
286#[serde(rename_all = "camelCase")]
287pub enum ClubMemberRole {
288 Member = 0,
289 Senior = 1,
290 VicePresident = 2,
291 President = 3,
292}
293
294impl Display for ClubMemberRole {
295 /// Writes this `ClubMemberRole` variant's name.
296 ///
297 /// # Examples
298 ///
299 /// ```rust
300 /// use brawl_api::ClubMemberRole;
301 ///
302 /// assert_eq!(
303 /// format!("{}", ClubMemberRole::Senior),
304 /// String::from("Senior")
305 /// );
306 /// ```
307 fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result {
308 write!(
309 f, "{}",
310 match *self {
311 ClubMemberRole::Member => "Member",
312 ClubMemberRole::Senior => "Senior",
313 ClubMemberRole::VicePresident => "VicePresident",
314 ClubMemberRole::President => "President",
315 }
316 )
317 }
318}
319
320impl PartialOrd for ClubMemberRole {
321 /// Compares and determines which `ClubMemberRole` is higher in the hierarchy:
322 /// `Member < Senior < VicePresident < President`.
323 ///
324 /// # Examples
325 ///
326 /// ```rust
327 /// use brawl_api::ClubMemberRole;
328 ///
329 /// // vice-president has more power (is higher in the hierarchy) than a normal Member
330 /// assert!(ClubMemberRole::Member < ClubMemberRole::VicePresident);
331 /// assert!(ClubMemberRole::President > ClubMemberRole::VicePresident);
332 /// assert!(ClubMemberRole::Senior > ClubMemberRole::Member);
333 /// assert!(ClubMemberRole::Member >= ClubMemberRole::Member);
334 /// ```
335 fn partial_cmp(&self, other: &ClubMemberRole) -> Option<Ordering> {
336 Some(self.cmp(other))
337 }
338}
339
340impl Ord for ClubMemberRole {
341 /// Compares and determines which `ClubMemberRole` is higher in the hierarchy:
342 /// `Member < Senior < VicePresident < President`.
343 ///
344 /// # Examples
345 ///
346 /// ```rust
347 /// use brawl_api::ClubMemberRole;
348 ///
349 /// // vice-president has more power (is higher in the hierarchy) than a normal Member
350 /// assert!(ClubMemberRole::Member < ClubMemberRole::VicePresident);
351 /// assert!(ClubMemberRole::President > ClubMemberRole::VicePresident);
352 /// assert!(ClubMemberRole::Senior > ClubMemberRole::Member);
353 /// assert!(ClubMemberRole::Member >= ClubMemberRole::Member);
354 /// ```
355 fn cmp(&self, other: &ClubMemberRole) -> Ordering {
356 (*self as u8).cmp(&(*other as u8))
357 }
358}
359
360impl Default for ClubMemberRole {
361 /// Defaults to [`ClubMemberRole::Member`] - that is the initial role that any club member
362 /// adquires after joining (it may be promoted later, though).
363 ///
364 /// # Examples
365 ///
366 /// ```rust
367 /// use brawl_api::ClubMemberRole;
368 ///
369 /// assert_eq!(ClubMemberRole::default(), ClubMemberRole::Member);
370 /// ```
371 ///
372 /// [`ClubMemberRole::Member`]: ./enum.ClubMemberRole.html#variant.Member
373 fn default() -> ClubMemberRole { ClubMemberRole::Member }
374}
375
376/// A struct representing a Brawl Stars club's member, with its club-relevant data
377/// (most importantly, its role). Use [`Player::fetch_from`] to fetch the full player data.
378///
379/// [`Player::fetch_from`]: ../players/player/struct.Player.html#method.fetch_from
380#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
381#[serde(rename_all = "camelCase")]
382pub struct ClubMember {
383
384 /// The member's tag.
385 #[serde(default)]
386 pub tag: String,
387
388 /// The member's name.
389 #[serde(default)]
390 pub name: String,
391
392 /// The member's trophies.
393 #[serde(default)]
394 pub trophies: usize,
395
396 /// The member's role in the guild. (Default is [`ClubMemberRole::Member`])
397 ///
398 /// [`ClubMemberRole::Member`]: ./enum.ClubMemberRole.html#variant.Member
399 #[serde(default)]
400 pub role: ClubMemberRole,
401
402 /// The member's name color, as an integer (Default is 0xffffff = 16777215 - this is used
403 /// when the data is not available).
404 #[serde(default = "oxffffff_default")]
405 #[serde(deserialize_with = "deserialize_number_from_string")] // parse num
406 pub name_color: u64
407}
408
409impl PartialOrd for ClubMember {
410 /// Compares and determines which `ClubMember` has a higher role.
411 ///
412 /// # Examples
413 ///
414 /// (**NOTE:** Club members are not meant to be initialized, but rather obtained from
415 /// a fetched [`Club`] instance. They are only instantiated here for this example.)
416 ///
417 /// ```rust
418 /// use brawl_api::{ClubMember, ClubMemberRole};
419 ///
420 /// let member_1 = ClubMember { role: ClubMemberRole::Member, ..ClubMember::default() };
421 /// let member_2 = ClubMember { role: ClubMemberRole::VicePresident, ..ClubMember::default() };
422 ///
423 /// assert!(member_1 < member_2) // vice-president has more power than a normal Member
424 /// ```
425 ///
426 /// [`Club`]: struct.Club.html
427 fn partial_cmp(&self, other: &ClubMember) -> Option<Ordering> {
428 Some(self.cmp(other))
429 }
430}
431
432impl Ord for ClubMember {
433 /// Compares and determines which `ClubMember` has a higher role.
434 ///
435 /// # Examples
436 ///
437 /// (**NOTE:** Club members are not meant to be initialized, but rather obtained from
438 /// a fetched [`Club`] instance. They are only instantiated here for this example.)
439 ///
440 /// ```rust
441 /// use brawl_api::{ClubMember, ClubMemberRole};
442 ///
443 /// let member_1 = ClubMember { role: ClubMemberRole::Member, ..ClubMember::default() };
444 /// let member_2 = ClubMember { role: ClubMemberRole::VicePresident, ..ClubMember::default() };
445 ///
446 /// assert!(member_1 < member_2) // vice-president has more power than a normal Member
447 /// ```
448 ///
449 /// [`Club`]: struct.Club.html
450 fn cmp(&self, other: &ClubMember) -> Ordering {
451 self.role.cmp(&other.role)
452 }
453}
454
455impl Default for ClubMember {
456
457 /// Returns an instance of `ClubMember` with initial values.
458 ///
459 /// # Examples
460 ///
461 /// ```rust
462 /// use brawl_api::model::{ClubMember, ClubMemberRole};
463 ///
464 /// assert_eq!(
465 /// ClubMember::default(),
466 /// ClubMember {
467 /// tag: String::from(""),
468 /// name: String::from(""),
469 /// trophies: 0,
470 /// role: ClubMemberRole::default(),
471 /// name_color: 0xff_ff_ff
472 /// }
473 /// );
474 /// ```
475 fn default() -> ClubMember {
476 ClubMember {
477 tag: String::from(""),
478 name: String::from(""),
479 trophies: 0,
480 role: ClubMemberRole::default(),
481 name_color: 0xff_ff_ff
482 }
483 }
484}
485
486/// Contains the model for the `/clubs/:tag/members` endpoint, which simply retrieves a club's
487/// members without needing to get the rest of the data.
488pub mod members {
489 use super::*;
490 use std::ops::{Deref, DerefMut};
491
492 /// Represents a list of Club members, without relating to a previous [`Club`] object.
493 /// This is only used if one does not want to fetch full club data, but only its members.
494 ///
495 /// Use [`ClubMembers::fetch`] to fetch the members from a specific club tag.
496 ///
497 /// [`Club`]: ../struct.Club.html
498 /// [`ClubMembers::fetch`]: #method.fetch
499 #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
500 pub struct ClubMembers {
501 /// The tag of the club whose members were fetched.
502 #[serde(skip)] // artificial
503 pub tag: String,
504
505 /// The fetched members of the specified club.
506 #[serde(default)]
507 pub items: Vec<ClubMember>
508 }
509
510 impl Deref for ClubMembers {
511 type Target = Vec<ClubMember>;
512
513 /// Obtain the club's members - dereferencing returns the [`items`] field.
514 ///
515 /// # Examples
516 ///
517 /// ```rust,ignore
518 /// use brawl_api::{Client, ClubMembers, traits::*};
519 ///
520 /// # fn main() -> Result<(), Box<dyn ::std::error::Error>> {
521 /// let client = Client::new("my auth token");
522 /// let members = ClubMembers::fetch(
523 /// &client, // <- the client containing the auth key
524 /// "#CLUB_TAG_HERE" // <- the club whose members should be fetched
525 /// )?;
526 ///
527 /// assert_eq!(members.items, *members);
528 ///
529 /// # Ok(())
530 /// # }
531 ///
532 /// ```
533 ///
534 /// [`items`]: #structfield.items
535 fn deref(&self) -> &Vec<ClubMember> {
536 &self.items
537 }
538 }
539
540 impl DerefMut for ClubMembers {
541 /// Obtain the club's members - dereferencing returns the [`items`] field.
542 ///
543 /// # Examples
544 ///
545 /// ```rust,ignore
546 /// use brawl_api::{Client, ClubMembers, traits::*};
547 ///
548 /// # fn main() -> Result<(), Box<dyn ::std::error::Error>> {
549 /// let client = Client::new("my auth token");
550 /// let members = ClubMembers::fetch(
551 /// &client, // <- the client containing the auth key
552 /// "#CLUB_TAG_HERE" // <- the club whose members should be fetched
553 /// )?;
554 ///
555 /// assert_eq!(members.items, *members);
556 ///
557 /// # Ok(())
558 /// # }
559 ///
560 /// ```
561 ///
562 /// [`items`]: #structfield.items
563 fn deref_mut(&mut self) -> &mut Vec<ClubMember> {
564 &mut self.items
565 }
566 }
567
568 impl GetFetchProp for ClubMembers {
569 type Property = str;
570
571 fn get_fetch_prop(&self) -> &str {
572 &*self.tag
573 }
574
575 fn get_route(tag: &str) -> Route {
576 Route::ClubMembers(auto_hashtag(tag))
577 }
578 }
579
580 impl From<Club> for ClubMembers {
581 /// Simply returns a given [`Club`]'s [`members`][Club.members] field.
582 ///
583 /// [`Club`]: ../struct.Club.html
584 /// [Club.members]: ../struct.Club.html#structfield.members
585 fn from(club: Club) -> ClubMembers {
586 club.members
587 }
588 }
589
590 impl From<&Club> for ClubMembers {
591 /// Simply returns a given [`Club`]'s [`members`][Club.members] field,
592 /// **while cloning**.
593 ///
594 /// [`Club`]: ../struct.Club.html
595 /// [Club.members]: ../struct.Club.html#structfield.members
596 fn from(club: &Club) -> ClubMembers {
597 club.members.to_owned()
598 }
599 }
600
601 impl<'a> From<&'a Club> for &'a ClubMembers {
602 /// Simply returns a given [`Club`]'s [`members`][Club.members] field.
603 ///
604 /// [`Club`]: ../struct.Club.html
605 /// [Club.members]: ../struct.Club.html#structfield.members
606 fn from(club: &'a Club) -> Self {
607 (&club.members) as &'a ClubMembers
608 }
609 }
610
611 #[cfg_attr(feature = "async", async_trait)]
612 impl PropFetchable for ClubMembers {
613 type Property = str;
614
615 /// (Sync) Fetches a club's members, given its tag, without fetching the rest of the data.
616 /// (If it is desired to fetch the rest of the data as well, simply fetching a [`Club`] is
617 /// enough, since that also fetches all of the members.)
618 ///
619 /// # Errors
620 ///
621 /// This function may error:
622 /// - While requesting (will return an [`Error::Request`]);
623 /// - After receiving a bad status code (API or other error - returns an [`Error::Status`]);
624 /// - After a ratelimit is indicated by the API, while also specifying when it is lifted ([`Error::Ratelimited`]);
625 /// - While parsing incoming JSON (will return an [`Error::Json`]).
626 ///
627 /// (All of those, of course, wrapped inside an `Err`.)
628 ///
629 /// # Examples
630 ///
631 /// ```rust,ignore
632 /// use brawl_api::{Client, ClubMembers, traits::*};
633 ///
634 /// # fn main() -> Result<(), Box<dyn ::std::error::Error>> {
635 /// let my_client = Client::new("my auth token");
636 /// let club_members = ClubMembers::fetch(&my_client, "#CLUBTAGHERE")?;
637 /// // now the members of the club with the given tag are available in the code
638 ///
639 /// # Ok(())
640 /// # }
641 /// ```
642 ///
643 /// [`Club`]: ../struct.Club.html
644 /// [`Error::Request`]: error/enum.Error.html#variant.Request
645 /// [`Error::Status`]: error/enum.Error.html#variant.Status
646 /// [`Error::Ratelimited`]: error/enum.Error.html#variant.Ratelimited
647 /// [`Error::Json`]: error/enum.Error.html#variant.Json
648 fn fetch(client: &Client, tag: &str) -> Result<ClubMembers> {
649 let route = Self::get_route(tag);
650 let mut members = fetch_route::<ClubMembers>(client, &route)?;
651 members.tag = tag.to_owned();
652 Ok(members)
653 }
654
655 /// (Async) Fetches a club's members, given its tag, without fetching the rest of the data.
656 /// (If it is desired to fetch the rest of the data as well, simply fetching a [`Club`] is
657 /// enough, since that also fetches all of the members.)
658 ///
659 /// # Errors
660 ///
661 /// This function may error:
662 /// - While requesting (will return an [`Error::Request`]);
663 /// - After receiving a bad status code (API or other error - returns an [`Error::Status`]);
664 /// - After a ratelimit is indicated by the API, while also specifying when it is lifted ([`Error::Ratelimited`]);
665 /// - While parsing incoming JSON (will return an [`Error::Json`]).
666 ///
667 /// (All of those, of course, wrapped inside an `Err`.)
668 ///
669 /// # Examples
670 ///
671 /// ```rust,ignore
672 /// use brawl_api::{Client, ClubMembers, traits::*};
673 ///
674 /// # async fn main() -> Result<(), Box<dyn ::std::error::Error>> {
675 /// let my_client = Client::new("my auth token");
676 /// let club_members = ClubMembers::a_fetch(&my_client, "#CLUBTAGHERE").await?;
677 /// // now the members of the club with the given tag are available in the code
678 ///
679 /// # Ok(())
680 /// # }
681 /// ```
682 ///
683 /// [`Club`]: ../struct.Club.html
684 /// [`Error::Request`]: error/enum.Error.html#variant.Request
685 /// [`Error::Status`]: error/enum.Error.html#variant.Status
686 /// [`Error::Ratelimited`]: error/enum.Error.html#variant.Ratelimited
687 /// [`Error::Json`]: error/enum.Error.html#variant.Json
688 #[cfg(feature="async")]
689 async fn a_fetch(client: &Client, tag: &'async_trait str) -> Result<ClubMembers>
690 where Self: 'async_trait,
691 Self::Property: 'async_trait,
692 {
693 let route = ClubMembers::get_route(tag);
694 let mut members = a_fetch_route::<ClubMembers>(client, &route).await?;
695 members.tag = tag.to_owned();
696 Ok(members)
697 }
698 }
699
700 impl Default for ClubMembers {
701 /// Returns an instance of `ClubMembers` with initial values.
702 ///
703 /// # Examples
704 ///
705 /// ```rust
706 /// use brawl_api::model::ClubMembers;
707 ///
708 /// assert_eq!(
709 /// ClubMembers::default(),
710 /// ClubMembers {
711 /// tag: String::from(""),
712 /// items: vec![],
713 /// }
714 /// );
715 /// ```
716 fn default() -> ClubMembers {
717 ClubMembers { tag: String::from(""), items: vec![] }
718 }
719 }
720}
721
722/////////////////////////////////// tests ///////////////////////////////////
723
724#[cfg(test)]
725mod tests {
726 use std::result::Result as StdResult;
727 use super::*;
728 use crate::error::Error as BrawlError;
729 use serde_json;
730
731 /// Tests for club deserialization from API-provided JSON.
732 #[test]
733 fn club_deser() -> StdResult<(), Box<dyn ::std::error::Error>> {
734 let club_json_s = r##"{
735 "tag": "#GGGGGGG",
736 "name": "Club",
737 "description": "Brawl Stars club",
738 "type": "open",
739 "requiredTrophies": 1000,
740 "trophies": 60000,
741 "members": [
742 {
743 "tag": "#PPP200JJJ",
744 "name": "Member #1",
745 "nameColor": "0xffff8afb",
746 "role": "vicePresident",
747 "trophies": 500
748 },
749 {
750 "tag": "#CCCCCCCCCC",
751 "name": "Member #2",
752 "nameColor": "0xff1ba5f5",
753 "role": "president",
754 "trophies": 200
755 },
756 {
757 "tag": "#VVVVVVVVV",
758 "name": "Member #3",
759 "nameColor": "0xffffff",
760 "role": "member",
761 "trophies": 8500
762 },
763 {
764 "tag": "#9999999999",
765 "name": "Member #4",
766 "nameColor": "0xff4ddba2",
767 "role": "member",
768 "trophies": 20000
769 },
770 {
771 "tag": "#UUUUUU888",
772 "name": "Member #5",
773 "nameColor": "0xff1ba5f5",
774 "role": "senior",
775 "trophies": 4500
776 },
777 {
778 "tag": "#JJJJJJJJJ",
779 "name": "Member ██▬█",
780 "nameColor": "0xff1ba5f5",
781 "role": "member",
782 "trophies": 26300
783 }
784 ]
785}"##;
786
787 let club: Club = serde_json::from_str::<Club>(club_json_s)
788 .map_err(BrawlError::Json)?;
789
790 assert_eq!(
791 club,
792 Club {
793 tag: String::from("#GGGGGGG"),
794 name: String::from("Club"),
795 description: Some(String::from("Brawl Stars club")),
796 club_type: ClubType::Open,
797 required_trophies: 1000,
798 trophies: 60000,
799 members: ClubMembers {
800 items: vec![
801 ClubMember {
802 tag: String::from("#PPP200JJJ"),
803 name: String::from("Member #1"),
804 name_color: 0xffff8afb,
805 role: ClubMemberRole::VicePresident,
806 trophies: 500
807 },
808 ClubMember {
809 tag: String::from("#CCCCCCCCCC"),
810 name: String::from("Member #2"),
811 name_color: 0xff1ba5f5,
812 role: ClubMemberRole::President,
813 trophies: 200
814 },
815 ClubMember {
816 tag: String::from("#VVVVVVVVV"),
817 name: String::from("Member #3"),
818 name_color: 0xffffff,
819 role: ClubMemberRole::Member,
820 trophies: 8500
821 },
822 ClubMember {
823 tag: String::from("#9999999999"),
824 name: String::from("Member #4"),
825 name_color: 0xff4ddba2,
826 role: ClubMemberRole::Member,
827 trophies: 20000
828 },
829 ClubMember {
830 tag: String::from("#UUUUUU888"),
831 name: String::from("Member #5"),
832 name_color: 0xff1ba5f5,
833 role: ClubMemberRole::Senior,
834 trophies: 4500
835 },
836 ClubMember {
837 tag: String::from("#JJJJJJJJJ"),
838 name: String::from("Member ██▬█"),
839 name_color: 0xff1ba5f5,
840 role: ClubMemberRole::Member,
841 trophies: 26300
842 }
843 ],
844 ..ClubMembers::default()
845 }
846 }
847 );
848
849 Ok(())
850 }
851
852 /// Tests for ClubMembers deserialization from API-provided JSON.
853 #[test]
854 fn club_members_deser() -> StdResult<(), Box<dyn ::std::error::Error>> {
855 let cm_json_s = r##"{
856 "items": [
857 {
858 "tag": "#PPP200JJJ",
859 "name": "Member #1",
860 "nameColor": "0xffff8afb",
861 "role": "vicePresident",
862 "trophies": 500
863 },
864 {
865 "tag": "#CCCCCCCCCC",
866 "name": "Member #2",
867 "nameColor": "0xff1ba5f5",
868 "role": "president",
869 "trophies": 200
870 },
871 {
872 "tag": "#VVVVVVVVV",
873 "name": "Member #3",
874 "nameColor": "0xffffff",
875 "role": "member",
876 "trophies": 8500
877 },
878 {
879 "tag": "#9999999999",
880 "name": "Member #4",
881 "nameColor": "0xff4ddba2",
882 "role": "member",
883 "trophies": 20000
884 },
885 {
886 "tag": "#UUUUUU888",
887 "name": "Member #5",
888 "nameColor": "0xff1ba5f5",
889 "role": "senior",
890 "trophies": 4500
891 },
892 {
893 "tag": "#JJJJJJJJJ",
894 "name": "Member ██▬█",
895 "nameColor": "0xff1ba5f5",
896 "role": "member",
897 "trophies": 26300
898 }
899 ],
900 "paging": {
901 "cursors": {}
902 }
903}"##;
904 let club_members: ClubMembers = serde_json::from_str::<ClubMembers>(cm_json_s)
905 .map_err(BrawlError::Json)?;
906
907 assert_eq!(
908 club_members,
909 ClubMembers {
910 items: vec![
911 ClubMember {
912 tag: String::from("#PPP200JJJ"),
913 name: String::from("Member #1"),
914 name_color: 0xffff8afb,
915 role: ClubMemberRole::VicePresident,
916 trophies: 500
917 },
918 ClubMember {
919 tag: String::from("#CCCCCCCCCC"),
920 name: String::from("Member #2"),
921 name_color: 0xff1ba5f5,
922 role: ClubMemberRole::President,
923 trophies: 200
924 },
925 ClubMember {
926 tag: String::from("#VVVVVVVVV"),
927 name: String::from("Member #3"),
928 name_color: 0xffffff,
929 role: ClubMemberRole::Member,
930 trophies: 8500
931 },
932 ClubMember {
933 tag: String::from("#9999999999"),
934 name: String::from("Member #4"),
935 name_color: 0xff4ddba2,
936 role: ClubMemberRole::Member,
937 trophies: 20000
938 },
939 ClubMember {
940 tag: String::from("#UUUUUU888"),
941 name: String::from("Member #5"),
942 name_color: 0xff1ba5f5,
943 role: ClubMemberRole::Senior,
944 trophies: 4500
945 },
946 ClubMember {
947 tag: String::from("#JJJJJJJJJ"),
948 name: String::from("Member ██▬█"),
949 name_color: 0xff1ba5f5,
950 role: ClubMemberRole::Member,
951 trophies: 26300
952 }
953 ],
954 ..ClubMembers::default()
955 }
956 );
957
958 Ok(())
959 }
960}
961