diff --git a/validation/api/src/lib.rs b/validation/api/src/lib.rs index 3034cc6..f6558b6 100644 --- a/validation/api/src/lib.rs +++ b/validation/api/src/lib.rs @@ -64,6 +64,20 @@ pub struct Context{ pub type ReqwestError=reqwest::Error; +// there are lots of action endpoints and they all follow the same pattern +macro_rules! action{ + ($fname:ident,$action:ident)=>{ + pub async fn $fname(&self,config:SubmissionID)->Result<(),Error>{ + let url_raw=format!(concat!("{}/submissions/{}/status/",stringify!($action)),self.base_url,config.0); + let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::ParseError)?; + + self.patch(url).await.map_err(Error::Reqwest)? + .error_for_status().map_err(Error::Reqwest)?; + + Ok(()) + } + }; +} impl Context{ pub fn new( base_url:String, @@ -120,13 +134,6 @@ impl Context{ Ok(()) } - pub async fn action_submission_validate(&self,config:SubmissionID)->Result<(),Error>{ - let url_raw=format!("{}/submissions/{}/status/validate",self.base_url,config.0); - let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::ParseError)?; - - self.patch(url).await.map_err(Error::Reqwest)? - .error_for_status().map_err(Error::Reqwest)?; - - Ok(()) - } + action!(action_submission_validate,validate); + action!(action_submission_publish,publish); } diff --git a/validation/src/main.rs b/validation/src/main.rs index 097207c..625da28 100644 --- a/validation/src/main.rs +++ b/validation/src/main.rs @@ -17,6 +17,8 @@ impl std::fmt::Display for StartupError{ } impl std::error::Error for StartupError{} +pub const GROUP_STRAFESNET:u64=6980477; + #[tokio::main] async fn main()->Result<(),StartupError>{ // talk to roblox @@ -30,7 +32,7 @@ async fn main()->Result<(),StartupError>{ // connect to nats let (publish_new,publish_fix,validator)=tokio::try_join!( - publish_new::Publisher::new(nasty.clone(),cookie_context.clone()), + publish_new::Publisher::new(nasty.clone(),cookie_context.clone(),api.clone()), publish_fix::Publisher::new(nasty.clone(),cookie_context.clone()), // clone nats here because it's dropped within the function scope, // meanining the last reference is dropped... diff --git a/validation/src/nats_types.rs b/validation/src/nats_types.rs index 1113368..a7f945d 100644 --- a/validation/src/nats_types.rs +++ b/validation/src/nats_types.rs @@ -14,6 +14,7 @@ pub struct ValidateRequest{ } // Create a new map +#[derive(serde::Deserialize)] pub struct PublishNewRequest{ pub submission_id:i64, pub model_id:u64, @@ -23,6 +24,7 @@ pub struct PublishNewRequest{ //games:HashSet, } +#[derive(serde::Deserialize)] pub struct PublishFixRequest{ pub submission_id:i64, pub model_id:u64, diff --git a/validation/src/publish_new.rs b/validation/src/publish_new.rs index f9c0530..c0bfffa 100644 --- a/validation/src/publish_new.rs +++ b/validation/src/publish_new.rs @@ -1,7 +1,13 @@ use futures::StreamExt; +use crate::nats_types::PublishNewRequest; + #[derive(Debug)] enum PublishError{ + Get(rbx_asset::cookie::GetError), + Json(serde_json::Error), + Create(rbx_asset::cookie::CreateError), + ApiActionSubmissionPublish(api::Error), } impl std::fmt::Display for PublishError{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ @@ -13,23 +19,59 @@ impl std::error::Error for PublishError{} pub struct Publisher{ subscriber:async_nats::Subscriber, roblox_cookie:rbx_asset::cookie::CookieContext, + api:api::Context, } impl Publisher{ pub async fn new( nats:async_nats::Client, roblox_cookie:rbx_asset::cookie::CookieContext, + api:api::Context, )->Result{ Ok(Self{ subscriber:nats.subscribe("publish_new").await?, roblox_cookie, + api, }) } pub async fn run(mut self){ while let Some(message)=self.subscriber.next().await{ - self.publish(message).await + self.publish_supress_error(message).await } } - async fn publish(&self,message:async_nats::Message){ + async fn publish_supress_error(&self,message:async_nats::Message){ + match self.publish(message).await{ + Ok(())=>println!("Published, hooray!"), + Err(e)=>println!("[PublishNew] There was an error, oopsie! {e}"), + } + } + async fn publish(&self,message:async_nats::Message)->Result<(),PublishError>{ println!("publish {:?}",message); + // decode json + let publish_info:PublishNewRequest=serde_json::from_slice(&message.payload).map_err(PublishError::Json)?; + + // download the map model version + let model_data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{ + asset_id:publish_info.model_id, + version:Some(publish_info.model_version), + }).await.map_err(PublishError::Get)?; + + // upload the map to the strafesnet group + let upload_response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{ + name:publish_info.display_name, + description:"".to_owned(), + ispublic:false, + allowComments:false, + groupId:Some(crate::GROUP_STRAFESNET), + },model_data).await.map_err(PublishError::Create)?; + + // create the map entry in the game database, including release date + // game_rpc.maps.create(upload_response.AssetId) + + // mark submission as published + self.api.action_submission_publish( + api::SubmissionID(publish_info.submission_id) + ).await.map_err(PublishError::ApiActionSubmissionPublish)?; + + Ok(()) } }