roblox_api/api/inventory/
v1.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{AssetTypeId, Error, Paging, client::Client};
4
5pub const URL: &str = "https://inventory.roblox.com/v1";
6
7#[repr(u8)]
8#[derive(Clone, Debug, Deserialize, Serialize)]
9pub enum ItemType {
10    Asset = 0,
11    Gamepass,
12    Badge,
13    Bundle,
14}
15
16#[derive(Clone, Debug, Deserialize, Serialize)]
17#[serde(rename_all = "camelCase")]
18pub struct AssetInfo {
19    pub id: u64,
20    #[serde(rename = "type")]
21    pub kind: String,
22    pub name: String,
23    pub instance_id: u64,
24}
25
26#[derive(Clone, Debug, Deserialize, Serialize)]
27pub struct UserOwnsAssets {
28    #[serde(rename = "nextPageCursor")]
29    pub next_cursor: Option<String>,
30    #[serde(rename = "previousPageCursor")]
31    pub previous_cursor: Option<String>,
32    #[serde(rename = "data")]
33    pub assets: Vec<AssetInfo>,
34}
35
36#[derive(Clone, Debug, Deserialize, Serialize)]
37#[serde(rename_all = "camelCase")]
38pub struct CollectibleInfo {
39    #[serde(rename = "assetId")]
40    pub id: u64,
41    pub original_price: u64,
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, Serialize)]
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    #[serde(rename_all = "camelCase")]
77    struct Response {
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_owns_assets(
90    client: &mut Client,
91    user_id: u64,
92    id: u64,
93    item_type: ItemType,
94    paging: Paging<'_>,
95) -> Result<UserOwnsAssets, Error> {
96    let item_type = item_type as u8;
97
98    let cursor = match paging.cursor {
99        Some(cursor) => cursor.to_string(),
100        None => String::new(),
101    };
102
103    let result = client
104        .requestor
105        .client
106        .get(format!("{URL}/users/{user_id}/items/{item_type}/{id}"))
107        .query(&[("cursor", cursor)])
108        .headers(client.requestor.default_headers.clone())
109        .send()
110        .await;
111
112    let response = client.validate_response(result).await?;
113    client
114        .requestor
115        .parse_json::<UserOwnsAssets>(response)
116        .await
117}
118
119pub async fn user_owned_collectibles(
120    client: &mut Client,
121    user_id: u64,
122    asset_type_id: Option<AssetTypeId>,
123    paging: Paging<'_>,
124) -> Result<UserOwnedCollectibles, Error> {
125    let limit = paging.limit.unwrap_or(10).to_string();
126    let sort_order = paging.order.unwrap_or_default().to_string();
127    let cursor = match paging.cursor {
128        Some(cursor) => cursor.to_string(),
129        None => String::new(),
130    };
131
132    let asset_type = match asset_type_id {
133        Some(id) => {
134            let id = id as u8;
135            id.to_string()
136        }
137        None => String::new(),
138    };
139
140    let result = client
141        .requestor
142        .client
143        .get(format!("{URL}/users/{user_id}/assets/collectibles"))
144        .query(&[
145            ("assetType", asset_type),
146            ("limit", limit),
147            ("sortOrder", sort_order),
148            ("cursor", cursor),
149        ])
150        .headers(client.requestor.default_headers.clone())
151        .send()
152        .await;
153
154    let response = client.validate_response(result).await?;
155    client
156        .requestor
157        .parse_json::<UserOwnedCollectibles>(response)
158        .await
159}