From abea7dd71220bb18de26e50a19b7e9484b6b3b03 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 16 Jul 2024 10:10:05 -0700 Subject: [PATCH] refactor get_asset (worthless, you can't actually download assets) --- rbx_asset/src/cloud.rs | 98 ++++++++++++++++++++++++++++++++++-------- src/main.rs | 25 ++++++----- 2 files changed, 91 insertions(+), 32 deletions(-) diff --git a/rbx_asset/src/cloud.rs b/rbx_asset/src/cloud.rs index dc276c8..4206497 100644 --- a/rbx_asset/src/cloud.rs +++ b/rbx_asset/src/cloud.rs @@ -37,22 +37,27 @@ pub struct UpdateAssetRequest{ //woo nested roblox stuff #[derive(Debug,serde::Deserialize,serde::Serialize)] #[allow(nonstandard_style,dead_code)] -pub struct Creator{ - pub userId:u64, - pub groupId:u64, +pub enum Creator{ + userId(String),//u64 string + groupId(String),//u64 string } #[derive(Debug,serde::Deserialize,serde::Serialize)] #[allow(nonstandard_style,dead_code)] pub struct CreationContext{ pub creator:Creator, - pub expectedPrice:u64, + pub expectedPrice:Option, } #[derive(Debug,serde::Deserialize,serde::Serialize)] #[allow(nonstandard_style,dead_code)] -pub enum ModerationResult{ - MODERATION_STATE_REVIEWING, - MODERATION_STATE_REJECTED, - MODERATION_STATE_APPROVED, +pub enum ModerationState{ + Reviewing, + Rejected, + Approved, +} +#[derive(Debug,serde::Deserialize,serde::Serialize)] +#[allow(nonstandard_style,dead_code)] +pub struct ModerationResult{ + pub moderationState:ModerationState, } #[derive(Debug,serde::Deserialize,serde::Serialize)] #[allow(nonstandard_style,dead_code)] @@ -83,6 +88,51 @@ impl std::fmt::Display for UpdateError{ } impl std::error::Error for UpdateError{} +#[allow(nonstandard_style,dead_code)] +pub struct GetAssetInfoRequest{ + pub asset_id:u64, +} +/* +{ + "assetId": "5692158972", + "assetType": "Model", + "creationContext":{ + "creator": + { + "groupId": "6980477" + } + }, + "description": "DisplayName: Ares\nCreator: titanicguy54", + "displayName": "bhop_ares.rbxmx", + "path": "assets/5692158972", + "revisionCreateTime": "2020-09-14T16:08:05.063Z", + "revisionId": "1", + "moderationResult":{ + "moderationState": "Approved" + }, + "state": "Active" +} +*/ +#[derive(Debug,serde::Deserialize,serde::Serialize)] +#[allow(nonstandard_style,dead_code)] +pub struct AssetResponse{ + pub assetId:String,//u64 wrapped in quotes wohoo!! + pub assetType:AssetType, + pub creationContext:CreationContext, + pub description:String, + pub displayName:String, + pub path:String, + pub revisionCreateTime:chrono::DateTime, + pub revisionId:String,//u64 + pub moderationResult:ModerationResult, + pub icon:Option, + pub previews:Option>, +} +#[allow(nonstandard_style,dead_code)] +pub struct GetAssetVersionRequest{ + pub asset_id:u64, + pub version:u64, +} #[allow(nonstandard_style,dead_code)] pub struct GetAssetRequest{ pub asset_id:u64, @@ -278,17 +328,17 @@ impl CloudContext{ Ok(resp.json::().await.map_err(UpdateError::Reqwest)?) } - pub async fn get_asset(&self,config:GetAssetRequest)->Result,GetError>{ - let mut url=reqwest::Url::parse("https://assetdelivery.roblox.com/v1/asset/").map_err(GetError::ParseError)?; - //url borrow scope - { - let mut query=url.query_pairs_mut();//borrow here - query.append_pair("ID",config.asset_id.to_string().as_str()); - if let Some(version)=config.version{ - query.append_pair("version",version.to_string().as_str()); - } - } - let resp=self.get(url).await.map_err(GetError::Reqwest)?; + pub async fn get_asset_info(&self,config:GetAssetInfoRequest)->Result{ + let raw_url=format!("https://apis.roblox.com/assets/v1/assets/{}",config.asset_id); + let url=reqwest::Url::parse(raw_url.as_str()).map_err(GetError::ParseError)?; + + Ok(self.get(url).await.map_err(GetError::Reqwest)? + .error_for_status().map_err(GetError::Reqwest)? + .json::().await.map_err(GetError::Reqwest)?) + } + pub async fn get_asset_version(&self,config:GetAssetVersionRequest)->Result,GetError>{ + let raw_url=format!("https://apis.roblox.com/assets/v1/assets/{}/versions/{}",config.asset_id,config.version); + let url=reqwest::Url::parse(raw_url.as_str()).map_err(GetError::ParseError)?; let body=self.get(url).await.map_err(GetError::Reqwest)? .error_for_status().map_err(GetError::Reqwest)? @@ -300,6 +350,16 @@ impl CloudContext{ Err(e)=>Err(e), }.map_err(GetError::IO) } + pub async fn get_asset(&self,config:GetAssetRequest)->Result,GetError>{ + let version=match config.version{ + Some(version)=>version, + None=>self.get_asset_info(GetAssetInfoRequest{asset_id:config.asset_id}).await?.revisionId.parse().unwrap(), + }; + self.get_asset_version(GetAssetVersionRequest{ + asset_id:config.asset_id, + version, + }).await + } pub async fn get_asset_versions(&self,config:AssetVersionsRequest)->Result{ let raw_url=format!("https://apis.roblox.com/assets/v1/assets/{}/versions",config.asset_id); let url=reqwest::Url::parse(raw_url.as_str()).map_err(AssetVersionsError::ParseError)?; diff --git a/src/main.rs b/src/main.rs index 6a7fc3f..51fa16c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::{io::Read,path::PathBuf}; use clap::{Args,Parser,Subcommand}; -use anyhow::Result as AResult; +use anyhow::{anyhow,Result as AResult}; use futures::StreamExt; use rbx_asset::cloud::{ApiKey,CloudContext}; use rbx_asset::cookie::{Cookie,CookieContext,AssetVersion,InventoryItem}; @@ -119,9 +119,9 @@ struct CreateAssetMediaSubcommand{ input_file:PathBuf, #[arg(long)] asset_type:AssetType, - #[arg(long)] - creator_user_id:u64, - #[arg(long)] + #[arg(long,group="creator",required=true)] + creator_user_id:Option, + #[arg(long,group="creator",required=true)] creator_group_id:Option, /// Expected price limits how much robux can be spent to create the asset (defaults to 0) #[arg(long)] @@ -413,8 +413,11 @@ async fn main()->AResult<()>{ subcommand.api_key_envvar, subcommand.api_key_file, ).await?, - creator_user_id:subcommand.creator_user_id, - creator_group_id:subcommand.creator_group_id, + creator:match (subcommand.creator_user_id,subcommand.creator_group_id){ + (Some(user_id),None)=>rbx_asset::cloud::Creator::userId(user_id.to_string()), + (None,Some(group_id))=>rbx_asset::cloud::Creator::groupId(group_id.to_string()), + other=>Err(anyhow!("Invalid creator {other:?}"))?, + }, input_file:subcommand.input_file, asset_type:subcommand.asset_type.cloud(), model_name:subcommand.model_name, @@ -568,8 +571,7 @@ struct CreateAssetMediaConfig{ model_name:String, description:String, input_file:PathBuf, - creator_user_id:u64, - creator_group_id:Option, + creator:rbx_asset::cloud::Creator, expected_price:Option, } @@ -580,11 +582,8 @@ async fn create_asset_media(config:CreateAssetMediaConfig)->AResult<()>{ displayName:config.model_name, description:config.description, creationContext:rbx_asset::cloud::CreationContext{ - creator:rbx_asset::cloud::Creator{ - userId:config.creator_user_id, - groupId:config.creator_group_id.unwrap_or(0), - }, - expectedPrice:config.expected_price.unwrap_or(0), + creator:config.creator, + expectedPrice:Some(config.expected_price.unwrap_or(0)), } },tokio::fs::read(config.input_file).await?).await?; println!("CreateResponse={:?}",resp);