wip
This commit is contained in:
parent
2d88f5bb51
commit
bc4776ae6c
114
src/main.rs
114
src/main.rs
@ -26,6 +26,7 @@ enum Commands{
|
||||
DownloadGroupInventoryJson(DownloadGroupInventoryJsonSubcommand),
|
||||
CreateAsset(CreateAssetSubcommand),
|
||||
CreateAssetMedia(CreateAssetMediaSubcommand),
|
||||
CreateAssetMedias(CreateAssetMediasSubcommand),
|
||||
UploadAsset(UpdateAssetSubcommand),
|
||||
UploadAssetMedia(UpdateAssetMediaSubcommand),
|
||||
UploadPlace(UpdatePlaceSubcommand),
|
||||
@ -128,6 +129,26 @@ struct CreateAssetMediaSubcommand{
|
||||
expected_price:Option<u64>,
|
||||
}
|
||||
#[derive(Args)]
|
||||
/// Automatically detect the media type from file extension and generate asset name and description
|
||||
struct CreateAssetMediasSubcommand{
|
||||
#[arg(long,group="api_key",required=true)]
|
||||
api_key_literal:Option<String>,
|
||||
#[arg(long,group="api_key",required=true)]
|
||||
api_key_envvar:Option<String>,
|
||||
#[arg(long,group="api_key",required=true)]
|
||||
api_key_file:Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
asset_type:AssetType,
|
||||
#[arg(long,group="creator",required=true)]
|
||||
creator_user_id:Option<u64>,
|
||||
#[arg(long,group="creator",required=true)]
|
||||
creator_group_id:Option<u64>,
|
||||
/// Expected price limits how much robux can be spent to create the asset (defaults to 0)
|
||||
#[arg(long)]
|
||||
expected_price:Option<u64>,
|
||||
input_files:Vec<PathBuf>,
|
||||
}
|
||||
#[derive(Args)]
|
||||
struct UpdateAssetSubcommand{
|
||||
#[arg(long)]
|
||||
asset_id:AssetID,
|
||||
@ -424,6 +445,20 @@ async fn main()->AResult<()>{
|
||||
description:subcommand.description.unwrap_or_else(||String::with_capacity(0)),
|
||||
expected_price:subcommand.expected_price,
|
||||
}).await,
|
||||
Commands::CreateAssetMedias(subcommand)=>create_asset_medias(CreateAssetMediasConfig{
|
||||
api_key:api_key_from_args(
|
||||
subcommand.api_key_literal,
|
||||
subcommand.api_key_envvar,
|
||||
subcommand.api_key_file,
|
||||
).await?,
|
||||
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_files:subcommand.input_files,
|
||||
expected_price:subcommand.expected_price,
|
||||
}).await,
|
||||
Commands::UploadAsset(subcommand)=>upload_asset(UploadAssetConfig{
|
||||
cookie:cookie_from_args(
|
||||
subcommand.cookie_literal,
|
||||
@ -614,6 +649,85 @@ async fn create_asset_media(config:CreateAssetMediaConfig)->AResult<()>{
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct CreateAssetMediasConfig{
|
||||
api_key:ApiKey,
|
||||
description:String,
|
||||
input_files:Vec<PathBuf>,
|
||||
creator:rbx_asset::cloud::Creator,
|
||||
expected_price:Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CreateAssetMediasError{
|
||||
NoFileStem(PathBuf),
|
||||
UnknownFourCC(Option<Vec<u8>>),
|
||||
}
|
||||
impl std::fmt::Display for CreateAssetMediasError{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for CreateAssetMediasError{}
|
||||
|
||||
async fn create_asset_medias(config:CreateAssetMediasConfig)->AResult<()>{
|
||||
let context=CloudContext::new(config.api_key);
|
||||
futures::stream::iter(config.input_files.into_iter()
|
||||
//step 1: read file, make create request
|
||||
.map(|path|{
|
||||
let config=&config;
|
||||
let context=&context;
|
||||
async move{
|
||||
let model_name=path.file_stem()
|
||||
.and_then(std::ffi::OsStr::to_str)
|
||||
.ok_or(CreateAssetMediasError::NoFileStem(path.clone()))?;
|
||||
let file=tokio::fs::read(path).await?;
|
||||
let asset_type=match file.get(0..4){
|
||||
Some(b"\x89PNG")=>rbx_asset::cloud::AssetType::Decal,
|
||||
//jpeg
|
||||
Some(b"\xFF\xD8\xFF\xE0")=>rbx_asset::cloud::AssetType::Decal,
|
||||
//Some("fbx")=>rbx_asset::cloud::AssetType::Model,
|
||||
//Some("ogg")=>rbx_asset::cloud::AssetType::Audio,
|
||||
fourcc=>Err(CreateAssetMediasError::UnknownFourCC(fourcc.map(<[u8]>::to_owned)))?,
|
||||
};
|
||||
Ok(context.create_asset(rbx_asset::cloud::CreateAssetRequest{
|
||||
assetType:asset_type,
|
||||
displayName:model_name.to_owned(),
|
||||
description:config.description.clone(),
|
||||
creationContext:rbx_asset::cloud::CreationContext{
|
||||
creator:config.creator,
|
||||
expectedPrice:Some(config.expected_price.unwrap_or(0)),
|
||||
}
|
||||
},file).await?)
|
||||
}
|
||||
}))
|
||||
//parallel requests
|
||||
.buffer_unordered(CONCURRENT_REQUESTS)
|
||||
//step 2: poll operation until it completes (as fast as possible no exp backoff or anything just hammer roblox)
|
||||
.filter_map(|create_result:AResult<_>|{
|
||||
let context=&context;
|
||||
async{
|
||||
match create_result{
|
||||
Ok(operation)=>match operation.wait(context).await{
|
||||
Ok(())=>Some(operation),
|
||||
Err(e)=>{
|
||||
eprintln!("operation error: {}",e);
|
||||
None
|
||||
},
|
||||
},
|
||||
Err(e)=>{
|
||||
eprintln!("create_asset error: {}",e);
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
//step 3: read decal id from operation and download it
|
||||
.filter_map(|operation|{
|
||||
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct UploadAssetConfig{
|
||||
cookie:Cookie,
|
||||
asset_id:AssetID,
|
||||
|
Loading…
Reference in New Issue
Block a user