You've already forked AstralRinth
forked from didirus/AstralRinth
Side types overhaul (#762)
* side types overhaul * fixes, fmt clippy * migration fix for v3 bug * fixed migration issues * more tested migration changes * fmt, clippy * bump cicd --------- Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use crate::database::models::loader_fields::VersionField;
|
||||
use crate::database::models::{project_item, version_item};
|
||||
use crate::database::redis::RedisPool;
|
||||
use crate::file_hosting::FileHost;
|
||||
use crate::models::ids::ImageId;
|
||||
@@ -88,63 +90,90 @@ pub async fn version_create(
|
||||
payload,
|
||||
req.headers().clone(),
|
||||
|legacy_create: InitialVersionData| {
|
||||
// Convert input data to V3 format
|
||||
let mut fields = HashMap::new();
|
||||
fields.insert(
|
||||
"game_versions".to_string(),
|
||||
json!(legacy_create.game_versions),
|
||||
);
|
||||
let client = client.clone();
|
||||
let redis = redis.clone();
|
||||
async move {
|
||||
// Convert input data to V3 format
|
||||
let mut fields = HashMap::new();
|
||||
fields.insert(
|
||||
"game_versions".to_string(),
|
||||
json!(legacy_create.game_versions),
|
||||
);
|
||||
|
||||
// TODO: will be overhauled with side-types overhaul
|
||||
// TODO: if not, should default to previous version
|
||||
fields.insert("client_side".to_string(), json!("required"));
|
||||
fields.insert("server_side".to_string(), json!("optional"));
|
||||
|
||||
// Handle project type via file extension prediction
|
||||
let mut project_type = None;
|
||||
for file_part in &legacy_create.file_parts {
|
||||
if let Some(ext) = file_part.split('.').last() {
|
||||
match ext {
|
||||
"mrpack" | "mrpack-primary" => {
|
||||
project_type = Some("modpack");
|
||||
break;
|
||||
// Copies side types of another version of the project.
|
||||
// If no version exists, defaults to all false.
|
||||
// TODO: write test for this to ensure predictible unchanging behaviour
|
||||
// This is inherently lossy, but not much can be done about it, as side types are no longer associated with projects,
|
||||
// so the 'missing' ones can't be easily accessed.
|
||||
let side_type_loader_field_names = [
|
||||
"singleplayer",
|
||||
"client_and_server",
|
||||
"client_only",
|
||||
"server_only",
|
||||
];
|
||||
fields.extend(
|
||||
side_type_loader_field_names
|
||||
.iter()
|
||||
.map(|f| (f.to_string(), json!(false))),
|
||||
);
|
||||
if let Some(example_version_fields) =
|
||||
get_example_version_fields(legacy_create.project_id, client, &redis).await?
|
||||
{
|
||||
fields.extend(example_version_fields.into_iter().filter_map(|f| {
|
||||
if side_type_loader_field_names.contains(&f.field_name.as_str()) {
|
||||
Some((f.field_name, f.value.serialize_internal()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// No other type matters
|
||||
_ => {}
|
||||
}
|
||||
break;
|
||||
}));
|
||||
}
|
||||
|
||||
// Handle project type via file extension prediction
|
||||
let mut project_type = None;
|
||||
for file_part in &legacy_create.file_parts {
|
||||
if let Some(ext) = file_part.split('.').last() {
|
||||
match ext {
|
||||
"mrpack" | "mrpack-primary" => {
|
||||
project_type = Some("modpack");
|
||||
break;
|
||||
}
|
||||
// No other type matters
|
||||
_ => {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Modpacks now use the "mrpack" loader, and loaders are converted to loader fields.
|
||||
// Setting of 'project_type' directly is removed, it's loader-based now.
|
||||
if project_type == Some("modpack") {
|
||||
fields.insert("mrpack_loaders".to_string(), json!(legacy_create.loaders));
|
||||
}
|
||||
|
||||
let loaders = if project_type == Some("modpack") {
|
||||
vec![Loader("mrpack".to_string())]
|
||||
} else {
|
||||
legacy_create.loaders
|
||||
};
|
||||
|
||||
Ok(v3::version_creation::InitialVersionData {
|
||||
project_id: legacy_create.project_id,
|
||||
file_parts: legacy_create.file_parts,
|
||||
version_number: legacy_create.version_number,
|
||||
version_title: legacy_create.version_title,
|
||||
version_body: legacy_create.version_body,
|
||||
dependencies: legacy_create.dependencies,
|
||||
release_channel: legacy_create.release_channel,
|
||||
loaders,
|
||||
featured: legacy_create.featured,
|
||||
primary_file: legacy_create.primary_file,
|
||||
status: legacy_create.status,
|
||||
file_types: legacy_create.file_types,
|
||||
uploaded_images: legacy_create.uploaded_images,
|
||||
ordering: legacy_create.ordering,
|
||||
fields,
|
||||
})
|
||||
}
|
||||
|
||||
// Modpacks now use the "mrpack" loader, and loaders are converted to loader fields.
|
||||
// Setting of 'project_type' directly is removed, it's loader-based now.
|
||||
if project_type == Some("modpack") {
|
||||
fields.insert("mrpack_loaders".to_string(), json!(legacy_create.loaders));
|
||||
}
|
||||
|
||||
let loaders = if project_type == Some("modpack") {
|
||||
vec![Loader("mrpack".to_string())]
|
||||
} else {
|
||||
legacy_create.loaders
|
||||
};
|
||||
|
||||
Ok(v3::version_creation::InitialVersionData {
|
||||
project_id: legacy_create.project_id,
|
||||
file_parts: legacy_create.file_parts,
|
||||
version_number: legacy_create.version_number,
|
||||
version_title: legacy_create.version_title,
|
||||
version_body: legacy_create.version_body,
|
||||
dependencies: legacy_create.dependencies,
|
||||
release_channel: legacy_create.release_channel,
|
||||
loaders,
|
||||
featured: legacy_create.featured,
|
||||
primary_file: legacy_create.primary_file,
|
||||
status: legacy_create.status,
|
||||
file_types: legacy_create.file_types,
|
||||
uploaded_images: legacy_create.uploaded_images,
|
||||
ordering: legacy_create.ordering,
|
||||
fields,
|
||||
})
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
@@ -170,6 +199,32 @@ pub async fn version_create(
|
||||
}
|
||||
}
|
||||
|
||||
// Gets version fields of an example version of a project, if one exists.
|
||||
async fn get_example_version_fields(
|
||||
project_id: Option<ProjectId>,
|
||||
pool: Data<PgPool>,
|
||||
redis: &RedisPool,
|
||||
) -> Result<Option<Vec<VersionField>>, CreateError> {
|
||||
let project_id = match project_id {
|
||||
Some(project_id) => project_id,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let vid = match project_item::Project::get_id(project_id.into(), &**pool, redis)
|
||||
.await?
|
||||
.and_then(|p| p.versions.first().cloned())
|
||||
{
|
||||
Some(vid) => vid,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let example_version = match version_item::Version::get(vid, &**pool, redis).await? {
|
||||
Some(version) => version,
|
||||
None => return Ok(None),
|
||||
};
|
||||
Ok(Some(example_version.version_fields))
|
||||
}
|
||||
|
||||
// under /api/v1/version/{version_id}
|
||||
#[post("{version_id}/file")]
|
||||
pub async fn upload_file_to_version(
|
||||
|
||||
Reference in New Issue
Block a user