roblox_api/api/inventory/
v1.rs

1use crate::{AssetTypeId, Error, Paging, client::Client};
2use serde::{Deserialize, Serialize};
3
4pub const URL: &str = "https://inventory.roblox.com/v1";
5
6#[repr(u8)]
7#[derive(Clone, Debug, Deserialize, Serialize)]
8pub enum ItemType {
9    Asset = 0,
10    Gamepass,
11    Badge,
12    Bundle,
13}
14
15#[derive(Clone, Debug, Deserialize)]
16pub struct AssetInfo {
17    pub id: u64,
18    #[serde(rename = "type")]
19    pub kind: String,
20    pub name: String,
21    #[serde(rename = "instanceId")]
22    pub instance_id: u64,
23}
24
25#[derive(Clone, Debug, Deserialize)]
26pub struct UserOwnedAssets {
27    #[serde(rename = "nextPageCursor")]
28    pub next_cursor: Option<String>,
29    #[serde(rename = "previousPageCursor")]
30    pub previous_cursor: Option<String>,
31    #[serde(rename = "data")]
32    pub assets: Vec<AssetInfo>,
33}
34
35#[derive(Clone, Debug, Deserialize)]
36pub struct CollectibleInfo {
37    #[serde(rename = "assetId")]
38    pub id: u64,
39    #[serde(rename = "originalPrice")]
40    pub original_price: u64,
41    #[serde(rename = "recentAveragePrice")]
42    pub recent_average_price: u64,
43    #[serde(rename = "assetStock")]
44    pub stock: u64,
45    #[serde(rename = "userAssetId")]
46    pub instance_id: u64,
47    pub name: String,
48    #[serde(rename = "buildersClubMembershipType")]
49    pub premium_membership_type: String,
50    #[serde(rename = "isOnHold")]
51    pub on_hold: bool,
52    #[serde(rename = "serialNumber")]
53    pub serial: Option<u64>,
54}
55
56#[derive(Clone, Debug, Deserialize)]
57pub struct UserOwnedCollectibles {
58    #[serde(rename = "nextPageCursor")]
59    pub next_cursor: Option<String>,
60    #[serde(rename = "previousPageCursor")]
61    pub previous_cursor: Option<String>,
62    #[serde(rename = "data")]
63    pub assets: Vec<CollectibleInfo>,
64}
65
66pub async fn can_view_inventory(client: &mut Client, user_id: u64) -> Result<bool, Error> {
67    let result = client
68        .requestor
69        .client
70        .get(format!("{URL}/users/{user_id}/can-view-inventory"))
71        .headers(client.requestor.default_headers.clone())
72        .send()
73        .await;
74
75    #[derive(Clone, Debug, Deserialize)]
76    struct Response {
77        #[serde(rename = "canView")]
78        can_view: bool,
79    }
80
81    let response = client.validate_response(result).await?;
82    Ok(client
83        .requestor
84        .parse_json::<Response>(response)
85        .await?
86        .can_view)
87}
88
89pub async fn user_owned_assets(
90    client: &mut Client,
91    user_id: u64,
92    id: u64,
93    item_type: ItemType,
94    paging: Paging<'_>,
95) -> Result<UserOwnedAssets, Error> {
96    let item_type = item_type as u8;
97
98    let cursor = match paging.cursor {
99        Some(cursor) => format!("&cursor={cursor}"),
100        None => String::new(),
101    };
102
103    let result = client
104        .requestor
105        .client
106        .get(format!(
107            "{URL}/users/{user_id}/items/{item_type}/{id}{cursor}"
108        ))
109        .headers(client.requestor.default_headers.clone())
110        .send()
111        .await;
112
113    let response = client.validate_response(result).await?;
114    client
115        .requestor
116        .parse_json::<UserOwnedAssets>(response)
117        .await
118}
119
120pub async fn user_owned_collectibles(
121    client: &mut Client,
122    user_id: u64,
123    asset_type_id: Option<AssetTypeId>,
124    paging: Paging<'_>,
125) -> Result<UserOwnedCollectibles, Error> {
126    let limit = paging.limit.unwrap_or(10);
127    let sort_order = paging.order.unwrap_or_default().to_string();
128    let cursor = match paging.cursor {
129        Some(cursor) => format!("&cursor={cursor}"),
130        None => String::new(),
131    };
132
133    let asset_type = match asset_type_id {
134        Some(id) => {
135            let id = id as u8;
136            format!("?assetType={id}")
137        }
138        None => String::new(),
139    };
140
141    let result = client
142        .requestor
143        .client
144        .get(format!(
145            "{URL}/users/{user_id}/assets/collectibles{asset_type}&limit={limit}&sortOrder={sort_order}{cursor}"
146        ))
147        .headers(client.requestor.default_headers.clone())
148        .send()
149        .await;
150
151    let response = client.validate_response(result).await?;
152    client
153        .requestor
154        .parse_json::<UserOwnedCollectibles>(response)
155        .await
156}