chore(clippy): enable and fix many stricter lints (#3783)

* chore(clippy): enable and fix many stricter lints

These ensure that the codebase uses more idiomatic, performant, and
concise language constructions.

* chore: make non-Clippy compiler warnings also deny by default
This commit is contained in:
Alejandro González
2025-06-14 02:10:12 +02:00
committed by GitHub
parent 301967d204
commit f84f8c1c2b
106 changed files with 542 additions and 760 deletions

View File

@@ -216,7 +216,7 @@ pub async fn playtime_ingest(
version_id: version.inner.id.0 as u64,
loader: playtime.loader,
game_version: playtime.game_version,
parent: playtime.parent.map(|x| x.0).unwrap_or(0),
parent: playtime.parent.map_or(0, |x| x.0),
});
}
}

View File

@@ -18,6 +18,7 @@ use actix_web::{HttpRequest, HttpResponse, get, patch, post, web};
use serde::Deserialize;
use sqlx::PgPool;
use std::collections::HashMap;
use std::fmt::Write;
use std::net::Ipv4Addr;
use std::sync::Arc;
use tracing::info;
@@ -221,9 +222,11 @@ pub async fn delphi_result_ingest(
for (issue, trace) in &body.issues {
for (path, code) in trace {
header.push_str(&format!(
write!(
&mut header,
"\n issue {issue} found at file {path}: \n ```\n{code}\n```"
));
)
.unwrap();
}
}
@@ -244,12 +247,15 @@ pub async fn delphi_result_ingest(
for (issue, trace) in &body.issues {
for path in trace.keys() {
thread_header
.push_str(&format!("\n\n- issue {issue} found at file {path}"));
write!(
&mut thread_header,
"\n\n- issue {issue} found at file {path}"
)
.unwrap();
}
if trace.is_empty() {
thread_header.push_str(&format!("\n\n- issue {issue} found",));
write!(&mut thread_header, "\n\n- issue {issue} found").unwrap();
}
}

View File

@@ -531,11 +531,9 @@ pub async fn edit_subscription(
if let Some(payment_method) = &edit_subscription.payment_method
{
let payment_method_id = if let Ok(id) =
let Ok(payment_method_id) =
PaymentMethodId::from_str(payment_method)
{
id
} else {
else {
return Err(ApiError::InvalidInput(
"Invalid payment method id".to_string(),
));
@@ -743,9 +741,7 @@ pub async fn edit_payment_method(
let (id,) = info.into_inner();
let payment_method_id = if let Ok(id) = PaymentMethodId::from_str(&id) {
id
} else {
let Ok(payment_method_id) = PaymentMethodId::from_str(&id) else {
return Err(ApiError::NotFound);
};
@@ -766,10 +762,7 @@ pub async fn edit_payment_method(
)
.await?;
if payment_method
.customer
.map(|x| x.id() == customer)
.unwrap_or(false)
if payment_method.customer.is_some_and(|x| x.id() == customer)
|| user.role.is_admin()
{
stripe::Customer::update(
@@ -812,9 +805,7 @@ pub async fn remove_payment_method(
let (id,) = info.into_inner();
let payment_method_id = if let Ok(id) = PaymentMethodId::from_str(&id) {
id
} else {
let Ok(payment_method_id) = PaymentMethodId::from_str(&id) else {
return Err(ApiError::NotFound);
};
@@ -864,10 +855,7 @@ pub async fn remove_payment_method(
}
}
if payment_method
.customer
.map(|x| x.id() == customer)
.unwrap_or(false)
if payment_method.customer.is_some_and(|x| x.id() == customer)
|| user.role.is_admin()
{
stripe::PaymentMethod::detach(&stripe_client, &payment_method_id)
@@ -1437,8 +1425,6 @@ pub async fn stripe_webhook(
pub user_subscription_item:
Option<user_subscription_item::DBUserSubscription>,
pub payment_metadata: Option<PaymentRequestMetadata>,
#[allow(dead_code)]
pub charge_type: ChargeType,
}
#[allow(clippy::too_many_arguments)]
@@ -1453,24 +1439,20 @@ pub async fn stripe_webhook(
transaction: &mut Transaction<'_, Postgres>,
) -> Result<PaymentIntentMetadata, ApiError> {
'metadata: {
let user_id = if let Some(user_id) = metadata
let Some(user_id) = metadata
.get("modrinth_user_id")
.and_then(|x| parse_base62(x).ok())
.map(|x| crate::database::models::ids::DBUserId(x as i64))
{
user_id
} else {
else {
break 'metadata;
};
let user = if let Some(user) =
let Some(user) =
crate::database::models::user_item::DBUser::get_id(
user_id, pool, redis,
)
.await?
{
user
} else {
else {
break 'metadata;
};
@@ -1478,22 +1460,20 @@ pub async fn stripe_webhook(
.get("modrinth_payment_metadata")
.and_then(|x| serde_json::from_str(x).ok());
let charge_id = if let Some(charge_id) = metadata
let Some(charge_id) = metadata
.get("modrinth_charge_id")
.and_then(|x| parse_base62(x).ok())
.map(|x| crate::database::models::ids::DBChargeId(x as i64))
{
charge_id
} else {
.map(|x| {
crate::database::models::ids::DBChargeId(x as i64)
})
else {
break 'metadata;
};
let charge_type = if let Some(charge_type) = metadata
let Some(charge_type) = metadata
.get("modrinth_charge_type")
.map(|x| ChargeType::from_string(x))
{
charge_type
} else {
else {
break 'metadata;
};
@@ -1505,21 +1485,19 @@ pub async fn stripe_webhook(
)
.await?
{
let price = if let Some(price) =
product_item::DBProductPrice::get(charge.price_id, pool)
.await?
{
price
} else {
let Some(price) = product_item::DBProductPrice::get(
charge.price_id,
pool,
)
.await?
else {
break 'metadata;
};
let product = if let Some(product) =
let Some(product) =
product_item::DBProduct::get(price.product_id, pool)
.await?
{
product
} else {
else {
break 'metadata;
};
@@ -1530,15 +1508,13 @@ pub async fn stripe_webhook(
charge.upsert(transaction).await?;
if let Some(subscription_id) = charge.subscription_id {
let mut subscription = if let Some(subscription) =
let Some(mut subscription) =
user_subscription_item::DBUserSubscription::get(
subscription_id,
pool,
)
.await?
{
subscription
} else {
else {
break 'metadata;
};
@@ -1567,58 +1543,49 @@ pub async fn stripe_webhook(
(charge, price, product, None)
}
} else {
let price_id = if let Some(price_id) = metadata
let Some(price_id) = metadata
.get("modrinth_price_id")
.and_then(|x| parse_base62(x).ok())
.map(|x| {
crate::database::models::ids::DBProductPriceId(
x as i64,
)
}) {
price_id
} else {
})
else {
break 'metadata;
};
let price = if let Some(price) =
let Some(price) =
product_item::DBProductPrice::get(price_id, pool)
.await?
{
price
} else {
else {
break 'metadata;
};
let product = if let Some(product) =
let Some(product) =
product_item::DBProduct::get(price.product_id, pool)
.await?
{
product
} else {
else {
break 'metadata;
};
let subscription = match &price.prices {
Price::OneTime { .. } => None,
Price::Recurring { intervals } => {
let interval = if let Some(interval) = metadata
let Some(interval) = metadata
.get("modrinth_subscription_interval")
.map(|x| PriceDuration::from_string(x))
{
interval
} else {
else {
break 'metadata;
};
if intervals.get(&interval).is_some() {
let subscription_id = if let Some(subscription_id) = metadata
let Some(subscription_id) = metadata
.get("modrinth_subscription_id")
.and_then(|x| parse_base62(x).ok())
.map(|x| {
crate::database::models::ids::DBUserSubscriptionId(x as i64)
}) {
subscription_id
} else {
}) else {
break 'metadata;
};
@@ -1687,7 +1654,6 @@ pub async fn stripe_webhook(
charge_item: charge,
user_subscription_item: subscription,
payment_metadata,
charge_type,
});
}
@@ -2049,10 +2015,9 @@ pub async fn stripe_webhook(
)
.await?;
if !customer
if customer
.invoice_settings
.map(|x| x.default_payment_method.is_some())
.unwrap_or(false)
.is_none_or(|x| x.default_payment_method.is_none())
{
stripe::Customer::update(
&stripe_client,
@@ -2187,12 +2152,10 @@ pub async fn index_subscriptions(pool: PgPool, redis: RedisPool) {
.await?;
for charge in all_charges {
let subscription = if let Some(subscription) = all_subscriptions
let Some(subscription) = all_subscriptions
.iter_mut()
.find(|x| Some(x.id) == charge.subscription_id)
{
subscription
} else {
else {
continue;
};
@@ -2200,29 +2163,23 @@ pub async fn index_subscriptions(pool: PgPool, redis: RedisPool) {
continue;
}
let product_price = if let Some(product_price) = subscription_prices
let Some(product_price) = subscription_prices
.iter()
.find(|x| x.id == subscription.price_id)
{
product_price
} else {
else {
continue;
};
let product = if let Some(product) = subscription_products
let Some(product) = subscription_products
.iter()
.find(|x| x.id == product_price.product_id)
{
product
} else {
else {
continue;
};
let user = if let Some(user) =
let Some(user) =
users.iter().find(|x| x.id == subscription.user_id)
{
user
} else {
else {
continue;
};
@@ -2350,19 +2307,14 @@ pub async fn index_billing(
.await?;
for mut charge in charges_to_do {
let product_price = if let Some(price) =
let Some(product_price) =
prices.iter().find(|x| x.id == charge.price_id)
{
price
} else {
else {
continue;
};
let user = if let Some(user) =
users.iter().find(|x| x.id == charge.user_id)
{
user
} else {
let Some(user) = users.iter().find(|x| x.id == charge.user_id)
else {
continue;
};
@@ -2399,17 +2351,14 @@ pub async fn index_billing(
)
.await?;
let currency = match Currency::from_str(
let Ok(currency) = Currency::from_str(
&product_price.currency_code.to_lowercase(),
) {
Ok(x) => x,
Err(_) => {
warn!(
"Could not find currency for {}",
product_price.currency_code
);
continue;
}
) else {
warn!(
"Could not find currency for {}",
product_price.currency_code
);
continue;
};
let mut intent =

View File

@@ -1249,7 +1249,7 @@ pub async fn delete_auth_provider(
.await?
.1;
if !user.auth_providers.map(|x| x.len() > 1).unwrap_or(false)
if user.auth_providers.is_none_or(|x| x.len() <= 1)
&& !user.has_password.unwrap_or(false)
{
return Err(ApiError::InvalidInput(

View File

@@ -217,8 +217,7 @@ pub async fn ws_init(
if status
.profile_name
.as_ref()
.map(|x| x.len() > 64)
.unwrap_or(false)
.is_some_and(|x| x.len() > 64)
{
return;
}

View File

@@ -250,7 +250,7 @@ fn find_file<'a>(
// Minecraft mods are not going to be both a mod and a modpack, so this minecraft-specific handling is fine
// As there can be multiple project types, returns the first allowable match
let mut fileexts = vec![];
for project_type in version.project_types.iter() {
for project_type in &version.project_types {
match project_type.as_str() {
"mod" => fileexts.push("jar"),
"modpack" => fileexts.push("mrpack"),
@@ -381,8 +381,10 @@ pub async fn version_file_sha1(
Ok(find_file(&project_id, &vnum, &version, &file)
.and_then(|file| file.hashes.get("sha1"))
.map(|hash_str| HttpResponse::Ok().body(hash_str.clone()))
.unwrap_or_else(|| HttpResponse::NotFound().body("")))
.map_or_else(
|| HttpResponse::NotFound().body(""),
|hash_str| HttpResponse::Ok().body(hash_str.clone()),
))
}
#[get("maven/modrinth/{id}/{versionnum}/{file}.sha512")]
@@ -426,6 +428,8 @@ pub async fn version_file_sha512(
Ok(find_file(&project_id, &vnum, &version, &file)
.and_then(|file| file.hashes.get("sha512"))
.map(|hash_str| HttpResponse::Ok().body(hash_str.clone()))
.unwrap_or_else(|| HttpResponse::NotFound().body("")))
.map_or_else(
|| HttpResponse::NotFound().body(""),
|hash_str| HttpResponse::Ok().body(hash_str.clone()),
))
}

View File

@@ -83,7 +83,7 @@ pub async fn project_search(
val
)
} else {
facet.to_string()
facet
}
})
.collect::<Vec<_>>()

View File

@@ -283,28 +283,23 @@ async fn get_example_version_fields(
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 Some(project_id) = project_id else {
return Ok(None);
};
let vid = match project_item::DBProject::get_id(
project_id.into(),
&**pool,
redis,
)
.await?
.and_then(|p| p.versions.first().cloned())
{
Some(vid) => vid,
None => return Ok(None),
let Some(vid) =
project_item::DBProject::get_id(project_id.into(), &**pool, redis)
.await?
.and_then(|p| p.versions.first().copied())
else {
return Ok(None);
};
let example_version =
match version_item::DBVersion::get(vid, &**pool, redis).await? {
Some(version) => version,
None => return Ok(None),
};
let Some(example_version) =
version_item::DBVersion::get(vid, &**pool, redis).await?
else {
return Ok(None);
};
Ok(Some(example_version.version_fields))
}

View File

@@ -256,13 +256,11 @@ pub async fn organization_get(
.filter(|x| {
logged_in
|| x.accepted
|| user_id
.map(|y: crate::database::models::DBUserId| {
y == x.user_id
})
.unwrap_or(false)
|| user_id.is_some_and(
|y: crate::database::models::DBUserId| y == x.user_id,
)
})
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -345,13 +343,11 @@ pub async fn organizations_get(
.filter(|x| {
logged_in
|| x.accepted
|| user_id
.map(|y: crate::database::models::DBUserId| {
y == x.user_id
})
.unwrap_or(false)
|| user_id.is_some_and(
|y: crate::database::models::DBUserId| y == x.user_id,
)
})
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -635,7 +631,7 @@ pub async fn organization_delete(
.try_collect::<Vec<_>>()
.await?;
for organization_project_team in organization_project_teams.iter() {
for organization_project_team in &organization_project_teams {
let new_id = crate::database::models::ids::generate_team_member_id(
&mut transaction,
)

View File

@@ -830,14 +830,13 @@ async fn get_user_balance(
.fetch_optional(pool)
.await?;
let (withdrawn, fees) = withdrawn
.map(|x| {
let (withdrawn, fees) =
withdrawn.map_or((Decimal::ZERO, Decimal::ZERO), |x| {
(
x.amount.unwrap_or(Decimal::ZERO),
x.fee.unwrap_or(Decimal::ZERO),
)
})
.unwrap_or((Decimal::ZERO, Decimal::ZERO));
});
Ok(UserBalance {
available: available.round_dp(16)

View File

@@ -360,15 +360,14 @@ async fn project_create_inner(
// The first multipart field must be named "data" and contain a
// JSON `ProjectCreateData` object.
let mut field = payload
.next()
.await
.map(|m| m.map_err(CreateError::MultipartError))
.unwrap_or_else(|| {
let mut field = payload.next().await.map_or_else(
|| {
Err(CreateError::MissingValueError(String::from(
"No `data` field in multipart upload",
)))
})?;
},
|m| m.map_err(CreateError::MultipartError),
)?;
let name = field.name().ok_or_else(|| {
CreateError::MissingValueError(String::from("Missing content name"))
@@ -550,8 +549,8 @@ async fn project_create_inner(
)));
};
// `index` is always valid for these lists
let created_version = versions.get_mut(index).unwrap();
let version_data = project_create_data.initial_versions.get(index).unwrap();
let created_version = &mut versions[index];
let version_data = &project_create_data.initial_versions[index];
// TODO: maybe redundant is this calculation done elsewhere?
let existing_file_names = created_version
@@ -670,10 +669,9 @@ async fn project_create_inner(
&team_member,
);
if !perms
.map(|x| x.contains(OrganizationPermissions::ADD_PROJECT))
.unwrap_or(false)
{
if !perms.is_some_and(|x| {
x.contains(OrganizationPermissions::ADD_PROJECT)
}) {
return Err(CreateError::CustomAuthenticationError(
"You do not have the permissions to create projects in this organization!"
.to_string(),

View File

@@ -448,7 +448,7 @@ pub async fn project_edit(
}
}
if team_member.map(|x| !x.accepted).unwrap_or(true) {
if team_member.is_none_or(|x| !x.accepted) {
let notified_members = sqlx::query!(
"
SELECT tm.user_id id
@@ -2397,13 +2397,11 @@ pub async fn project_get_organization(
.filter(|x| {
logged_in
|| x.accepted
|| user_id
.map(|y: crate::database::models::DBUserId| {
y == x.user_id
})
.unwrap_or(false)
|| user_id.is_some_and(
|y: crate::database::models::DBUserId| y == x.user_id,
)
})
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,

View File

@@ -148,16 +148,15 @@ pub async fn loader_fields_list(
))
})?;
let loader_field_enum_id = match loader_field.field_type {
LoaderFieldType::Enum(enum_id)
| LoaderFieldType::ArrayEnum(enum_id) => enum_id,
_ => {
return Err(ApiError::InvalidInput(format!(
"'{}' is not an enumerable field, but an '{}' field.",
query.loader_field,
loader_field.field_type.to_str()
)));
}
let (LoaderFieldType::Enum(loader_field_enum_id)
| LoaderFieldType::ArrayEnum(loader_field_enum_id)) =
loader_field.field_type
else {
return Err(ApiError::InvalidInput(format!(
"'{}' is not an enumerable field, but an '{}' field.",
query.loader_field,
loader_field.field_type.to_str()
)));
};
let results: Vec<_> = if let Some(filters) = query.filters {

View File

@@ -101,13 +101,11 @@ pub async fn team_members_get_project(
.filter(|x| {
logged_in
|| x.accepted
|| user_id
.map(|y: crate::database::models::DBUserId| {
y == x.user_id
})
.unwrap_or(false)
|| user_id.is_some_and(
|y: crate::database::models::DBUserId| y == x.user_id,
)
})
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -176,13 +174,11 @@ pub async fn team_members_get_organization(
.filter(|x| {
logged_in
|| x.accepted
|| user_id
.map(|y: crate::database::models::DBUserId| {
y == x.user_id
})
.unwrap_or(false)
|| user_id.is_some_and(
|y: crate::database::models::DBUserId| y == x.user_id,
)
})
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -242,11 +238,11 @@ pub async fn team_members_get(
.filter(|x| {
logged_in
|| x.accepted
|| user_id
.map(|y: crate::database::models::DBUserId| y == x.user_id)
.unwrap_or(false)
|| user_id.is_some_and(
|y: crate::database::models::DBUserId| y == x.user_id,
)
})
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -319,7 +315,7 @@ pub async fn teams_get(
let team_members = members
.into_iter()
.filter(|x| logged_in || x.accepted)
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -592,8 +588,7 @@ pub async fn add_team_member(
};
if new_user_organization_team_member
.as_ref()
.map(|tm| tm.is_owner)
.unwrap_or(false)
.is_some_and(|tm| tm.is_owner)
&& new_member.permissions != ProjectPermissions::all()
{
return Err(ApiError::InvalidInput(
@@ -748,12 +743,10 @@ pub async fn edit_team_member(
if organization_team_member
.as_ref()
.map(|x| x.is_owner)
.unwrap_or(false)
.is_some_and(|x| x.is_owner)
&& edit_member
.permissions
.map(|x| x != ProjectPermissions::all())
.unwrap_or(false)
.is_some_and(|x| x != ProjectPermissions::all())
{
return Err(ApiError::CustomAuthentication(
"You cannot override the project permissions of the organization owner!"
@@ -1011,7 +1004,7 @@ pub async fn transfer_ownership(
.collect();
// If the owner of the organization is a member of the project, remove them
for team_id in team_ids.iter() {
for team_id in &team_ids {
DBTeamMember::delete(
*team_id,
new_owner.user_id.into(),

View File

@@ -119,7 +119,7 @@ pub async fn filter_authorized_threads(
let project_thread_ids = check_threads
.iter()
.filter(|x| x.type_ == ThreadType::Project)
.flat_map(|x| x.project_id.map(|x| x.0))
.filter_map(|x| x.project_id.map(|x| x.0))
.collect::<Vec<_>>();
if !project_thread_ids.is_empty() {
@@ -148,13 +148,12 @@ pub async fn filter_authorized_threads(
.await?;
}
let org_project_thread_ids = check_threads
let mut org_project_thread_ids = check_threads
.iter()
.filter(|x| x.type_ == ThreadType::Project)
.flat_map(|x| x.project_id.map(|x| x.0))
.collect::<Vec<_>>();
.filter_map(|x| x.project_id.map(|x| x.0));
if !org_project_thread_ids.is_empty() {
if org_project_thread_ids.next().is_some() {
sqlx::query!(
"
SELECT m.id FROM mods m
@@ -184,7 +183,7 @@ pub async fn filter_authorized_threads(
let report_thread_ids = check_threads
.iter()
.filter(|x| x.type_ == ThreadType::Report)
.flat_map(|x| x.report_id.map(|x| x.0))
.filter_map(|x| x.report_id.map(|x| x.0))
.collect::<Vec<_>>();
if !report_thread_ids.is_empty() {

View File

@@ -207,7 +207,7 @@ pub async fn user_get(
.ok();
let response: crate::models::users::User =
if auth_user.map(|x| x.role.is_admin()).unwrap_or(false) {
if auth_user.is_some_and(|x| x.role.is_admin()) {
crate::models::users::User::from_full(data)
} else {
data.into()
@@ -242,9 +242,8 @@ pub async fn collections_list(
if let Some(id) = id_option.map(|x| x.id) {
let user_id: UserId = id.into();
let can_view_private = user
.map(|y| y.role.is_mod() || y.id == user_id)
.unwrap_or(false);
let can_view_private =
user.is_some_and(|y| y.role.is_mod() || y.id == user_id);
let project_data = DBUser::get_collections(id, &**pool).await?;
@@ -334,7 +333,7 @@ pub async fn orgs_list(
let team_members: Vec<_> = members_data
.into_iter()
.filter(|x| logged_in || x.accepted || id == x.user_id)
.flat_map(|data| {
.filter_map(|data| {
users.iter().find(|x| x.id == data.user_id).map(|user| {
crate::models::teams::TeamMember::from(
data,
@@ -412,8 +411,7 @@ pub async fn user_edit(
if existing_user_id_option
.map(|x| UserId::from(x.id))
.map(|id| id == user.id)
.unwrap_or(true)
.is_none_or(|id| id == user.id)
{
sqlx::query!(
"

View File

@@ -606,13 +606,10 @@ async fn upload_file_to_version_inner(
let result = models::DBVersion::get(version_id, &**client, &redis).await?;
let version = match result {
Some(v) => v,
None => {
return Err(CreateError::InvalidInput(
"An invalid version id was supplied".to_string(),
));
}
let Some(version) = result else {
return Err(CreateError::InvalidInput(
"An invalid version id was supplied".to_string(),
));
};
let all_loaders =
@@ -1065,7 +1062,7 @@ pub fn try_create_version_fields(
.filter(|lf| !lf.optional)
.map(|lf| lf.field.clone())
.collect::<HashSet<_>>();
for (key, value) in submitted_fields.iter() {
for (key, value) in submitted_fields {
let loader_field = loader_fields
.iter()
.find(|lf| &lf.field == key)

View File

@@ -794,8 +794,7 @@ pub async fn version_list(
.filter(|version| {
filters
.featured
.map(|featured| featured == version.inner.featured)
.unwrap_or(true)
.is_none_or(|featured| featured == version.inner.featured)
})
.cloned()
.collect::<Vec<_>>();
@@ -830,22 +829,20 @@ pub async fn version_list(
}
joined_filters.into_iter().for_each(|filter| {
versions
.iter()
.find(|version| {
// TODO: This is the bandaid fix for detecting auto-featured versions.
let game_versions = version
.version_fields
.iter()
.find(|vf| vf.field_name == "game_versions")
.map(|vf| vf.value.clone())
.map(|v| v.as_strings())
.unwrap_or_default();
game_versions.contains(&filter.0.version)
&& version.loaders.contains(&filter.1.loader)
})
.map(|version| response.push(version.clone()))
.unwrap_or(());
if let Some(version) = versions.iter().find(|version| {
// TODO: This is the bandaid fix for detecting auto-featured versions.
let game_versions = version
.version_fields
.iter()
.find(|vf| vf.field_name == "game_versions")
.map(|vf| vf.value.clone())
.map(|v| v.as_strings())
.unwrap_or_default();
game_versions.contains(&filter.0.version)
&& version.loaders.contains(&filter.1.loader)
}) {
response.push(version.clone());
}
});
if response.is_empty() {