wip: write some script validation code
This commit is contained in:
parent
dc7645319e
commit
dd193e6e8f
@ -10,6 +10,7 @@ pub struct ValidateRequest{
|
|||||||
pub submission_id:u64,
|
pub submission_id:u64,
|
||||||
pub model_id:u64,
|
pub model_id:u64,
|
||||||
pub model_version:u64,
|
pub model_version:u64,
|
||||||
|
pub validated_model_id:Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new map
|
// Create a new map
|
||||||
|
@ -17,6 +17,10 @@ enum ValidateError{
|
|||||||
Get(rbx_asset::cookie::GetError),
|
Get(rbx_asset::cookie::GetError),
|
||||||
Json(serde_json::Error),
|
Json(serde_json::Error),
|
||||||
ReadDom(ReadDomError),
|
ReadDom(ReadDomError),
|
||||||
|
ApiGetReplacements(api::GetReplacementsError),
|
||||||
|
WriteDom(rbx_binary::EncodeError),
|
||||||
|
Upload(rbx_asset::cookie::UploadError),
|
||||||
|
Create(rbx_asset::cookie::CreateError),
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for ValidateError{
|
impl std::fmt::Display for ValidateError{
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
@ -72,11 +76,87 @@ impl Validator{
|
|||||||
// decode dom (slow!)
|
// decode dom (slow!)
|
||||||
let mut dom=read_dom(&mut std::io::Cursor::new(data)).map_err(ValidateError::ReadDom)?;
|
let mut dom=read_dom(&mut std::io::Cursor::new(data)).map_err(ValidateError::ReadDom)?;
|
||||||
|
|
||||||
// validate map
|
/* VALIDATE MAP */
|
||||||
// validate(dom)
|
|
||||||
|
// collect unique scripts
|
||||||
|
let script_refs=get_script_refs(&dom);
|
||||||
|
let mut script_map=std::collections::HashMap::<String,Option<String>>::new();
|
||||||
|
for &script_ref in &script_refs{
|
||||||
|
if let Some(script)=dom.get_by_ref(script_ref){
|
||||||
|
if let Some(rbx_dom_weak::types::Variant::String(source))=script.properties.get("Source"){
|
||||||
|
script_map.insert(source.clone(),None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ["local a=true","local b=true"]
|
||||||
|
let script_list:Vec<&str>=script_map.keys().map(|s|s.as_str()).collect();
|
||||||
|
let j=serde_json::to_string(&script_list).map_err(ValidateError::Json)?;
|
||||||
|
|
||||||
|
// send all scripts to REST endpoint and receive the replacements
|
||||||
|
let replacements=self.api.get_replacements(j).await.map_err(ValidateError::ApiGetReplacements)?;
|
||||||
|
|
||||||
|
// assume the iteration order will not change if no keys are inserted or removed
|
||||||
|
for (map_value,replacement) in script_map.values_mut().zip(replacements){
|
||||||
|
*map_value=replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the replacements
|
||||||
|
let mut any_replaced=false;
|
||||||
|
for &script_ref in &script_refs{
|
||||||
|
if let Some(script)=dom.get_by_ref_mut(script_ref){
|
||||||
|
if let Some(rbx_dom_weak::types::Variant::String(source))=script.properties.get_mut("Source"){
|
||||||
|
if let Some(Some(replacement))=script_map.get(source.as_str()){
|
||||||
|
any_replaced=true;
|
||||||
|
*source=replacement.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// reply with validity
|
// reply with validity
|
||||||
Ok(Valid::Untouched)
|
Ok(if any_replaced{
|
||||||
|
// serialize model (slow!)
|
||||||
|
let mut data=Vec::new();
|
||||||
|
rbx_binary::to_writer(&mut data,&dom,&[dom.root_ref()]).map_err(ValidateError::WriteDom)?;
|
||||||
|
|
||||||
|
// upload a model lol
|
||||||
|
let (model_id,model_version)=if let Some(model_id)=validate_info.validated_model_id{
|
||||||
|
// upload to existing id
|
||||||
|
let response=self.roblox_cookie.upload(rbx_asset::cookie::UploadRequest{
|
||||||
|
assetid:model_id,
|
||||||
|
name:None,
|
||||||
|
description:None,
|
||||||
|
ispublic:None,
|
||||||
|
allowComments:None,
|
||||||
|
groupId:None,
|
||||||
|
},data).await.map_err(ValidateError::Upload)?;
|
||||||
|
|
||||||
|
// response.AssetVersionId is not the right one
|
||||||
|
let model_version=get_model_version_number();
|
||||||
|
(response.AssetId,model_version)
|
||||||
|
}else{
|
||||||
|
// create new model
|
||||||
|
let response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{
|
||||||
|
name:dom.root().name,
|
||||||
|
description:"".to_owned(),
|
||||||
|
ispublic:true,
|
||||||
|
allowComments:true,
|
||||||
|
groupId:None,
|
||||||
|
},data).await.map_err(ValidateError::Create)?;
|
||||||
|
|
||||||
|
// response.AssetVersionId is not the right one
|
||||||
|
let model_version=get_model_version_number();
|
||||||
|
(response.AssetId,model_version)
|
||||||
|
};
|
||||||
|
|
||||||
|
// tell the submission validate request to change the model
|
||||||
|
Valid::Modified(ModelVersion{
|
||||||
|
model_id,
|
||||||
|
model_version,
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
Valid::Untouched
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,3 +191,33 @@ fn read_dom<R:std::io::Read+std::io::Seek>(input:&mut R)->Result<rbx_dom_weak::W
|
|||||||
_=>Err(ReadDomError::UnknownFormat(first_8)),
|
_=>Err(ReadDomError::UnknownFormat(first_8)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn class_is_a(class:&str,superclass:&str)->bool{
|
||||||
|
if class==superclass{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
let class_descriptor=rbx_reflection_database::get().classes.get(class);
|
||||||
|
if let Some(descriptor)=&class_descriptor{
|
||||||
|
if let Some(class_super)=&descriptor.superclass{
|
||||||
|
return class_is_a(&class_super,superclass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recursive_collect_superclass(objects:&mut std::vec::Vec<rbx_dom_weak::types::Ref>,dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str){
|
||||||
|
for &referent in instance.children(){
|
||||||
|
if let Some(c)=dom.get_by_ref(referent){
|
||||||
|
if class_is_a(c.class.as_str(),superclass){
|
||||||
|
objects.push(c.referent());//copy ref
|
||||||
|
}
|
||||||
|
recursive_collect_superclass(objects,dom,c,superclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_script_refs(dom:&rbx_dom_weak::WeakDom)->Vec<rbx_dom_weak::types::Ref>{
|
||||||
|
let mut scripts=std::vec::Vec::new();
|
||||||
|
recursive_collect_superclass(&mut scripts,dom,dom.root(),"LuaSourceContainer");
|
||||||
|
scripts
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user