Skip to main content

roblox_api/api/gamepasses/
v1.rs

1use serde::{Deserialize, Serialize};
2use strum_macros::{Display, EnumString};
3
4use crate::{DateTime, Error, Paging, client::Client};
5
6pub const URL: &str = "https://apis.roblox.com/game-passes/v1";
7
8#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Display, EnumString)]
9pub enum CreatorType {
10    User,
11    Group,
12}
13
14#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
15#[serde(rename_all = "PascalCase")]
16pub struct Creator {
17    pub id: u64,
18    pub name: String,
19    #[serde(rename = "CreatorType")]
20    pub kind: CreatorType,
21    #[serde(rename = "CreatorTargetId")]
22    pub target_id: u64,
23}
24
25#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
26#[serde(rename_all = "camelCase")]
27pub struct GamepassCreator {
28    #[serde(rename = "creatorId")]
29    pub id: u64,
30    pub name: String,
31    #[serde(rename = "creatorType")]
32    pub kind: CreatorType,
33}
34
35#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
36#[serde(rename_all = "camelCase")]
37pub struct Gamepass {
38    #[serde(rename = "gamePassId")]
39    pub id: u64,
40    pub name: String,
41    pub description: String,
42
43    #[serde(rename = "iconAssetId")]
44    pub icon_image_id: Option<u64>,
45
46    pub price: Option<u64>,
47    #[serde(rename = "isForSale")]
48    pub on_sale: bool,
49    pub creator: GamepassCreator,
50}
51
52#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
53#[serde(rename_all = "camelCase")]
54pub struct PriceInformation {
55    #[serde(rename = "defaultPriceInRobux")]
56    pub price_in_robux: u64,
57    pub enabled_features: Vec<String>, // Such as RegionalPricing
58}
59
60#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
61#[serde(rename_all = "camelCase")]
62pub struct GamepassDetails {
63    #[serde(rename = "gamePassId")]
64    pub id: u64,
65    pub name: String,
66    pub description: String,
67
68    pub place_id: u64,
69    #[serde(rename = "iconAssetId")]
70    pub icon_image_id: u64,
71
72    #[serde(rename = "createdTimestamp")]
73    pub created: DateTime,
74    #[serde(rename = "updatedTimestamp")]
75    pub updated: DateTime,
76
77    #[serde(rename = "isForSale")]
78    pub on_sale: bool,
79    pub price_information: Option<PriceInformation>,
80}
81
82#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
83#[serde(rename_all = "PascalCase")]
84pub struct GamepassProductInformation {
85    #[serde(rename = "TargetId")]
86    pub id: u64,
87    pub asset_id: u64,
88    pub product_id: u64,
89
90    pub name: String,
91    pub description: String,
92
93    pub product_type: String,
94    pub asset_type_id: u8, // seems to be 0?
95
96    pub creator: Creator,
97
98    #[serde(rename = "IconImageAssetId")]
99    pub icon_image_id: u64,
100
101    pub created: DateTime,
102    pub updated: DateTime,
103
104    #[serde(rename = "PriceInRobux")]
105    pub robux_price: Option<u64>,
106    #[serde(rename = "PriceInTickets")]
107    pub tickets_price: Option<u64>,
108
109    pub sales: u64,
110    pub remaining: Option<u64>,
111
112    #[serde(rename = "IsForSale")]
113    pub on_sale: bool,
114
115    pub is_new: bool,
116    pub is_public_domain: bool,
117    pub is_limited: bool,
118    pub is_limited_unique: bool,
119
120    pub minimum_membership_level: u8,
121}
122
123pub async fn details(client: &mut Client, id: u64) -> Result<GamepassDetails, Error> {
124    let result = client
125        .requestor
126        .client
127        .get(format!("{URL}/game-passes/{id}/details"))
128        .headers(client.requestor.default_headers.clone())
129        .send()
130        .await;
131
132    let response = client.requestor.validate_response(result).await?;
133    client
134        .requestor
135        .parse_json::<GamepassDetails>(response)
136        .await
137}
138
139pub async fn product_information(
140    client: &mut Client,
141    id: u64,
142) -> Result<GamepassProductInformation, Error> {
143    let result = client
144        .requestor
145        .client
146        .get(format!("{URL}/game-passes/{id}/product-info"))
147        .headers(client.requestor.default_headers.clone())
148        .send()
149        .await;
150
151    let response = client.requestor.validate_response(result).await?;
152    client
153        .requestor
154        .parse_json::<GamepassProductInformation>(response)
155        .await
156}
157
158/// The cursor is the gamepass_id you want to start from
159pub async fn user_gamepasses(
160    client: &mut Client,
161    id: u64,
162    paging: Paging<'_>,
163) -> Result<Vec<Gamepass>, Error> {
164    let limit = paging.limit.unwrap_or(100).to_string();
165    let cursor = match paging.cursor {
166        Some(cursor) => cursor.to_string(),
167        None => String::new(),
168    };
169
170    let result = client
171        .requestor
172        .client
173        .get(format!("{URL}/users/{id}/game-passes"))
174        .query(&[("count", limit), ("exclusiveStartId", cursor)])
175        .headers(client.requestor.default_headers.clone())
176        .send()
177        .await;
178
179    #[derive(Debug, Deserialize)]
180    struct Response {
181        #[serde(rename = "gamePasses")]
182        gamepasses: Vec<Gamepass>,
183    }
184
185    let response = client.requestor.validate_response(result).await?;
186    Ok(client
187        .requestor
188        .parse_json::<Response>(response)
189        .await?
190        .gamepasses)
191}