Fix some issues with search and mod creation (#77)

This commit is contained in:
Aeledfyr 2020-10-16 12:04:38 -05:00 committed by GitHub
parent 77d35b61a9
commit 7983e82b60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 34 deletions

View File

@ -203,7 +203,12 @@ async fn mod_create_inner(
while let Some(chunk) = field.next().await { while let Some(chunk) = field.next().await {
data.extend_from_slice(&chunk.map_err(CreateError::MultipartError)?); data.extend_from_slice(&chunk.map_err(CreateError::MultipartError)?);
} }
mod_create_data = Some(serde_json::from_slice(&data)?); let create_data: ModCreateData = serde_json::from_slice(&data)?;
check_length("mod_name", 3, 255, &*create_data.mod_name)?;
check_length("mod_description", 3, 2048, &*create_data.mod_description)?;
mod_create_data = Some(create_data);
continue; continue;
} }
@ -211,9 +216,6 @@ async fn mod_create_inner(
CreateError::InvalidInput(String::from("`data` field must come before file fields")) CreateError::InvalidInput(String::from("`data` field must come before file fields"))
})?; })?;
check_length("mod_name", 3, 255, &*create_data.mod_name)?;
check_length("mod_description", 3, 2048, &*create_data.mod_description)?;
let (file_name, file_extension) = let (file_name, file_extension) =
super::version_creation::get_name_ext(&content_disposition)?; super::version_creation::get_name_ext(&content_disposition)?;
@ -374,18 +376,35 @@ async fn mod_create_inner(
file_name: upload_data.file_name.clone(), file_name: upload_data.file_name.clone(),
}); });
let mut author_username = None;
let mut author_id = None;
let team = models::team_item::TeamBuilder { let team = models::team_item::TeamBuilder {
members: create_data members: create_data
.team_members .team_members
.into_iter() .into_iter()
.map(|member| models::team_item::TeamMemberBuilder { .map(|member| {
if member.role == crate::models::teams::OWNER_ROLE {
author_id = Some(member.user_id);
author_username = Some(member.name.clone());
}
models::team_item::TeamMemberBuilder {
user_id: member.user_id.into(), user_id: member.user_id.into(),
name: member.name, name: member.name,
role: member.role, role: member.role,
}
}) })
.collect(), .collect(),
}; };
let (author_username, author_id) = if let (Some(u), Some(id)) = (author_username, author_id) {
(u, id)
} else {
return Err(CreateError::InvalidInput(String::from(
"A mod must have an author",
)));
};
let team_id = team.insert(&mut *transaction).await?; let team_id = team.insert(&mut *transaction).await?;
let status = ModStatus::Processing; let status = ModStatus::Processing;
@ -440,8 +459,8 @@ async fn mod_create_inner(
versions: versions_list, versions: versions_list,
page_url: format!("https://modrinth.com/mod/{}", mod_id), page_url: format!("https://modrinth.com/mod/{}", mod_id),
icon_url: mod_builder.icon_url.clone().unwrap(), icon_url: mod_builder.icon_url.clone().unwrap(),
author: user.username, author: author_username,
author_url: format!("https://modrinth.com/user/{}", user.id), author_url: format!("https://modrinth.com/user/{}", author_id),
// TODO: latest version info // TODO: latest version info
latest_version: String::new(), latest_version: String::new(),
downloads: 0, downloads: 0,

View File

@ -186,12 +186,15 @@ pub async fn index_curseforge(
.date_modified .date_modified
.parse::<chrono::DateTime<chrono::Utc>>()?; .parse::<chrono::DateTime<chrono::Utc>>()?;
let mut author = String::new(); let author;
let mut author_url = String::new(); let author_url;
if curseforge_mod.authors.len() > 0 { if let Some(user) = curseforge_mod.authors.get(0) {
author = (&curseforge_mod.authors[0].name).to_string(); author = user.name.clone();
author_url = (&curseforge_mod.authors[0].url).to_string(); author_url = user.url.clone();
} else {
author = String::from("unknown");
author_url = curseforge_mod.website_url.clone();
} }
docs_to_add.push(UploadSearchMod { docs_to_add.push(UploadSearchMod {

View File

@ -12,14 +12,14 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
let mut docs_to_add: Vec<UploadSearchMod> = vec![]; let mut docs_to_add: Vec<UploadSearchMod> = vec![];
let mut results = sqlx::query!( let mut mods = sqlx::query!(
" "
SELECT m.id, m.title, m.description, m.downloads, m.icon_url, m.body_url, m.published, m.updated, m.team_id FROM mods m SELECT m.id, m.title, m.description, m.downloads, m.icon_url, m.body_url, m.published, m.updated, m.team_id FROM mods m
" "
).fetch(&pool); ).fetch(&pool);
while let Some(result) = results.next().await { while let Some(result) = mods.next().await {
if let Ok(result) = result { if let Ok(mod_data) = result {
let versions: Vec<String> = sqlx::query!( let versions: Vec<String> = sqlx::query!(
" "
SELECT gv.version FROM versions SELECT gv.version FROM versions
@ -27,7 +27,7 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
INNER JOIN game_versions gv ON gvv.game_version_id=gv.id INNER JOIN game_versions gv ON gvv.game_version_id=gv.id
WHERE versions.mod_id = $1 WHERE versions.mod_id = $1
", ",
result.id mod_data.id
) )
.fetch_many(&pool) .fetch_many(&pool)
.try_filter_map(|e| async { Ok(e.right().map(|c| c.version)) }) .try_filter_map(|e| async { Ok(e.right().map(|c| c.version)) })
@ -41,7 +41,7 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
INNER JOIN loaders ON loaders.id = lv.loader_id INNER JOIN loaders ON loaders.id = lv.loader_id
WHERE versions.mod_id = $1 WHERE versions.mod_id = $1
", ",
result.id mod_data.id
) )
.fetch_many(&pool) .fetch_many(&pool)
.try_filter_map(|e| async { Ok(e.right().map(|c| c.loader)) }) .try_filter_map(|e| async { Ok(e.right().map(|c| c.loader)) })
@ -55,7 +55,7 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
INNER JOIN categories c ON mc.joining_category_id=c.id INNER JOIN categories c ON mc.joining_category_id=c.id
WHERE mc.joining_mod_id = $1 WHERE mc.joining_mod_id = $1
", ",
result.id mod_data.id
) )
.fetch_many(&pool) .fetch_many(&pool)
.try_filter_map(|e| async { Ok(e.right().map(|c| c.category)) }) .try_filter_map(|e| async { Ok(e.right().map(|c| c.category)) })
@ -71,32 +71,35 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
WHERE tm.team_id = $2 WHERE tm.team_id = $2
", ",
crate::models::teams::OWNER_ROLE, crate::models::teams::OWNER_ROLE,
result.team_id, mod_data.team_id,
) )
.fetch_one(&pool) .fetch_one(&pool)
.await?; .await?;
let mut icon_url = "".to_string(); let mut icon_url = "".to_string();
if let Some(url) = result.icon_url { if let Some(url) = mod_data.icon_url {
icon_url = url; icon_url = url;
} }
let mod_id = crate::models::ids::ModId(mod_data.id as u64);
let author_id = crate::models::ids::UserId(user.id as u64);
docs_to_add.push(UploadSearchMod { docs_to_add.push(UploadSearchMod {
mod_id: format!("local-{}", crate::models::ids::ModId(result.id as u64)), mod_id: format!("local-{}", mod_id),
title: result.title, title: mod_data.title,
description: result.description, description: mod_data.description,
categories, categories,
versions, versions,
downloads: result.downloads, downloads: mod_data.downloads,
page_url: format!("https://modrinth.com/mod/{}", result.id), page_url: format!("https://modrinth.com/mod/{}", mod_id),
icon_url, icon_url,
author: user.username, author: user.username,
author_url: format!("https://modrinth.com/user/{}", user.id), author_url: format!("https://modrinth.com/user/{}", author_id),
date_created: result.published, date_created: mod_data.published,
created_timestamp: result.published.timestamp(), created_timestamp: mod_data.published.timestamp(),
date_modified: result.updated, date_modified: mod_data.updated,
modified_timestamp: result.updated.timestamp(), modified_timestamp: mod_data.updated.timestamp(),
latest_version: "".to_string(), // TODO: Info about latest version latest_version: "".to_string(), // TODO: Info about latest version
host: Cow::Borrowed("modrinth"), host: Cow::Borrowed("modrinth"),
empty: Cow::Borrowed("{}{}{}"), empty: Cow::Borrowed("{}{}{}"),

View File

@ -23,6 +23,8 @@ pub enum SearchError {
IntParsingError(#[from] std::num::ParseIntError), IntParsingError(#[from] std::num::ParseIntError),
#[error("Environment Error")] #[error("Environment Error")]
EnvError(#[from] dotenv::Error), EnvError(#[from] dotenv::Error),
#[error("Invalid index to sort by: {0}")]
InvalidIndex(String),
} }
impl actix_web::ResponseError for SearchError { impl actix_web::ResponseError for SearchError {
@ -32,6 +34,7 @@ impl actix_web::ResponseError for SearchError {
SearchError::IndexDBError(..) => StatusCode::INTERNAL_SERVER_ERROR, SearchError::IndexDBError(..) => StatusCode::INTERNAL_SERVER_ERROR,
SearchError::SerDeError(..) => StatusCode::BAD_REQUEST, SearchError::SerDeError(..) => StatusCode::BAD_REQUEST,
SearchError::IntParsingError(..) => StatusCode::BAD_REQUEST, SearchError::IntParsingError(..) => StatusCode::BAD_REQUEST,
SearchError::InvalidIndex(..) => StatusCode::BAD_REQUEST,
} }
} }
@ -42,6 +45,7 @@ impl actix_web::ResponseError for SearchError {
SearchError::IndexDBError(..) => "indexdb_error", SearchError::IndexDBError(..) => "indexdb_error",
SearchError::SerDeError(..) => "invalid_input", SearchError::SerDeError(..) => "invalid_input",
SearchError::IntParsingError(..) => "invalid_input", SearchError::IntParsingError(..) => "invalid_input",
SearchError::InvalidIndex(..) => "invalid_input",
}, },
description: &self.to_string(), description: &self.to_string(),
}) })
@ -161,8 +165,16 @@ pub async fn search_for_mod(info: &SearchRequest) -> Result<SearchResults, Searc
query = query.with_facet_filters(facets); query = query.with_facet_filters(facets);
} }
let index = match index {
"relevance" => "relevance_mods",
"downloads" => "downloads_mods",
"updated" => "updated_mods",
"newest" => "newest_mods",
i => return Err(SearchError::InvalidIndex(i.to_string())),
};
let results = client let results = client
.get_index(format!("{}_mods", index).as_ref()) .get_index(index)
.await? .await?
.search::<ResultSearchMod>(&query) .search::<ResultSearchMod>(&query)
.await?; .await?;