summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md12
-rw-r--r--src/main.rs2
-rw-r--r--src/routes.rs18
-rw-r--r--src/routes/album.rs87
-rw-r--r--src/routes/artist.rs66
5 files changed, 178 insertions, 7 deletions
diff --git a/README.md b/README.md
index 164f0b3..879e026 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,15 @@
# Balalaika
School project of a lyrics game site.
+## Set up env
+Create a .env file and fill using env_example as a guide.
+
## Setup database
To manage the database through the program's scripts use
`cargo run-script`
-You can install the app with `cargo install cargo-run-script`
+You can install the app with
+`cargo install cargo-run-script`
Available scripts:
```
@@ -15,7 +19,7 @@ db_start
db_stop
```
-The stop/start scripts assume you're using systemd.
+The start/stop scripts assume that you're using systemd.
If not, just start/stop the mariadb service manually.
## Changes
@@ -23,7 +27,3 @@ If not, just start/stop the mariadb service manually.
You can only search a parameter at a time.
This is because Rust needs to process the sql queries ahead of time
in order to make them safe to injection attacks.
-
-### SearchResults changed its name
-Since searchResults was highly unintuitive,
-it has been renamed to just "name".
diff --git a/src/main.rs b/src/main.rs
index 9d6ec4f..bddb0b6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -31,6 +31,8 @@ async fn main() -> std::io::Result<()> {
.app_data(web::Data::new(app_state.clone()))
.route("/", web::get().to(root))
.service(routes::song::song)
+ .service(routes::album::album)
+ .service(routes::artist::artist)
})
.bind(("127.0.0.1", 8000))?
.run()
diff --git a/src/routes.rs b/src/routes.rs
index a219da1..d984505 100644
--- a/src/routes.rs
+++ b/src/routes.rs
@@ -1,14 +1,30 @@
use serde::Serialize;
pub mod song;
+pub mod album;
+pub mod artist;
#[derive(Serialize)]
pub struct Song {
- id: Option<i32>,
name: Option<String>,
+ id: Option<i32>,
lyrics: Option<String>,
album_name: Option<String>,
album_id: Option<i32>,
artist_name: Option<String>,
artist_id: Option<i32>,
}
+
+#[derive(Serialize)]
+pub struct Album {
+ name: Option<String>,
+ id: Option<i32>,
+ artist_name: Option<String>,
+ artist_id: Option<i32>,
+}
+
+#[derive(Serialize)]
+pub struct Artist {
+ name: Option<String>,
+ id: Option<i32>,
+}
diff --git a/src/routes/album.rs b/src/routes/album.rs
new file mode 100644
index 0000000..1948339
--- /dev/null
+++ b/src/routes/album.rs
@@ -0,0 +1,87 @@
+use crate::routes::Album;
+use crate::AppState;
+use actix_web::{get, web, HttpResponse};
+use serde::Deserialize;
+
+#[derive(Deserialize)]
+struct AlbumQueryOptions {
+ id: Option<String>,
+ name: Option<String>,
+ artist: Option<String>,
+}
+
+#[get("/api/album")]
+pub async fn album(
+ app_state: web::Data<AppState>,
+ get_args: web::Query<AlbumQueryOptions>,
+) -> HttpResponse {
+ let search_attempt: sqlx::Result<Vec<Album>>;
+
+ match true {
+ _ if check_if_exists(&get_args.id) => {
+ search_attempt = sqlx::query_as!(
+ Album,
+ "SELECT album.name, album.id,
+ artist.name as artist_name, artist.id as artist_id
+ FROM album
+ INNER JOIN artist ON album.artist_id = artist.id
+ WHERE album.id=?",
+ &get_args.id,
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ _ if check_if_exists(&get_args.name) => {
+ let new_name : String = format!("{}{}{}", "%", &get_args.name.clone().unwrap(), "%");
+ search_attempt = sqlx::query_as!(
+ Album,
+ "SELECT album.name, album.id,
+ artist.name as artist_name, artist.id as artist_id
+ FROM album
+ INNER JOIN artist ON album.artist_id = artist.id
+ WHERE LOWER(album.name) LIKE LOWER(?)",
+ new_name,
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ _ if check_if_exists(&get_args.artist) => {
+ search_attempt = sqlx::query_as!(
+ Album,
+ "SELECT album.name, album.id,
+ artist.name as artist_name, artist.id as artist_id
+ FROM album
+ INNER JOIN artist ON album.artist_id = artist.id
+ WHERE album.artist_id=?
+ ",
+ &get_args.artist,
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ _ => {
+ search_attempt = sqlx::query_as!(
+ Album,
+ "SELECT album.name, album.id,
+ artist.name as artist_name, artist.id as artist_id
+ FROM album
+ INNER JOIN artist ON album.artist_id = artist.id
+ ",
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ };
+
+ match search_attempt {
+ Ok(album_list) => HttpResponse::Ok().json(album_list),
+ Err(e) => HttpResponse::Ok().body(format!("{}", e)),
+ }
+}
+
+fn check_if_exists(value: &Option<String>) -> bool {
+ match value {
+ Some(_) => true,
+ None => false,
+ }
+}
diff --git a/src/routes/artist.rs b/src/routes/artist.rs
new file mode 100644
index 0000000..bf18e34
--- /dev/null
+++ b/src/routes/artist.rs
@@ -0,0 +1,66 @@
+use crate::routes::Artist;
+use crate::AppState;
+use actix_web::{get, web, HttpResponse};
+use serde::Deserialize;
+
+#[derive(Deserialize)]
+struct ArtistQueryOptions {
+ id: Option<String>,
+ name: Option<String>,
+}
+
+#[get("/api/artist")]
+pub async fn artist(
+ app_state: web::Data<AppState>,
+ get_args: web::Query<ArtistQueryOptions>,
+) -> HttpResponse {
+ let search_attempt: sqlx::Result<Vec<Artist>>;
+
+ match true {
+ _ if check_if_exists(&get_args.id) => {
+ search_attempt = sqlx::query_as!(
+ Artist,
+ "SELECT name, id
+ FROM artist
+ WHERE id=?",
+ &get_args.id,
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ _ if check_if_exists(&get_args.name) => {
+ let new_name : String = format!("{}{}{}", "%", &get_args.name.clone().unwrap(), "%");
+ search_attempt = sqlx::query_as!(
+ Artist,
+ "SELECT name, id
+ FROM artist
+ WHERE LOWER(name) LIKE LOWER(?)",
+ new_name,
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ _ => {
+ search_attempt = sqlx::query_as!(
+ Artist,
+ "SELECT name, id
+ FROM artist
+ ",
+ )
+ .fetch_all(&app_state.pool)
+ .await;
+ }
+ };
+
+ match search_attempt {
+ Ok(artist_list) => HttpResponse::Ok().json(artist_list),
+ Err(e) => HttpResponse::Ok().body(format!("{}", e)),
+ }
+}
+
+fn check_if_exists(value: &Option<String>) -> bool {
+ match value {
+ Some(_) => true,
+ None => false,
+ }
+}