diff --git a/Cargo.lock b/Cargo.lock index 74a1c20..ee6861c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1903,8 +1903,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "submissions-api" -version = "0.7.2" +version = "0.8.0" dependencies = [ + "chrono", "reqwest", "serde", "serde_json", diff --git a/validation/api/Cargo.toml b/validation/api/Cargo.toml index e4080ef..1bbcd73 100644 --- a/validation/api/Cargo.toml +++ b/validation/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "submissions-api" -version = "0.7.2" +version = "0.8.0" edition = "2021" publish = ["strafesnet"] repository = "https://git.itzana.me/StrafesNET/maps-service" @@ -11,6 +11,7 @@ authors = ["Rhys Lloyd "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = { version = "0.4.41", features = ["serde"] } reqwest = { version = "0", features = ["json"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/validation/api/src/external.rs b/validation/api/src/external.rs index 4d19bef..82ade93 100644 --- a/validation/api/src/external.rs +++ b/validation/api/src/external.rs @@ -150,6 +150,84 @@ impl Context{ self.0.delete(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)?; + Ok(()) + } + pub async fn get_submissions(&self,config:GetSubmissionsRequest<'_>)->Result{ + let url_raw=format!("{}/submissions",self.0.base_url); + let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; + + { + let mut query_pairs=url.query_pairs_mut(); + query_pairs.append_pair("Page",config.Page.to_string().as_str()); + query_pairs.append_pair("Limit",config.Limit.to_string().as_str()); + if let Some(sort)=config.Sort{ + query_pairs.append_pair("Sort",(sort as u8).to_string().as_str()); + } + if let Some(display_name)=config.DisplayName{ + query_pairs.append_pair("DisplayName",display_name); + } + if let Some(creator)=config.Creator{ + query_pairs.append_pair("Creator",creator); + } + if let Some(game_id)=config.GameID{ + query_pairs.append_pair("GameID",(game_id as u8).to_string().as_str()); + } + if let Some(submitter)=config.Submitter{ + query_pairs.append_pair("Submitter",submitter.to_string().as_str()); + } + if let Some(asset_id)=config.AssetID{ + query_pairs.append_pair("AssetID",asset_id.to_string().as_str()); + } + if let Some(uploaded_asset_id)=config.UploadedAssetID{ + query_pairs.append_pair("UploadedAssetID",uploaded_asset_id.to_string().as_str()); + } + if let Some(status_id)=config.StatusID{ + query_pairs.append_pair("StatusID",(status_id as u8).to_string().as_str()); + } + } + + response_ok( + self.0.get(url).await.map_err(Error::Reqwest)? + ).await.map_err(Error::Response)? + .json().await.map_err(Error::ReqwestJson) + } + pub async fn get_maps(&self,config:GetMapsRequest<'_>)->Result,Error>{ + let url_raw=format!("{}/maps",self.0.base_url); + let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; + + { + let mut query_pairs=url.query_pairs_mut(); + query_pairs.append_pair("Page",config.Page.to_string().as_str()); + query_pairs.append_pair("Limit",config.Limit.to_string().as_str()); + if let Some(sort)=config.Sort{ + query_pairs.append_pair("Sort",(sort as u8).to_string().as_str()); + } + if let Some(display_name)=config.DisplayName{ + query_pairs.append_pair("DisplayName",display_name); + } + if let Some(creator)=config.Creator{ + query_pairs.append_pair("Creator",creator); + } + if let Some(game_id)=config.GameID{ + query_pairs.append_pair("GameID",(game_id as u8).to_string().as_str()); + } + } + + response_ok( + self.0.get(url).await.map_err(Error::Reqwest)? + ).await.map_err(Error::Response)? + .json().await.map_err(Error::ReqwestJson) + } + pub async fn release_submissions(&self,config:ReleaseRequest<'_>)->Result<(),Error>{ + let url_raw=format!("{}/release-submissions",self.0.base_url); + let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; + + let body=serde_json::to_string(config.schedule).map_err(Error::JSON)?; + + response_ok( + self.0.post(url,body).await.map_err(Error::Reqwest)? + ).await.map_err(Error::Response)?; + Ok(()) } } diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index 0375300..f9717cc 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -169,7 +169,7 @@ impl Context{ ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) ("Creator",config.Creator.as_str()) - ("GameID",config.GameID.to_string().as_str()) + ("GameID",(config.GameID as u8).to_string().as_str()) ); action!("submissions",action_submission_validated,config,SubmissionID,"status/validator-validated",config.0,); action!("submissions",update_submission_validated_model,config,UpdateSubmissionModelRequest,"validated-model",config.SubmissionID, @@ -201,7 +201,7 @@ impl Context{ ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) ("Creator",config.Creator.as_str()) - ("GameID",config.GameID.to_string().as_str()) + ("GameID",(config.GameID as u8).to_string().as_str()) ); action!("mapfixes",action_mapfix_validated,config,MapfixID,"status/validator-validated",config.0,); action!("mapfixes",update_mapfix_validated_model,config,UpdateMapfixModelRequest,"validated-model",config.MapfixID, diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index be8ca5f..14207c4 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -67,6 +67,14 @@ pub async fn response_ok(response:reqwest::Response)->Result{ pub AssetOwner:i64, pub DisplayName:&'a str, pub Creator:&'a str, - pub GameID:i32, + pub GameID:GameID, pub AssetID:u64, pub AssetVersion:u64, pub TargetAssetID:u64, @@ -94,7 +102,7 @@ pub struct CreateSubmissionRequest<'a>{ pub AssetOwner:i64, pub DisplayName:&'a str, pub Creator:&'a str, - pub GameID:i32, + pub GameID:GameID, pub AssetID:u64, pub AssetVersion:u64, pub Status:u32, @@ -235,6 +243,97 @@ pub struct UpdateSubmissionModelRequest{ pub ModelVersion:u64, } +#[derive(Clone,Debug)] +pub enum Sort{ + Disabled=0, + DisplayNameAscending=1, + DisplayNameDescending=2, + DateAscending=3, + DateDescending=4, +} + +#[derive(Clone,Debug,serde_repr::Deserialize_repr)] +#[repr(u8)] +pub enum SubmissionStatus{ + // Phase: Creation + UnderConstruction=0, + ChangesRequested=1, + + // Phase: Review + Submitting=2, + Submitted=3, + + // Phase: Testing + AcceptedUnvalidated=4, // pending script review, can re-trigger validation + Validating=5, + Validated=6, + Uploading=7, + Uploaded=8, // uploaded to the group, but pending release + + // Phase: Final SubmissionStatus + Rejected=9, + Released=10, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug)] +pub struct GetSubmissionsRequest<'a>{ + pub Page:u32, + pub Limit:u32, + pub Sort:Option, + pub DisplayName:Option<&'a str>, + pub Creator:Option<&'a str>, + pub GameID:Option, + pub Submitter:Option, + pub AssetID:Option, + pub UploadedAssetID:Option, + pub StatusID:Option, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Deserialize)] +pub struct SubmissionResponse{ + pub ID:i64, + pub DisplayName:String, + pub Creator:String, + pub GameID:GameID, + pub CreatedAt:i64, + pub UpdatedAt:i64, + pub Submitter:u64, + pub AssetID:u64, + pub AssetVersion:u64, + pub UploadedAssetID:u64, + pub StatusID:SubmissionStatus, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Deserialize)] +pub struct SubmissionsResponse{ + pub Total:u64, + pub Submissions:Vec, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug)] +pub struct GetMapsRequest<'a>{ + pub Page:u32, + pub Limit:u32, + pub Sort:Option, + pub DisplayName:Option<&'a str>, + pub Creator:Option<&'a str>, + pub GameID:Option, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Deserialize)] +pub struct MapResponse{ + pub ID:i64, + pub DisplayName:String, + pub Creator:String, + pub GameID:GameID, + pub Date:i64, +} + #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionSubmissionSubmittedRequest{ @@ -242,7 +341,7 @@ pub struct ActionSubmissionSubmittedRequest{ pub ModelVersion:u64, pub DisplayName:String, pub Creator:String, - pub GameID:u32, + pub GameID:GameID, } #[allow(nonstandard_style)] @@ -266,7 +365,7 @@ pub struct ActionSubmissionAcceptedRequest{ pub ErrorMessage:String, } -#[derive(Clone,Copy,Debug,serde::Deserialize)] +#[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] pub struct SubmissionID(pub i64); #[allow(nonstandard_style)] @@ -284,7 +383,7 @@ pub struct ActionMapfixSubmittedRequest{ pub ModelVersion:u64, pub DisplayName:String, pub Creator:String, - pub GameID:u32, + pub GameID:GameID, } #[allow(nonstandard_style)] @@ -316,3 +415,14 @@ pub struct ActionOperationFailedRequest{ pub OperationID:i32, pub StatusMessage:String, } + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Serialize)] +pub struct ReleaseInfo{ + pub SubmissionID:SubmissionID, + pub Date:chrono::DateTime, +} + +pub struct ReleaseRequest<'a>{ + pub schedule:&'a [ReleaseInfo], +} diff --git a/validation/src/check_mapfix.rs b/validation/src/check_mapfix.rs index d8ed2fd..c2eed90 100644 --- a/validation/src/check_mapfix.rs +++ b/validation/src/check_mapfix.rs @@ -27,7 +27,7 @@ impl crate::message_handler::MessageHandler{ ModelVersion:version, DisplayName:map_info.display_name, Creator:map_info.creator, - GameID:map_info.game_id as u32, + GameID:map_info.game_id.into(), } ).await.map_err(Error::ApiActionMapfixCheck)?, // update the mapfix model status to request changes diff --git a/validation/src/check_submission.rs b/validation/src/check_submission.rs index 7e6463a..37ae360 100644 --- a/validation/src/check_submission.rs +++ b/validation/src/check_submission.rs @@ -28,7 +28,7 @@ impl crate::message_handler::MessageHandler{ ModelVersion:version, DisplayName:map_info.display_name, Creator:map_info.creator, - GameID:map_info.game_id as u32, + GameID:map_info.game_id.into(), } ).await.map_err(Error::ApiActionSubmissionCheck)?, // update the submission model status to request changes diff --git a/validation/src/create_mapfix.rs b/validation/src/create_mapfix.rs index 0884efc..d697675 100644 --- a/validation/src/create_mapfix.rs +++ b/validation/src/create_mapfix.rs @@ -28,7 +28,7 @@ impl crate::message_handler::MessageHandler{ DisplayName:create_request.DisplayName.as_deref().unwrap_or_default(), Creator:create_request.Creator.as_deref().unwrap_or_default(), // not great TODO: make this great - GameID:create_request.GameID.unwrap_or(crate::rbx_util::GameID::Bhop) as i32, + GameID:create_request.GameID.unwrap_or(crate::rbx_util::GameID::Bhop).into(), AssetID:create_info.ModelID, AssetVersion:create_request.AssetVersion, TargetAssetID:create_info.TargetAssetID, diff --git a/validation/src/create_submission.rs b/validation/src/create_submission.rs index 56b3bd0..807044f 100644 --- a/validation/src/create_submission.rs +++ b/validation/src/create_submission.rs @@ -42,7 +42,7 @@ impl crate::message_handler::MessageHandler{ AssetOwner:create_request.AssetOwner as i64, DisplayName:display_name, Creator:creator, - GameID:game_id as i32, + GameID:game_id.into(), AssetID:create_info.ModelID, AssetVersion:create_request.AssetVersion, Status:create_info.Status, diff --git a/validation/src/rbx_util.rs b/validation/src/rbx_util.rs index 59cff0d..4f4451c 100644 --- a/validation/src/rbx_util.rs +++ b/validation/src/rbx_util.rs @@ -37,6 +37,15 @@ pub enum GameID{ Surf=2, FlyTrials=5, } +impl From for submissions_api::types::GameID{ + fn from(value:GameID)->Self{ + match value{ + GameID::Bhop=>submissions_api::types::GameID::Bhop, + GameID::Surf=>submissions_api::types::GameID::Surf, + GameID::FlyTrials=>submissions_api::types::GameID::FlyTrials, + } + } +} #[derive(Debug)] pub struct ParseGameIDError; impl std::str::FromStr for GameID{