You've already forked AstralRinth
forked from didirus/AstralRinth
move to monorepo dir
This commit is contained in:
32
apps/labrinth/src/validate/datapack.rs
Normal file
32
apps/labrinth/src/validate/datapack.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use crate::validate::{SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct DataPackValidator;
|
||||
|
||||
impl super::Validator for DataPackValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["datapack"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("pack.mcmeta").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No pack.mcmeta present for datapack file. Tip: Make sure pack.mcmeta is in the root directory of your datapack!",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
34
apps/labrinth/src/validate/fabric.rs
Normal file
34
apps/labrinth/src/validate/fabric.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use crate::validate::{filter_out_packs, SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct FabricValidator;
|
||||
|
||||
impl super::Validator for FabricValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["fabric"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("fabric.mod.json").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No fabric.mod.json present for Fabric file.",
|
||||
));
|
||||
}
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
77
apps/labrinth/src/validate/forge.rs
Normal file
77
apps/labrinth/src/validate/forge.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use crate::validate::{filter_out_packs, SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use chrono::DateTime;
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct ForgeValidator;
|
||||
|
||||
impl super::Validator for ForgeValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["jar", "zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["forge"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
// Time since release of 1.13, the first forge version which uses the new TOML system
|
||||
SupportedGameVersions::PastDate(DateTime::from_timestamp(1540122067, 0).unwrap())
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("META-INF/mods.toml").is_err()
|
||||
&& archive.by_name("META-INF/MANIFEST.MF").is_err()
|
||||
&& !archive.file_names().any(|x| x.ends_with(".class"))
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No mods.toml or valid class files present for Forge file.",
|
||||
));
|
||||
}
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LegacyForgeValidator;
|
||||
|
||||
impl super::Validator for LegacyForgeValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["jar", "zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["forge"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
// Times between versions 1.5.2 to 1.12.2, which all use the legacy way of defining mods
|
||||
SupportedGameVersions::Range(
|
||||
DateTime::from_timestamp(0, 0).unwrap(),
|
||||
DateTime::from_timestamp(1540122066, 0).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("mcmod.info").is_err()
|
||||
&& archive.by_name("META-INF/MANIFEST.MF").is_err()
|
||||
&& !archive.file_names().any(|x| x.ends_with(".class"))
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"Forge mod file does not contain mcmod.info or valid class files!",
|
||||
));
|
||||
};
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
34
apps/labrinth/src/validate/liteloader.rs
Normal file
34
apps/labrinth/src/validate/liteloader.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use crate::validate::{filter_out_packs, SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct LiteLoaderValidator;
|
||||
|
||||
impl super::Validator for LiteLoaderValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["litemod", "jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["liteloader"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("litemod.json").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No litemod.json present for LiteLoader file.",
|
||||
));
|
||||
}
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
266
apps/labrinth/src/validate/mod.rs
Normal file
266
apps/labrinth/src/validate/mod.rs
Normal file
@@ -0,0 +1,266 @@
|
||||
use crate::database::models::legacy_loader_fields::MinecraftGameVersion;
|
||||
use crate::database::models::loader_fields::VersionField;
|
||||
use crate::database::models::DatabaseError;
|
||||
use crate::database::redis::RedisPool;
|
||||
use crate::models::pack::PackFormat;
|
||||
use crate::models::projects::{FileType, Loader};
|
||||
use crate::validate::datapack::DataPackValidator;
|
||||
use crate::validate::fabric::FabricValidator;
|
||||
use crate::validate::forge::{ForgeValidator, LegacyForgeValidator};
|
||||
use crate::validate::liteloader::LiteLoaderValidator;
|
||||
use crate::validate::modpack::ModpackValidator;
|
||||
use crate::validate::neoforge::NeoForgeValidator;
|
||||
use crate::validate::plugin::*;
|
||||
use crate::validate::quilt::QuiltValidator;
|
||||
use crate::validate::resourcepack::{PackValidator, TexturePackValidator};
|
||||
use crate::validate::rift::RiftValidator;
|
||||
use crate::validate::shader::{CanvasShaderValidator, CoreShaderValidator, ShaderValidator};
|
||||
use chrono::{DateTime, Utc};
|
||||
use std::io::Cursor;
|
||||
use thiserror::Error;
|
||||
use zip::ZipArchive;
|
||||
|
||||
mod datapack;
|
||||
mod fabric;
|
||||
mod forge;
|
||||
mod liteloader;
|
||||
mod modpack;
|
||||
mod neoforge;
|
||||
pub mod plugin;
|
||||
mod quilt;
|
||||
mod resourcepack;
|
||||
mod rift;
|
||||
mod shader;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ValidationError {
|
||||
#[error("Unable to read Zip Archive: {0}")]
|
||||
Zip(#[from] zip::result::ZipError),
|
||||
#[error("IO Error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("Error while validating JSON for uploaded file: {0}")]
|
||||
SerDe(#[from] serde_json::Error),
|
||||
#[error("Invalid Input: {0}")]
|
||||
InvalidInput(std::borrow::Cow<'static, str>),
|
||||
#[error("Error while managing threads")]
|
||||
Blocking(#[from] actix_web::error::BlockingError),
|
||||
#[error("Error while querying database")]
|
||||
Database(#[from] DatabaseError),
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum ValidationResult {
|
||||
/// File should be marked as primary with pack file data
|
||||
PassWithPackDataAndFiles {
|
||||
format: PackFormat,
|
||||
files: Vec<String>,
|
||||
},
|
||||
/// File should be marked as primary
|
||||
Pass,
|
||||
/// File should not be marked primary, the reason for which is inside the String
|
||||
Warning(&'static str),
|
||||
}
|
||||
|
||||
impl ValidationResult {
|
||||
pub fn is_passed(&self) -> bool {
|
||||
match self {
|
||||
ValidationResult::PassWithPackDataAndFiles { .. } => true,
|
||||
ValidationResult::Pass => true,
|
||||
ValidationResult::Warning(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SupportedGameVersions {
|
||||
All,
|
||||
PastDate(DateTime<Utc>),
|
||||
Range(DateTime<Utc>, DateTime<Utc>),
|
||||
#[allow(dead_code)]
|
||||
Custom(Vec<MinecraftGameVersion>),
|
||||
}
|
||||
|
||||
pub trait Validator: Sync {
|
||||
fn get_file_extensions(&self) -> &[&str];
|
||||
fn get_supported_loaders(&self) -> &[&str];
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions;
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError>;
|
||||
}
|
||||
|
||||
static ALWAYS_ALLOWED_EXT: &[&str] = &["zip", "txt"];
|
||||
|
||||
static VALIDATORS: &[&dyn Validator] = &[
|
||||
&ModpackValidator,
|
||||
&FabricValidator,
|
||||
&ForgeValidator,
|
||||
&LegacyForgeValidator,
|
||||
&QuiltValidator,
|
||||
&LiteLoaderValidator,
|
||||
&PackValidator,
|
||||
&TexturePackValidator,
|
||||
&PluginYmlValidator,
|
||||
&BungeeCordValidator,
|
||||
&VelocityValidator,
|
||||
&SpongeValidator,
|
||||
&CanvasShaderValidator,
|
||||
&ShaderValidator,
|
||||
&CoreShaderValidator,
|
||||
&DataPackValidator,
|
||||
&RiftValidator,
|
||||
&NeoForgeValidator,
|
||||
];
|
||||
|
||||
/// The return value is whether this file should be marked as primary or not, based on the analysis of the file
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn validate_file(
|
||||
data: bytes::Bytes,
|
||||
file_extension: String,
|
||||
loaders: Vec<Loader>,
|
||||
file_type: Option<FileType>,
|
||||
version_fields: Vec<VersionField>,
|
||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
redis: &RedisPool,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
let game_versions = version_fields
|
||||
.into_iter()
|
||||
.find_map(|v| MinecraftGameVersion::try_from_version_field(&v).ok())
|
||||
.unwrap_or_default();
|
||||
let all_game_versions =
|
||||
MinecraftGameVersion::list(None, None, &mut *transaction, redis).await?;
|
||||
|
||||
validate_minecraft_file(
|
||||
data,
|
||||
file_extension,
|
||||
loaders,
|
||||
game_versions,
|
||||
all_game_versions,
|
||||
file_type,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn validate_minecraft_file(
|
||||
data: bytes::Bytes,
|
||||
file_extension: String,
|
||||
loaders: Vec<Loader>,
|
||||
game_versions: Vec<MinecraftGameVersion>,
|
||||
all_game_versions: Vec<MinecraftGameVersion>,
|
||||
file_type: Option<FileType>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
actix_web::web::block(move || {
|
||||
let reader = Cursor::new(data);
|
||||
let mut zip = ZipArchive::new(reader)?;
|
||||
|
||||
if let Some(file_type) = file_type {
|
||||
match file_type {
|
||||
FileType::RequiredResourcePack | FileType::OptionalResourcePack => {
|
||||
return PackValidator.validate(&mut zip);
|
||||
}
|
||||
FileType::Unknown => {}
|
||||
}
|
||||
}
|
||||
|
||||
let mut visited = false;
|
||||
let mut saved_result = None;
|
||||
for validator in VALIDATORS {
|
||||
if loaders
|
||||
.iter()
|
||||
.any(|x| validator.get_supported_loaders().contains(&&*x.0))
|
||||
&& game_version_supported(
|
||||
&game_versions,
|
||||
&all_game_versions,
|
||||
validator.get_supported_game_versions(),
|
||||
)
|
||||
{
|
||||
if validator.get_file_extensions().contains(&&*file_extension) {
|
||||
let result = validator.validate(&mut zip)?;
|
||||
match result {
|
||||
ValidationResult::PassWithPackDataAndFiles { .. } => {
|
||||
saved_result = Some(result);
|
||||
}
|
||||
ValidationResult::Pass => {
|
||||
if saved_result.is_none() {
|
||||
saved_result = Some(result);
|
||||
}
|
||||
}
|
||||
ValidationResult::Warning(_) => {
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
visited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(result) = saved_result {
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
if visited {
|
||||
if ALWAYS_ALLOWED_EXT.contains(&&*file_extension) {
|
||||
Ok(ValidationResult::Warning(
|
||||
"File extension is invalid for input file",
|
||||
))
|
||||
} else {
|
||||
Err(ValidationError::InvalidInput(
|
||||
format!("File extension {file_extension} is invalid for input file").into(),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
// Write tests for this
|
||||
fn game_version_supported(
|
||||
game_versions: &[MinecraftGameVersion],
|
||||
all_game_versions: &[MinecraftGameVersion],
|
||||
supported_game_versions: SupportedGameVersions,
|
||||
) -> bool {
|
||||
match supported_game_versions {
|
||||
SupportedGameVersions::All => true,
|
||||
SupportedGameVersions::PastDate(date) => game_versions.iter().any(|x| {
|
||||
all_game_versions
|
||||
.iter()
|
||||
.find(|y| y.version == x.version)
|
||||
.map(|x| x.created > date)
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
SupportedGameVersions::Range(before, after) => game_versions.iter().any(|x| {
|
||||
all_game_versions
|
||||
.iter()
|
||||
.find(|y| y.version == x.version)
|
||||
.map(|x| x.created > before && x.created < after)
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
SupportedGameVersions::Custom(versions) => {
|
||||
let version_ids = versions.iter().map(|gv| gv.id).collect::<Vec<_>>();
|
||||
let game_version_ids: Vec<_> = game_versions.iter().map(|gv| gv.id).collect::<Vec<_>>();
|
||||
version_ids.iter().any(|x| game_version_ids.contains(x))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filter_out_packs(
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if (archive.by_name("modlist.html").is_ok() && archive.by_name("manifest.json").is_ok())
|
||||
|| archive
|
||||
.file_names()
|
||||
.any(|x| x.starts_with("mods/") && x.ends_with(".jar"))
|
||||
|| archive
|
||||
.file_names()
|
||||
.any(|x| x.starts_with("override/mods/") && x.ends_with(".jar"))
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"Invalid modpack file. You must upload a valid .MRPACK file.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
101
apps/labrinth/src/validate/modpack.rs
Normal file
101
apps/labrinth/src/validate/modpack.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
use crate::models::pack::{PackFileHash, PackFormat};
|
||||
use crate::util::validate::validation_errors_to_string;
|
||||
use crate::validate::{SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::{Cursor, Read};
|
||||
use std::path::Component;
|
||||
use validator::Validate;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct ModpackValidator;
|
||||
|
||||
impl super::Validator for ModpackValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["mrpack"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["mrpack"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
let pack: PackFormat = {
|
||||
let mut file = if let Ok(file) = archive.by_name("modrinth.index.json") {
|
||||
file
|
||||
} else {
|
||||
return Ok(ValidationResult::Warning("Pack manifest is missing."));
|
||||
};
|
||||
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents)?;
|
||||
|
||||
serde_json::from_str(&contents)?
|
||||
};
|
||||
|
||||
pack.validate().map_err(|err| {
|
||||
ValidationError::InvalidInput(validation_errors_to_string(err, None).into())
|
||||
})?;
|
||||
|
||||
if pack.game != "minecraft" {
|
||||
return Err(ValidationError::InvalidInput(
|
||||
format!("Game {0} does not exist!", pack.game).into(),
|
||||
));
|
||||
}
|
||||
|
||||
if pack.files.is_empty() && !archive.file_names().any(|x| x.starts_with("overrides/")) {
|
||||
return Err(ValidationError::InvalidInput("Pack has no files!".into()));
|
||||
}
|
||||
|
||||
for file in &pack.files {
|
||||
if !file.hashes.contains_key(&PackFileHash::Sha1) {
|
||||
return Err(ValidationError::InvalidInput(
|
||||
"All pack files must provide a SHA1 hash!".into(),
|
||||
));
|
||||
}
|
||||
|
||||
if !file.hashes.contains_key(&PackFileHash::Sha512) {
|
||||
return Err(ValidationError::InvalidInput(
|
||||
"All pack files must provide a SHA512 hash!".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let path = std::path::Path::new(&file.path)
|
||||
.components()
|
||||
.next()
|
||||
.ok_or_else(|| ValidationError::InvalidInput("Invalid pack file path!".into()))?;
|
||||
|
||||
match path {
|
||||
Component::CurDir | Component::Normal(_) => {}
|
||||
_ => {
|
||||
return Err(ValidationError::InvalidInput(
|
||||
"Invalid pack file path!".into(),
|
||||
))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(ValidationResult::PassWithPackDataAndFiles {
|
||||
format: pack,
|
||||
files: archive
|
||||
.file_names()
|
||||
.filter(|x| {
|
||||
(x.ends_with("jar") || x.ends_with("zip"))
|
||||
&& (x.starts_with("overrides/mods")
|
||||
|| x.starts_with("client-overrides/mods")
|
||||
|| x.starts_with("server-overrides/mods")
|
||||
|| x.starts_with("overrides/resourcepacks")
|
||||
|| x.starts_with("server-overrides/resourcepacks")
|
||||
|| x.starts_with("overrides/shaderpacks")
|
||||
|| x.starts_with("client-overrides/shaderpacks"))
|
||||
})
|
||||
.flat_map(|x| x.rsplit('/').next().map(|x| x.to_string()))
|
||||
.collect::<Vec<String>>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
38
apps/labrinth/src/validate/neoforge.rs
Normal file
38
apps/labrinth/src/validate/neoforge.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use crate::validate::{filter_out_packs, SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct NeoForgeValidator;
|
||||
|
||||
impl super::Validator for NeoForgeValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["jar", "zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["neoforge"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("META-INF/mods.toml").is_err()
|
||||
&& archive.by_name("META-INF/neoforge.mods.toml").is_err()
|
||||
&& archive.by_name("META-INF/MANIFEST.MF").is_err()
|
||||
&& !archive.file_names().any(|x| x.ends_with(".class"))
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No neoforge.mods.toml, mods.toml, or valid class files present for NeoForge file.",
|
||||
));
|
||||
}
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
129
apps/labrinth/src/validate/plugin.rs
Normal file
129
apps/labrinth/src/validate/plugin.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
use crate::validate::{SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct PluginYmlValidator;
|
||||
|
||||
impl super::Validator for PluginYmlValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip", "jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["bukkit", "spigot", "paper", "purpur", "folia"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if !archive
|
||||
.file_names()
|
||||
.any(|name| name == "plugin.yml" || name == "paper-plugin.yml")
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No plugin.yml or paper-plugin.yml present for plugin file.",
|
||||
));
|
||||
};
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BungeeCordValidator;
|
||||
|
||||
impl super::Validator for BungeeCordValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip", "jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["bungeecord", "waterfall"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if !archive
|
||||
.file_names()
|
||||
.any(|name| name == "plugin.yml" || name == "bungee.yml")
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No plugin.yml or bungee.yml present for plugin file.",
|
||||
));
|
||||
};
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VelocityValidator;
|
||||
|
||||
impl super::Validator for VelocityValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip", "jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["velocity"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("velocity-plugin.json").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No velocity-plugin.json present for plugin file.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpongeValidator;
|
||||
|
||||
impl super::Validator for SpongeValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip", "jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["sponge"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if !archive.file_names().any(|name| {
|
||||
name == "sponge_plugins.json"
|
||||
|| name == "mcmod.info"
|
||||
|| name == "META-INF/sponge_plugins.json"
|
||||
}) {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No sponge_plugins.json or mcmod.info present for Sponge plugin.",
|
||||
));
|
||||
};
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
36
apps/labrinth/src/validate/quilt.rs
Normal file
36
apps/labrinth/src/validate/quilt.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use crate::validate::{filter_out_packs, SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use chrono::DateTime;
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct QuiltValidator;
|
||||
|
||||
impl super::Validator for QuiltValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["jar", "zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["quilt"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::PastDate(DateTime::from_timestamp(1646070100, 0).unwrap())
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("quilt.mod.json").is_err() && archive.by_name("fabric.mod.json").is_err()
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No quilt.mod.json present for Quilt file.",
|
||||
));
|
||||
}
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
67
apps/labrinth/src/validate/resourcepack.rs
Normal file
67
apps/labrinth/src/validate/resourcepack.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use crate::validate::{SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use chrono::DateTime;
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct PackValidator;
|
||||
|
||||
impl super::Validator for PackValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["minecraft"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
// Time since release of 13w24a which replaced texture packs with resource packs
|
||||
SupportedGameVersions::PastDate(DateTime::from_timestamp(1371137542, 0).unwrap())
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("pack.mcmeta").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TexturePackValidator;
|
||||
|
||||
impl super::Validator for TexturePackValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["minecraft"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
// a1.2.2a to 13w23b
|
||||
SupportedGameVersions::Range(
|
||||
DateTime::from_timestamp(1289339999, 0).unwrap(),
|
||||
DateTime::from_timestamp(1370651522, 0).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("pack.txt").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No pack.txt present for pack file.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
34
apps/labrinth/src/validate/rift.rs
Normal file
34
apps/labrinth/src/validate/rift.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use crate::validate::{filter_out_packs, SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct RiftValidator;
|
||||
|
||||
impl super::Validator for RiftValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["jar"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["rift"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("riftmod.json").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No riftmod.json present for Rift file.",
|
||||
));
|
||||
}
|
||||
|
||||
filter_out_packs(archive)?;
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
105
apps/labrinth/src/validate/shader.rs
Normal file
105
apps/labrinth/src/validate/shader.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use crate::validate::{SupportedGameVersions, ValidationError, ValidationResult};
|
||||
use std::io::Cursor;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub struct ShaderValidator;
|
||||
|
||||
impl super::Validator for ShaderValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["optifine", "iris"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if !archive.file_names().any(|x| x.starts_with("shaders/")) {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No shaders folder present for OptiFine/Iris shader.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CanvasShaderValidator;
|
||||
|
||||
impl super::Validator for CanvasShaderValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["canvas"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("pack.mcmeta").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!",
|
||||
));
|
||||
};
|
||||
|
||||
if !archive.file_names().any(|x| x.contains("/pipelines/")) {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No pipeline shaders folder present for canvas shaders.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CoreShaderValidator;
|
||||
|
||||
impl super::Validator for CoreShaderValidator {
|
||||
fn get_file_extensions(&self) -> &[&str] {
|
||||
&["zip"]
|
||||
}
|
||||
|
||||
fn get_supported_loaders(&self) -> &[&str] {
|
||||
&["vanilla"]
|
||||
}
|
||||
|
||||
fn get_supported_game_versions(&self) -> SupportedGameVersions {
|
||||
SupportedGameVersions::All
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
if archive.by_name("pack.mcmeta").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!",
|
||||
));
|
||||
};
|
||||
|
||||
if !archive
|
||||
.file_names()
|
||||
.any(|x| x.starts_with("assets/minecraft/shaders/"))
|
||||
{
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No shaders folder present for vanilla shaders.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user