From d3d58ff3586621075a88909ada7baca6c88a2c4d Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 25 Sep 2024 15:51:22 -0700 Subject: [PATCH 1/9] crate info and licenses --- rbx_asset/Cargo.toml | 4 + rbx_asset/LICENSE-APACHE | 176 ++++++++++++++++++++++++++++++++++++ rbx_asset/LICENSE-MIT | 23 +++++ rox_compiler/Cargo.toml | 5 + rox_compiler/LICENSE-APACHE | 176 ++++++++++++++++++++++++++++++++++++ rox_compiler/LICENSE-MIT | 23 +++++ 6 files changed, 407 insertions(+) create mode 100644 rbx_asset/LICENSE-APACHE create mode 100644 rbx_asset/LICENSE-MIT create mode 100644 rox_compiler/LICENSE-APACHE create mode 100644 rox_compiler/LICENSE-MIT diff --git a/rbx_asset/Cargo.toml b/rbx_asset/Cargo.toml index a440029..2da2624 100644 --- a/rbx_asset/Cargo.toml +++ b/rbx_asset/Cargo.toml @@ -3,6 +3,10 @@ name = "rbx_asset" version = "0.2.2" edition = "2021" publish = ["strafesnet"] +repository = "https://git.itzana.me/StrafesNET/asset-tool" +license = "MIT OR Apache-2.0" +description = "Strongly typed interface to the Roblox API using a Cookie or an API key." +authors = ["Rhys Lloyd "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/rbx_asset/LICENSE-APACHE b/rbx_asset/LICENSE-APACHE new file mode 100644 index 0000000..a7e77cb --- /dev/null +++ b/rbx_asset/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/rbx_asset/LICENSE-MIT b/rbx_asset/LICENSE-MIT new file mode 100644 index 0000000..468cd79 --- /dev/null +++ b/rbx_asset/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/rox_compiler/Cargo.toml b/rox_compiler/Cargo.toml index 4b57ee8..0375d05 100644 --- a/rox_compiler/Cargo.toml +++ b/rox_compiler/Cargo.toml @@ -2,6 +2,11 @@ name = "rox_compiler" version = "0.1.0" edition = "2021" +publish = ["strafesnet"] +repository = "https://git.itzana.me/StrafesNET/asset-tool" +license = "MIT OR Apache-2.0" +description = "Read/write a folder structure from Roblox place/model files." +authors = ["Rhys Lloyd "] [dependencies] futures = "0.3.30" diff --git a/rox_compiler/LICENSE-APACHE b/rox_compiler/LICENSE-APACHE new file mode 100644 index 0000000..a7e77cb --- /dev/null +++ b/rox_compiler/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/rox_compiler/LICENSE-MIT b/rox_compiler/LICENSE-MIT new file mode 100644 index 0000000..468cd79 --- /dev/null +++ b/rox_compiler/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file -- 2.45.2 From ac674778f637ae32bb99a3103d2de2c4879b2cf8 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 1 Oct 2024 10:48:25 -0700 Subject: [PATCH 2/9] enable getting creations pages from user or group --- rbx_asset/src/cookie.rs | 39 ++++++++++++++++++++++++------------ src/main.rs | 44 ++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/rbx_asset/src/cookie.rs b/rbx_asset/src/cookie.rs index 3557c7d..b58c684 100644 --- a/rbx_asset/src/cookie.rs +++ b/rbx_asset/src/cookie.rs @@ -114,19 +114,31 @@ impl std::fmt::Display for AssetVersionsPageError{ } impl std::error::Error for AssetVersionsPageError{} -pub struct InventoryPageRequest{ - pub group:u64, +pub enum Owner{ + User(u64), + Group(u64), +} +impl Owner{ + fn get_url_info(&self)->(&str,u64){ + match self{ + &Owner::User(id)=>("user",id), + &Owner::Group(id)=>("group",id), + } + } +} +pub struct CreationsPageRequest{ + pub owner:Owner, pub cursor:Option, } #[derive(serde::Deserialize,serde::Serialize)] #[allow(nonstandard_style,dead_code)] -pub struct InventoryItem{ +pub struct CreationsItem{ pub id:u64, pub name:String, } #[derive(serde::Deserialize,serde::Serialize)] #[allow(nonstandard_style,dead_code)] -pub struct InventoryPageResponse{ +pub struct CreationsPageResponse{ pub totalResults:u64,//up to 50 pub filteredKeyword:Option,//"" pub searchDebugInfo:Option,//null @@ -135,19 +147,19 @@ pub struct InventoryPageResponse{ pub imageSearchStatus:Option,//null pub previousPageCursor:Option, pub nextPageCursor:Option, - pub data:Vec, + pub data:Vec, } #[derive(Debug)] -pub enum InventoryPageError{ +pub enum CreationsPageError{ ParseError(url::ParseError), Reqwest(reqwest::Error), } -impl std::fmt::Display for InventoryPageError{ +impl std::fmt::Display for CreationsPageError{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f,"{self:?}") } } -impl std::error::Error for InventoryPageError{} +impl std::error::Error for CreationsPageError{} //idk how to do this better enum ReaderType{ @@ -305,8 +317,9 @@ impl CookieContext{ .error_for_status().map_err(AssetVersionsPageError::Reqwest)? .json::().await.map_err(AssetVersionsPageError::Reqwest) } - pub async fn get_inventory_page(&self,config:InventoryPageRequest)->Result{ - let mut url=reqwest::Url::parse(format!("https://apis.roblox.com/toolbox-service/v1/creations/group/{}/10?limit=50",config.group).as_str()).map_err(InventoryPageError::ParseError)?; + pub async fn get_creations_page(&self,config:&CreationsPageRequest)->Result{ + let (owner,id)=config.owner.get_url_info(); + let mut url=reqwest::Url::parse(format!("https://apis.roblox.com/toolbox-service/v1/creations/{}/{}/10?limit=50",owner,id).as_str()).map_err(CreationsPageError::ParseError)?; //url borrow scope { let mut query=url.query_pairs_mut();//borrow here @@ -315,8 +328,8 @@ impl CookieContext{ } } - self.get(url).await.map_err(InventoryPageError::Reqwest)? - .error_for_status().map_err(InventoryPageError::Reqwest)? - .json::().await.map_err(InventoryPageError::Reqwest) + self.get(url).await.map_err(CreationsPageError::Reqwest)? + .error_for_status().map_err(CreationsPageError::Reqwest)? + .json::().await.map_err(CreationsPageError::Reqwest) } } diff --git a/src/main.rs b/src/main.rs index a525d7a..418a9a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use clap::{Args,Parser,Subcommand}; use anyhow::{anyhow,Result as AResult}; use futures::StreamExt; use rbx_asset::cloud::{ApiKey,CloudContext}; -use rbx_asset::cookie::{Cookie,CookieContext,AssetVersion,InventoryItem}; +use rbx_asset::cookie::{Cookie,CookieContext,AssetVersion,CreationsItem}; type AssetID=u64; type AssetIDFileMap=Vec<(AssetID,PathBuf)>; @@ -23,7 +23,7 @@ enum Commands{ DownloadHistory(DownloadHistorySubcommand), Download(DownloadSubcommand), DownloadDecompile(DownloadDecompileSubcommand), - DownloadGroupInventoryJson(DownloadGroupInventoryJsonSubcommand), + DownloadCreationsJson(DownloadCreationsJsonSubcommand), CreateAsset(CreateAssetSubcommand), CreateAssetMedia(CreateAssetMediaSubcommand), CreateAssetMedias(CreateAssetMediasSubcommand), @@ -72,9 +72,9 @@ struct DownloadSubcommand{ #[arg(required=true)] asset_ids:Vec, } -/// Download the list of asset ids (not the assets themselves) in a group inventory. The output is written to `output_folder/versions.json` +/// Download the list of asset ids (not the assets themselves) created by a group or user. The output is written to `output_folder/versions.json` #[derive(Args)] -struct DownloadGroupInventoryJsonSubcommand{ +struct DownloadCreationsJsonSubcommand{ #[arg(long,group="cookie",required=true)] cookie_literal:Option, #[arg(long,group="cookie",required=true)] @@ -83,8 +83,10 @@ struct DownloadGroupInventoryJsonSubcommand{ cookie_file:Option, #[arg(long)] output_folder:Option, - #[arg(long)] - group:u64, + #[arg(long,group="owner",required=true)] + group_id:Option, + #[arg(long,group="owner",required=true)] + user_id:Option, } /// Upload a (.rbxm, .rbxmx) model file, creating a new asset. Can be any type of model, including modulescripts. #[derive(Args)] @@ -427,13 +429,16 @@ async fn main()->AResult<()>{ write_scripts:subcommand.write_scripts.unwrap_or(true), }).await }, - Commands::DownloadGroupInventoryJson(subcommand)=>download_group_inventory_json( + Commands::DownloadCreationsJson(subcommand)=>download_creations_json( cookie_from_args( subcommand.cookie_literal, subcommand.cookie_envvar, subcommand.cookie_file, ).await?, - subcommand.group, + owner_from_args( + subcommand.user_id, + subcommand.group_id, + )?, subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()), ).await, Commands::CreateAsset(subcommand)=>create_asset(CreateAssetConfig{ @@ -603,6 +608,14 @@ async fn api_key_from_args(literal:Option,environment:Option,fil }; Ok(ApiKey::new(api_key)) } +fn owner_from_args(user_id:Option,group_id:Option)->AResult{ + let owner=match (user_id,group_id){ + (Some(id),None)=>rbx_asset::cookie::Owner::User(id), + (None,Some(id))=>rbx_asset::cookie::Owner::Group(id), + _=>Err(anyhow::Error::msg("Illegal owner argument pair"))?, + }; + Ok(owner) +} struct CreateAssetConfig{ cookie:Cookie, @@ -890,23 +903,26 @@ async fn download_list(cookie:Cookie,asset_id_file_map:AssetIDFileMap)->AResult< Ok(()) } -async fn get_inventory_pages(context:&CookieContext,group:u64)->AResult>{ - let mut cursor:Option=None; +async fn get_creations_pages(context:&CookieContext,owner:rbx_asset::cookie::Owner)->AResult>{ + let mut config=rbx_asset::cookie::CreationsPageRequest{ + owner, + cursor:None, + }; let mut asset_list=Vec::new(); loop{ - let mut page=context.get_inventory_page(rbx_asset::cookie::InventoryPageRequest{group,cursor}).await?; + let mut page=context.get_creations_page(&config).await?; asset_list.append(&mut page.data); if page.nextPageCursor.is_none(){ break; } - cursor=page.nextPageCursor; + config.cursor=page.nextPageCursor; } Ok(asset_list) } -async fn download_group_inventory_json(cookie:Cookie,group:u64,output_folder:PathBuf)->AResult<()>{ +async fn download_creations_json(cookie:Cookie,owner:rbx_asset::cookie::Owner,output_folder:PathBuf)->AResult<()>{ let context=CookieContext::new(cookie); - let item_list=get_inventory_pages(&context,group).await?; + let item_list=get_creations_pages(&context,owner).await?; let mut path=output_folder.clone(); path.set_file_name("versions.json"); -- 2.45.2 From 94792ebf02b417c98aaac2829db460154b82b82c Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 1 Oct 2024 11:30:37 -0700 Subject: [PATCH 3/9] unite PageErrors --- rbx_asset/src/cookie.rs | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/rbx_asset/src/cookie.rs b/rbx_asset/src/cookie.rs index b58c684..b4921bf 100644 --- a/rbx_asset/src/cookie.rs +++ b/rbx_asset/src/cookie.rs @@ -103,16 +103,16 @@ pub struct AssetVersionsPageResponse{ pub data:Vec, } #[derive(Debug)] -pub enum AssetVersionsPageError{ +pub enum PageError{ ParseError(url::ParseError), Reqwest(reqwest::Error), } -impl std::fmt::Display for AssetVersionsPageError{ +impl std::fmt::Display for PageError{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f,"{self:?}") } } -impl std::error::Error for AssetVersionsPageError{} +impl std::error::Error for PageError{} pub enum Owner{ User(u64), @@ -149,17 +149,6 @@ pub struct CreationsPageResponse{ pub nextPageCursor:Option, pub data:Vec, } -#[derive(Debug)] -pub enum CreationsPageError{ - ParseError(url::ParseError), - Reqwest(reqwest::Error), -} -impl std::fmt::Display for CreationsPageError{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f,"{self:?}") - } -} -impl std::error::Error for CreationsPageError{} //idk how to do this better enum ReaderType{ @@ -300,8 +289,8 @@ impl CookieContext{ Err(e)=>Err(e), }.map_err(GetError::IO) } - pub async fn get_asset_versions_page(&self,config:AssetVersionsPageRequest)->Result{ - let mut url=reqwest::Url::parse(format!("https://develop.roblox.com/v1/assets/{}/saved-versions",config.asset_id).as_str()).map_err(AssetVersionsPageError::ParseError)?; + pub async fn get_asset_versions_page(&self,config:AssetVersionsPageRequest)->Result{ + let mut url=reqwest::Url::parse(format!("https://develop.roblox.com/v1/assets/{}/saved-versions",config.asset_id).as_str()).map_err(PageError::ParseError)?; //url borrow scope { let mut query=url.query_pairs_mut();//borrow here @@ -313,13 +302,13 @@ impl CookieContext{ } } - self.get(url).await.map_err(AssetVersionsPageError::Reqwest)? - .error_for_status().map_err(AssetVersionsPageError::Reqwest)? - .json::().await.map_err(AssetVersionsPageError::Reqwest) + self.get(url).await.map_err(PageError::Reqwest)? + .error_for_status().map_err(PageError::Reqwest)? + .json::().await.map_err(PageError::Reqwest) } - pub async fn get_creations_page(&self,config:&CreationsPageRequest)->Result{ + pub async fn get_creations_page(&self,config:&CreationsPageRequest)->Result{ let (owner,id)=config.owner.get_url_info(); - let mut url=reqwest::Url::parse(format!("https://apis.roblox.com/toolbox-service/v1/creations/{}/{}/10?limit=50",owner,id).as_str()).map_err(CreationsPageError::ParseError)?; + let mut url=reqwest::Url::parse(format!("https://apis.roblox.com/toolbox-service/v1/creations/{}/{}/10?limit=50",owner,id).as_str()).map_err(PageError::ParseError)?; //url borrow scope { let mut query=url.query_pairs_mut();//borrow here @@ -328,8 +317,8 @@ impl CookieContext{ } } - self.get(url).await.map_err(CreationsPageError::Reqwest)? - .error_for_status().map_err(CreationsPageError::Reqwest)? - .json::().await.map_err(CreationsPageError::Reqwest) + self.get(url).await.map_err(PageError::Reqwest)? + .error_for_status().map_err(PageError::Reqwest)? + .json::().await.map_err(PageError::Reqwest) } } -- 2.45.2 From ea0239c78b4378e5d48fd28600b22fd96eee2906 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 1 Oct 2024 11:31:23 -0700 Subject: [PATCH 4/9] cookie.get_user_inventory_page --- rbx_asset/src/cookie.rs | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/rbx_asset/src/cookie.rs b/rbx_asset/src/cookie.rs index b4921bf..7f1d7dc 100644 --- a/rbx_asset/src/cookie.rs +++ b/rbx_asset/src/cookie.rs @@ -150,6 +150,38 @@ pub struct CreationsPageResponse{ pub data:Vec, } +pub struct UserInventoryPageRequest{ + pub user_id:u64, + pub cursor:Option, +} + +#[derive(serde::Deserialize,serde::Serialize)] +#[allow(nonstandard_style,dead_code)] +pub struct UserInventoryItemOwner{ + userId:u64, + username:String, + buildersClubMembershipType:u64, +} +#[derive(serde::Deserialize,serde::Serialize)] +#[allow(nonstandard_style,dead_code)] +pub struct UserInventoryItem{ + userAssetId:u64, + assetId:u64, + assetName:String, + collectibleItemId:Option, + collectibleItemInstanceId:Option, + owner:UserInventoryItemOwner, + created:chrono::DateTime, + updated:chrono::DateTime, +} +#[derive(serde::Deserialize,serde::Serialize)] +#[allow(nonstandard_style,dead_code)] +pub struct UserInventoryPageResponse{ + pub previousPageCursor:Option, + pub nextPageCursor:Option, + pub data:Vec, +} + //idk how to do this better enum ReaderType{ GZip(flate2::read::GzDecoder>), @@ -321,4 +353,18 @@ impl CookieContext{ .error_for_status().map_err(PageError::Reqwest)? .json::().await.map_err(PageError::Reqwest) } + pub async fn get_user_inventory_page(&self,config:&UserInventoryPageRequest)->Result{ + let mut url=reqwest::Url::parse(format!("https://inventory.roblox.com/v2/users/{}/inventory/10?limit=100&sortOrder=Desc",config.user_id).as_str()).map_err(PageError::ParseError)?; + //url borrow scope + { + let mut query=url.query_pairs_mut();//borrow here + if let Some(cursor)=config.cursor.as_deref(){ + query.append_pair("cursor",cursor); + } + } + + self.get(url).await.map_err(PageError::Reqwest)? + .error_for_status().map_err(PageError::Reqwest)? + .json::().await.map_err(PageError::Reqwest) + } } -- 2.45.2 From 28bcf8005bdecf5cd43b5ac5c353c15a4c5f8981 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 1 Oct 2024 11:38:34 -0700 Subject: [PATCH 5/9] download_user_inventory_json --- src/main.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/main.rs b/src/main.rs index 418a9a4..12e2e84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ enum Commands{ Download(DownloadSubcommand), DownloadDecompile(DownloadDecompileSubcommand), DownloadCreationsJson(DownloadCreationsJsonSubcommand), + DownloadUserInventoryJson(DownloadUserInventoryJsonSubcommand), CreateAsset(CreateAssetSubcommand), CreateAssetMedia(CreateAssetMediaSubcommand), CreateAssetMedias(CreateAssetMediasSubcommand), @@ -88,6 +89,20 @@ struct DownloadCreationsJsonSubcommand{ #[arg(long,group="owner",required=true)] user_id:Option, } +/// Download the list of asset ids (not the assets themselves) in a user's inventory. The output is written to `output_folder/versions.json` +#[derive(Args)] +struct DownloadUserInventoryJsonSubcommand{ + #[arg(long,group="cookie",required=true)] + cookie_literal:Option, + #[arg(long,group="cookie",required=true)] + cookie_envvar:Option, + #[arg(long,group="cookie",required=true)] + cookie_file:Option, + #[arg(long)] + output_folder:Option, + #[arg(long)] + user_id:u64, +} /// Upload a (.rbxm, .rbxmx) model file, creating a new asset. Can be any type of model, including modulescripts. #[derive(Args)] struct CreateAssetSubcommand{ @@ -441,6 +456,15 @@ async fn main()->AResult<()>{ )?, subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()), ).await, + Commands::DownloadUserInventoryJson(subcommand)=>download_user_inventory_json( + cookie_from_args( + subcommand.cookie_literal, + subcommand.cookie_envvar, + subcommand.cookie_file, + ).await?, + subcommand.user_id, + subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()), + ).await, Commands::CreateAsset(subcommand)=>create_asset(CreateAssetConfig{ cookie:cookie_from_args( subcommand.cookie_literal, @@ -931,6 +955,34 @@ 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>{ + let mut config=rbx_asset::cookie::UserInventoryPageRequest{ + user_id, + cursor:None, + }; + let mut asset_list=Vec::new(); + loop{ + let mut page=context.get_user_inventory_page(&config).await?; + asset_list.append(&mut page.data); + if page.nextPageCursor.is_none(){ + break; + } + config.cursor=page.nextPageCursor; + } + Ok(asset_list) +} + +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?; + + let mut path=output_folder.clone(); + path.set_file_name("versions.json"); + tokio::fs::write(path,serde_json::to_string(&item_list)?).await?; + + Ok(()) +} + async fn get_version_history(context:&CookieContext,asset_id:AssetID)->AResult>{ let mut cursor:Option=None; let mut asset_list=Vec::new(); -- 2.45.2 From 321ef9b51e30e21f9cd73994fabe9753873e2d97 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 1 Oct 2024 10:52:12 -0700 Subject: [PATCH 6/9] rbx_asset v0.2.3 user inventory --- Cargo.lock | 2 +- rbx_asset/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe02508..b11c36f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1159,7 +1159,7 @@ dependencies = [ [[package]] name = "rbx_asset" -version = "0.2.2" +version = "0.2.3" dependencies = [ "chrono", "flate2", diff --git a/rbx_asset/Cargo.toml b/rbx_asset/Cargo.toml index 2da2624..96e64b0 100644 --- a/rbx_asset/Cargo.toml +++ b/rbx_asset/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rbx_asset" -version = "0.2.2" +version = "0.2.3" edition = "2021" publish = ["strafesnet"] repository = "https://git.itzana.me/StrafesNET/asset-tool" -- 2.45.2 From 1b2e13b4c7bdd4ad487f0b740cf9dde0c9b270c0 Mon Sep 17 00:00:00 2001 From: 9382 Date: Tue, 1 Oct 2024 20:32:59 +0100 Subject: [PATCH 7/9] fix decompiling history into git Why does this work and the version with the directory doesn't? yeah idk. But hey, this one successfully stages the files, so ill take it --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 12e2e84..853c3ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1266,11 +1266,11 @@ async fn write_commit(config:WriteCommitConfig,b:Result(), Err(e)=>println!("tree_index.add_all error: {}",e), } - match tree_index.update_all(std::iter::once(config.output_folder.as_path()),None){ + match tree_index.update_all(std::iter::once("*"),None){ Ok(_)=>(), Err(e)=>println!("tree_index.update_all error: {}",e), } -- 2.45.2 From a572d10447f45fb11ccf4aae6c968d33ed72b16b Mon Sep 17 00:00:00 2001 From: 9382 Date: Tue, 1 Oct 2024 20:44:43 +0100 Subject: [PATCH 8/9] support output-folder option for git-related features Repository-based logic seems to automatically be made relative to the top-level path the repo was initialised with, so we can actually support an output folder with no issues here --- src/main.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 853c3ae..133e8e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -325,8 +325,8 @@ struct DownloadDecompileSubcommand{ struct DecompileHistoryIntoGitSubcommand{ #[arg(long)] input_folder:PathBuf, - //currently output folder must be the current folder due to git2 limitations - //output_folder:cli.output.unwrap(), + #[arg(long)] + output_folder:Option, #[arg(long)] style:Style, #[arg(long)] @@ -351,8 +351,8 @@ struct DownloadAndDecompileHistoryIntoGitSubcommand{ cookie_envvar:Option, #[arg(long,group="cookie",required=true)] cookie_file:Option, - //currently output folder must be the current folder due to git2 limitations - //output_folder:cli.output.unwrap(), + #[arg(long)] + output_folder:Option, #[arg(long)] style:Style, #[arg(long)] @@ -590,7 +590,7 @@ async fn main()->AResult<()>{ git_committer_name:subcommand.git_committer_name, git_committer_email:subcommand.git_committer_email, input_folder:subcommand.input_folder, - output_folder:std::env::current_dir()?, + output_folder:subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()), style:subcommand.style.rox(), write_template:subcommand.write_template.unwrap_or(false), write_models:subcommand.write_models.unwrap_or(false), @@ -605,7 +605,7 @@ async fn main()->AResult<()>{ subcommand.cookie_file, ).await?, asset_id:subcommand.asset_id, - output_folder:std::env::current_dir()?, + output_folder:subcommand.output_folder.unwrap_or_else(||std::env::current_dir().unwrap()), style:subcommand.style.rox(), write_template:subcommand.write_template.unwrap_or(false), write_models:subcommand.write_models.unwrap_or(false), -- 2.45.2 From a693da9cb262d558d107e62293e5d46a55408406 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 1 Oct 2024 10:52:45 -0700 Subject: [PATCH 9/9] asset-tool v0.4.7 user inventory + git fix --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b11c36f..5bd90a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,7 +110,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "asset-tool" -version = "0.4.6" +version = "0.4.7" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 39afa1f..cab10bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ workspace = { members = ["rbx_asset", "rox_compiler"] } [package] name = "asset-tool" -version = "0.4.6" +version = "0.4.7" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -- 2.45.2