validation: implement publish_new

This commit is contained in:
Quaternions 2024-12-11 17:43:01 -08:00
parent 6677a698be
commit 796935da86
4 changed files with 323 additions and 8 deletions

290
validation/Cargo.lock generated
View File

@ -41,6 +41,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anyhow"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
[[package]] [[package]]
name = "api" name = "api"
version = "0.1.0" version = "0.1.0"
@ -99,6 +105,39 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "async-stream"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-stream-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-trait"
version = "0.1.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -111,6 +150,53 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "axum"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"sync_wrapper 1.0.2",
"tower 0.5.1",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 1.0.2",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.74" version = "0.3.74"
@ -391,6 +477,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.35" version = "0.8.35"
@ -596,13 +688,19 @@ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"http", "http",
"indexmap", "indexmap 2.7.0",
"slab", "slab",
"tokio", "tokio",
"tokio-util", "tokio-util",
"tracing", "tracing",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.2" version = "0.15.2"
@ -649,6 +747,12 @@ version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.5.1" version = "1.5.1"
@ -662,6 +766,7 @@ dependencies = [
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
"httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"smallvec", "smallvec",
@ -686,6 +791,19 @@ dependencies = [
"tower-service", "tower-service",
] ]
[[package]]
name = "hyper-timeout"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
dependencies = [
"hyper",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]] [[package]]
name = "hyper-tls" name = "hyper-tls"
version = "0.6.0" version = "0.6.0"
@ -883,6 +1001,16 @@ dependencies = [
"icu_properties", "icu_properties",
] ]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.7.0" version = "2.7.0"
@ -890,7 +1018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown 0.15.2",
] ]
[[package]] [[package]]
@ -899,6 +1027,15 @@ version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.14" version = "1.0.14"
@ -976,12 +1113,20 @@ dependencies = [
"rbx_dom_weak", "rbx_dom_weak",
"rbx_reflection_database", "rbx_reflection_database",
"rbx_xml", "rbx_xml",
"rust-grpc",
"serde", "serde",
"serde_json", "serde_json",
"siphasher", "siphasher",
"tokio", "tokio",
"tonic",
] ]
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.4"
@ -1257,6 +1402,40 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "prost"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-derive"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "prost-types"
version = "0.13.3-serde1"
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
checksum = "8819b8aaed4d56560ff473ee45247539098b6fba5c8748a429903c499d5bc4a9"
dependencies = [
"prost",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.37"
@ -1448,7 +1627,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper 1.0.2",
"system-configuration", "system-configuration",
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
@ -1497,6 +1676,18 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "rust-grpc"
version = "1.0.3"
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
checksum = "9d241d8d3ce1f24ce54ead69478676d138526bc0d44bb51bea2d87e5d8e3af22"
dependencies = [
"prost",
"prost-types",
"serde",
"tonic",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -1590,6 +1781,12 @@ dependencies = [
"untrusted", "untrusted",
] ]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.18" version = "1.0.18"
@ -1820,6 +2017,12 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]] [[package]]
name = "sync_wrapper" name = "sync_wrapper"
version = "1.0.2" version = "1.0.2"
@ -1983,6 +2186,17 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-stream"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.12" version = "0.7.12"
@ -2017,6 +2231,76 @@ dependencies = [
"tokio-util", "tokio-util",
] ]
[[package]]
name = "tonic"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
dependencies = [
"async-stream",
"async-trait",
"axum",
"base64 0.22.1",
"bytes",
"h2",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"prost",
"socket2",
"tokio",
"tokio-stream",
"tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"indexmap 1.9.3",
"pin-project",
"pin-project-lite",
"rand",
"slab",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
"sync_wrapper 0.1.2",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.3" version = "0.3.3"

View File

@ -12,7 +12,9 @@ rbx_binary = { version = "0.7.4", registry = "strafesnet"}
rbx_dom_weak = { version = "2.9.0", registry = "strafesnet"} rbx_dom_weak = { version = "2.9.0", registry = "strafesnet"}
rbx_reflection_database = { version = "0.2.12", registry = "strafesnet"} rbx_reflection_database = { version = "0.2.12", registry = "strafesnet"}
rbx_xml = { version = "0.13.3", registry = "strafesnet"} rbx_xml = { version = "0.13.3", registry = "strafesnet"}
rust-grpc = { version = "1.0.3", registry = "strafesnet" }
serde = { version = "1.0.215", features = ["derive"] } serde = { version = "1.0.215", features = ["derive"] }
serde_json = "1.0.133" serde_json = "1.0.133"
siphasher = "1.0.1" siphasher = "1.0.1"
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "fs"] } tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread", "fs"] }
tonic = "0.12.3"

View File

@ -9,6 +9,7 @@ enum StartupError{
API(api::ReqwestError), API(api::ReqwestError),
NatsConnect(async_nats::ConnectError), NatsConnect(async_nats::ConnectError),
NatsSubscribe(async_nats::SubscribeError), NatsSubscribe(async_nats::SubscribeError),
GRPCConnect(tonic::transport::Error),
} }
impl std::fmt::Display for StartupError{ impl std::fmt::Display for StartupError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
@ -19,6 +20,9 @@ impl std::error::Error for StartupError{}
pub const GROUP_STRAFESNET:u64=6980477; pub const GROUP_STRAFESNET:u64=6980477;
// annoying mile-long type
pub type MapsServiceClient=rust_grpc::maps::maps_service_client::MapsServiceClient<tonic::transport::channel::Channel>;
#[tokio::main] #[tokio::main]
async fn main()->Result<(),StartupError>{ async fn main()->Result<(),StartupError>{
// talk to roblox through STRAFESNET_CI2 account // talk to roblox through STRAFESNET_CI2 account
@ -33,9 +37,13 @@ async fn main()->Result<(),StartupError>{
let nats_host=std::env::var("NATS_HOST").expect("NATS_HOST env required"); let nats_host=std::env::var("NATS_HOST").expect("NATS_HOST env required");
let nasty=async_nats::connect(nats_host).await.map_err(StartupError::NatsConnect)?; let nasty=async_nats::connect(nats_host).await.map_err(StartupError::NatsConnect)?;
// data-service grpc for creating map entries
let data_host=std::env::var("DATA_HOST").expect("DATA_HOST env required");
let maps_grpc=MapsServiceClient::connect(data_host).await.map_err(StartupError::GRPCConnect)?;
// connect to nats // connect to nats
let (publish_new,publish_fix,validator)=tokio::try_join!( let (publish_new,publish_fix,validator)=tokio::try_join!(
publish_new::Publisher::new(nasty.clone(),cookie_context.clone(),api.clone()), publish_new::Publisher::new(nasty.clone(),cookie_context.clone(),api.clone(),maps_grpc),
publish_fix::Publisher::new(nasty.clone(),cookie_context.clone()), publish_fix::Publisher::new(nasty.clone(),cookie_context.clone()),
// clone nats here because it's dropped within the function scope, // clone nats here because it's dropped within the function scope,
// meanining the last reference is dropped... // meanining the last reference is dropped...

View File

@ -8,6 +8,8 @@ enum PublishError{
Get(rbx_asset::cookie::GetError), Get(rbx_asset::cookie::GetError),
Json(serde_json::Error), Json(serde_json::Error),
Create(rbx_asset::cookie::CreateError), Create(rbx_asset::cookie::CreateError),
SystemTime(std::time::SystemTimeError),
MapCreate(tonic::Status),
ApiActionSubmissionPublish(api::Error), ApiActionSubmissionPublish(api::Error),
} }
impl std::fmt::Display for PublishError{ impl std::fmt::Display for PublishError{
@ -21,17 +23,20 @@ pub struct Publisher{
subscriber:async_nats::Subscriber, subscriber:async_nats::Subscriber,
roblox_cookie:rbx_asset::cookie::CookieContext, roblox_cookie:rbx_asset::cookie::CookieContext,
api:api::Context, api:api::Context,
maps_grpc:crate::MapsServiceClient,
} }
impl Publisher{ impl Publisher{
pub async fn new( pub async fn new(
nats:async_nats::Client, nats:async_nats::Client,
roblox_cookie:rbx_asset::cookie::CookieContext, roblox_cookie:rbx_asset::cookie::CookieContext,
api:api::Context, api:api::Context,
maps_grpc:crate::MapsServiceClient,
)->Result<Self,async_nats::SubscribeError>{ )->Result<Self,async_nats::SubscribeError>{
Ok(Self{ Ok(Self{
subscriber:nats.subscribe("publish_new").await?, subscriber:nats.subscribe("publish_new").await?,
roblox_cookie, roblox_cookie,
api, api,
maps_grpc,
}) })
} }
pub async fn run(mut self){ pub async fn run(mut self){
@ -41,12 +46,12 @@ impl Publisher{
} }
async fn publish_supress_error(&self,message:async_nats::Message){ async fn publish_supress_error(&self,message:async_nats::Message){
match self.publish(message).await{ match self.publish(message).await{
Ok(())=>println!("Published, hooray!"), Ok(())=>println!("[PublishNew] Published, hooray!"),
Err(e)=>println!("[PublishNew] There was an error, oopsie! {e}"), Err(e)=>println!("[PublishNew] There was an error, oopsie! {e}"),
} }
} }
async fn publish(&self,message:async_nats::Message)->Result<(),PublishError>{ async fn publish(&self,message:async_nats::Message)->Result<(),PublishError>{
println!("publish {:?}",message); println!("publish_new {:?}",message);
// decode json // decode json
let publish_info:PublishNewRequest=serde_json::from_slice(&message.payload).map_err(PublishError::Json)?; let publish_info:PublishNewRequest=serde_json::from_slice(&message.payload).map_err(PublishError::Json)?;
@ -58,7 +63,7 @@ impl Publisher{
// upload the map to the strafesnet group // upload the map to the strafesnet group
let upload_response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{ let upload_response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{
name:publish_info.DisplayName, name:publish_info.DisplayName.clone(),
description:"".to_owned(), description:"".to_owned(),
ispublic:false, ispublic:false,
allowComments:false, allowComments:false,
@ -66,7 +71,23 @@ impl Publisher{
},model_data).await.map_err(PublishError::Create)?; },model_data).await.map_err(PublishError::Create)?;
// create the map entry in the game database, including release date // create the map entry in the game database, including release date
// game_rpc.maps.create(upload_response.AssetId) self.maps_grpc.clone().create(rust_grpc::maps::MapRequest{
id:upload_response.AssetId as i64,
display_name:Some(publish_info.DisplayName),
creator:Some(publish_info.Creator),
game_id:Some(publish_info.GameID as i32),
// TODO: scheduling algorithm
date:Some(
// Publish one week from now
(
std::time::SystemTime::now()
+std::time::Duration::from_secs(7*24*60*60)
)
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.map_err(PublishError::SystemTime)?
.as_secs() as i64
),
}).await.map_err(PublishError::MapCreate)?;
// mark submission as published // mark submission as published
self.api.action_submission_publish( self.api.action_submission_publish(