You've already forked AstralRinth
forked from didirus/AstralRinth
111 lines
3.2 KiB
Rust
111 lines
3.2 KiB
Rust
use crate::models::projects::SideType;
|
|
use crate::parse_strings_from_var;
|
|
use serde::{Deserialize, Serialize};
|
|
use validator::Validate;
|
|
|
|
#[derive(Serialize, Deserialize, Validate, Eq, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PackFormat {
|
|
pub game: String,
|
|
pub format_version: i32,
|
|
#[validate(length(min = 1, max = 512))]
|
|
pub version_id: String,
|
|
#[validate(length(min = 1, max = 512))]
|
|
pub name: String,
|
|
#[validate(length(max = 2048))]
|
|
pub summary: Option<String>,
|
|
#[validate]
|
|
pub files: Vec<PackFile>,
|
|
pub dependencies: std::collections::HashMap<PackDependency, String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Validate, Eq, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PackFile {
|
|
pub path: String,
|
|
pub hashes: std::collections::HashMap<PackFileHash, String>,
|
|
pub env: Option<std::collections::HashMap<EnvType, SideType>>,
|
|
#[validate(custom(function = "validate_download_url"))]
|
|
pub downloads: Vec<String>,
|
|
pub file_size: u32,
|
|
}
|
|
|
|
fn validate_download_url(values: &[String]) -> Result<(), validator::ValidationError> {
|
|
for value in values {
|
|
let url = url::Url::parse(value)
|
|
.ok()
|
|
.ok_or_else(|| validator::ValidationError::new("invalid URL"))?;
|
|
|
|
if url.as_str() != value {
|
|
return Err(validator::ValidationError::new("invalid URL"));
|
|
}
|
|
|
|
let domains = parse_strings_from_var("WHITELISTED_MODPACK_DOMAINS").unwrap_or_default();
|
|
if !domains.contains(
|
|
&url.domain()
|
|
.ok_or_else(|| validator::ValidationError::new("invalid URL"))?
|
|
.to_string(),
|
|
) {
|
|
return Err(validator::ValidationError::new(
|
|
"File download source is not from allowed sources",
|
|
));
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)]
|
|
#[serde(rename_all = "camelCase", from = "String")]
|
|
pub enum PackFileHash {
|
|
Sha1,
|
|
Sha512,
|
|
Unknown(String),
|
|
}
|
|
|
|
impl From<String> for PackFileHash {
|
|
fn from(s: String) -> Self {
|
|
return match s.as_str() {
|
|
"sha1" => PackFileHash::Sha1,
|
|
"sha512" => PackFileHash::Sha512,
|
|
_ => PackFileHash::Unknown(s),
|
|
};
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub enum EnvType {
|
|
Client,
|
|
Server,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
pub enum PackDependency {
|
|
Forge,
|
|
Neoforge,
|
|
FabricLoader,
|
|
QuiltLoader,
|
|
Minecraft,
|
|
}
|
|
|
|
impl std::fmt::Display for PackDependency {
|
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
fmt.write_str(self.as_str())
|
|
}
|
|
}
|
|
|
|
impl PackDependency {
|
|
// These are constant, so this can remove unnecessary allocations (`to_string`)
|
|
pub fn as_str(&self) -> &'static str {
|
|
match self {
|
|
PackDependency::Forge => "forge",
|
|
PackDependency::Neoforge => "neoforge",
|
|
PackDependency::FabricLoader => "fabric-loader",
|
|
PackDependency::Minecraft => "minecraft",
|
|
PackDependency::QuiltLoader => "quilt-loader",
|
|
}
|
|
}
|
|
}
|