steam-rs 0.5.1

Safe Rust bindings for the Steam Web API
Documentation
//! Implements the `GetPlayerAchievements` endpoint

use serde::{Deserialize, Serialize};

use crate::{
    errors::{ErrorHandle, SteamUserStatsError},
    macros::{do_http, gen_args, optional_argument},
    steam_id::SteamId,
    Steam, BASE,
};

use super::INTERFACE;

const ENDPOINT: &str = "GetPlayerAchievements";
const VERSION: &str = "1";

#[derive(Debug, Clone, Deserialize, Serialize)]
struct Wrapper {
    playerstats: PlayerStats,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PlayerStats {
    pub error: Option<String>,
    pub success: bool,
    #[serde(rename = "steamID")]
    // TODO: Make this SteamId
    pub steam_id: Option<String>,
    #[serde(rename = "gameName")]
    pub game_name: Option<String>,
    pub achievements: Option<Vec<Achievement>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Achievement {
    pub apiname: Option<String>,
    pub achieved: u8,
    // TODO: Reconsider this
    pub unlocktime: Option<u64>,
}

impl Steam {
    /// Gets the list of achievements the specified user has unlocked in an app.
    ///
    /// # Arguments
    /// * `steamid` - The user's SteamID.
    /// * `appid` - The ID of the application (game) to get achievements for.
    /// * `language` - Localized language to return (english, french, etc.).
    pub async fn get_player_achievements(
        &self,
        steamid: SteamId,
        appid: u32,
        language: Option<&str>,
    ) -> Result<PlayerStats, SteamUserStatsError> {
        let key = &self.api_key.clone();
        let steamid = steamid.into_u64();
        let args = gen_args!(key, appid, steamid) + &optional_argument!(language, "l");
        let url = format!("{BASE}/{INTERFACE}/{ENDPOINT}/v{VERSION}/?{args}");
        let wrapper = do_http!(
            url,
            Wrapper,
            ErrorHandle,
            SteamUserStatsError::GetPlayerAchievements
        );
        Ok(wrapper.playerstats)
    }
}

impl Achievement {
    pub fn achieved(&self) -> bool {
        self.achieved == 1
    }
}