You've already forked AstralRinth
forked from didirus/AstralRinth
Monetization status, additional files fix, deps fix (#574)
This commit is contained in:
10
migrations/20230416033024_deps-project-mandatory.sql
Normal file
10
migrations/20230416033024_deps-project-mandatory.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
UPDATE dependencies AS d
|
||||||
|
SET mod_dependency_id = v.mod_id
|
||||||
|
FROM versions AS v
|
||||||
|
WHERE v.id = d.dependency_id;
|
||||||
|
|
||||||
|
ALTER TABLE users DROP COLUMN flame_anvil_key;
|
||||||
|
ALTER TABLE mods DROP COLUMN flame_anvil_project;
|
||||||
|
ALTER TABLE mods DROP COLUMN flame_anvil_user;
|
||||||
|
|
||||||
|
ALTER TABLE mods ADD COLUMN monetization_status varchar(64) NOT NULL default 'monetized';
|
||||||
2157
sqlx-data.json
2157
sqlx-data.json
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
use super::ids::*;
|
use super::ids::*;
|
||||||
use crate::models::projects::ProjectStatus;
|
use crate::models::projects::{MonetizationStatus, ProjectStatus};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ pub struct ProjectBuilder {
|
|||||||
pub gallery_items: Vec<GalleryItem>,
|
pub gallery_items: Vec<GalleryItem>,
|
||||||
pub color: Option<u32>,
|
pub color: Option<u32>,
|
||||||
pub thread_id: ThreadId,
|
pub thread_id: ThreadId,
|
||||||
|
pub monetization_status: MonetizationStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectBuilder {
|
impl ProjectBuilder {
|
||||||
@@ -141,13 +142,12 @@ impl ProjectBuilder {
|
|||||||
slug: self.slug,
|
slug: self.slug,
|
||||||
moderation_message: None,
|
moderation_message: None,
|
||||||
moderation_message_body: None,
|
moderation_message_body: None,
|
||||||
flame_anvil_project: None,
|
|
||||||
flame_anvil_user: None,
|
|
||||||
webhook_sent: false,
|
webhook_sent: false,
|
||||||
color: self.color,
|
color: self.color,
|
||||||
loaders: vec![],
|
loaders: vec![],
|
||||||
game_versions: vec![],
|
game_versions: vec![],
|
||||||
thread_id: Some(self.thread_id),
|
thread_id: Some(self.thread_id),
|
||||||
|
monetization_status: self.monetization_status,
|
||||||
};
|
};
|
||||||
project_struct.insert(&mut *transaction).await?;
|
project_struct.insert(&mut *transaction).await?;
|
||||||
|
|
||||||
@@ -226,13 +226,12 @@ pub struct Project {
|
|||||||
pub slug: Option<String>,
|
pub slug: Option<String>,
|
||||||
pub moderation_message: Option<String>,
|
pub moderation_message: Option<String>,
|
||||||
pub moderation_message_body: Option<String>,
|
pub moderation_message_body: Option<String>,
|
||||||
pub flame_anvil_project: Option<i32>,
|
|
||||||
pub flame_anvil_user: Option<UserId>,
|
|
||||||
pub webhook_sent: bool,
|
pub webhook_sent: bool,
|
||||||
pub color: Option<u32>,
|
pub color: Option<u32>,
|
||||||
pub loaders: Vec<String>,
|
pub loaders: Vec<String>,
|
||||||
pub game_versions: Vec<String>,
|
pub game_versions: Vec<String>,
|
||||||
pub thread_id: Option<ThreadId>,
|
pub thread_id: Option<ThreadId>,
|
||||||
|
pub monetization_status: MonetizationStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
@@ -247,14 +246,14 @@ impl Project {
|
|||||||
published, downloads, icon_url, issues_url,
|
published, downloads, icon_url, issues_url,
|
||||||
source_url, wiki_url, status, requested_status, discord_url,
|
source_url, wiki_url, status, requested_status, discord_url,
|
||||||
client_side, server_side, license_url, license,
|
client_side, server_side, license_url, license,
|
||||||
slug, project_type, color, thread_id
|
slug, project_type, color, thread_id, monetization_status
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1, $2, $3, $4, $5,
|
$1, $2, $3, $4, $5,
|
||||||
$6, $7, $8, $9,
|
$6, $7, $8, $9,
|
||||||
$10, $11, $12, $13, $14,
|
$10, $11, $12, $13, $14,
|
||||||
$15, $16, $17, $18,
|
$15, $16, $17, $18,
|
||||||
LOWER($19), $20, $21, $22
|
LOWER($19), $20, $21, $22, $23
|
||||||
)
|
)
|
||||||
",
|
",
|
||||||
self.id as ProjectId,
|
self.id as ProjectId,
|
||||||
@@ -279,6 +278,7 @@ impl Project {
|
|||||||
self.project_type as ProjectTypeId,
|
self.project_type as ProjectTypeId,
|
||||||
self.color.map(|x| x as i32),
|
self.color.map(|x| x as i32),
|
||||||
self.thread_id.map(|x| x.0),
|
self.thread_id.map(|x| x.0),
|
||||||
|
self.monetization_status.as_str(),
|
||||||
)
|
)
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -316,8 +316,8 @@ impl Project {
|
|||||||
updated, approved, queued, status, requested_status,
|
updated, approved, queued, status, requested_status,
|
||||||
issues_url, source_url, wiki_url, discord_url, license_url,
|
issues_url, source_url, wiki_url, discord_url, license_url,
|
||||||
team_id, client_side, server_side, license, slug,
|
team_id, client_side, server_side, license, slug,
|
||||||
moderation_message, moderation_message_body, flame_anvil_project,
|
moderation_message, moderation_message_body,
|
||||||
flame_anvil_user, webhook_sent, color, loaders, game_versions, thread_id
|
webhook_sent, color, loaders, game_versions, thread_id, monetization_status
|
||||||
FROM mods
|
FROM mods
|
||||||
WHERE id = ANY($1)
|
WHERE id = ANY($1)
|
||||||
",
|
",
|
||||||
@@ -356,14 +356,13 @@ impl Project {
|
|||||||
moderation_message: m.moderation_message,
|
moderation_message: m.moderation_message,
|
||||||
moderation_message_body: m.moderation_message_body,
|
moderation_message_body: m.moderation_message_body,
|
||||||
approved: m.approved,
|
approved: m.approved,
|
||||||
flame_anvil_project: m.flame_anvil_project,
|
|
||||||
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
|
||||||
webhook_sent: m.webhook_sent,
|
webhook_sent: m.webhook_sent,
|
||||||
color: m.color.map(|x| x as u32),
|
color: m.color.map(|x| x as u32),
|
||||||
loaders: m.loaders,
|
loaders: m.loaders,
|
||||||
game_versions: m.game_versions,
|
game_versions: m.game_versions,
|
||||||
queued: m.queued,
|
queued: m.queued,
|
||||||
thread_id: m.thread_id.map(ThreadId),
|
thread_id: m.thread_id.map(ThreadId),
|
||||||
|
monetization_status: MonetizationStatus::from_str(&m.monetization_status),
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.try_collect::<Vec<Project>>()
|
.try_collect::<Vec<Project>>()
|
||||||
@@ -678,8 +677,8 @@ impl Project {
|
|||||||
m.updated updated, m.approved approved, m.queued, m.status status, m.requested_status requested_status,
|
m.updated updated, m.approved approved, m.queued, m.status status, m.requested_status requested_status,
|
||||||
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
||||||
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
||||||
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, m.flame_anvil_project flame_anvil_project, m.flame_anvil_user flame_anvil_user, m.webhook_sent, m.color,
|
cs.name client_side_type, ss.name server_side_type, pt.name project_type_name, m.webhook_sent, m.color,
|
||||||
m.loaders loaders, m.game_versions game_versions, m.thread_id thread_id,
|
m.loaders loaders, m.game_versions game_versions, m.thread_id thread_id, m.monetization_status monetization_status,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is false) categories,
|
||||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null and mc.is_additional is true) additional_categories,
|
||||||
JSONB_AGG(DISTINCT jsonb_build_object('id', v.id, 'date_published', v.date_published)) filter (where v.id is not null) versions,
|
JSONB_AGG(DISTINCT jsonb_build_object('id', v.id, 'date_published', v.date_published)) filter (where v.id is not null) versions,
|
||||||
@@ -738,14 +737,15 @@ impl Project {
|
|||||||
moderation_message: m.moderation_message,
|
moderation_message: m.moderation_message,
|
||||||
moderation_message_body: m.moderation_message_body,
|
moderation_message_body: m.moderation_message_body,
|
||||||
approved: m.approved,
|
approved: m.approved,
|
||||||
flame_anvil_project: m.flame_anvil_project,
|
|
||||||
flame_anvil_user: m.flame_anvil_user.map(UserId),
|
|
||||||
webhook_sent: m.webhook_sent,
|
webhook_sent: m.webhook_sent,
|
||||||
color: m.color.map(|x| x as u32),
|
color: m.color.map(|x| x as u32),
|
||||||
loaders: m.loaders,
|
loaders: m.loaders,
|
||||||
game_versions: m.game_versions,
|
game_versions: m.game_versions,
|
||||||
queued: m.queued,
|
queued: m.queued,
|
||||||
thread_id: m.thread_id.map(ThreadId),
|
thread_id: m.thread_id.map(ThreadId),
|
||||||
|
monetization_status: MonetizationStatus::from_str(
|
||||||
|
&m.monetization_status,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
project_type: m.project_type_name,
|
project_type: m.project_type_name,
|
||||||
categories: m.categories.unwrap_or_default(),
|
categories: m.categories.unwrap_or_default(),
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ impl TeamMember {
|
|||||||
u.avatar_url avatar_url, u.username username, u.bio bio,
|
u.avatar_url avatar_url, u.username username, u.bio bio,
|
||||||
u.created created, u.role user_role, u.badges badges, u.balance balance,
|
u.created created, u.role user_role, u.badges badges, u.balance balance,
|
||||||
u.payout_wallet payout_wallet, u.payout_wallet_type payout_wallet_type,
|
u.payout_wallet payout_wallet, u.payout_wallet_type payout_wallet_type,
|
||||||
u.payout_address payout_address, u.flame_anvil_key flame_anvil_key
|
u.payout_address payout_address
|
||||||
FROM team_members tm
|
FROM team_members tm
|
||||||
INNER JOIN users u ON u.id = tm.user_id
|
INNER JOIN users u ON u.id = tm.user_id
|
||||||
WHERE tm.team_id = ANY($1)
|
WHERE tm.team_id = ANY($1)
|
||||||
@@ -166,7 +166,6 @@ impl TeamMember {
|
|||||||
payout_wallet: m.payout_wallet.map(|x| RecipientWallet::from_string(&x)),
|
payout_wallet: m.payout_wallet.map(|x| RecipientWallet::from_string(&x)),
|
||||||
payout_wallet_type: m.payout_wallet_type.map(|x| RecipientType::from_string(&x)),
|
payout_wallet_type: m.payout_wallet_type.map(|x| RecipientType::from_string(&x)),
|
||||||
payout_address: m.payout_address,
|
payout_address: m.payout_address,
|
||||||
flame_anvil_key: m.flame_anvil_key,
|
|
||||||
},
|
},
|
||||||
payouts_split: m.payouts_split,
|
payouts_split: m.payouts_split,
|
||||||
ordering: m.ordering,
|
ordering: m.ordering,
|
||||||
@@ -318,18 +317,6 @@ impl TeamMember {
|
|||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||||
) -> Result<(), super::DatabaseError> {
|
) -> Result<(), super::DatabaseError> {
|
||||||
sqlx::query!(
|
|
||||||
"
|
|
||||||
UPDATE mods
|
|
||||||
SET flame_anvil_user = NULL
|
|
||||||
WHERE (team_id = $1 AND flame_anvil_user = $2 )
|
|
||||||
",
|
|
||||||
id as TeamId,
|
|
||||||
user_id as UserId,
|
|
||||||
)
|
|
||||||
.execute(&mut *transaction)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
DELETE FROM team_members
|
DELETE FROM team_members
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ pub struct User {
|
|||||||
pub payout_wallet: Option<RecipientWallet>,
|
pub payout_wallet: Option<RecipientWallet>,
|
||||||
pub payout_wallet_type: Option<RecipientType>,
|
pub payout_wallet_type: Option<RecipientType>,
|
||||||
pub payout_address: Option<String>,
|
pub payout_address: Option<String>,
|
||||||
pub flame_anvil_key: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
@@ -76,7 +75,7 @@ impl User {
|
|||||||
u.avatar_url, u.username, u.bio,
|
u.avatar_url, u.username, u.bio,
|
||||||
u.created, u.role, u.badges,
|
u.created, u.role, u.badges,
|
||||||
u.balance, u.payout_wallet, u.payout_wallet_type,
|
u.balance, u.payout_wallet, u.payout_wallet_type,
|
||||||
u.payout_address, u.flame_anvil_key
|
u.payout_address
|
||||||
FROM users u
|
FROM users u
|
||||||
WHERE u.github_id = $1
|
WHERE u.github_id = $1
|
||||||
",
|
",
|
||||||
@@ -106,7 +105,6 @@ impl User {
|
|||||||
.payout_wallet_type
|
.payout_wallet_type
|
||||||
.map(|x| RecipientType::from_string(&x)),
|
.map(|x| RecipientType::from_string(&x)),
|
||||||
payout_address: row.payout_address,
|
payout_address: row.payout_address,
|
||||||
flame_anvil_key: row.flame_anvil_key,
|
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -126,7 +124,7 @@ impl User {
|
|||||||
u.avatar_url, u.username, u.bio,
|
u.avatar_url, u.username, u.bio,
|
||||||
u.created, u.role, u.badges,
|
u.created, u.role, u.badges,
|
||||||
u.balance, u.payout_wallet, u.payout_wallet_type,
|
u.balance, u.payout_wallet, u.payout_wallet_type,
|
||||||
u.payout_address, u.flame_anvil_key
|
u.payout_address
|
||||||
FROM users u
|
FROM users u
|
||||||
WHERE LOWER(u.username) = LOWER($1)
|
WHERE LOWER(u.username) = LOWER($1)
|
||||||
",
|
",
|
||||||
@@ -156,7 +154,6 @@ impl User {
|
|||||||
.payout_wallet_type
|
.payout_wallet_type
|
||||||
.map(|x| RecipientType::from_string(&x)),
|
.map(|x| RecipientType::from_string(&x)),
|
||||||
payout_address: row.payout_address,
|
payout_address: row.payout_address,
|
||||||
flame_anvil_key: row.flame_anvil_key,
|
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -179,7 +176,7 @@ impl User {
|
|||||||
u.avatar_url, u.username, u.bio,
|
u.avatar_url, u.username, u.bio,
|
||||||
u.created, u.role, u.badges,
|
u.created, u.role, u.badges,
|
||||||
u.balance, u.payout_wallet, u.payout_wallet_type,
|
u.balance, u.payout_wallet, u.payout_wallet_type,
|
||||||
u.payout_address, u.flame_anvil_key
|
u.payout_address
|
||||||
FROM users u
|
FROM users u
|
||||||
WHERE u.id = ANY($1)
|
WHERE u.id = ANY($1)
|
||||||
",
|
",
|
||||||
@@ -206,7 +203,6 @@ impl User {
|
|||||||
.payout_wallet_type
|
.payout_wallet_type
|
||||||
.map(|x| RecipientType::from_string(&x)),
|
.map(|x| RecipientType::from_string(&x)),
|
||||||
payout_address: u.payout_address,
|
payout_address: u.payout_address,
|
||||||
flame_anvil_key: u.flame_anvil_key,
|
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.try_collect::<Vec<User>>()
|
.try_collect::<Vec<User>>()
|
||||||
|
|||||||
@@ -37,31 +37,20 @@ impl DependencyBuilder {
|
|||||||
version_id: VersionId,
|
version_id: VersionId,
|
||||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||||
) -> Result<(), DatabaseError> {
|
) -> Result<(), DatabaseError> {
|
||||||
let (version_dependency_id, project_dependency_id): (
|
let project_id = if let Some(project_id) = self.project_id {
|
||||||
Option<VersionId>,
|
Some(project_id)
|
||||||
Option<ProjectId>,
|
} else if let Some(version_id) = self.version_id {
|
||||||
) = if self.version_id.is_some() {
|
sqlx::query!(
|
||||||
(self.version_id, None)
|
"
|
||||||
} else if let Some(project_id) = self.project_id {
|
SELECT mod_id FROM versions WHERE id = $1
|
||||||
let version_id = sqlx::query!(
|
|
||||||
"
|
|
||||||
SELECT version.id id FROM (
|
|
||||||
SELECT DISTINCT ON(v.id) v.id, v.date_published FROM versions v
|
|
||||||
INNER JOIN game_versions_versions gvv ON gvv.joining_version_id = v.id AND gvv.game_version_id IN (SELECT game_version_id FROM game_versions_versions WHERE joining_version_id = $2)
|
|
||||||
INNER JOIN loaders_versions lv ON lv.version_id = v.id AND lv.loader_id IN (SELECT loader_id FROM loaders_versions WHERE version_id = $2)
|
|
||||||
WHERE v.mod_id = $1
|
|
||||||
) AS version
|
|
||||||
ORDER BY version.date_published DESC
|
|
||||||
LIMIT 1
|
|
||||||
",
|
",
|
||||||
project_id as ProjectId,
|
version_id as VersionId,
|
||||||
version_id as VersionId,
|
)
|
||||||
)
|
.fetch_optional(&mut *transaction)
|
||||||
.fetch_optional(&mut *transaction).await?.map(|x| VersionId(x.id));
|
.await?
|
||||||
|
.map(|x| ProjectId(x.mod_id))
|
||||||
(version_id, Some(project_id))
|
|
||||||
} else {
|
} else {
|
||||||
(None, None)
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@@ -71,8 +60,8 @@ impl DependencyBuilder {
|
|||||||
",
|
",
|
||||||
version_id as VersionId,
|
version_id as VersionId,
|
||||||
self.dependency_type,
|
self.dependency_type,
|
||||||
version_dependency_id.map(|x| x.0),
|
project_id.map(|x| x.0),
|
||||||
project_dependency_id.map(|x| x.0),
|
self.version_id.map(|x| x.0),
|
||||||
self.file_name,
|
self.file_name,
|
||||||
)
|
)
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
@@ -206,41 +195,6 @@ impl VersionBuilder {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync dependencies
|
|
||||||
|
|
||||||
use futures::stream::TryStreamExt;
|
|
||||||
|
|
||||||
let dependencies = sqlx::query!(
|
|
||||||
"
|
|
||||||
SELECT d.id id
|
|
||||||
FROM dependencies d
|
|
||||||
INNER JOIN game_versions_versions gvv ON gvv.joining_version_id = d.dependent_id AND gvv.game_version_id = ANY($2)
|
|
||||||
INNER JOIN loaders_versions lv ON lv.version_id = d.dependent_id AND lv.loader_id = ANY($3)
|
|
||||||
WHERE d.mod_dependency_id = $1
|
|
||||||
",
|
|
||||||
self.project_id as ProjectId,
|
|
||||||
&self.game_versions.iter().map(|x| x.0).collect::<Vec<i32>>(),
|
|
||||||
&self.loaders.iter().map(|x| x.0).collect::<Vec<i32>>(),
|
|
||||||
)
|
|
||||||
.fetch_many(&mut *transaction)
|
|
||||||
.try_filter_map(|e| async {
|
|
||||||
Ok(e.right().map(|d| d.id as i64))
|
|
||||||
})
|
|
||||||
.try_collect::<Vec<i64>>()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
sqlx::query!(
|
|
||||||
"
|
|
||||||
UPDATE dependencies
|
|
||||||
SET dependency_id = $2
|
|
||||||
WHERE id = ANY($1::bigint[])
|
|
||||||
",
|
|
||||||
dependencies.as_slice(),
|
|
||||||
self.version_id as VersionId,
|
|
||||||
)
|
|
||||||
.execute(&mut *transaction)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(self.version_id)
|
Ok(self.version_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,32 +279,6 @@ impl Version {
|
|||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
use futures::TryStreamExt;
|
|
||||||
|
|
||||||
let game_versions: Vec<i32> = sqlx::query!(
|
|
||||||
"
|
|
||||||
SELECT game_version_id id FROM game_versions_versions
|
|
||||||
WHERE joining_version_id = $1
|
|
||||||
",
|
|
||||||
id as VersionId,
|
|
||||||
)
|
|
||||||
.fetch_many(&mut *transaction)
|
|
||||||
.try_filter_map(|e| async { Ok(e.right().map(|c| c.id)) })
|
|
||||||
.try_collect::<Vec<i32>>()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let loaders: Vec<i32> = sqlx::query!(
|
|
||||||
"
|
|
||||||
SELECT loader_id id FROM loaders_versions
|
|
||||||
WHERE version_id = $1
|
|
||||||
",
|
|
||||||
id as VersionId,
|
|
||||||
)
|
|
||||||
.fetch_many(&mut *transaction)
|
|
||||||
.try_filter_map(|e| async { Ok(e.right().map(|c| c.id)) })
|
|
||||||
.try_collect::<Vec<i32>>()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
DELETE FROM game_versions_versions gvv
|
DELETE FROM game_versions_versions gvv
|
||||||
@@ -406,32 +334,14 @@ impl Version {
|
|||||||
.fetch_one(&mut *transaction)
|
.fetch_one(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let new_version_id = sqlx::query!(
|
|
||||||
"
|
|
||||||
SELECT v.id id
|
|
||||||
FROM versions v
|
|
||||||
INNER JOIN game_versions_versions gvv ON gvv.joining_version_id = v.id AND gvv.game_version_id = ANY($2)
|
|
||||||
INNER JOIN loaders_versions lv ON lv.version_id = v.id AND lv.loader_id = ANY($3)
|
|
||||||
WHERE v.mod_id = $1
|
|
||||||
ORDER BY v.date_published DESC
|
|
||||||
LIMIT 1
|
|
||||||
",
|
|
||||||
project_id.mod_id,
|
|
||||||
&game_versions,
|
|
||||||
&loaders,
|
|
||||||
)
|
|
||||||
.fetch_optional(&mut *transaction)
|
|
||||||
.await?
|
|
||||||
.map(|x| x.id);
|
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
UPDATE dependencies
|
UPDATE dependencies
|
||||||
SET dependency_id = $2
|
SET dependency_id = NULL, mod_dependency_id = $2
|
||||||
WHERE dependency_id = $1
|
WHERE dependency_id = $1
|
||||||
",
|
",
|
||||||
id as VersionId,
|
id as VersionId,
|
||||||
new_version_id,
|
project_id.mod_id,
|
||||||
)
|
)
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -102,16 +102,14 @@ pub struct Project {
|
|||||||
/// A string of URLs to visual content featuring the project
|
/// A string of URLs to visual content featuring the project
|
||||||
pub gallery: Vec<GalleryItem>,
|
pub gallery: Vec<GalleryItem>,
|
||||||
|
|
||||||
/// The project linked from FlameAnvil to sync with
|
|
||||||
pub flame_anvil_project: Option<i32>,
|
|
||||||
/// The user_id of the team member whose token
|
|
||||||
pub flame_anvil_user: Option<UserId>,
|
|
||||||
|
|
||||||
/// The color of the project (picked from icon)
|
/// The color of the project (picked from icon)
|
||||||
pub color: Option<u32>,
|
pub color: Option<u32>,
|
||||||
|
|
||||||
/// The thread of the moderation messages of the project
|
/// The thread of the moderation messages of the project
|
||||||
pub thread_id: Option<ThreadId>,
|
pub thread_id: Option<ThreadId>,
|
||||||
|
|
||||||
|
/// The monetization status of this project
|
||||||
|
pub monetization_status: MonetizationStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<QueryProject> for Project {
|
impl From<QueryProject> for Project {
|
||||||
@@ -197,10 +195,9 @@ impl From<QueryProject> for Project {
|
|||||||
ordering: x.ordering,
|
ordering: x.ordering,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
flame_anvil_project: m.flame_anvil_project,
|
|
||||||
flame_anvil_user: m.flame_anvil_user.map(|x| x.into()),
|
|
||||||
color: m.color,
|
color: m.color,
|
||||||
thread_id: m.thread_id.map(|x| x.into()),
|
thread_id: m.thread_id.map(|x| x.into()),
|
||||||
|
monetization_status: m.monetization_status,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,6 +415,39 @@ impl ProjectStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub enum MonetizationStatus {
|
||||||
|
ForceDemonetized,
|
||||||
|
Demonetized,
|
||||||
|
Monetized,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for MonetizationStatus {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
fmt.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MonetizationStatus {
|
||||||
|
pub fn from_str(string: &str) -> MonetizationStatus {
|
||||||
|
match string {
|
||||||
|
"force-demonetized" => MonetizationStatus::ForceDemonetized,
|
||||||
|
"demonetized" => MonetizationStatus::Demonetized,
|
||||||
|
"monetized" => MonetizationStatus::Monetized,
|
||||||
|
_ => MonetizationStatus::Monetized,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// These are constant, so this can remove unnecessary allocations (`to_string`)
|
||||||
|
pub fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
MonetizationStatus::ForceDemonetized => "force-demonetized",
|
||||||
|
MonetizationStatus::Demonetized => "demonetized",
|
||||||
|
MonetizationStatus::Monetized => "monetized",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A specific version of a project
|
/// A specific version of a project
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Version {
|
pub struct Version {
|
||||||
|
|||||||
@@ -71,12 +71,7 @@ pub struct TeamMember {
|
|||||||
|
|
||||||
impl TeamMember {
|
impl TeamMember {
|
||||||
pub fn from(data: QueryTeamMember, override_permissions: bool) -> Self {
|
pub fn from(data: QueryTeamMember, override_permissions: bool) -> Self {
|
||||||
let has_flame_anvil_key = data.user.flame_anvil_key.is_some();
|
let user: User = data.user.into();
|
||||||
let mut user: User = data.user.into();
|
|
||||||
|
|
||||||
if !override_permissions {
|
|
||||||
user.has_flame_anvil_key = Some(has_flame_anvil_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
team_id: data.team_id.into(),
|
team_id: data.team_id.into(),
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ pub struct User {
|
|||||||
pub role: Role,
|
pub role: Role,
|
||||||
pub badges: Badges,
|
pub badges: Badges,
|
||||||
pub payout_data: Option<UserPayoutData>,
|
pub payout_data: Option<UserPayoutData>,
|
||||||
pub has_flame_anvil_key: Option<bool>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
@@ -141,7 +140,6 @@ impl From<DBUser> for User {
|
|||||||
role: Role::from_string(&data.role),
|
role: Role::from_string(&data.role),
|
||||||
badges: data.badges,
|
badges: data.badges,
|
||||||
payout_data: None,
|
payout_data: None,
|
||||||
has_flame_anvil_key: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::models::ids::ProjectId;
|
use crate::models::ids::ProjectId;
|
||||||
|
use crate::models::projects::MonetizationStatus;
|
||||||
use crate::routes::ApiError;
|
use crate::routes::ApiError;
|
||||||
use crate::util::guards::admin_key_guard;
|
use crate::util::guards::admin_key_guard;
|
||||||
use crate::DownloadQueue;
|
use crate::DownloadQueue;
|
||||||
@@ -166,15 +167,17 @@ pub async fn process_payout(
|
|||||||
let mut projects_map: HashMap<i64, Project> = HashMap::new();
|
let mut projects_map: HashMap<i64, Project> = HashMap::new();
|
||||||
|
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
SELECT m.id id, tm.user_id user_id, tm.payouts_split payouts_split, pt.name project_type
|
SELECT m.id id, tm.user_id user_id, tm.payouts_split payouts_split, pt.name project_type
|
||||||
FROM mods m
|
FROM mods m
|
||||||
INNER JOIN team_members tm on m.team_id = tm.team_id AND tm.accepted = TRUE
|
INNER JOIN team_members tm on m.team_id = tm.team_id AND tm.accepted = TRUE
|
||||||
INNER JOIN project_types pt ON pt.id = m.project_type
|
INNER JOIN project_types pt ON pt.id = m.project_type
|
||||||
WHERE m.id = ANY($1)
|
WHERE m.id = ANY($1) AND m.monetization_status = $2
|
||||||
",
|
",
|
||||||
&multipliers.values.keys().flat_map(|x| x.parse::<i64>().ok()).collect::<Vec<i64>>()
|
&multipliers.values.keys().flat_map(|x| x.parse::<i64>().ok()).collect::<Vec<i64>>(),
|
||||||
|
MonetizationStatus::Monetized.as_str(),
|
||||||
)
|
)
|
||||||
.fetch_many(&mut *transaction)
|
.fetch_many(&mut *transaction)
|
||||||
.try_for_each(|e| {
|
.try_for_each(|e| {
|
||||||
|
|||||||
@@ -278,7 +278,6 @@ pub async fn auth_callback(
|
|||||||
payout_wallet: None,
|
payout_wallet: None,
|
||||||
payout_wallet_type: None,
|
payout_wallet_type: None,
|
||||||
payout_address: None,
|
payout_address: None,
|
||||||
flame_anvil_key: None,
|
|
||||||
}
|
}
|
||||||
.insert(&mut transaction)
|
.insert(&mut transaction)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use crate::database::models::thread_item::ThreadBuilder;
|
|||||||
use crate::file_hosting::{FileHost, FileHostingError};
|
use crate::file_hosting::{FileHost, FileHostingError};
|
||||||
use crate::models::error::ApiError;
|
use crate::models::error::ApiError;
|
||||||
use crate::models::projects::{
|
use crate::models::projects::{
|
||||||
DonationLink, License, ProjectId, ProjectStatus, SideType, VersionId,
|
DonationLink, License, MonetizationStatus, ProjectId, ProjectStatus,
|
||||||
VersionStatus,
|
SideType, VersionId, VersionStatus,
|
||||||
};
|
};
|
||||||
use crate::models::threads::ThreadType;
|
use crate::models::threads::ThreadType;
|
||||||
use crate::models::users::UserId;
|
use crate::models::users::UserId;
|
||||||
@@ -802,6 +802,7 @@ async fn project_create_inner(
|
|||||||
.collect(),
|
.collect(),
|
||||||
color: icon_data.and_then(|x| x.1),
|
color: icon_data.and_then(|x| x.1),
|
||||||
thread_id,
|
thread_id,
|
||||||
|
monetization_status: MonetizationStatus::Monetized,
|
||||||
};
|
};
|
||||||
|
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
@@ -847,10 +848,9 @@ async fn project_create_inner(
|
|||||||
discord_url: project_builder.discord_url.clone(),
|
discord_url: project_builder.discord_url.clone(),
|
||||||
donation_urls: project_create_data.donation_urls.clone(),
|
donation_urls: project_create_data.donation_urls.clone(),
|
||||||
gallery: gallery_urls,
|
gallery: gallery_urls,
|
||||||
flame_anvil_project: None,
|
|
||||||
flame_anvil_user: None,
|
|
||||||
color: project_builder.color,
|
color: project_builder.color,
|
||||||
thread_id: Some(project_builder.thread_id.into()),
|
thread_id: Some(project_builder.thread_id.into()),
|
||||||
|
monetization_status: project_builder.monetization_status,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _project_id = project_builder.insert(&mut *transaction).await?;
|
let _project_id = project_builder.insert(&mut *transaction).await?;
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ use crate::models;
|
|||||||
use crate::models::ids::base62_impl::parse_base62;
|
use crate::models::ids::base62_impl::parse_base62;
|
||||||
use crate::models::notifications::NotificationBody;
|
use crate::models::notifications::NotificationBody;
|
||||||
use crate::models::projects::{
|
use crate::models::projects::{
|
||||||
DonationLink, Project, ProjectId, ProjectStatus, SearchRequest, SideType,
|
DonationLink, MonetizationStatus, Project, ProjectId, ProjectStatus,
|
||||||
|
SearchRequest, SideType,
|
||||||
};
|
};
|
||||||
use crate::models::teams::Permissions;
|
use crate::models::teams::Permissions;
|
||||||
use crate::models::threads::MessageBody;
|
use crate::models::threads::MessageBody;
|
||||||
@@ -416,6 +417,7 @@ pub struct EditProject {
|
|||||||
)]
|
)]
|
||||||
#[validate(length(max = 65536))]
|
#[validate(length(max = 65536))]
|
||||||
pub moderation_message_body: Option<Option<String>>,
|
pub moderation_message_body: Option<Option<String>>,
|
||||||
|
pub monetization_status: Option<MonetizationStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[patch("{id}")]
|
#[patch("{id}")]
|
||||||
@@ -1156,6 +1158,40 @@ pub async fn project_edit(
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(monetization_status) = &new_project.monetization_status
|
||||||
|
{
|
||||||
|
if !perms.contains(Permissions::EDIT_DETAILS) {
|
||||||
|
return Err(ApiError::CustomAuthentication(
|
||||||
|
"You do not have the permissions to edit the monetization status of this project!"
|
||||||
|
.to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*monetization_status
|
||||||
|
== MonetizationStatus::ForceDemonetized
|
||||||
|
|| project_item.inner.monetization_status
|
||||||
|
== MonetizationStatus::ForceDemonetized)
|
||||||
|
&& !user.role.is_mod()
|
||||||
|
{
|
||||||
|
return Err(ApiError::CustomAuthentication(
|
||||||
|
"You do not have the permissions to edit the monetization status of this project!"
|
||||||
|
.to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlx::query!(
|
||||||
|
"
|
||||||
|
UPDATE mods
|
||||||
|
SET monetization_status = $1
|
||||||
|
WHERE (id = $2)
|
||||||
|
",
|
||||||
|
monetization_status.as_str(),
|
||||||
|
id as database::models::ids::ProjectId,
|
||||||
|
)
|
||||||
|
.execute(&mut *transaction)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
transaction.commit().await?;
|
transaction.commit().await?;
|
||||||
Ok(HttpResponse::NoContent().body(""))
|
Ok(HttpResponse::NoContent().body(""))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ pub async fn report_get(
|
|||||||
crate::database::models::report_item::Report::get(id, &**pool).await?;
|
crate::database::models::report_item::Report::get(id, &**pool).await?;
|
||||||
|
|
||||||
if let Some(report) = report {
|
if let Some(report) = report {
|
||||||
if !user.role.is_mod() && report.user_id != Some(user.id.into()) {
|
if !user.role.is_mod() && report.reporter != user.id.into() {
|
||||||
return Ok(HttpResponse::NotFound().body(""));
|
return Ok(HttpResponse::NotFound().body(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,13 +173,6 @@ pub struct EditUser {
|
|||||||
)]
|
)]
|
||||||
#[validate]
|
#[validate]
|
||||||
pub payout_data: Option<Option<EditPayoutData>>,
|
pub payout_data: Option<Option<EditPayoutData>>,
|
||||||
#[serde(
|
|
||||||
default,
|
|
||||||
skip_serializing_if = "Option::is_none",
|
|
||||||
with = "::serde_with::rust::double_option"
|
|
||||||
)]
|
|
||||||
#[validate(length(min = 1, max = 40), regex = "RE_URL_SAFE")]
|
|
||||||
pub flame_anvil_key: Option<Option<String>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Validate)]
|
#[derive(Serialize, Deserialize, Validate)]
|
||||||
@@ -394,33 +387,6 @@ pub async fn user_edit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(flame_anvil_key) = &new_user.flame_anvil_key {
|
|
||||||
if flame_anvil_key.is_none() {
|
|
||||||
sqlx::query!(
|
|
||||||
"
|
|
||||||
UPDATE mods
|
|
||||||
SET flame_anvil_user = NULL
|
|
||||||
WHERE (flame_anvil_user = $1)
|
|
||||||
",
|
|
||||||
id as crate::database::models::ids::UserId,
|
|
||||||
)
|
|
||||||
.execute(&mut *transaction)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlx::query!(
|
|
||||||
"
|
|
||||||
UPDATE users
|
|
||||||
SET flame_anvil_key = $1
|
|
||||||
WHERE (id = $2)
|
|
||||||
",
|
|
||||||
flame_anvil_key.as_deref(),
|
|
||||||
id as crate::database::models::ids::UserId,
|
|
||||||
)
|
|
||||||
.execute(&mut *transaction)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction.commit().await?;
|
transaction.commit().await?;
|
||||||
Ok(HttpResponse::NoContent().body(""))
|
Ok(HttpResponse::NoContent().body(""))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -854,6 +854,12 @@ pub async fn upload_file(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let ValidationResult::Warning(msg) = validation_result {
|
||||||
|
if primary {
|
||||||
|
return Err(CreateError::InvalidInput(msg.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
version_files.push(VersionFileBuilder {
|
version_files.push(VersionFileBuilder {
|
||||||
filename: file_name.to_string(),
|
filename: file_name.to_string(),
|
||||||
url: format!("{cdn_url}/{file_path_encode}"),
|
url: format!("{cdn_url}/{file_path_encode}"),
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ where
|
|||||||
payout_wallet_type: result.payout_wallet_type,
|
payout_wallet_type: result.payout_wallet_type,
|
||||||
payout_address: result.payout_address,
|
payout_address: result.payout_address,
|
||||||
}),
|
}),
|
||||||
has_flame_anvil_key: Some(result.flame_anvil_key.is_some()),
|
|
||||||
}),
|
}),
|
||||||
None => Err(AuthenticationError::InvalidCredentials),
|
None => Err(AuthenticationError::InvalidCredentials),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ impl super::Validator for DataPackValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("pack.mcmeta").map_err(|_| {
|
if archive.by_name("pack.mcmeta").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No pack.mcmeta present for datapack file. Tip: Make sure pack.mcmeta is in the root directory of your datapack!".into(),
|
"No pack.mcmeta present for datapack file. Tip: Make sure pack.mcmeta is in the root directory of your datapack!",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
Ok(ValidationResult::Pass)
|
Ok(ValidationResult::Pass)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ impl super::Validator for FabricValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("fabric.mod.json").map_err(|_| {
|
if archive.by_name("fabric.mod.json").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No fabric.mod.json present for Fabric file.".into(),
|
"No fabric.mod.json present for Fabric file.",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
if !archive.file_names().any(|name| {
|
if !archive.file_names().any(|name| {
|
||||||
name.ends_with("refmap.json") || name.ends_with(".class")
|
name.ends_with("refmap.json") || name.ends_with(".class")
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ impl super::Validator for LiteLoaderValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("litemod.json").map_err(|_| {
|
if archive.by_name("litemod.json").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No litemod.json present for LiteLoader file.".into(),
|
"No litemod.json present for LiteLoader file.",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
Ok(ValidationResult::Pass)
|
Ok(ValidationResult::Pass)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,9 @@ pub trait Validator: Sync {
|
|||||||
) -> Result<ValidationResult, ValidationError>;
|
) -> Result<ValidationResult, ValidationError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALIDATORS: [&dyn Validator; 16] = [
|
static ALWAYS_ALLOWED_EXT: &[&str] = &["zip", "txt"];
|
||||||
|
|
||||||
|
static VALIDATORS: &[&dyn Validator] = &[
|
||||||
&ModpackValidator,
|
&ModpackValidator,
|
||||||
&FabricValidator,
|
&FabricValidator,
|
||||||
&ForgeValidator,
|
&ForgeValidator,
|
||||||
@@ -127,7 +129,7 @@ pub async fn validate_file(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut visited = false;
|
let mut visited = false;
|
||||||
for validator in &VALIDATORS {
|
for validator in VALIDATORS {
|
||||||
if validator.get_project_types().contains(&&*project_type)
|
if validator.get_project_types().contains(&&*project_type)
|
||||||
&& loaders
|
&& loaders
|
||||||
.iter()
|
.iter()
|
||||||
@@ -147,12 +149,16 @@ pub async fn validate_file(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if visited {
|
if visited {
|
||||||
Err(ValidationError::InvalidInput(
|
if ALWAYS_ALLOWED_EXT.contains(&&*file_extension) {
|
||||||
format!(
|
Ok(ValidationResult::Warning("File extension is invalid for input file"))
|
||||||
"File extension {file_extension} is invalid for input file"
|
} else {
|
||||||
)
|
Err(ValidationError::InvalidInput(
|
||||||
.into(),
|
format!(
|
||||||
))
|
"File extension {file_extension} is invalid for input file"
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(ValidationResult::Pass)
|
Ok(ValidationResult::Pass)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ impl super::Validator for ModpackValidator {
|
|||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
let pack: PackFormat = {
|
let pack: PackFormat = {
|
||||||
let mut file =
|
let mut file =
|
||||||
archive.by_name("modrinth.index.json").map_err(|_| {
|
if let Ok(file) = archive.by_name("modrinth.index.json") {
|
||||||
ValidationError::InvalidInput(
|
file
|
||||||
"Pack manifest is missing.".into(),
|
} else {
|
||||||
)
|
return Ok(ValidationResult::Warning(
|
||||||
})?;
|
"Pack manifest is missing.",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
file.read_to_string(&mut contents)?;
|
file.read_to_string(&mut contents)?;
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ impl super::Validator for BungeeCordValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("bungee.yml").map_err(|_| {
|
if archive.by_name("bungee.yml").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No bungee.yml present for plugin file.".into(),
|
"No bungee.yml present for plugin file.",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
Ok(ValidationResult::Pass)
|
Ok(ValidationResult::Pass)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ impl super::Validator for QuiltValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("quilt.mod.json").map_err(|_| {
|
if archive.by_name("quilt.mod.json").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No quilt.mod.json present for Quilt file.".into(),
|
"No quilt.mod.json present for Quilt file.",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
if !archive.file_names().any(|name| {
|
if !archive.file_names().any(|name| {
|
||||||
name.ends_with("refmap.json") || name.ends_with(".class")
|
name.ends_with("refmap.json") || name.ends_with(".class")
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ impl super::Validator for PackValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("pack.mcmeta").map_err(|_| {
|
if archive.by_name("pack.mcmeta").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!".into(),
|
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
Ok(ValidationResult::Pass)
|
Ok(ValidationResult::Pass)
|
||||||
}
|
}
|
||||||
@@ -75,11 +75,11 @@ impl super::Validator for TexturePackValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("pack.txt").map_err(|_| {
|
if archive.by_name("pack.txt").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No pack.txt present for pack file.".into(),
|
"No pack.txt present for pack file.",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
|
|
||||||
Ok(ValidationResult::Pass)
|
Ok(ValidationResult::Pass)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ impl super::Validator for ShaderValidator {
|
|||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
if !archive.file_names().any(|x| x.starts_with("shaders/")) {
|
if !archive.file_names().any(|x| x.starts_with("shaders/")) {
|
||||||
return Err(ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No shaders folder present for OptiFine/Iris shader.".into(),
|
"No shaders folder present for OptiFine/Iris shader.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,15 +60,15 @@ impl super::Validator for CanvasShaderValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("pack.mcmeta").map_err(|_| {
|
if archive.by_name("pack.mcmeta").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!".into(),
|
"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/")) {
|
if !archive.file_names().any(|x| x.contains("/pipelines/")) {
|
||||||
return Err(ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No pipeline shaders folder present for canvas shaders.".into(),
|
"No pipeline shaders folder present for canvas shaders.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,18 +99,18 @@ impl super::Validator for CoreShaderValidator {
|
|||||||
&self,
|
&self,
|
||||||
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
archive.by_name("pack.mcmeta").map_err(|_| {
|
if archive.by_name("pack.mcmeta").is_err() {
|
||||||
ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!".into(),
|
"No pack.mcmeta present for pack file. Tip: Make sure pack.mcmeta is in the root directory of your pack!",
|
||||||
)
|
));
|
||||||
})?;
|
};
|
||||||
|
|
||||||
if !archive
|
if !archive
|
||||||
.file_names()
|
.file_names()
|
||||||
.any(|x| x.starts_with("assets/minecraft/shaders/"))
|
.any(|x| x.starts_with("assets/minecraft/shaders/"))
|
||||||
{
|
{
|
||||||
return Err(ValidationError::InvalidInput(
|
return Ok(ValidationResult::Warning(
|
||||||
"No shaders folder present for vanilla shaders.".into(),
|
"No shaders folder present for vanilla shaders.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user