From 34af33607b4685b934d67e145d142444d33ad511 Mon Sep 17 00:00:00 2001 From: Geometrically <18202329+Geometrically@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:56:41 -0700 Subject: [PATCH] Update file restrictions, download counting, project colors, etc (#515) * Update file restrictions, download counting, project colors, etc * Run fmt + clippy + prepare --- sqlx-data.json | 387 ++++++++++++++-------------- src/routes/admin.rs | 49 ++-- src/routes/version_creation.rs | 7 +- src/routes/version_file.rs | 70 +++-- src/search/indexing/local_import.rs | 6 +- src/search/indexing/mod.rs | 3 + src/search/mod.rs | 3 +- src/util/img.rs | 5 +- 8 files changed, 286 insertions(+), 244 deletions(-) diff --git a/sqlx-data.json b/sqlx-data.json index 63266bdc..ff61bd32 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -12,6 +12,34 @@ }, "query": "\n DELETE FROM mods_donations\n WHERE joining_mod_id = $1\n " }, + "02843e787de72594e186a14734bd02099ca6d2f07dcc06da8d6d8a069638ca2a": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + }, + { + "name": "mod_id", + "ordinal": 1, + "type_info": "Int8" + } + ], + "nullable": [ + false, + false + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Int8" + ] + } + }, + "query": "\n SELECT id, mod_id FROM versions\n WHERE ((version_number = $1 OR id = $3) AND mod_id = $2)\n " + }, "03006da8781d9c07d564c6b406221cb0557623abe3242e79a21868482e6d9898": { "describe": { "columns": [], @@ -1260,29 +1288,6 @@ }, "query": "\n DELETE FROM notifications_actions\n WHERE notification_id = ANY($1)\n " }, - "27c463b15f160d63c1cf82b08ee965e8408899f254c8a4c53f0e244ba615a1ed": { - "describe": { - "columns": [ - { - "name": "project_id", - "ordinal": 0, - "type_info": "Int8" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [ - "TextArray", - "Bytea", - "Text", - "TextArray" - ] - } - }, - "query": "\n SELECT v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id AND v.status != ANY($1)\n INNER JOIN mods m on v.mod_id = m.id\n WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4)\n " - }, "28d5825964b0fddc43bd7d6851daf91845b79c9e88c82d5c7d97ae02502d0b4f": { "describe": { "columns": [], @@ -1690,29 +1695,6 @@ }, "query": "\n UPDATE mods_gallery\n SET featured = $2\n WHERE id = $1\n " }, - "3b57a94086bb52bea14715799e25ac108c5b47f8b08b176614f5b1c1d243a047": { - "describe": { - "columns": [ - { - "name": "version_id", - "ordinal": 0, - "type_info": "Int8" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [ - "TextArray", - "Bytea", - "Text", - "TextArray" - ] - } - }, - "query": "\n SELECT f.version_id version_id\n FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v on f.version_id = v.id AND v.status != ANY($1)\n INNER JOIN mods m on v.mod_id = m.id\n WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4)\n " - }, "3bdcbfa5abe43cc9b4f996f147277a7f6921cca00f82cad0ef5d85032c761a36": { "describe": { "columns": [], @@ -1929,27 +1911,6 @@ }, "query": "\n UPDATE users\n SET stripe_customer_id = NULL, midas_expires = NULL, is_overdue = NULL\n WHERE (stripe_customer_id = $1)\n " }, - "4298552497a48adb9ace61c8dcf989c4d35866866b61c0cc4d45909b1d31c660": { - "describe": { - "columns": [ - { - "name": "exists", - "ordinal": 0, - "type_info": "Bool" - } - ], - "nullable": [ - null - ], - "parameters": { - "Left": [ - "Bytea", - "Text" - ] - } - }, - "query": "\n SELECT EXISTS(SELECT 1 FROM hashes h\n WHERE h.algorithm = $2 AND h.hash = $1)\n " - }, "42d0a51c5a2eec6860a904b7753c4907b1b03fb5f081f07149367222bcdc62fb": { "describe": { "columns": [ @@ -2729,6 +2690,47 @@ }, "query": "\n DELETE FROM mod_follows\n WHERE mod_id = $1\n " }, + "5e0bac32b936202670596d24c0a2a6bbe30f4f4fdc28ad5a3846ac4c51c77b7d": { + "describe": { + "columns": [ + { + "name": "url", + "ordinal": 0, + "type_info": "Varchar" + }, + { + "name": "id", + "ordinal": 1, + "type_info": "Int8" + }, + { + "name": "version_id", + "ordinal": 2, + "type_info": "Int8" + }, + { + "name": "project_id", + "ordinal": 3, + "type_info": "Int8" + } + ], + "nullable": [ + false, + false, + false, + false + ], + "parameters": { + "Left": [ + "TextArray", + "Bytea", + "Text", + "TextArray" + ] + } + }, + "query": "\n SELECT f.url url, f.id id, f.version_id version_id, v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id AND v.status != ANY($1)\n INNER JOIN mods m on v.mod_id = m.id\n WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4)\n ORDER BY v.date_published ASC\n " + }, "5eb2795d25d6d03e22564048c198d821cd5ff22eb4e39b9dd7f198c9113d4f87": { "describe": { "columns": [], @@ -2836,47 +2838,6 @@ }, "query": "\n UPDATE mods\n SET requested_status = $1\n WHERE (id = $2)\n " }, - "67932e9e1fbf8980449e47c353ed40050bacac5fe5577256b28836cf36f9c1a0": { - "describe": { - "columns": [ - { - "name": "url", - "ordinal": 0, - "type_info": "Varchar" - }, - { - "name": "id", - "ordinal": 1, - "type_info": "Int8" - }, - { - "name": "version_id", - "ordinal": 2, - "type_info": "Int8" - }, - { - "name": "project_id", - "ordinal": 3, - "type_info": "Int8" - } - ], - "nullable": [ - false, - false, - false, - false - ], - "parameters": { - "Left": [ - "TextArray", - "Bytea", - "Text", - "TextArray" - ] - } - }, - "query": "\n SELECT f.url url, f.id id, f.version_id version_id, v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id AND v.status != ANY($1)\n INNER JOIN mods m on v.mod_id = m.id\n WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4)\n " - }, "67d021f0776276081d3c50ca97afa6b78b98860bf929009e845e9c00a192e3b5": { "describe": { "columns": [ @@ -2897,32 +2858,6 @@ }, "query": "\n SELECT id FROM report_types\n WHERE name = $1\n " }, - "68f0e36e5dde4d05955de634227f3e65d16730e0ff260c7a33eff89b5f2ee972": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int8" - }, - { - "name": "project_id", - "ordinal": 1, - "type_info": "Int8" - } - ], - "nullable": [ - false, - false - ], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "\n SELECT v.id id, v.mod_id project_id FROM files f\n INNER JOIN versions v ON v.id = f.version_id\n WHERE f.url = $1\n " - }, "69bb839ea7fd5687538656e1907599d75e2c4948a54d58446bec8a90170ee618": { "describe": { "columns": [ @@ -2989,6 +2924,28 @@ }, "query": "\n INSERT INTO loaders_versions (loader_id, version_id)\n VALUES ($1, $2)\n " }, + "6c8b8a2f11c0b4e7a5973547fe1611a0fa4ef366d5c8a91d9fb9a1360ea04d46": { + "describe": { + "columns": [ + { + "name": "exists", + "ordinal": 0, + "type_info": "Bool" + } + ], + "nullable": [ + null + ], + "parameters": { + "Left": [ + "Bytea", + "Text", + "Int8" + ] + } + }, + "query": "\n SELECT EXISTS(SELECT 1 FROM hashes h\n INNER JOIN files f ON f.id = h.file_id\n INNER JOIN versions v ON v.id = f.version_id\n WHERE h.algorithm = $2 AND h.hash = $1 AND v.mod_id != $3)\n " + }, "6d10ec782e422e868681827a6eb999edc6bf4fe8fa2b94d1f8970db2578c6db4": { "describe": { "columns": [ @@ -3424,6 +3381,29 @@ }, "query": "\n DELETE FROM loaders_versions WHERE version_id = $1\n " }, + "7a27b31e1e671c33898b88a5ecba8a95b6920c1bb1527a44d5c54432a14a5d18": { + "describe": { + "columns": [ + { + "name": "project_id", + "ordinal": 0, + "type_info": "Int8" + } + ], + "nullable": [ + false + ], + "parameters": { + "Left": [ + "TextArray", + "Bytea", + "Text", + "TextArray" + ] + } + }, + "query": "\n SELECT v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id AND v.status != ANY($1)\n INNER JOIN mods m on v.mod_id = m.id\n WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4)\n ORDER BY v.date_published ASC\n " + }, "7ab21e7613dd88e97cf602e76bff62170c13ceef8104a4ce4cb2d101f8ce4f48": { "describe": { "columns": [], @@ -5718,33 +5698,28 @@ }, "query": "\n SELECT category FROM categories\n WHERE id = $1\n " }, - "c6830506451f89d8fa97c70a1edf723cedffae550e91dd0fa09fa04306fd56e8": { + "c79e4f7d3ffbda57daaf58f61cc0397a423b7bc877d2abc975c262d668f41f70": { "describe": { "columns": [ { - "name": "id", + "name": "version_id", "ordinal": 0, "type_info": "Int8" - }, - { - "name": "mod_id", - "ordinal": 1, - "type_info": "Int8" } ], "nullable": [ - false, false ], "parameters": { "Left": [ + "TextArray", + "Bytea", "Text", - "Int8", - "Int8" + "TextArray" ] } }, - "query": "SELECT id, mod_id FROM versions\n WHERE ((version_number = $1 OR id = $3) AND mod_id = $2)" + "query": "\n SELECT f.version_id version_id\n FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v on f.version_id = v.id AND v.status != ANY($1)\n INNER JOIN mods m on v.mod_id = m.id\n WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4)\n ORDER BY v.date_published ASC\n " }, "c8a27a122160a0896914c786deef9e8193eb240501d30d5ffb4129e2103efd3d": { "describe": { @@ -6263,6 +6238,51 @@ }, "query": "\n DELETE FROM files\n WHERE files.version_id = $1\n " }, + "da83d33451ec3240956d989237d0c14bec19c2cc19363207d1536d7b48aa5baa": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + }, + { + "name": "version_id", + "ordinal": 1, + "type_info": "Int8" + }, + { + "name": "filename", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "version_number", + "ordinal": 3, + "type_info": "Varchar" + }, + { + "name": "project_id", + "ordinal": 4, + "type_info": "Int8" + } + ], + "nullable": [ + false, + false, + false, + false, + false + ], + "parameters": { + "Left": [ + "Bytea", + "Text" + ] + } + }, + "query": "\n SELECT f.id id, f.version_id version_id, f.filename filename, v.version_number version_number, v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id\n WHERE h.algorithm = $2 AND h.hash = $1\n ORDER BY v.date_published ASC\n " + }, "dc6aa2e7bfd5d5004620ddd4cd6a47ecc56159e1489054e0652d56df802fb5e5": { "describe": { "columns": [], @@ -6333,6 +6353,38 @@ }, "query": "\n SELECT id, user_id, role, permissions, accepted, payouts_split, ordering\n FROM team_members\n WHERE (team_id = $1 AND user_id = $2)\n " }, + "dd57a6dd89fefedbde796ef02b308ce7dba17ca0c65ffd5f9e35e296a72d4c1c": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + }, + { + "name": "mod_id", + "ordinal": 1, + "type_info": "Int8" + }, + { + "name": "file_type", + "ordinal": 2, + "type_info": "Varchar" + } + ], + "nullable": [ + false, + false, + true + ], + "parameters": { + "Left": [ + "Text" + ] + } + }, + "query": "\n SELECT v.id id, v.mod_id mod_id, file_type FROM files f\n INNER JOIN versions v ON v.id = f.version_id\n WHERE f.url = $1\n " + }, "df35aee011aa176f5511729afd68b493ac70b997168cb502b5fd7e4224da27bb": { "describe": { "columns": [ @@ -7191,51 +7243,6 @@ }, "query": "\n DELETE FROM dependencies WHERE mod_dependency_id = $1\n " }, - "ef3d43d3424824eed67370f10cc0672581a95a169bf404022cbe3cac0415d99c": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int8" - }, - { - "name": "version_id", - "ordinal": 1, - "type_info": "Int8" - }, - { - "name": "filename", - "ordinal": 2, - "type_info": "Varchar" - }, - { - "name": "version_number", - "ordinal": 3, - "type_info": "Varchar" - }, - { - "name": "project_id", - "ordinal": 4, - "type_info": "Int8" - } - ], - "nullable": [ - false, - false, - false, - false, - false - ], - "parameters": { - "Left": [ - "Bytea", - "Text" - ] - } - }, - "query": "\n SELECT f.id id, f.version_id version_id, f.filename filename, v.version_number version_number, v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id\n WHERE h.algorithm = $2 AND h.hash = $1\n " - }, "ef59f99fc0ab66ff5779d0e71c4a2134e2f26eed002ff9ea5626ea3e23518594": { "describe": { "columns": [ diff --git a/src/routes/admin.rs b/src/routes/admin.rs index 8db7a4b5..a0375934 100644 --- a/src/routes/admin.rs +++ b/src/routes/admin.rs @@ -34,9 +34,24 @@ pub async fn count_download( .ok() .map(|x| x as i64); - let (version_id, project_id) = if let Some(version) = sqlx::query!( - "SELECT id, mod_id FROM versions - WHERE ((version_number = $1 OR id = $3) AND mod_id = $2)", + let (version_id, project_id, file_type) = if let Some(version) = + sqlx::query!( + " + SELECT v.id id, v.mod_id mod_id, file_type FROM files f + INNER JOIN versions v ON v.id = f.version_id + WHERE f.url = $1 + ", + download_body.url, + ) + .fetch_optional(pool.as_ref()) + .await? + { + (version.id, version.mod_id, version.file_type) + } else if let Some(version) = sqlx::query!( + " + SELECT id, mod_id FROM versions + WHERE ((version_number = $1 OR id = $3) AND mod_id = $2) + ", download_body.version_name, project_id as crate::database::models::ids::ProjectId, id_option @@ -44,31 +59,21 @@ pub async fn count_download( .fetch_optional(pool.as_ref()) .await? { - (version.id, version.mod_id) - } else if let Some(version) = sqlx::query!( - " - SELECT v.id id, v.mod_id project_id FROM files f - INNER JOIN versions v ON v.id = f.version_id - WHERE f.url = $1 - ", - download_body.url, - ) - .fetch_optional(pool.as_ref()) - .await? - { - (version.id, version.project_id) + (version.id, version.mod_id, None) } else { return Err(ApiError::InvalidInput( "Specified version does not exist!".to_string(), )); }; - download_queue - .add( - crate::database::models::ProjectId(project_id), - crate::database::models::VersionId(version_id), - ) - .await; + if file_type.is_none() { + download_queue + .add( + crate::database::models::ProjectId(project_id), + crate::database::models::VersionId(version_id), + ) + .await; + } let client = reqwest::Client::new(); diff --git a/src/routes/version_creation.rs b/src/routes/version_creation.rs index cf240782..5314e179 100644 --- a/src/routes/version_creation.rs +++ b/src/routes/version_creation.rs @@ -677,10 +677,13 @@ pub async fn upload_file( let exists = sqlx::query!( " SELECT EXISTS(SELECT 1 FROM hashes h - WHERE h.algorithm = $2 AND h.hash = $1) + INNER JOIN files f ON f.id = h.file_id + INNER JOIN versions v ON v.id = f.version_id + WHERE h.algorithm = $2 AND h.hash = $1 AND v.mod_id != $3) ", hash.as_bytes(), - "sha1" + "sha1", + project_id.0 as i64 ) .fetch_one(&mut *transaction) .await? diff --git a/src/routes/version_file.rs b/src/routes/version_file.rs index d86bd746..82694ce1 100644 --- a/src/routes/version_file.rs +++ b/src/routes/version_file.rs @@ -1,32 +1,41 @@ use super::ApiError; use crate::database::models::{version_item::QueryVersion, DatabaseError}; +use crate::models::ids::VersionId; use crate::models::projects::{GameVersion, Loader, Version}; use crate::models::teams::Permissions; use crate::util::auth::get_user_from_headers; use crate::util::routes::ok_or_not_found; use crate::{database, models}; use actix_web::{delete, get, post, web, HttpRequest, HttpResponse}; +use itertools::Itertools; use serde::{Deserialize, Serialize}; use sqlx::PgPool; use std::collections::HashMap; use tokio::sync::RwLock; #[derive(Deserialize)] -pub struct Algorithm { +pub struct HashQuery { #[serde(default = "default_algorithm")] pub algorithm: String, + #[serde(default = "default_multiple")] + pub multiple: bool, + pub version_id: Option, } fn default_algorithm() -> String { "sha1".into() } +fn default_multiple() -> bool { + false +} + // under /api/v1/version_file/{hash} #[get("{version_id}")] pub async fn get_version_from_hash( info: web::Path<(String,)>, pool: web::Data, - algorithm: web::Query, + hash_query: web::Query, ) -> Result { let hash = info.into_inner().0.to_lowercase(); @@ -38,32 +47,42 @@ pub async fn get_version_from_hash( INNER JOIN versions v on f.version_id = v.id AND v.status != ANY($1) INNER JOIN mods m on v.mod_id = m.id WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4) + ORDER BY v.date_published ASC ", &*crate::models::projects::VersionStatus::iterator() .filter(|x| x.is_hidden()) .map(|x| x.to_string()) .collect::>(), hash.as_bytes(), - algorithm.algorithm, + hash_query.algorithm, &*crate::models::projects::ProjectStatus::iterator() .filter(|x| x.is_hidden()) .map(|x| x.to_string()) .collect::>(), ) - .fetch_optional(&**pool) + .fetch_all(&**pool) .await?; - if let Some(id) = result { - let version_data = database::models::Version::get_full( - database::models::VersionId(id.version_id), - &**pool, - ) - .await?; + let versions_data = database::models::Version::get_many_full( + result + .iter() + .map(|x| database::models::VersionId(x.version_id)) + .collect(), + &**pool, + ) + .await?; - if let Some(data) = version_data { - Ok(HttpResponse::Ok().json(models::projects::Version::from(data))) + if let Some(first) = versions_data.first() { + if hash_query.multiple { + Ok(HttpResponse::Ok().json( + versions_data + .into_iter() + .map(models::projects::Version::from) + .collect::>(), + )) } else { - Ok(HttpResponse::NotFound().body("")) + Ok(HttpResponse::Ok() + .json(models::projects::Version::from(first.clone()))) } } else { Ok(HttpResponse::NotFound().body("")) @@ -80,7 +99,7 @@ pub struct DownloadRedirect { pub async fn download_version( info: web::Path<(String,)>, pool: web::Data, - algorithm: web::Query, + hash_query: web::Query, ) -> Result { let hash = info.into_inner().0.to_lowercase(); let mut transaction = pool.begin().await?; @@ -92,10 +111,11 @@ pub async fn download_version( INNER JOIN versions v ON v.id = f.version_id AND v.status != ANY($1) INNER JOIN mods m on v.mod_id = m.id WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4) + ORDER BY v.date_published ASC ", &*crate::models::projects::VersionStatus::iterator().filter(|x| x.is_hidden()).map(|x| x.to_string()).collect::>(), hash.as_bytes(), - algorithm.algorithm, + hash_query.algorithm, &*crate::models::projects::ProjectStatus::iterator().filter(|x| x.is_hidden()).map(|x| x.to_string()).collect::>(), ) .fetch_optional(&mut *transaction) @@ -118,7 +138,7 @@ pub async fn delete_file( req: HttpRequest, info: web::Path<(String,)>, pool: web::Data, - algorithm: web::Query, + hash_query: web::Query, ) -> Result { let user = get_user_from_headers(req.headers(), &**pool).await?; @@ -130,15 +150,18 @@ pub async fn delete_file( INNER JOIN files f ON h.file_id = f.id INNER JOIN versions v ON v.id = f.version_id WHERE h.algorithm = $2 AND h.hash = $1 + ORDER BY v.date_published ASC ", hash.as_bytes(), - algorithm.algorithm + hash_query.algorithm ) - .fetch_optional(&**pool) - .await - ?; + .fetch_all(&**pool) + .await?; - if let Some(row) = result { + if let Some(row) = result.iter().find_or_first(|x| { + hash_query.version_id.is_none() + || Some(x.version_id) == hash_query.version_id.map(|x| x.0 as i64) + }) { if !user.role.is_admin() { let team_member = database::models::TeamMember::get_from_user_id_version( @@ -227,7 +250,7 @@ pub struct UpdateData { pub async fn get_update_from_hash( info: web::Path<(String,)>, pool: web::Data, - algorithm: web::Query, + hash_query: web::Query, update_data: web::Json, ) -> Result { let hash = info.into_inner().0.to_lowercase(); @@ -243,13 +266,14 @@ pub async fn get_update_from_hash( INNER JOIN versions v ON v.id = f.version_id AND v.status != ANY($1) INNER JOIN mods m on v.mod_id = m.id WHERE h.algorithm = $3 AND h.hash = $2 AND m.status != ANY($4) + ORDER BY v.date_published ASC ", &*crate::models::projects::VersionStatus::iterator() .filter(|x| x.is_hidden()) .map(|x| x.to_string()) .collect::>(), hash.as_bytes(), - algorithm.algorithm, + hash_query.algorithm, &*crate::models::projects::ProjectStatus::iterator() .filter(|x| x.is_hidden()) .map(|x| x.to_string()) diff --git a/src/search/indexing/local_import.rs b/src/search/indexing/local_import.rs index 5a7e55d7..ec805c6c 100644 --- a/src/search/indexing/local_import.rs +++ b/src/search/indexing/local_import.rs @@ -70,9 +70,6 @@ pub async fn index_local( _ => false, }; - let mut gallery = m.featured_gallery.unwrap_or_default(); - gallery.append(&mut m.gallery.unwrap_or_default()); - UploadSearchProject { project_id: project_id.to_string(), title: m.title, @@ -93,10 +90,11 @@ pub async fn index_local( server_side: m.server_side_type, slug: m.slug, project_type: m.project_type_name, - gallery, + gallery: m.gallery.unwrap_or_default(), display_categories, open_source, color: m.color.map(|x| x as u32), + featured_gallery: m.featured_gallery.unwrap_or_default().first().cloned(), } })) }) diff --git a/src/search/indexing/mod.rs b/src/search/indexing/mod.rs index 2b2948c3..f6b16f34 100644 --- a/src/search/indexing/mod.rs +++ b/src/search/indexing/mod.rs @@ -198,6 +198,8 @@ const DEFAULT_DISPLAYED_ATTRIBUTES: &[&str] = &[ "client_side", "server_side", "gallery", + "featured_gallery", + "color", ]; const DEFAULT_SEARCHABLE_ATTRIBUTES: &[&str] = @@ -218,6 +220,7 @@ const DEFAULT_ATTRIBUTES_FOR_FACETING: &[&str] = &[ "date_modified", "project_id", "open_source", + "color", ]; const DEFAULT_SORTABLE_ATTRIBUTES: &[&str] = diff --git a/src/search/mod.rs b/src/search/mod.rs index d3d173dd..3373c3d2 100644 --- a/src/search/mod.rs +++ b/src/search/mod.rs @@ -89,6 +89,7 @@ pub struct UploadSearchProject { pub client_side: String, pub server_side: String, pub gallery: Vec, + pub featured_gallery: Option, /// RFC 3339 formatted creation date of the project pub date_created: DateTime, /// Unix timestamp of the creation date of the project @@ -119,7 +120,6 @@ pub struct ResultSearchProject { pub description: String, pub categories: Vec, pub display_categories: Vec, - // TODO: more efficient format for listing versions, without many repetitions pub versions: Vec, pub downloads: i32, pub follows: i32, @@ -133,6 +133,7 @@ pub struct ResultSearchProject { pub client_side: String, pub server_side: String, pub gallery: Vec, + pub featured_gallery: Option, pub color: Option, } diff --git a/src/util/img.rs b/src/util/img.rs index 1dd12f38..b7b8b8a4 100644 --- a/src/util/img.rs +++ b/src/util/img.rs @@ -3,8 +3,9 @@ use image::imageops::FilterType; use image::{EncodableLayout, ImageError}; pub fn get_color_from_img(data: &[u8]) -> Result, ImageError> { - let image = - image::load_from_memory(data)?.resize(256, 256, FilterType::Nearest); + let image = image::load_from_memory(data)? + .resize(256, 256, FilterType::Nearest) + .crop_imm(128, 128, 64, 64); let color = color_thief::get_palette( image.to_rgb8().as_bytes(), ColorFormat::Rgb,