diff --git a/sql/maps/search_maps.sql b/sql/maps/search_maps.sql new file mode 100644 index 0000000..8795376 --- /dev/null +++ b/sql/maps/search_maps.sql @@ -0,0 +1,9 @@ +SELECT record_maps.map, category, points, stars, mappers, release, width, height, tiles + FROM record_maps JOIN record_mapinfo_array ON record_maps.map = record_mapinfo_array.map + WHERE ($1::TEXT IS NULL OR record_maps.map ILIKE $1) + AND (COALESCE(ARRAY_LENGTH($2::TEXT[], 1), NULL)::BOOLEAN IS TRUE OR $2::TEXT[] <@ mappers::TEXT[]) + AND ($3::TEXT IS NULL OR category = $3) + AND ($4::SMALLINT[] IS NULL OR stars = ANY($4)) + AND ($5::TIMESTAMP IS NULL OR release >= $5) + AND ($6::TIMESTAMP IS NULL OR release <= $6) + AND (COALESCE(ARRAY_LENGTH($7::TEXT[], 1), NULL)::BOOLEAN IS TRUE OR $7::TEXT[] <@ tiles::TEXT[]) \ No newline at end of file diff --git a/src/api/maps.rs b/src/api/maps.rs index b384830..bd2815d 100644 --- a/src/api/maps.rs +++ b/src/api/maps.rs @@ -1,3 +1,4 @@ +use chrono::NaiveDateTime; use rocket::{serde::json::Json, Route, State}; use crate::database::{models::map::Map, DatabaseHandler}; @@ -40,11 +41,40 @@ async fn get_maps_by_mapper( } } +#[get("/search?&&&&&&")] +async fn search_maps<'a>( + db: &State, + map: Option<&str>, + mappers: Option>, + category: Option<&str>, + stars: Option>, + release_after: Option<&str>, + release_before: Option<&str>, + tiles: Option>, +) -> Result>, String> { + match Map::search_maps( + db, + map, + mappers, + category, + stars, + release_after.map(|x| NaiveDateTime::parse_from_str(x, "%Y-%m-%d").unwrap()), + release_before.map(|x| NaiveDateTime::parse_from_str(x, "%Y-%m-%d").unwrap()), + tiles, + ) + .await + { + Ok(maps) => Ok(Json(maps)), + Err(err) => Err(format!("Error: {}", err)), + } +} + pub fn get_all_routes() -> Vec { routes![ get_all_maps, get_map_by_name, get_maps_by_category, - get_maps_by_mapper + get_maps_by_mapper, + search_maps ] } diff --git a/src/database/models/map.rs b/src/database/models/map.rs index abf71f8..f100d4e 100644 --- a/src/database/models/map.rs +++ b/src/database/models/map.rs @@ -55,6 +55,36 @@ impl Map { .fetch_all(&db.pool) .await } + + /// Experimental function to search for maps. + pub async fn search_maps( + db: &DatabaseHandler, + map: Option<&str>, + mappers: Option>, + category: Option<&str>, + stars: Option>, + release_after: Option, + release_before: Option, + tiles: Option>, + ) -> Result, sqlx::Error> { + let stars = stars.unwrap_or((0..=5).collect()); + let mappers = mappers.unwrap_or(vec!["%".to_string()]); + let tiles = tiles.unwrap_or(vec!["%".to_string()]); + + sqlx::query_file_as!( + Map, + "sql/maps/search_maps.sql", + map.map(|map| format!("%{}%", map)), + mappers.as_slice(), + category, + stars.as_slice(), + release_after, + release_before, + tiles.as_slice(), + ) + .fetch_all(&db.pool) + .await + } } #[cfg(test)]