Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Possible use-cases:
| :white_check_mark: | Places |
| :x: | Instances |
| :white_check_mark: | Subscriptions |
| :x: | Inventory |
| :white_check_mark: | Inventory |
| :white_check_mark: | User Notifications |
| :white_check_mark: | User |
| :x: | Creator Store |
Expand Down
17 changes: 17 additions & 0 deletions docs/cli/cli-inventory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Inventory API

## List
List inventory items for a given user.

```
Usage: rbxcloud inventory list [OPTIONS] --user-id <USER_ID> --api-key <API_KEY>

Options:
-u, --user-id <USER_ID> Roblox user ID
-p, --pretty Pretty-print the JSON response
-m, --max-page-size <MAX_PAGE_SIZE> Max page size
-n, --page-token <PAGE_TOKEN> Next page token
-f, --filter <FILTER> Filter string
-a, --api-key <API_KEY> Roblox Open Cloud API Key [env: RBXCLOUD_API_KEY=]
-h, --help Print help
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ nav:
- DataStore: cli/cli-datastore.md
- Experience: cli/cli-experience.md
- Group: cli/cli-group.md
- Inventory: cli/cli-inventory.md
- Luau Execution: cli/cli-luau-execution.md
- Messaging: cli/cli-messaging.md
- Notification: cli/cli-notification.md
Expand Down
73 changes: 73 additions & 0 deletions src/cli/inventory_cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use clap::{Args, Subcommand};
use rbxcloud::rbx::{types::RobloxUserId, v2::Client};

#[derive(Debug, Subcommand)]
pub enum InventoryCommands {
/// List inventory items for a given user
List {
/// Roblox user ID
#[clap(short, long, value_parser)]
user_id: u64,

/// Pretty-print the JSON response
#[clap(short, long, value_parser, default_value_t = false)]
pretty: bool,

/// Max page size
#[clap(short, long, value_parser)]
max_page_size: Option<u32>,

/// Next page token
#[clap(short = 'n', long, value_parser)]
page_token: Option<String>,

/// Filter string
#[clap(short, long, value_parser)]
filter: Option<String>,

/// Roblox Open Cloud API Key
#[clap(short, long, value_parser, env = "RBXCLOUD_API_KEY")]
api_key: String,
},
}

#[derive(Debug, Args)]
pub struct Inventory {
#[clap(subcommand)]
command: InventoryCommands,
}

impl Inventory {
pub async fn run(self) -> anyhow::Result<Option<String>> {
match self.command {
InventoryCommands::List {
user_id,
pretty,
max_page_size,
page_token,
filter,
api_key,
} => {
let client = Client::new(&api_key);

let inventory = client.inventory();

let res = inventory
.list_inventory_items(RobloxUserId(user_id), max_page_size, page_token, filter)
.await;

match res {
Ok(data) => {
let r = if pretty {
serde_json::to_string_pretty(&data)?
} else {
serde_json::to_string(&data)?
};
Ok(Some(r))
}
Err(err) => Err(anyhow::anyhow!(err)),
}
}
}
}
}
6 changes: 6 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod assets_cli;
mod datastore_cli;
mod experience_cli;
mod group_cli;
mod inventory_cli;
mod luau_execution_cli;
mod messaging_cli;
mod notification_cli;
Expand All @@ -12,6 +13,7 @@ mod universe_cli;
mod user_cli;

use clap::{Parser, Subcommand};
use inventory_cli::Inventory;
use luau_execution_cli::Luau;
use universe_cli::Universe;
use user_cli::User;
Expand Down Expand Up @@ -46,6 +48,9 @@ pub enum Command {
/// Access the Roblox OrderedDataStore API
OrderedDatastore(OrderedDataStore),

/// Access the Roblox user inventory API
Inventory(Inventory),

/// Access the Roblox Group API
Group(Group),

Expand Down Expand Up @@ -76,6 +81,7 @@ impl Cli {
Command::Datastore(command) => command.run().await,
Command::OrderedDatastore(command) => command.run().await,
Command::Group(command) => command.run().await,
Command::Inventory(command) => command.run().await,
Command::Luau(command) => command.run().await,
Command::Subscription(command) => command.run().await,
Command::Notification(command) => command.run().await,
Expand Down
2 changes: 1 addition & 1 deletion src/rbx/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct PlaceId(pub u64);
pub struct ReturnLimit(pub u64);

/// Represents a Roblox user's ID.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct RobloxUserId(pub u64);

#[derive(Debug, Clone, Copy)]
Expand Down
180 changes: 180 additions & 0 deletions src/rbx/v2/inventory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
use serde::{Deserialize, Serialize};

use crate::rbx::{error::Error, types::RobloxUserId, util::QueryString};

use super::http_err::handle_http_err;

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ListInventoryItemsParams {
pub api_key: String,
pub user_id: RobloxUserId,
pub max_page_size: Option<u32>,
pub page_token: Option<String>,
pub filter: Option<String>,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItems {
inventory_items: Vec<InventoryItem>,
next_page_token: String,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItem {
path: String,
#[serde(skip_serializing_if = "Option::is_none")]
asset_details: Option<InventoryItemAssetDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
badge_details: Option<InventoryItemBadgeDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
game_pass_details: Option<InventoryItemGamePassDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
private_server_details: Option<InventoryItemPrivateServerDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
add_time: Option<String>,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItemAssetDetails {
asset_id: String,
instance_id: String,
inventory_item_asset_type: InventoryItemAssetType,
#[serde(skip_serializing_if = "Option::is_none")]
collectible_details: Option<InventoryItemCollectibleDetails>,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItemBadgeDetails {
badge_id: String,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItemGamePassDetails {
game_pass_id: String,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItemPrivateServerDetails {
private_server_id: String,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct InventoryItemCollectibleDetails {
item_id: String,
instance_id: String,
instance_state: InventoryItemInstanceState,
#[serde(skip_serializing_if = "Option::is_none")]
serial_number: Option<u64>,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum InventoryItemInstanceState {
CollectibleItemInstanceStateUnspecified,
Available,
Hold,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum InventoryItemAssetType {
ClassicTshirt,
Audio,
Hat,
Model,
ClassicShirt,
ClassicPants,
Decal,
ClassicHead,
Face,
Gear,
Animation,
Torso,
RightArm,
LeftArm,
LeftLeg,
RightLeg,
Package,
Plugin,
MeshPart,
HairAccessory,
FaceAccessory,
NeckAccessory,
ShoulderAccessory,
FrontAccessory,
BackAccessory,
WaistAccessory,
ClimbAnimation,
DeathAnimation,
FallAnimation,
IdleAnimation,
JumpAnimation,
RunAnimation,
SwimAnimation,
WalkAnimation,
PoseAnimation,
EmoteAnimation,
Video,
TshirtAccessory,
ShirtAccessory,
PantsAccessory,
JacketAccessory,
SweaterAccessory,
ShortsAccessory,
LeftShoeAccessory,
RightShoeAccessory,
DressSkirtAccessory,
EyebrowAccessory,
EyelashAccessory,
MoodAnimation,
DynamicHead,
CreatedPlace,
PurchasedPlace,
}

pub async fn list_inventory_items(
params: &ListInventoryItemsParams,
) -> Result<InventoryItems, Error> {
let client = reqwest::Client::new();

let url = format!(
"https://apis.roblox.com/cloud/v2/users/{userId}/inventory-items",
userId = params.user_id,
);

let mut query: QueryString = vec![];
if let Some(max_page_size) = params.max_page_size {
query.push(("maxPageSize", format!("{max_page_size}")));
}
if let Some(page_token) = &params.page_token {
query.push(("pageToken", page_token.clone()));
}
if let Some(filter) = &params.filter {
query.push(("filter", filter.clone()));
}

let res = client
.get(url)
.header("x-api-key", &params.api_key)
.query(&query)
.send()
.await?;

let status = res.status();

if !status.is_success() {
let code = status.as_u16();
return handle_http_err(code);
}

let body = res.json::<InventoryItems>().await?;
Ok(body)
}
2 changes: 0 additions & 2 deletions src/rbx/v2/luau_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,6 @@ pub async fn get_luau_execution_task_logs(
.send()
.await?;

println!("URL SENT: {}", res.url());

let status = res.status();

if !status.is_success() {
Expand Down
Loading