psn_rs 0.1.0

Interact with PlayStation Network API in full Rust!
Documentation
use reqwest::{
    header::{ACCEPT_LANGUAGE, HeaderMap, HeaderValue, USER_AGENT},
    redirect::Policy,
};

use crate::{PSNApiResult, PSNClient, PSNError};

const DEFAULT_USER_AGENT: &str = "Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86 Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36";
const DEFAULT_ACCEPT_LANGUAGE: &str = "en-US,en;q=0.9";
const NPSSO_TOKEN_LENGTH: usize = 64;

/// Main API client builder.
/// Must be used to create a new [`PSNClient`] instance.
pub struct PSNClientBuilder {
    client_builder: reqwest::ClientBuilder,
    npsso: Option<String>,
}

impl PSNClientBuilder {
    /// Create a new [`PSNClientBuilder`] instance.
    pub fn new() -> Self {
        Self::default()
    }

    /// Set the NPSSO token for the client.
    pub fn npsso<S: ToString>(mut self, npsso: S) -> Self {
        self.npsso = Some(npsso.to_string());
        self
    }

    /// Set custom headers for the client.
    pub fn custom_headers(mut self, headers: HeaderMap) -> Self {
        self.client_builder = self.client_builder.default_headers(headers);
        self
    }

    /// Build the [`PSNClient`] instance.
    pub fn build(self) -> PSNApiResult<PSNClient> {
        let mut headers = HeaderMap::new();
        headers.insert(USER_AGENT, HeaderValue::from_static(DEFAULT_USER_AGENT));
        headers.insert(
            ACCEPT_LANGUAGE,
            HeaderValue::from_static(DEFAULT_ACCEPT_LANGUAGE),
        );
        headers.insert("Country", HeaderValue::from_static("US"));

        log::trace!("checking npsso token length");
        let npsso = self.npsso.ok_or(PSNError::NoNPSSOTokenProvided)?;
        if !npsso.len() == NPSSO_TOKEN_LENGTH {
            return Err(PSNError::GenericError(
                "invalid npsso token length".to_string(),
            ));
        }
        log::trace!("npsso length OK");

        Ok(PSNClient::new(self.client_builder.build()?, npsso))
    }
}

impl Default for PSNClientBuilder {
    fn default() -> Self {
        let client_builder = reqwest::ClientBuilder::new().redirect(Policy::none());
        Self {
            client_builder,
            npsso: None,
        }
    }
}