You've already forked AstralRinth
forked from didirus/AstralRinth
Add mod lists for modpacks, liteloader support, update actix, fix moderation webhook (#357)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
pub mod error;
|
||||
pub mod ids;
|
||||
pub mod notifications;
|
||||
pub mod pack;
|
||||
pub mod projects;
|
||||
pub mod reports;
|
||||
pub mod teams;
|
||||
|
||||
111
src/models/pack.rs
Normal file
111
src/models/pack.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
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 = 3, max = 512))]
|
||||
pub version_id: String,
|
||||
#[validate(length(min = 3, 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,
|
||||
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::FabricLoader => "fabric-loader",
|
||||
PackDependency::Minecraft => "minecraft",
|
||||
PackDependency::QuiltLoader => "quilt-loader",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ pub struct ModeratorMessage {
|
||||
pub body: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum SideType {
|
||||
Required,
|
||||
@@ -368,6 +368,7 @@ impl From<QueryVersion> for Version {
|
||||
.map(|d| Dependency {
|
||||
version_id: d.version_id.map(|i| VersionId(i.0 as u64)),
|
||||
project_id: d.project_id.map(|i| ProjectId(i.0 as u64)),
|
||||
file_name: d.file_name,
|
||||
dependency_type: DependencyType::from_str(
|
||||
d.dependency_type.as_str(),
|
||||
),
|
||||
@@ -399,7 +400,7 @@ pub struct VersionFile {
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
/// A dependency which describes what versions are required, break support, or are optional to the
|
||||
/// A dendency which describes what versions are required, break support, or are optional to the
|
||||
/// version's functionality
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Dependency {
|
||||
@@ -407,6 +408,8 @@ pub struct Dependency {
|
||||
pub version_id: Option<VersionId>,
|
||||
/// The project ID that the dependency is synced with and auto-updated
|
||||
pub project_id: Option<ProjectId>,
|
||||
/// The filename of the dependency. Used exclusively for external mods on modpacks
|
||||
pub file_name: Option<String>,
|
||||
/// The type of the dependency
|
||||
pub dependency_type: DependencyType,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user