gw2api_rs/v2/
account.rs

1//! Exposes details about player accounts. All endpoints in this module required authentication.
2pub mod characters;
3
4use std::collections::HashMap;
5use std::fmt::{self, Formatter};
6use std::num::NonZeroU8;
7
8use chrono::{DateTime, Utc};
9use serde::de::{Error, MapAccess, SeqAccess, Visitor};
10use serde::ser::{SerializeMap, SerializeSeq};
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13use crate::{Authentication, ClientExecutor, RequestBuilder};
14
15/// Basic information about an account.
16#[derive(Clone, Debug, Serialize, Deserialize)]
17pub struct Account {
18    /// A globally unique GUID for the account.
19    pub id: String,
20    /// The age of the account in seconds.
21    pub age: u64,
22    /// The unique display name of the account. Note that it is possible for the name to
23    /// change.
24    pub name: String,
25    /// The home world of the account.
26    pub world: u64,
27    /// A list of guilds the account has joined.
28    pub guilds: Vec<String>,
29    /// A list of guilds the account has leader access to.
30    ///
31    /// **Requires the `guilds` scope.** This is `None` if the scope is missing.
32    pub guild_leader: Option<Vec<String>>,
33    /// The account creation date.
34    pub created: DateTime<Utc>,
35    /// A list of content the account has access to.
36    pub access: AccountAccess,
37    /// Whether the account has unlocked the commander tag.
38    pub commander: bool,
39    /// The fractal level of the account.
40    ///
41    /// **Requires the `progression` scope.** This is `None` if the scope is missing.
42    pub fractal_level: Option<u8>,
43    /// The number of daily achievement points unlocked by the account.
44    ///
45    /// **Requires the `progression` scope.** This is `None` if the scope is missing.
46    pub daily_ap: Option<u16>,
47    /// The number of monthly achievement points unlocked by the account.
48    ///
49    /// **Requires the `progression` scope.** This is `None` if the scope is missing.
50    pub monthly_ap: Option<u16>,
51    /// The WvW rank of the account.
52    ///
53    /// **Requires the `progression` scope.** This is `None` if the scope is missing.
54    pub wvw_rank: Option<u16>,
55    /// The date when the account information was last changed.
56    pub last_modified: DateTime<Utc>,
57    /// The amount of build storage slots unlocked by the account.
58    ///
59    /// **Requires the `builds` scope.** This is `None` if the scope is missing.
60    pub build_storage_slots: Option<u64>,
61}
62
63impl Account {
64    const URI: &'static str = "/v2/account";
65
66    /// Returns the information about the currently authenticated account.
67    ///
68    /// # Authentication
69    ///
70    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
71    /// When authenticated it returns information about the account of the current access token.
72    ///
73    /// # Examples
74    ///
75    /// ```no_run
76    /// # use gw2api_rs::{Client, Result};
77    /// # use gw2api_rs::v2::account::Account;
78    /// #
79    /// # async fn run() -> Result<()> {
80    /// # let token = "";
81    /// let client: Client = Client::builder().access_token(token).into();
82    /// let account = Account::get(&client).await?;
83    /// println!("{:?}", account);
84    /// # Ok(())
85    /// # }
86    /// ```
87    ///
88    /// Using the [`blocking`] client:
89    ///
90    /// ```no_run
91    /// # use gw2api_rs::Result;
92    /// # use gw2api_rs::blocking::Client;
93    /// # use gw2api_rs::v2::account::Account;
94    /// #
95    /// # fn run() -> Result<()> {
96    /// # let token = "";
97    /// let client: Client = Client::builder().access_token(token).into();
98    /// let account = Account::get(&client)?;
99    /// println!("{:?}", account);
100    /// # Ok(())
101    /// # }
102    /// ```
103    ///
104    /// [`Error`]: struct@crate::Error
105    /// [`blocking`]: crate::blocking
106    pub fn get<C>(client: &C) -> C::Result
107    where
108        C: ClientExecutor<Self>,
109    {
110        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
111    }
112}
113
114/// A list of content an [`Account`] has access to.
115#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
116pub struct AccountAccess(u8);
117
118impl AccountAccess {
119    const NONE: u8 = 1 << 0;
120    const PLAY_FOR_FREE: u8 = 1 << 1;
121    const GUILD_WARS_2: u8 = 1 << 2;
122    const HEART_OF_THORNS: u8 = 1 << 3;
123    const PATH_OF_FIRE: u8 = 1 << 4;
124    const END_OF_DRAGONS: u8 = 1 << 5;
125
126    const NONE_STR: &'static str = "None";
127    const PLAY_FOR_FREE_STR: &'static str = "PlayForFree";
128    const GUILD_WARS_2_STR: &'static str = "GuildWars2";
129    const HEART_OF_THORNS_STR: &'static str = "HeartOfThorns";
130    const PATH_OF_FIRE_STR: &'static str = "PathOfFire";
131    const END_OF_DRAGONS_STR: &'static str = "EndOfDragons";
132
133    #[inline]
134    fn len(&self) -> usize {
135        self.0.count_ones() as usize
136    }
137
138    /// Returns `true` if the account has no access.
139    ///
140    /// Note that this probably shouldn't ever happen.
141    #[inline]
142    pub fn none(&self) -> bool {
143        self.0 & Self::NONE != 0
144    }
145
146    /// Returns `true` if the account has free to play access.
147    #[inline]
148    pub fn play_for_free(&self) -> bool {
149        self.0 & Self::PLAY_FOR_FREE != 0
150    }
151
152    /// Returns `true` if the account has access to the base game of Guild Wars 2.
153    #[inline]
154    pub fn guild_wars_2(&self) -> bool {
155        self.0 & Self::GUILD_WARS_2 != 0
156    }
157
158    /// Returns `true` if the account has access to the Heart of Thorns expansion.
159    #[inline]
160    pub fn heart_of_thorns(&self) -> bool {
161        self.0 & Self::HEART_OF_THORNS != 0
162    }
163
164    /// Returns `true` if the account has access to the Path of Fire expansion.
165    #[inline]
166    pub fn path_of_fire(&self) -> bool {
167        self.0 & Self::PATH_OF_FIRE != 0
168    }
169
170    /// Returns `true` if the account has access to the End of Dragons expansion.
171    #[inline]
172    pub fn end_of_dragons(&self) -> bool {
173        self.0 & Self::END_OF_DRAGONS != 0
174    }
175}
176
177impl Serialize for AccountAccess {
178    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
179    where
180        S: Serializer,
181    {
182        let mut seq = serializer.serialize_seq(Some(self.len()))?;
183
184        // if self.none() {
185        //     seq.serialize_element(Self::NONE_STR)?;
186        // }
187
188        if self.play_for_free() {
189            seq.serialize_element(Self::PLAY_FOR_FREE_STR)?;
190        }
191
192        if self.guild_wars_2() {
193            seq.serialize_element(Self::GUILD_WARS_2_STR)?;
194        }
195
196        if self.heart_of_thorns() {
197            seq.serialize_element(Self::HEART_OF_THORNS_STR)?;
198        }
199
200        if self.path_of_fire() {
201            seq.serialize_element(Self::PATH_OF_FIRE_STR)?;
202        }
203
204        if self.end_of_dragons() {
205            seq.serialize_element(Self::END_OF_DRAGONS_STR)?;
206        }
207
208        seq.end()
209    }
210}
211
212impl<'de> Deserialize<'de> for AccountAccess {
213    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214    where
215        D: Deserializer<'de>,
216    {
217        struct AccountAccessVisitor;
218
219        impl<'de> Visitor<'de> for AccountAccessVisitor {
220            type Value = AccountAccess;
221
222            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
223                formatter.write_str("a sequence of access strings")
224            }
225
226            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
227            where
228                A: SeqAccess<'de>,
229            {
230                let mut state = 0;
231
232                loop {
233                    let elem = seq.next_element::<&str>()?;
234
235                    match elem {
236                        Some(AccountAccess::NONE_STR) => {
237                            state |= AccountAccess::NONE;
238                        }
239                        Some(AccountAccess::PLAY_FOR_FREE_STR) => {
240                            state |= AccountAccess::PLAY_FOR_FREE;
241                        }
242                        Some(AccountAccess::GUILD_WARS_2_STR) => {
243                            state |= AccountAccess::GUILD_WARS_2;
244                        }
245                        Some(AccountAccess::HEART_OF_THORNS_STR) => {
246                            state |= AccountAccess::HEART_OF_THORNS;
247                        }
248                        Some(AccountAccess::PATH_OF_FIRE_STR) => {
249                            state |= AccountAccess::PATH_OF_FIRE;
250                        }
251                        Some(AccountAccess::END_OF_DRAGONS_STR) => {
252                            state |= AccountAccess::END_OF_DRAGONS;
253                        }
254                        Some(_) => return Err(A::Error::custom("invalid account access")),
255                        None => return Ok(AccountAccess(state)),
256                    }
257                }
258            }
259        }
260
261        deserializer.deserialize_seq(AccountAccessVisitor)
262    }
263}
264
265/// A list of achievements unlocked by the account.
266#[derive(Clone, Debug, Serialize, Deserialize)]
267#[serde(transparent)]
268pub struct AccountAchievements(pub Vec<AccountAchievement>);
269
270impl AccountAchievements {
271    const URI: &'static str = "/v2/account/achievements";
272
273    /// Returns a list of achievements unlocked by the currently authenticated account.
274    ///
275    /// # Authentication
276    ///
277    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
278    /// When authenticated it returns a list of achievements unlocked by the account of the current
279    /// access token.
280    ///
281    /// # Examples
282    ///
283    /// ```no_run
284    /// # use gw2api_rs::{Client, Result};
285    /// # use gw2api_rs::v2::account::AccountAchievements;
286    /// #
287    /// # async fn run() -> Result<()> {
288    /// # let token = "";
289    /// let client: Client = Client::builder().access_token(token).into();
290    /// let achievements = AccountAchievements::get(&client).await?;
291    /// println!("{:?}", achievements);
292    /// # Ok(())
293    /// # }
294    /// ```
295    ///
296    /// Using the [`blocking`] client:
297    ///
298    /// ```no_run
299    /// # use gw2api_rs::Result;
300    /// # use gw2api_rs::blocking::Client;
301    /// # use gw2api_rs::v2::account::AccountAchievements;
302    /// #
303    /// # fn run() -> Result<()> {
304    /// # let token = "";
305    /// let client: Client = Client::builder().access_token(token).into();
306    /// let achievements = AccountAchievements::get(&client)?;
307    /// println!("{:?}", achievements);
308    /// # Ok(())
309    /// # }
310    /// ```
311    ///
312    /// [`Error`]: struct@crate::Error
313    /// [`blocking`]: crate::blocking
314    pub fn get<C>(client: &C) -> C::Result
315    where
316        C: ClientExecutor<Self>,
317    {
318        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
319    }
320}
321
322/// An achievement unlocked by an account.
323#[derive(Clone, Debug, Serialize, Deserialize)]
324pub struct AccountAchievement {
325    /// The id of the achievement.
326    pub id: u64,
327    pub bits: Option<Vec<u64>>,
328    /// The current progress towards the achievement.
329    pub current: Option<u64>,
330    /// The amount if objectives required to complete the achievement.
331    pub max: Option<u64>,
332    /// Whether the achievement has been completed.
333    pub done: bool,
334    /// The number of times this achievement has been completed. Only avaliable for repeatable
335    /// achievements.
336    pub repeated: Option<u64>,
337    /// Whether the achievement has been unlocked (not completed).
338    ///
339    /// Note that a `None` value also indicates that the achievment is unlocked.
340    pub unlocked: Option<bool>,
341}
342
343impl AccountAchievement {
344    /// Returns `true` if this achievement is unlocked.
345    #[inline]
346    pub fn is_unlocked(&self) -> bool {
347        self.unlocked.unwrap_or(true)
348    }
349}
350
351/// A list of items stored in the account's bank/vault.
352#[derive(Clone, Debug, Serialize, Deserialize)]
353#[serde(transparent)]
354pub struct AccountBank(pub Vec<Option<BankItem>>);
355
356impl AccountBank {
357    const URI: &'static str = "/v2/account/bank";
358
359    /// Returns a list of items stored in the account's bank.
360    ///
361    /// # Authentication
362    ///
363    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
364    /// When authenticated it returns the account's bank of the current access token.
365    ///
366    /// # Examples
367    ///
368    /// ```no_run
369    /// # use gw2api_rs::{Client, Result};
370    /// # use gw2api_rs::v2::account::AccountBank;
371    /// #
372    /// # async fn run() -> Result<()> {
373    /// # let token = "";
374    /// let client: Client = Client::builder().access_token(token).into();
375    /// let bank = AccountBank::get(&client).await?;
376    /// # Ok(())
377    /// # }
378    /// ```
379    ///
380    /// Using the [`blocking`] client:
381    ///
382    /// ```no_run
383    /// # use gw2api_rs::Result;
384    /// # use gw2api_rs::blocking::Client;
385    /// # use gw2api_rs::v2::account::AccountBank;
386    /// #
387    /// # fn run() -> Result<()> {
388    /// # let token = "";
389    /// let client: Client = Client::builder().access_token(token).into();
390    /// let bank = AccountBank::get(&client)?;
391    /// # Ok(())
392    /// # }
393    /// ```
394    ///
395    /// [`Error`]: struct@crate::Error
396    /// [`blocking`]: crate::blocking
397    pub fn get<C>(client: &C) -> C::Result
398    where
399        C: ClientExecutor<Self>,
400    {
401        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
402    }
403}
404
405/// A single item stored in an [`AccountBank`].
406#[derive(Clone, Debug, Serialize, Deserialize)]
407pub struct BankItem {
408    /// The id of the item.
409    pub id: u64,
410    /// The number of items stored on this stack.
411    pub count: u16,
412    /// The number of charges remaining on this item. Only avaliable for some items.
413    pub charges: Option<u64>,
414    /// The id of the skin applied on this item. Only avaliable for some items.
415    pub skin: Option<u64>,
416    /// A list of ids of dyes applied on this item. Only avaliable for some items.
417    pub dyes: Option<Vec<u64>>,
418    /// A list of upgrades applied on this item. Only avaliable for some items.
419    pub upgrades: Option<Vec<u64>>,
420    pub upgrade_slot_indices: Option<Vec<u64>>,
421    /// A list of infusions applied on this item. Only avaliable for some items.
422    pub infusions: Option<Vec<u64>>,
423    /// Whom the item is bound to. If `None` the item is not bound at all.
424    pub binding: Option<ItemBinding>,
425    /// The name of the character the item is bound to. Only avaliable if `binding` is
426    /// `Character`.
427    pub bound_to: Option<String>,
428    pub stats: Option<Vec<ItemStats>>,
429}
430
431#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
432pub enum ItemBinding {
433    Account,
434    Character,
435}
436
437#[derive(Clone, Debug, Serialize, Deserialize)]
438pub struct ItemStats {
439    pub id: u64,
440    pub attributes: HashMap<String, f64>,
441}
442
443/// A list of items that have been crafted by the account since daily reset.
444#[derive(Clone, Debug, Serialize, Deserialize)]
445#[serde(transparent)]
446pub struct AccountDailyCrafting(pub Vec<String>);
447
448impl AccountDailyCrafting {
449    const URI: &'static str = "/v2/account/dailycrafting";
450
451    /// Returns a list of items that have been crafted by the currently authenticated account since
452    /// daily reset.
453    ///
454    /// # Authentication
455    ///
456    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
457    /// When authenticated it returns a list of items crafted by the account of the current access
458    /// token.
459    ///
460    /// # Examples
461    ///
462    /// ```no_run
463    /// # use gw2api_rs::{Client, Result};
464    /// # use gw2api_rs::v2::account::AccountDailyCrafting;
465    /// #
466    /// # async fn run() -> Result<()> {
467    /// # let token = "";
468    /// let client: Client = Client::builder().access_token(token).into();
469    /// let items = AccountDailyCrafting::get(&client).await?;
470    /// # Ok(())
471    /// # }
472    /// ```
473    ///
474    /// Using the [`blocking`] client:
475    ///
476    /// ```no_run
477    /// # use gw2api_rs::Result;
478    /// # use gw2api_rs::blocking::Client;
479    /// # use gw2api_rs::v2::account::AccountDailyCrafting;
480    /// #
481    /// # fn run() -> Result<()> {
482    /// # let token = "";
483    /// let client: Client = Client::builder().access_token(token).into();
484    /// let items = AccountDailyCrafting::get(&client)?;
485    /// # Ok(())
486    /// # }
487    /// ```
488    ///
489    /// [`Error`]: struct@crate::Error
490    /// [`blocking`]: crate::blocking
491    pub fn get<C>(client: &C) -> C::Result
492    where
493        C: ClientExecutor<Self>,
494    {
495        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
496    }
497}
498
499/// A list of dungeon paths completed since daily reset.
500#[derive(Clone, Debug, Serialize, Deserialize)]
501pub struct AccountDungeons(pub Vec<String>);
502
503impl AccountDungeons {
504    const URI: &'static str = "/v2/account/dungeons";
505
506    /// Returns a list of dungeon paths completed by the currently authenticatd account since the
507    /// daily reset.
508    ///
509    /// # Authentication
510    ///
511    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
512    /// When authenticated it returns a list of dungeon paths completed by the account of the
513    /// current access token.
514    ///
515    /// # Examples
516    ///
517    /// ```no_run
518    /// # use gw2api_rs::{Client, Result};
519    /// # use gw2api_rs::v2::account::AccountDungeons;
520    /// #
521    /// # async fn run() -> Result<()> {
522    /// # let token = "";
523    /// let client: Client = Client::builder().access_token(token).into();
524    /// let paths = AccountDungeons::get(&client).await?;
525    /// # Ok(())
526    /// # }
527    /// ```
528    ///
529    /// Using the [`blocking`] client:
530    ///
531    /// ```no_run
532    /// # use gw2api_rs::Result;
533    /// # use gw2api_rs::blocking::Client;
534    /// # use gw2api_rs::v2::account::AccountDungeons;
535    /// #
536    /// # fn run() -> Result<()> {
537    /// # let token = "";
538    /// let client: Client = Client::builder().access_token(token).into();
539    /// let paths = AccountDungeons::get(&client)?;
540    /// # Ok(())
541    /// # }
542    /// ```
543    ///
544    /// [`Error`]: struct@crate::Error
545    /// [`blocking`]: crate::blocking
546    pub fn get<C>(client: &C) -> C::Result
547    where
548        C: ClientExecutor<Self>,
549    {
550        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
551    }
552}
553
554/// A list of dyes unlocked by an account.
555#[derive(Clone, Debug, Serialize, Deserialize)]
556#[serde(transparent)]
557pub struct AccountDyes(pub Vec<u64>);
558
559impl AccountDyes {
560    const URI: &'static str = "/v2/account/dyes";
561
562    /// Returns a list of dyes unlocked by the currently authenticated account.
563    ///
564    /// # Authentication
565    ///
566    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
567    /// When authenticated it returns the dyes unlocked by the account of the current access token.
568    ///
569    /// # Examples
570    ///
571    /// ```no_run
572    /// # use gw2api_rs::{Client, Result};
573    /// # use gw2api_rs::v2::account::AccountDyes;
574    /// #
575    /// # async fn run() -> Result<()> {
576    /// # let token = "";
577    /// let client: Client = Client::builder().access_token(token).into();
578    /// let dyes = AccountDyes::get(&client).await?;
579    /// # Ok(())
580    /// # }
581    /// ```
582    ///
583    /// Using the [`blocking`] client:
584    ///
585    /// ```no_run
586    /// # use gw2api_rs::Result;
587    /// # use gw2api_rs::blocking::Client;
588    /// # use gw2api_rs::v2::account::AccountDyes;
589    /// #
590    /// # fn run() -> Result<()> {
591    /// # let token = "";
592    /// let client: Client = Client::builder().access_token(token).into();
593    /// let dyes = AccountDyes::get(&client)?;
594    /// # Ok(())
595    /// # }
596    /// ```
597    ///
598    /// [`Error`]: struct@crate::Error
599    /// [`blocking`]: crate::blocking
600    pub fn get<C>(client: &C) -> C::Result
601    where
602        C: ClientExecutor<Self>,
603    {
604        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
605    }
606}
607
608/// A list of finishers unlocked.
609#[derive(Clone, Debug, Serialize, Deserialize)]
610#[serde(transparent)]
611pub struct AccountFinishers(pub Vec<AccountFinisher>);
612
613impl AccountFinishers {
614    const URI: &'static str = "/v2/account/finishers";
615
616    /// Returns a list of finishers unlocked by the currently authenticated account.
617    ///
618    /// # Authentication
619    ///
620    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
621    /// When authenticated it returns a list of finishers unlocked by the account of the current
622    /// access token.
623    ///
624    /// # Examples
625    ///
626    /// ```no_run
627    /// # use gw2api_rs::{Client, Result};
628    /// # use gw2api_rs::v2::account::AccountFinishers;
629    /// #
630    /// # async fn run() -> Result<()> {
631    /// # let token = "";
632    /// let client: Client = Client::builder().access_token(token).into();
633    /// let finishers = AccountFinishers::get(&client).await?;
634    /// # Ok(())
635    /// # }
636    /// ```
637    ///
638    /// Using the [`blocking`] client:
639    ///
640    /// ```no_run
641    /// # use gw2api_rs::Result;
642    /// # use gw2api_rs::blocking::Client;
643    /// # use gw2api_rs::v2::account::AccountFinishers;
644    /// #
645    /// # fn run() -> Result<()> {
646    /// # let token = "";
647    /// let client: Client = Client::builder().access_token(token).into();
648    /// let finishers = AccountFinishers::get(&client)?;
649    /// # Ok(())
650    /// # }
651    /// ```
652    ///
653    /// [`Error`]: struct@crate::Error
654    /// [`blocking`]: crate::blocking
655    pub fn get<C>(client: &C) -> C::Result
656    where
657        C: ClientExecutor<Self>,
658    {
659        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
660    }
661}
662
663/// A single finisher unlocked by an account.
664#[derive(Clone, Debug, Serialize, Deserialize)]
665pub struct AccountFinisher {
666    /// The id of the finisher.
667    pub id: u64,
668    /// Whether the finisher is unlocked permanently.
669    #[serde(default = "AccountFinisher::serde_default_permanent")]
670    pub permanent: bool,
671    /// The number of uses remaining if `permanent` is `false`.
672    ///
673    /// This field is always `0` if `permanent` is `true`.
674    #[serde(default)]
675    pub quantity: u64,
676}
677
678impl AccountFinisher {
679    #[inline]
680    fn serde_default_permanent() -> bool {
681        true
682    }
683}
684
685/// A list of gliders unlocked by an account.
686#[derive(Clone, Debug, Serialize, Deserialize)]
687#[serde(transparent)]
688pub struct AccountGliders(pub Vec<u64>);
689
690impl AccountGliders {
691    const URI: &'static str = "/v2/account/gliders";
692
693    /// Returns a list of gliders unlocked by the currently authenticated account.
694    ///
695    /// # Authentication
696    ///
697    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
698    /// When authenticated it returns a list of gliders unlocked by the account of the current
699    /// access token.
700    ///
701    /// # Examples
702    ///
703    /// ```no_run
704    /// # use gw2api_rs::{Client, Result};
705    /// # use gw2api_rs::v2::account::AccountGliders;
706    /// #
707    /// # async fn run() -> Result<()> {
708    /// # let token = "";
709    /// let client: Client = Client::builder().access_token(token).into();
710    /// let gliders = AccountGliders::get(&client).await?;
711    /// # Ok(())
712    /// # }
713    /// ```
714    ///
715    /// Using the [`blocking`] client:
716    ///
717    /// ```no_run
718    /// # use gw2api_rs::Result;
719    /// # use gw2api_rs::blocking::Client;
720    /// # use gw2api_rs::v2::account::AccountGliders;
721    /// #
722    /// # fn run() -> Result<()> {
723    /// # let token = "";
724    /// let client: Client = Client::builder().access_token(token).into();
725    /// let gliders = AccountGliders::get(&client)?;
726    /// # Ok(())
727    /// # }
728    /// ```
729    ///
730    /// [`Error`]: struct@crate::Error
731    /// [`blocking`]: crate::blocking
732    pub fn get<C>(client: &C) -> C::Result
733    where
734        C: ClientExecutor<Self>,
735    {
736        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
737    }
738}
739
740/// A list of home cats unlocked by an account.
741#[derive(Clone, Debug, Serialize, Deserialize)]
742#[serde(transparent)]
743pub struct AccountHomeCats(pub Vec<u64>);
744
745impl AccountHomeCats {
746    const URI: &'static str = "/v2/account/home/cats";
747
748    /// Returns a list of home cats unlocked by the currently authenticated account.
749    ///
750    /// # Authentication
751    ///
752    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
753    /// When authenticated it returns a list of home cats unlocked by the account of the current
754    /// access token.
755    ///
756    /// # Examples
757    ///
758    /// ```no_run
759    /// # use gw2api_rs::{Client, Result};
760    /// # use gw2api_rs::v2::account::AccountHomeCats;
761    /// #
762    /// # async fn run() -> Result<()> {
763    /// # let token = "";
764    /// let client: Client = Client::builder().access_token(token).into();
765    /// let cats = AccountHomeCats::get(&client).await?;
766    /// # Ok(())
767    /// # }
768    /// ```
769    ///
770    /// Using the [`blocking`] client:
771    ///
772    /// ```no_run
773    /// # use gw2api_rs::Result;
774    /// # use gw2api_rs::blocking::Client;
775    /// # use gw2api_rs::v2::account::AccountHomeCats;
776    /// #
777    /// # fn run() -> Result<()> {
778    /// # let token = "";
779    /// let client: Client = Client::builder().access_token(token).into();
780    /// let cats = AccountHomeCats::get(&client)?;
781    /// # Ok(())
782    /// # }
783    /// ```
784    ///
785    /// [`Error`]: struct@crate::Error
786    /// [`blocking`]: crate::blocking
787    pub fn get<C>(client: &C) -> C::Result
788    where
789        C: ClientExecutor<Self>,
790    {
791        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
792    }
793}
794
795/// A list of home nodes unlocked by an account.
796#[derive(Clone, Debug, Serialize, Deserialize)]
797#[serde(transparent)]
798pub struct AccountHomeNodes(pub Vec<String>);
799
800impl AccountHomeNodes {
801    const URI: &'static str = "/v2/account/home/nodes";
802
803    /// Returns a list of home nodes unlocked by the currently authenticated account.
804    ///
805    /// # Authentication
806    ///
807    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
808    /// When authenticated it returns a list of home nodes unlocked by the account of the current
809    /// access token.
810    ///
811    /// # Examples
812    ///
813    /// ```no_run
814    /// # use gw2api_rs::{Client, Result};
815    /// # use gw2api_rs::v2::account::AccountHomeNodes;
816    /// #
817    /// # async fn run() -> Result<()> {
818    /// # let token = "";
819    /// let client: Client = Client::builder().access_token(token).into();
820    /// let nodes = AccountHomeNodes::get(&client).await?;
821    /// # Ok(())
822    /// # }
823    /// ```
824    ///
825    /// Using the [`blocking`] client:
826    ///
827    /// ```no_run
828    /// # use gw2api_rs::Result;
829    /// # use gw2api_rs::blocking::Client;
830    /// # use gw2api_rs::v2::account::AccountHomeNodes;
831    /// #
832    /// # fn run() -> Result<()> {
833    /// # let token = "";
834    /// let client: Client = Client::builder().access_token(token).into();
835    /// let nodes = AccountHomeNodes::get(&client)?;
836    /// # Ok(())
837    /// # }
838    /// ```
839    ///
840    /// [`Error`]: struct@crate::Error
841    /// [`blocking`]: crate::blocking
842    pub fn get<C>(client: &C) -> C::Result
843    where
844        C: ClientExecutor<Self>,
845    {
846        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
847    }
848}
849
850/// A list of items stored in the shared inventory slots of an account.
851///
852/// A `None` value indicates an empty slot.
853#[derive(Clone, Debug, Serialize, Deserialize)]
854#[serde(transparent)]
855pub struct AccountInventory(pub Vec<Option<InventoryItem>>);
856
857impl AccountInventory {
858    const URI: &'static str = "/v2/account/inventory";
859
860    /// Returns a list of items stored in the shared inventory slots of the currently authenticated
861    /// account.
862    ///
863    /// # Authentication
864    ///
865    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
866    /// When authenticated it returns a list of item stored in the shared inventory slots of the
867    /// account of the current access token.
868    ///
869    /// # Examples
870    ///
871    /// ```no_run
872    /// # use gw2api_rs::{Client, Result};
873    /// # use gw2api_rs::v2::account::AccountInventory;
874    /// #
875    /// # async fn run() -> Result<()> {
876    /// # let token = "";
877    /// let client: Client = Client::builder().access_token(token).into();
878    /// let inventory = AccountInventory::get(&client).await?;
879    /// # Ok(())
880    /// # }
881    /// ```
882    ///
883    /// Using the [`blocking`] client:
884    ///
885    /// ```no_run
886    /// # use gw2api_rs::Result;
887    /// # use gw2api_rs::blocking::Client;
888    /// # use gw2api_rs::v2::account::AccountInventory;
889    /// #
890    /// # fn run() -> Result<()> {
891    /// # let token = "";
892    /// let client: Client = Client::builder().access_token(token).into();
893    /// let inventory = AccountInventory::get(&client)?;
894    /// # Ok(())
895    /// # }
896    /// ```
897    ///
898    /// [`Error`]: struct@crate::Error
899    /// [`blocking`]: crate::blocking
900    pub fn get<C>(client: &C) -> C::Result
901    where
902        C: ClientExecutor<Self>,
903    {
904        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
905    }
906}
907
908#[derive(Clone, Debug, Serialize, Deserialize)]
909pub struct InventoryItem {
910    pub id: u64,
911    pub count: u64,
912    pub charges: Option<u64>,
913    pub skin: Option<u64>,
914    pub upgrades: Option<Vec<u64>>,
915    pub infusions: Option<Vec<u64>>,
916    pub binding: ItemBinding,
917}
918
919/// The current luck value of an account.
920pub struct AccountLuck(pub u64);
921
922impl AccountLuck {
923    const URI: &'static str = "/v2/account/luck";
924
925    /// Returns the unlocked luck value of the currently authenticated account.
926    ///
927    /// # Authentication
928    ///
929    /// This endpoint requires authentication and returns an [`Error`] if no access token is set.
930    /// When authenticated it returns unlocked luck value of the account of the current access
931    /// token.
932    ///
933    /// # Examples
934    ///
935    /// ```no_run
936    /// # use gw2api_rs::{Client, Result};
937    /// # use gw2api_rs::v2::account::AccountLuck;
938    /// #
939    /// # async fn run() -> Result<()> {
940    /// # let token = "";
941    /// let client: Client = Client::builder().access_token(token).into();
942    /// let luck = AccountLuck::get(&client).await?;
943    /// # Ok(())
944    /// # }
945    /// ```
946    ///
947    /// Using the [`blocking`] client:
948    ///
949    /// ```no_run
950    /// # use gw2api_rs::Result;
951    /// # use gw2api_rs::blocking::Client;
952    /// # use gw2api_rs::v2::account::AccountLuck;
953    /// #
954    /// # fn run() -> Result<()> {
955    /// # let token = "";
956    /// let client: Client = Client::builder().access_token(token).into();
957    /// let luck = AccountLuck::get(&client)?;
958    /// # Ok(())
959    /// # }
960    /// ```
961    ///
962    /// [`Error`]: struct@crate::Error
963    /// [`blocking`]: crate::blocking
964    pub fn get<C>(client: &C) -> C::Result
965    where
966        C: ClientExecutor<Self>,
967    {
968        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
969    }
970}
971
972impl Serialize for AccountLuck {
973    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
974    where
975        S: Serializer,
976    {
977        struct Map(u64);
978
979        impl Serialize for Map {
980            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
981            where
982                S: Serializer,
983            {
984                let mut map = serializer.serialize_map(Some(2))?;
985                map.serialize_entry("id", "luck")?;
986                map.serialize_entry("value", &self.0)?;
987                map.end()
988            }
989        }
990
991        let len = if self.0 == 0 { 0 } else { 1 };
992
993        let mut seq = serializer.serialize_seq(Some(len))?;
994
995        if self.0 != 0 {
996            seq.serialize_element(&Map(self.0))?;
997        }
998
999        seq.end()
1000    }
1001}
1002
1003impl<'de> Deserialize<'de> for AccountLuck {
1004    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1005    where
1006        D: Deserializer<'de>,
1007    {
1008        struct LuckVisitor;
1009
1010        impl<'de> Visitor<'de> for LuckVisitor {
1011            type Value = AccountLuck;
1012
1013            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1014                write!(formatter, "a sequence with one or zero elements")
1015            }
1016
1017            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1018            where
1019                A: SeqAccess<'de>,
1020            {
1021                struct Map(AccountLuck);
1022
1023                impl<'de> Deserialize<'de> for Map {
1024                    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1025                    where
1026                        D: Deserializer<'de>,
1027                    {
1028                        struct LuckMapVisitor;
1029
1030                        impl<'de> Visitor<'de> for LuckMapVisitor {
1031                            type Value = Map;
1032
1033                            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1034                                write!(formatter, "a map containing account luck")
1035                            }
1036
1037                            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1038                            where
1039                                A: MapAccess<'de>,
1040                            {
1041                                let value;
1042
1043                                match map.next_key::<&str>()? {
1044                                    Some(key) => match key {
1045                                        "id" => match map.next_value()? {
1046                                            Some("luck") => (),
1047                                            _ => {
1048                                                return Err(A::Error::custom(
1049                                                    "expected a luck id value",
1050                                                ))
1051                                            }
1052                                        },
1053                                        _ => {
1054                                            return Err(A::Error::custom(
1055                                                "expected a luck id value",
1056                                            ))
1057                                        }
1058                                    },
1059                                    None => {
1060                                        return Err(A::Error::custom("missing fields id, value"))
1061                                    }
1062                                }
1063
1064                                match map.next_key::<&str>()? {
1065                                    Some(key) => match key {
1066                                        "value" => match map.next_value()? {
1067                                            Some(val) => value = val,
1068                                            None => {
1069                                                return Err(A::Error::custom("expected a value"))
1070                                            }
1071                                        },
1072                                        _ => return Err(A::Error::custom("expected a value")),
1073                                    },
1074                                    None => return Err(A::Error::custom("missing fields value")),
1075                                }
1076
1077                                Ok(Map(AccountLuck(value)))
1078                            }
1079                        }
1080
1081                        deserializer.deserialize_map(LuckMapVisitor)
1082                    }
1083                }
1084
1085                match seq.next_element::<Map>()? {
1086                    Some(map) => Ok(map.0),
1087                    None => Ok(AccountLuck(0)),
1088                }
1089            }
1090        }
1091
1092        deserializer.deserialize_seq(LuckVisitor)
1093    }
1094}
1095
1096/// A list of legendary items unlocked in the account armory.
1097#[derive(Clone, Debug, Serialize, Deserialize)]
1098pub struct AccountLegendaryArmory(Vec<LegendaryArmoryItem>);
1099
1100impl AccountLegendaryArmory {
1101    const URI: &'static str = "/v2/account/legendaryarmory";
1102
1103    pub fn get<C>(client: &C) -> C::Result
1104    where
1105        C: ClientExecutor<Self>,
1106    {
1107        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1108    }
1109}
1110
1111/// An item in unlocked in the legendary armory.
1112#[derive(Clone, Debug, Serialize, Deserialize)]
1113pub struct LegendaryArmoryItem {
1114    /// The id of the legendary item.
1115    pub id: u64,
1116    /// The number of items unlocked. This value is in the range of 1 to 4.
1117    pub count: NonZeroU8,
1118}
1119
1120/// A list of unlocked mail carriers.
1121#[derive(Clone, Debug, Serialize, Deserialize)]
1122pub struct AccountMailCarriers(pub Vec<u64>);
1123
1124impl AccountMailCarriers {
1125    const URI: &'static str = "/v2/account/mailcarriers";
1126
1127    pub fn get<C>(client: &C) -> C::Result
1128    where
1129        C: ClientExecutor<Self>,
1130    {
1131        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1132    }
1133}
1134
1135#[derive(Clone, Debug, Serialize, Deserialize)]
1136pub struct AccountMapChests(Vec<String>);
1137
1138impl AccountMapChests {
1139    const URI: &'static str = "/v2/account/mapchests";
1140
1141    pub fn get<C>(client: &C) -> C::Result
1142    where
1143        C: ClientExecutor<Self>,
1144    {
1145        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1146    }
1147}
1148
1149/// A list of unlocked masteries.
1150#[derive(Clone, Debug, Serialize, Deserialize)]
1151pub struct AccountMasteries(pub Vec<AccountMastery>);
1152
1153impl AccountMasteries {
1154    const URI: &'static str = "/v2/account/masteries";
1155
1156    pub fn get<C>(client: &C) -> C::Result
1157    where
1158        C: ClientExecutor<Self>,
1159    {
1160        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1161    }
1162}
1163
1164/// A single unlocked mastery.
1165#[derive(Clone, Debug, Serialize, Deserialize)]
1166pub struct AccountMastery {
1167    /// The id of the mastery track.
1168    pub id: u64,
1169    /// The unlocked level of the mastery track.
1170    pub level: u8,
1171}
1172
1173#[derive(Clone, Debug, Serialize, Deserialize)]
1174pub struct AccountMasteryPoints {
1175    pub totals: Vec<RegionMasteryPoints>,
1176    pub unlocked: Vec<u64>,
1177}
1178
1179impl AccountMasteryPoints {
1180    const URI: &'static str = "/v2/account/mastery/points";
1181
1182    pub fn get<C>(client: &C) -> C::Result
1183    where
1184        C: ClientExecutor<Self>,
1185    {
1186        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1187    }
1188}
1189
1190#[derive(Clone, Debug, Serialize, Deserialize)]
1191pub struct RegionMasteryPoints {
1192    /// The mastery region.
1193    pub region: String,
1194    /// The number of mastery points spent in mastery tracks.
1195    pub spent: u64,
1196    /// The number of mastery points unlocked.
1197    pub earned: u64,
1198}
1199
1200/// The account's material storage.
1201#[derive(Clone, Debug, Serialize, Deserialize)]
1202pub struct AccountMaterials(Vec<AccountMaterial>);
1203
1204impl AccountMaterials {
1205    const URI: &'static str = "/v2/account/materials";
1206
1207    pub fn get<C>(client: &C) -> C::Result
1208    where
1209        C: ClientExecutor<Self>,
1210    {
1211        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1212    }
1213}
1214
1215/// A material slot in the account's material storage.
1216#[derive(Clone, Debug, Serialize, Deserialize)]
1217pub struct AccountMaterial {
1218    /// The id of the item.
1219    pub id: u64,
1220    /// The id of the category this item belongs to.
1221    pub category: u8,
1222    /// The binding of the item.
1223    pub binding: Option<ItemBinding>,
1224    /// The number of items of this material stored.
1225    pub count: u16,
1226}
1227
1228#[derive(Clone, Debug, Serialize, Deserialize)]
1229pub struct AccountMinis(pub Vec<u64>);
1230
1231impl AccountMinis {
1232    const URI: &'static str = "/v2/account/minis";
1233
1234    pub fn get<C>(client: &C) -> C::Result
1235    where
1236        C: ClientExecutor<Self>,
1237    {
1238        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1239    }
1240}
1241
1242/// A list of unlocked mount skins.
1243#[derive(Clone, Debug, Serialize, Deserialize)]
1244pub struct AccountMountSkins(pub Vec<u64>);
1245
1246impl AccountMountSkins {
1247    const URI: &'static str = "/v2/account/mounts/skins";
1248
1249    pub fn get<C>(client: &C) -> C::Result
1250    where
1251        C: ClientExecutor<Self>,
1252    {
1253        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1254    }
1255}
1256
1257/// A list of unlocked mount types.
1258#[derive(Clone, Debug, Serialize, Deserialize)]
1259pub struct AccountMountTypes(pub Vec<String>);
1260
1261impl AccountMountTypes {
1262    const URI: &'static str = "/v2/account/mounts/types";
1263
1264    pub fn get<C>(client: &C) -> C::Result
1265    where
1266        C: ClientExecutor<Self>,
1267    {
1268        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1269    }
1270}
1271
1272/// A list of unlocked novelties.
1273#[derive(Clone, Debug, Serialize, Deserialize)]
1274pub struct AccountNovelties(pub Vec<u64>);
1275
1276impl AccountNovelties {
1277    const URI: &'static str = "/v2/account/novelties";
1278
1279    pub fn get<C>(client: &C) -> C::Result
1280    where
1281        C: ClientExecutor<Self>,
1282    {
1283        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1284    }
1285}
1286
1287/// A list of unlocked outfits.
1288#[derive(Clone, Debug, Serialize, Deserialize)]
1289pub struct AccountOutfits(pub Vec<u64>);
1290
1291impl AccountOutfits {
1292    const URI: &'static str = "/v2/account/outfits";
1293
1294    pub fn get<C>(client: &C) -> C::Result
1295    where
1296        C: ClientExecutor<Self>,
1297    {
1298        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1299    }
1300}
1301
1302/// A list of account-wide progression.
1303#[derive(Clone, Debug, Serialize, Deserialize)]
1304pub struct AccountProgression(pub Vec<AccountProgressionItem>);
1305
1306impl AccountProgression {
1307    const URI: &'static str = "/v2/account/progression";
1308
1309    pub fn get<C>(client: &C) -> C::Result
1310    where
1311        C: ClientExecutor<Self>,
1312    {
1313        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1314    }
1315}
1316
1317#[derive(Clone, Debug, Serialize, Deserialize)]
1318pub struct AccountProgressionItem {
1319    /// The name of the progression item.
1320    pub id: String,
1321    /// The value of the progression item.
1322    pub value: u64,
1323}
1324
1325/// A list of unlocked PvP heroes.
1326#[derive(Clone, Debug, Serialize, Deserialize)]
1327pub struct AccountPvPHeroes(pub Vec<u64>);
1328
1329impl AccountPvPHeroes {
1330    const URI: &'static str = "/v2/account/pvp/heroes";
1331
1332    pub fn get<C>(client: &C) -> C::Result
1333    where
1334        C: ClientExecutor<Self>,
1335    {
1336        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1337    }
1338}
1339
1340/// A list of raid encounters completed since weekly reset.
1341#[derive(Clone, Debug, Serialize, Deserialize)]
1342pub struct AccountRaids(pub Vec<String>);
1343
1344impl AccountRaids {
1345    const URI: &'static str = "/v2/account/raids";
1346
1347    pub fn get<C>(client: &C) -> C::Result
1348    where
1349        C: ClientExecutor<Self>,
1350    {
1351        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1352    }
1353}
1354
1355/// A list of unlocked recipes.
1356#[derive(Clone, Debug, Serialize, Deserialize)]
1357pub struct AccountRecipes(pub Vec<u64>);
1358
1359impl AccountRecipes {
1360    const URI: &'static str = "/v2/account/recipes";
1361
1362    pub fn get<C>(client: &C) -> C::Result
1363    where
1364        C: ClientExecutor<Self>,
1365    {
1366        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1367    }
1368}
1369
1370/// A list of unlocked skins.
1371#[derive(Clone, Debug, Serialize, Deserialize)]
1372pub struct AccountSkins(pub Vec<u64>);
1373
1374impl AccountSkins {
1375    const URI: &'static str = "/v2/account/skins";
1376
1377    pub fn get<C>(client: &C) -> C::Result
1378    where
1379        C: ClientExecutor<Self>,
1380    {
1381        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1382    }
1383}
1384
1385/// A list of unlocked titles.
1386#[derive(Clone, Debug, Serialize, Deserialize)]
1387pub struct AccountTitles(pub Vec<u64>);
1388
1389impl AccountTitles {
1390    const URI: &'static str = "/v2/account/titles";
1391
1392    pub fn get<C>(client: &C) -> C::Result
1393    where
1394        C: ClientExecutor<Self>,
1395    {
1396        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1397    }
1398}
1399
1400/// A list of currencies in an account's wallet.
1401#[derive(Clone, Debug, Serialize, Deserialize)]
1402pub struct AccountWallet(pub Vec<AccountCurrency>);
1403
1404impl AccountWallet {
1405    const URI: &'static str = "/v2/account/wallet";
1406
1407    pub fn get<C>(client: &C) -> C::Result
1408    where
1409        C: ClientExecutor<Self>,
1410    {
1411        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1412    }
1413}
1414
1415/// A currency in an account's wallet.
1416#[derive(Clone, Debug, Serialize, Deserialize)]
1417pub struct AccountCurrency {
1418    /// The id of the currency.
1419    pub id: u64,
1420    /// The amount of the currency.
1421    pub value: u64,
1422}
1423
1424/// A list of world bosses completed since daily reset.
1425#[derive(Clone, Debug, Serialize, Deserialize)]
1426pub struct AccountWorldBosses(pub Vec<String>);
1427
1428impl AccountWorldBosses {
1429    const URI: &'static str = "/v2/account/worldbosses";
1430
1431    pub fn get<C>(client: &C) -> C::Result
1432    where
1433        C: ClientExecutor<Self>,
1434    {
1435        client.send(RequestBuilder::new(Self::URI).authenticated(Authentication::Required))
1436    }
1437}