diff --git a/src/main.rs b/src/main.rs index e8501ba..3109041 100644 --- a/src/main.rs +++ b/src/main.rs @@ -133,6 +133,8 @@ struct DownloadUserInventoryJsonSubcommand{ output_folder:Option<PathBuf>, #[arg(long)] user_id:u64, + #[arg(long)] + continue_from_cursor:Option<bool>, } /// Upload a (.rbxm, .rbxmx) model file, creating a new asset. Can be any type of model, including modulescripts. #[derive(Args)] @@ -539,6 +541,7 @@ async fn main()->AResult<()>{ ).await?, subcommand.user_id, subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()), + subcommand.continue_from_cursor.unwrap_or(false), ).await, Commands::CreateAsset(subcommand)=>create_asset(CreateAssetConfig{ cookie:cookie_from_args( @@ -1058,12 +1061,11 @@ async fn download_creations_json(cookie:Cookie,owner:rbx_asset::cookie::Owner,ou Ok(()) } -async fn get_user_inventory_pages(context:&CookieContext,user_id:u64)->AResult<Vec<rbx_asset::cookie::UserInventoryItem>>{ - let mut config=rbx_asset::cookie::UserInventoryPageRequest{ - user_id, - cursor:None, - }; - let mut asset_list=Vec::new(); +async fn get_user_inventory_pages( + context:&CookieContext, + asset_list:&mut Vec<rbx_asset::cookie::UserInventoryItem>, + config:&mut rbx_asset::cookie::UserInventoryPageRequest, +)->AResult<()>{ loop{ let mut page=context.get_user_inventory_page(&config).await?; asset_list.append(&mut page.data); @@ -1072,16 +1074,57 @@ async fn get_user_inventory_pages(context:&CookieContext,user_id:u64)->AResult<V } config.cursor=page.nextPageCursor; } - Ok(asset_list) + Ok(()) } -async fn download_user_inventory_json(cookie:Cookie,user_id:u64,output_folder:PathBuf)->AResult<()>{ - let context=CookieContext::new(cookie); - let item_list=get_user_inventory_pages(&context,user_id).await?; +async fn download_user_inventory_json(cookie:Cookie,user_id:u64,output_folder:PathBuf,continue_from_cursor:bool)->AResult<()>{ + let mut versions_path=output_folder.clone(); + versions_path.set_file_name("versions.json"); + let mut cursor_path=output_folder.clone(); + cursor_path.set_file_name("cursor.json"); - let mut path=output_folder.clone(); - path.set_file_name("versions.json"); - tokio::fs::write(path,serde_json::to_string(&item_list)?).await?; + let context=CookieContext::new(cookie); + + let (mut asset_list,mut config)=if continue_from_cursor{ + // load state from files + let (versions,cursor)=tokio::try_join!( + tokio::fs::read(versions_path.as_path()), + tokio::fs::read_to_string(cursor_path.as_path()), + )?; + ( + serde_json::from_slice(&versions)?, + rbx_asset::cookie::UserInventoryPageRequest{ + user_id, + cursor:Some(cursor), + } + ) + }else{ + // create new state + ( + Vec::new(), + rbx_asset::cookie::UserInventoryPageRequest{ + user_id, + cursor:None, + } + ) + }; + + match get_user_inventory_pages(&context,&mut asset_list,&mut config).await{ + Ok(())=>println!("Pages polling complete"), + Err(e)=>println!("Error: {e}"), + } + + let cursor_fut=async{ + if let Some(cursor)=config.cursor{ + println!("writing cursor state..."); + // there was a problem, write out cursor + tokio::fs::write(cursor_path,cursor).await?; + } + Ok(()) + }; + let versions_fut=tokio::fs::write(versions_path,serde_json::to_string(&asset_list)?); + + tokio::try_join!(versions_fut,cursor_fut)?; Ok(()) }