Skip to content

Commit

Permalink
add /v1/me/mods
Browse files Browse the repository at this point in the history
  • Loading branch information
Fleeym committed Mar 1, 2024
1 parent 5c072d6 commit dc6fe36
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 4 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 40 additions & 3 deletions src/endpoints/developers.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
use actix_web::{delete, post, put, web, HttpResponse, Responder};
use serde::Deserialize;
use actix_web::{delete, get, post, put, web, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
use sqlx::Acquire;

use crate::{
auth::token,
extractors::auth::Auth,
types::{
api::ApiError,
api::{ApiError, ApiResponse},
models::{developer::Developer, mod_entity::Mod},
},
AppData,
};

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct SimpleDevMod {
pub id: String,
pub featured: bool,
pub download_count: i32,
pub versions: Vec<SimpleDevModVersion>,
}

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct SimpleDevModVersion {
pub name: String,
pub version: String,
pub download_count: i32,
pub validated: bool,
}

#[derive(Deserialize)]
struct AddDevPath {
id: String,
Expand Down Expand Up @@ -157,3 +173,24 @@ pub async fn update_profile(
.or(Err(ApiError::TransactionError))?;
Ok(HttpResponse::NoContent())
}

#[derive(Deserialize)]
struct GetOwnModsQuery {
validated: Option<bool>,
}

#[get("v1/me/mods")]
pub async fn get_own_mods(
data: web::Data<AppData>,
query: web::Query<GetOwnModsQuery>,
auth: Auth,
) -> Result<impl Responder, ApiError> {
let dev = auth.into_developer()?;
let mut pool = data.db.acquire().await.or(Err(ApiError::DbAcquireError))?;
let validated = query.validated.unwrap_or(true);
let mods: Vec<SimpleDevMod> = Mod::get_all_for_dev(dev.id, validated, &mut pool).await?;
Ok(HttpResponse::Ok().json(ApiResponse {
error: "".to_string(),
payload: mods,
}))
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ async fn main() -> anyhow::Result<()> {
.service(endpoints::developers::remove_dev_from_mod)
.service(endpoints::developers::delete_tokens)
.service(endpoints::developers::update_profile)
.service(endpoints::developers::get_own_mods)
.service(endpoints::tags::index)
.service(health)
})
Expand Down
78 changes: 77 additions & 1 deletion src/types/models/mod_entity.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::{
endpoints::mods::{IndexQueryParams, IndexSortType},
endpoints::{
developers::{SimpleDevMod, SimpleDevModVersion},
mods::{IndexQueryParams, IndexSortType},
},
types::{
api::{ApiError, PaginatedData},
mod_json::ModJson,
Expand Down Expand Up @@ -370,6 +373,79 @@ impl Mod {
})
}

pub async fn get_all_for_dev(
id: i32,
validated: bool,
pool: &mut PgConnection,
) -> Result<Vec<SimpleDevMod>, ApiError> {
struct Record {
id: String,
featured: bool,
mod_download_count: i32,
name: String,
version: String,
mod_version_download_count: i32,
validated: bool,
}
let records: Vec<Record> = match sqlx::query_as!(
Record,
"SELECT
m.id, m.featured, m.download_count as mod_download_count,
mv.name, mv.version, mv.download_count as mod_version_download_count,
mv.validated
FROM mods m
INNER JOIN mod_versions mv ON m.id = mv.mod_id
INNER JOIN mods_developers md ON md.mod_id = m.id
WHERE md.developer_id = $1 AND mv.validated = $2",
id,
validated
)
.fetch_all(&mut *pool)
.await
{
Ok(e) => e,
Err(e) => {
log::error!("{}", e);
return Err(ApiError::DbError);
}
};

if records.is_empty() {
return Ok(vec![]);
}

let mut versions: HashMap<String, Vec<SimpleDevModVersion>> = HashMap::new();

for record in &records {
let version = SimpleDevModVersion {
name: record.name.clone(),
version: record.version.clone(),
download_count: record.mod_version_download_count,
validated: record.validated,
};

versions.entry(record.id.clone()).or_default().push(version);
}

let mut map: HashMap<String, SimpleDevMod> = HashMap::new();

for i in records {
let mod_entity = SimpleDevMod {
id: i.id.clone(),
featured: i.featured,
download_count: i.mod_download_count,
versions: versions.entry(i.id.clone()).or_default().clone(),
};
if !map.contains_key(&i.id) {
map.insert(i.id.clone(), mod_entity);
}
}

let mods: Vec<SimpleDevMod> = map.into_iter().map(|x| x.1).collect();

Ok(mods)
}

pub async fn get_one(id: &str, pool: &mut PgConnection) -> Result<Option<Mod>, ApiError> {
let records: Vec<ModRecordGetOne> = sqlx::query_as!(
ModRecordGetOne,
Expand Down

0 comments on commit dc6fe36

Please sign in to comment.