You've already forked AstralRinth
forked from didirus/AstralRinth
* search patch for accurate loader/gv filtering * backup * basic search test * finished test * incomplete commit; backing up * Working multipat reroute backup * working rough draft v3 * most tests passing * works * search v2 conversion * added some tags.rs v2 conversions * Worked through warnings, unwraps, prints * refactors * new search test * version files changes fixes * redesign to revs * removed old caches * removed games * fmt clippy * merge conflicts * fmt, prepare * moved v2 routes over to v3 * fixes; tests passing * project type changes * moved files over * fmt, clippy, prepare, etc * loaders to loader_fields, added tests * fmt, clippy, prepare * fixed sorting bug * reversed back- wrong order for consistency * fmt; clippy; prepare --------- Co-authored-by: Jai A <jaiagr+gpg@pm.me>
285 lines
7.2 KiB
Rust
285 lines
7.2 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use crate::database::redis::RedisPool;
|
|
|
|
use super::ids::*;
|
|
use super::DatabaseError;
|
|
use futures::TryStreamExt;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
const TAGS_NAMESPACE: &str = "tags";
|
|
|
|
pub struct ProjectType {
|
|
pub id: ProjectTypeId,
|
|
pub name: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct Category {
|
|
pub id: CategoryId,
|
|
pub category: String,
|
|
pub project_type: String,
|
|
pub icon: String,
|
|
pub header: String,
|
|
}
|
|
|
|
pub struct ReportType {
|
|
pub id: ReportTypeId,
|
|
pub report_type: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct DonationPlatform {
|
|
pub id: DonationPlatformId,
|
|
pub short: String,
|
|
pub name: String,
|
|
}
|
|
|
|
impl Category {
|
|
// Gets hashmap of category ids matching a name
|
|
// Multiple categories can have the same name, but different project types, so we need to return a hashmap
|
|
// ProjectTypeId -> CategoryId
|
|
pub async fn get_ids<'a, E>(
|
|
name: &str,
|
|
exec: E,
|
|
) -> Result<HashMap<ProjectTypeId, CategoryId>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT id, project_type FROM categories
|
|
WHERE category = $1
|
|
",
|
|
name,
|
|
)
|
|
.fetch_all(exec)
|
|
.await?;
|
|
|
|
let mut map = HashMap::new();
|
|
for r in result {
|
|
map.insert(ProjectTypeId(r.project_type), CategoryId(r.id));
|
|
}
|
|
|
|
Ok(map)
|
|
}
|
|
|
|
pub async fn get_id_project<'a, E>(
|
|
name: &str,
|
|
project_type: ProjectTypeId,
|
|
exec: E,
|
|
) -> Result<Option<CategoryId>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT id FROM categories
|
|
WHERE category = $1 AND project_type = $2
|
|
",
|
|
name,
|
|
project_type as ProjectTypeId
|
|
)
|
|
.fetch_optional(exec)
|
|
.await?;
|
|
|
|
Ok(result.map(|r| CategoryId(r.id)))
|
|
}
|
|
|
|
pub async fn list<'a, E>(exec: E, redis: &RedisPool) -> Result<Vec<Category>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let res: Option<Vec<Category>> = redis
|
|
.get_deserialized_from_json(TAGS_NAMESPACE, "category")
|
|
.await?;
|
|
|
|
if let Some(res) = res {
|
|
return Ok(res);
|
|
}
|
|
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT c.id id, c.category category, c.icon icon, c.header category_header, pt.name project_type
|
|
FROM categories c
|
|
INNER JOIN project_types pt ON c.project_type = pt.id
|
|
ORDER BY c.ordering, c.category
|
|
"
|
|
)
|
|
.fetch_many(exec)
|
|
.try_filter_map(|e| async {
|
|
Ok(e.right().map(|c| Category {
|
|
id: CategoryId(c.id),
|
|
category: c.category,
|
|
project_type: c.project_type,
|
|
icon: c.icon,
|
|
header: c.category_header
|
|
}))
|
|
})
|
|
.try_collect::<Vec<Category>>()
|
|
.await?;
|
|
|
|
redis
|
|
.set_serialized_to_json(TAGS_NAMESPACE, "category", &result, None)
|
|
.await?;
|
|
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
impl DonationPlatform {
|
|
pub async fn get_id<'a, E>(
|
|
id: &str,
|
|
exec: E,
|
|
) -> Result<Option<DonationPlatformId>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT id FROM donation_platforms
|
|
WHERE short = $1
|
|
",
|
|
id
|
|
)
|
|
.fetch_optional(exec)
|
|
.await?;
|
|
|
|
Ok(result.map(|r| DonationPlatformId(r.id)))
|
|
}
|
|
|
|
pub async fn list<'a, E>(
|
|
exec: E,
|
|
redis: &RedisPool,
|
|
) -> Result<Vec<DonationPlatform>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let res: Option<Vec<DonationPlatform>> = redis
|
|
.get_deserialized_from_json(TAGS_NAMESPACE, "donation_platform")
|
|
.await?;
|
|
|
|
if let Some(res) = res {
|
|
return Ok(res);
|
|
}
|
|
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT id, short, name FROM donation_platforms
|
|
"
|
|
)
|
|
.fetch_many(exec)
|
|
.try_filter_map(|e| async {
|
|
Ok(e.right().map(|c| DonationPlatform {
|
|
id: DonationPlatformId(c.id),
|
|
short: c.short,
|
|
name: c.name,
|
|
}))
|
|
})
|
|
.try_collect::<Vec<DonationPlatform>>()
|
|
.await?;
|
|
|
|
redis
|
|
.set_serialized_to_json(TAGS_NAMESPACE, "donation_platform", &result, None)
|
|
.await?;
|
|
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
impl ReportType {
|
|
pub async fn get_id<'a, E>(name: &str, exec: E) -> Result<Option<ReportTypeId>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT id FROM report_types
|
|
WHERE name = $1
|
|
",
|
|
name
|
|
)
|
|
.fetch_optional(exec)
|
|
.await?;
|
|
|
|
Ok(result.map(|r| ReportTypeId(r.id)))
|
|
}
|
|
|
|
pub async fn list<'a, E>(exec: E, redis: &RedisPool) -> Result<Vec<String>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let res: Option<Vec<String>> = redis
|
|
.get_deserialized_from_json(TAGS_NAMESPACE, "report_type")
|
|
.await?;
|
|
|
|
if let Some(res) = res {
|
|
return Ok(res);
|
|
}
|
|
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT name FROM report_types
|
|
"
|
|
)
|
|
.fetch_many(exec)
|
|
.try_filter_map(|e| async { Ok(e.right().map(|c| c.name)) })
|
|
.try_collect::<Vec<String>>()
|
|
.await?;
|
|
|
|
redis
|
|
.set_serialized_to_json(TAGS_NAMESPACE, "report_type", &result, None)
|
|
.await?;
|
|
|
|
Ok(result)
|
|
}
|
|
}
|
|
|
|
impl ProjectType {
|
|
pub async fn get_id<'a, E>(name: &str, exec: E) -> Result<Option<ProjectTypeId>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT id FROM project_types
|
|
WHERE name = $1
|
|
",
|
|
name
|
|
)
|
|
.fetch_optional(exec)
|
|
.await?;
|
|
|
|
Ok(result.map(|r| ProjectTypeId(r.id)))
|
|
}
|
|
|
|
pub async fn list<'a, E>(exec: E, redis: &RedisPool) -> Result<Vec<String>, DatabaseError>
|
|
where
|
|
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
|
{
|
|
let res: Option<Vec<String>> = redis
|
|
.get_deserialized_from_json(TAGS_NAMESPACE, "project_type")
|
|
.await?;
|
|
|
|
if let Some(res) = res {
|
|
return Ok(res);
|
|
}
|
|
|
|
let result = sqlx::query!(
|
|
"
|
|
SELECT name FROM project_types
|
|
"
|
|
)
|
|
.fetch_many(exec)
|
|
.try_filter_map(|e| async { Ok(e.right().map(|c| c.name)) })
|
|
.try_collect::<Vec<String>>()
|
|
.await?;
|
|
|
|
redis
|
|
.set_serialized_to_json(TAGS_NAMESPACE, "project_type", &result, None)
|
|
.await?;
|
|
|
|
Ok(result)
|
|
}
|
|
}
|