roblox-api 0.1.8

Roblox web api bindings
Documentation
use serde::{Deserialize, Serialize};
use strum_macros::{Display, EnumString};

use crate::{DateTime, Paging, endpoint};

pub const URL: &str = "https://apis.roblox.com/game-passes/v1";

#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Display, EnumString)]
pub enum CreatorType {
    User,
    Group,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "PascalCase")]
pub struct Creator {
    pub id: u64,
    pub name: String,
    #[serde(rename = "CreatorType")]
    pub kind: CreatorType,
    #[serde(rename = "CreatorTargetId")]
    pub target_id: u64,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GamepassCreator {
    #[serde(rename = "creatorId")]
    pub id: u64,
    pub name: String,
    #[serde(rename = "creatorType")]
    pub kind: CreatorType,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Gamepass {
    #[serde(rename = "gamePassId")]
    pub id: u64,
    pub name: String,
    pub description: String,

    #[serde(rename = "iconAssetId")]
    pub icon_image_id: Option<u64>,

    pub price: Option<u64>,
    #[serde(rename = "isForSale")]
    pub on_sale: bool,
    pub creator: GamepassCreator,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct PriceInformation {
    #[serde(rename = "defaultPriceInRobux")]
    pub price_in_robux: u64,
    pub enabled_features: Vec<String>, // Such as RegionalPricing
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GamepassDetails {
    #[serde(rename = "gamePassId")]
    pub id: u64,
    pub name: String,
    pub description: String,

    pub place_id: u64,
    #[serde(rename = "iconAssetId")]
    pub icon_image_id: u64,

    #[serde(rename = "createdTimestamp")]
    pub created: DateTime,
    #[serde(rename = "updatedTimestamp")]
    pub updated: DateTime,

    #[serde(rename = "isForSale")]
    pub on_sale: bool,
    pub price_information: Option<PriceInformation>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "PascalCase")]
pub struct GamepassProductInformation {
    #[serde(rename = "TargetId")]
    pub id: u64,
    pub asset_id: u64,
    pub product_id: u64,

    pub name: String,
    pub description: String,

    pub product_type: String,
    pub asset_type_id: u8, // seems to be 0?

    pub creator: Creator,

    #[serde(rename = "IconImageAssetId")]
    pub icon_image_id: u64,

    pub created: DateTime,
    pub updated: DateTime,

    #[serde(rename = "PriceInRobux")]
    pub robux_price: Option<u64>,
    #[serde(rename = "PriceInTickets")]
    pub tickets_price: Option<u64>,

    pub sales: u64,
    pub remaining: Option<u64>,

    #[serde(rename = "IsForSale")]
    pub on_sale: bool,

    pub is_new: bool,
    pub is_public_domain: bool,
    pub is_limited: bool,
    pub is_limited_unique: bool,

    pub minimum_membership_level: u8,
}

endpoint! {
    details(id: u64) -> GamepassDetails {
        GET "{URL}/game-passes/{id}/details";
    }

    product_information(id: u64) -> GamepassProductInformation {
        GET "{URL}/game-passes/{id}/product-info";
    }

    /// The cursor is the gamepass_id you want to start from
    user_gamepasses(id: u64, paging: Paging<'_>) -> Vec<Gamepass> {
        GET "{URL}/users/{id}/game-passes";

        types {
            Response {
                gamepasses("gamePasses"): Vec<Gamepass>,
            }
        }

        prelude {
            let count = paging.limit.unwrap_or(100).to_string();
            let cursor = match paging.cursor {
                Some(cursor) => cursor.to_string(),
                None => String::new(),
            };
        }

        query {
            "count" => &count,
            "exclusiveStartId" => &cursor,
        }

        map |r: Response| r.gamepasses
    }
}