From f748d93b3facb95a4d41109aea4eee96e75d96d5 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 14 Aug 2025 23:11:41 +0000 Subject: [PATCH] tsk-41: Adding auth (#43) Closes #41 Reviewed-on: https://git.kundeng.us/phoenix/songparser/pulls/43 Co-authored-by: phoenix Co-committed-by: phoenix --- .env.docker.sample | 2 + .env.sample | 2 + .gitignore | 2 + Cargo.lock | 95 ++++++++++++++++++-- Cargo.toml | 8 +- src/api.rs | 64 +++++++++++--- src/config.rs | 6 ++ src/main.rs | 182 ++++++++++++++++++++++++++++---------- src/the_rest.rs | 28 +++--- src/update_queued_song.rs | 7 +- 10 files changed, 312 insertions(+), 84 deletions(-) create mode 100644 src/config.rs diff --git a/.env.docker.sample b/.env.docker.sample index be6a3d3..f116df7 100644 --- a/.env.docker.sample +++ b/.env.docker.sample @@ -1,2 +1,4 @@ ROOT_DIRECTORY=/home/songparser/mydata ICARUS_BASE_API_URL=http://localhost:3000 +ICARUS_AUTH_BASE_API_URL=http://localhost:3001 +SERVICE_PASSPHRASE=iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH diff --git a/.env.sample b/.env.sample index be6a3d3..f116df7 100644 --- a/.env.sample +++ b/.env.sample @@ -1,2 +1,4 @@ ROOT_DIRECTORY=/home/songparser/mydata ICARUS_BASE_API_URL=http://localhost:3000 +ICARUS_AUTH_BASE_API_URL=http://localhost:3001 +SERVICE_PASSPHRASE=iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH diff --git a/.gitignore b/.gitignore index fedaa2b..c2a0c1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target .env +.env.local +.env.docker diff --git a/Cargo.lock b/Cargo.lock index 553b8e5..af8391a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,21 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -501,8 +516,8 @@ dependencies = [ [[package]] name = "icarus_envy" -version = "0.3.0" -source = "git+ssh://git@git.kundeng.us/phoenix/icarus_envy.git?tag=v0.3.0-devel-d73fba9899-006#d73fba9899372b0655a90cb426645930135152da" +version = "0.3.2" +source = "git+ssh://git@git.kundeng.us/phoenix/icarus_envy.git?tag=v0.3.2-18-d498f60046-006#d498f600468c7e5fcf03a640f8c5b9476765fe96" dependencies = [ "const_format", "dotenvy", @@ -511,16 +526,17 @@ dependencies = [ [[package]] name = "icarus_meta" version = "0.3.0" -source = "git+ssh://git@git.kundeng.us/phoenix/icarus_meta.git?tag=v0.3.0-devel-f4b71de969-680#f4b71de9692029a706b1ce82c39f6715c560158e" +source = "git+ssh://git@git.kundeng.us/phoenix/icarus_meta.git?tag=v0.3.0#f87c049ab3139995230485b33038a0425f2e7430" dependencies = [ "lofty", ] [[package]] name = "icarus_models" -version = "0.4.5" -source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.4.5-devel-655d05dabb-111#655d05dabbdadb9b28940564a1eb82470aa4f166" +version = "0.5.5" +source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.5.5-devel-bd793db08e-111#bd793db08e06b256ffecd9f4528e55e3026fede7" dependencies = [ + "josekit", "rand", "serde", "serde_json", @@ -667,6 +683,23 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "josekit" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a808e078330e6af222eb0044b71d4b1ff981bfef43e7bc8133a88234e0c86a0c" +dependencies = [ + "anyhow", + "base64", + "flate2", + "openssl", + "regex", + "serde", + "serde_json", + "thiserror", + "time", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -1009,6 +1042,35 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "reqwest" version = "0.12.20" @@ -1195,6 +1257,7 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ + "indexmap", "itoa", "memchr", "ryu", @@ -1255,7 +1318,7 @@ dependencies = [ [[package]] name = "songparser" -version = "0.2.4" +version = "0.2.5" dependencies = [ "futures", "icarus_envy", @@ -1347,6 +1410,26 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thiserror" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.3.41" diff --git a/Cargo.toml b/Cargo.toml index cd5e6fe..3d91bd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "songparser" -version = "0.2.4" +version = "0.2.5" edition = "2024" rust-version = "1.88" @@ -13,6 +13,6 @@ serde_json = { version = "1.0.140" } time = { version = "0.3.41", features = ["macros", "serde"] } uuid = { version = "1.17.0", features = ["v4", "serde"] } rand = { version = "0.9.1" } -icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.3.0-devel-f4b71de969-680" } -icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.4.5-devel-655d05dabb-111" } -icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.3.0-devel-d73fba9899-006" } +icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.3.0" } +icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.5.5-devel-bd793db08e-111" } +icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.3.2-18-d498f60046-006" } diff --git a/src/api.rs b/src/api.rs index f4d0933..ff23283 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,8 +1,20 @@ -pub async fn fetch_next_queue_item(base_url: &String) -> Result { +pub async fn fetch_next_queue_item( + app: &crate::config::App, +) -> Result { let client = reqwest::Client::new(); let fetch_endpoint = String::from("api/v2/song/queue/next"); - let api_url = format!("{base_url}/{fetch_endpoint}"); - client.get(api_url).send().await + let api_url = format!("{}/{fetch_endpoint}", app.uri); + let (key, header) = auth_header(app).await; + + client.get(api_url).header(key, header).send().await +} + +pub async fn auth_header( + app: &crate::config::App, +) -> (reqwest::header::HeaderName, reqwest::header::HeaderValue) { + let bearer = format!("Bearer {}", app.token.token); + let header_value = reqwest::header::HeaderValue::from_str(&bearer).unwrap(); + (reqwest::header::AUTHORIZATION, header_value) } pub mod parsing { @@ -27,27 +39,30 @@ pub mod parsing { pub mod fetch_song_queue_data { pub async fn get_data( - base_url: &String, + app: &crate::config::App, id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::new(); let endpoint = String::from("api/v2/song/queue"); - let api_url = format!("{base_url}/{endpoint}/{id}"); - client.get(api_url).send().await + let api_url = format!("{}/{endpoint}/{id}", app.uri); + let (key, header) = super::auth_header(app).await; + client.get(api_url).header(key, header).send().await } } pub mod get_metadata_queue { pub async fn get( - base_url: &String, + app: &crate::config::App, song_queue_id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::new(); let endpoint = String::from("api/v2/song/metadata/queue"); - let api_url = format!("{base_url}/{endpoint}"); + let api_url = format!("{}/{endpoint}", app.uri); + let (key, header) = super::auth_header(app).await; client .get(api_url) .query(&[("song_queue_id", song_queue_id)]) + .header(key, header) .send() .await } @@ -90,27 +105,30 @@ pub mod get_metadata_queue { pub mod get_coverart_queue { pub async fn get( - base_url: &String, + app: &crate::config::App, song_queue_id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::new(); let endpoint = String::from("api/v2/coverart/queue"); - let api_url = format!("{base_url}/{endpoint}"); + let api_url = format!("{}/{endpoint}", app.uri); + let (key, header) = super::auth_header(app).await; client .get(api_url) .query(&[("song_queue_id", song_queue_id)]) + .header(key, header) .send() .await } pub async fn get_data( - base_url: &String, + app: &crate::config::App, coverart_queue_id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::new(); let endpoint = String::from("api/v2/coverart/queue/data"); - let api_url = format!("{base_url}/{endpoint}/{coverart_queue_id}"); - client.get(api_url).send().await + let api_url = format!("{}/{endpoint}/{coverart_queue_id}", app.uri); + let (key, header) = super::auth_header(app).await; + client.get(api_url).header(key, header).send().await } pub mod response { @@ -129,3 +147,23 @@ pub mod get_coverart_queue { } } } + +pub mod service_token { + pub mod response { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec, + } + } +} + +pub mod refresh_token { + pub mod response { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec, + } + } +} diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..8f07e8c --- /dev/null +++ b/src/config.rs @@ -0,0 +1,6 @@ +#[derive(Default, Debug)] +pub struct App { + pub uri: String, + pub auth_uri: String, + pub token: icarus_models::login_result::LoginResult, +} diff --git a/src/main.rs b/src/main.rs index aa85b54..86b306c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ pub mod api; +pub mod config; pub mod responses; pub mod the_rest; pub mod update_queued_song; @@ -10,33 +11,61 @@ pub const SECONDS_TO_SLEEP: u64 = 5; #[tokio::main] async fn main() -> Result<(), Box> { - let app_base_url = icarus_envy::environment::get_icarus_base_api_url().await; + let mut app = config::App { + uri: icarus_envy::environment::get_icarus_base_api_url().await, + auth_uri: icarus_envy::environment::get_icarus_auth_base_api_url().await, + ..Default::default() + }; + match auth::get_token(&app).await { + Ok(login_result) => { + app.token = login_result; + } + Err(err) => { + eprintln!("Error: {err:?}"); + std::process::exit(-1); + } + }; loop { - println!("Base URL: {app_base_url}"); + println!("Base URL: {:?}", app.uri); + println!("Auth URL: {:?}", app.auth_uri); + println!("Token: {:?}", app.token); - match is_queue_empty(&app_base_url).await { + if auth::did_token_expire(&app.token).await { + println!("Token expired"); + app.token = match auth::get_refresh_token(&app).await { + Ok(login_result) => login_result, + Err(err) => { + eprintln!("Error: {err:?}"); + continue; + } + }; + + println!("Token refreshed"); + println!("Refreshed token: {:?}", app.token); + } else { + println!("Token did not expire"); + } + + match is_queue_empty(&app).await { Ok((empty, song_queue_item)) => { if !empty { println!("Queue is not empty"); println!("SongQueueItem: {song_queue_item:?}"); + let song_queue_id = song_queue_item.data[0].id; let user_id = song_queue_item.data[0].user_id; // TODO: Do something with the result later - match some_work(&app_base_url, &song_queue_id, &user_id).await { + match some_work(&app, &song_queue_id, &user_id).await { Ok(( _song, _coverart, (song_queue_id, song_queue_path), (coverart_queue_id, coverart_queue_path), )) => { - match wipe_data_from_queues( - &app_base_url, - &song_queue_id, - &coverart_queue_id, - ) - .await + match wipe_data_from_queues(&app, &song_queue_id, &coverart_queue_id) + .await { Ok(_) => { match cleanup(&song_queue_path, &coverart_queue_path).await { @@ -71,35 +100,100 @@ async fn main() -> Result<(), Box> { } } +mod auth { + pub async fn get_token( + app: &crate::config::App, + ) -> Result { + let client = reqwest::Client::new(); + let endpoint = String::from("api/v2/service/login"); + let api_url = format!("{}/{endpoint}", app.auth_uri); + + let payload = serde_json::json!({ + "passphrase": icarus_envy::environment::get_service_passphrase().await, + }); + + match client.post(api_url).json(&payload).send().await { + Ok(response) => match response + .json::() + .await + { + Ok(resp) => { + if resp.data.is_empty() { + Err(std::io::Error::other(String::from("No token returned"))) + } else { + Ok(resp.data[0].clone()) + } + } + Err(err) => Err(std::io::Error::other(err.to_string())), + }, + Err(err) => Err(std::io::Error::other(err.to_string())), + } + } + + // TODO: Might want to put the functionality within icarus_models at some point + pub async fn did_token_expire(login_result: &icarus_models::login_result::LoginResult) -> bool { + let current_time = time::OffsetDateTime::now_utc(); + let expire_time = + time::OffsetDateTime::from_unix_timestamp(login_result.expiration).unwrap(); + current_time > expire_time + } + + pub async fn get_refresh_token( + app: &crate::config::App, + ) -> Result { + let client = reqwest::Client::new(); + let endpoint = String::from("api/v2/token/refresh"); + let api_url = format!("{}/{endpoint}", app.auth_uri); + + let payload = serde_json::json!({ + "access_token": app.token.token + }); + + match client.post(api_url).json(&payload).send().await { + Ok(response) => match response + .json::() + .await + { + Ok(resp) => { + if resp.data.is_empty() { + Err(std::io::Error::other(String::from("No token returned"))) + } else { + Ok(resp.data[0].clone()) + } + } + Err(err) => Err(std::io::Error::other(err.to_string())), + }, + Err(err) => Err(std::io::Error::other(err.to_string())), + } + } +} + async fn wipe_data_from_queues( - app_base_url: &String, + app: &config::App, song_queue_id: &uuid::Uuid, coverart_queue_id: &uuid::Uuid, ) -> Result<(), std::io::Error> { - match the_rest::wipe_data::song_queue::wipe_data(app_base_url, song_queue_id).await { + match the_rest::wipe_data::song_queue::wipe_data(app, song_queue_id).await { Ok(response) => match response .json::() .await { - Ok(_resp) => match the_rest::wipe_data::coverart_queue::wipe_data( - app_base_url, - coverart_queue_id, - ) - .await - { - Ok(inner_response) => match inner_response - .json::() - .await - { - Ok(_inner_resp) => { - println!("Wiped data from CoverArt queue"); - println!("Resp: {_inner_resp:?}"); - Ok(()) - } + Ok(_resp) => { + match the_rest::wipe_data::coverart_queue::wipe_data(app, coverart_queue_id).await { + Ok(inner_response) => match inner_response + .json::() + .await + { + Ok(_inner_resp) => { + println!("Wiped data from CoverArt queue"); + println!("Resp: {_inner_resp:?}"); + Ok(()) + } + Err(err) => Err(std::io::Error::other(err.to_string())), + }, Err(err) => Err(std::io::Error::other(err.to_string())), - }, - Err(err) => Err(std::io::Error::other(err.to_string())), - }, + } + } Err(err) => Err(std::io::Error::other(err.to_string())), }, Err(err) => Err(std::io::Error::other(err.to_string())), @@ -124,9 +218,9 @@ async fn cleanup( } async fn is_queue_empty( - api_url: &String, + app: &config::App, ) -> Result<(bool, responses::fetch_next_queue_item::SongQueueItem), reqwest::Error> { - match api::fetch_next_queue_item(api_url).await { + match api::fetch_next_queue_item(app).await { Ok(response) => { match response .json::() @@ -147,7 +241,7 @@ async fn is_queue_empty( } async fn some_work( - app_base_url: &String, + app: &crate::config::App, song_queue_id: &uuid::Uuid, user_id: &uuid::Uuid, ) -> Result< @@ -159,12 +253,12 @@ async fn some_work( ), std::io::Error, > { - match prep_song(app_base_url, song_queue_id).await { + match prep_song(app, song_queue_id).await { Ok((song_queue_path, coverart_queue_path, metadata, coverart_queue_id)) => { match apply_metadata(&song_queue_path, &coverart_queue_path, &metadata).await { Ok(_applied) => { match update_queued_song::update_queued_song( - app_base_url, + app, &song_queue_path, song_queue_id, ) @@ -182,10 +276,7 @@ async fn some_work( let song_type = String::from("flac"); match the_rest::create_song::create( - app_base_url, - &metadata, - user_id, - &song_type, + app, &metadata, user_id, &song_type, ) .await { @@ -197,7 +288,7 @@ async fn some_work( println!("Response: {resp:?}"); let song = &resp.data[0]; - match the_rest::create_coverart::create(app_base_url, &song.id, &coverart_queue_id).await { + match the_rest::create_coverart::create(app, &song.id, &coverart_queue_id).await { Ok(response) => match response.json::().await { Ok(resp) => { println!("CoverArt sent and successfully parsed response"); @@ -233,7 +324,7 @@ async fn some_work( } async fn prep_song( - api_url: &String, + app: &crate::config::App, song_queue_id: &uuid::Uuid, ) -> Result< ( @@ -244,7 +335,7 @@ async fn prep_song( ), reqwest::Error, > { - match api::fetch_song_queue_data::get_data(api_url, song_queue_id).await { + match api::fetch_song_queue_data::get_data(app, song_queue_id).await { Ok(response) => { // Process data here... match api::parsing::parse_response_into_bytes(response).await { @@ -254,7 +345,7 @@ async fn prep_song( println!("Saved at: {song_queue_path:?}"); - match api::get_metadata_queue::get(api_url, song_queue_id).await { + match api::get_metadata_queue::get(app, song_queue_id).await { Ok(response) => { match response .json::() @@ -269,15 +360,14 @@ async fn prep_song( println!("Created at: {created_at:?}"); println!("Getting coverart queue"); - match api::get_coverart_queue::get(api_url, song_queue_id).await - { + match api::get_coverart_queue::get(app, song_queue_id).await { Ok(response) => { match response.json::().await { Ok(response) => { let coverart_queue_id = &response.data[0].id; println!("Coverart queue Id: {coverart_queue_id:?}"); - match api::get_coverart_queue::get_data(api_url, coverart_queue_id).await { + match api::get_coverart_queue::get_data(app, coverart_queue_id).await { Ok(response) => match api::parsing::parse_response_into_bytes(response).await { Ok(coverart_queue_bytes) => { let (directory, filename) = generate_coverart_queue_dir_and_filename().await; diff --git a/src/the_rest.rs b/src/the_rest.rs index dbf85fb..08aeb4b 100644 --- a/src/the_rest.rs +++ b/src/the_rest.rs @@ -2,7 +2,7 @@ pub mod create_song { pub async fn create( - base_url: &String, + app: &crate::config::App, metadata_queue: &crate::api::get_metadata_queue::response::Metadata, user_id: &uuid::Uuid, song_type: &String, @@ -28,9 +28,10 @@ pub mod create_song { let client = reqwest::Client::builder().build()?; - let url = format!("{base_url}/api/v2/song"); + let url = format!("{}/api/v2/song", app.uri); + let (key, header) = crate::api::auth_header(app).await; - let request = client.post(url).json(&payload); + let request = client.post(url).json(&payload).header(key, header); request.send().await } @@ -46,14 +47,15 @@ pub mod create_song { pub mod create_coverart { pub async fn create( - base_url: &String, + app: &crate::config::App, song_id: &uuid::Uuid, coverart_queue_id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::builder().build()?; - let url = format!("{base_url}/api/v2/coverart"); + let url = format!("{}/api/v2/coverart", app.uri); let payload = get_payload(song_id, coverart_queue_id); - let request = client.post(url).json(&payload); + let (key, header) = crate::api::auth_header(app).await; + let request = client.post(url).json(&payload).header(key, header); request.send().await } @@ -77,15 +79,16 @@ pub mod create_coverart { pub mod wipe_data { pub mod song_queue { pub async fn wipe_data( - base_url: &String, + app: &crate::config::App, song_queue_id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::builder().build()?; - let url = format!("{base_url}/api/v2/song/queue/data/wipe"); + let url = format!("{}/api/v2/song/queue/data/wipe", app.uri); let payload = serde_json::json!({ "song_queue_id": song_queue_id }); - let request = client.patch(url).json(&payload); + let (key, header) = crate::api::auth_header(app).await; + let request = client.patch(url).json(&payload).header(key, header); request.send().await } @@ -100,15 +103,16 @@ pub mod wipe_data { } pub mod coverart_queue { pub async fn wipe_data( - base_url: &String, + app: &crate::config::App, coverart_queue_id: &uuid::Uuid, ) -> Result { let client = reqwest::Client::builder().build()?; - let url = format!("{base_url}/api/v2/coverart/queue/data/wipe"); + let url = format!("{}/api/v2/coverart/queue/data/wipe", app.uri); let payload = serde_json::json!({ "coverart_queue_id": coverart_queue_id }); - let request = client.patch(url).json(&payload); + let (key, header) = crate::api::auth_header(app).await; + let request = client.patch(url).json(&payload).header(key, header); request.send().await } diff --git a/src/update_queued_song.rs b/src/update_queued_song.rs index b7f3322..7a95dac 100644 --- a/src/update_queued_song.rs +++ b/src/update_queued_song.rs @@ -1,5 +1,5 @@ pub async fn update_queued_song( - base_url: &String, + app: &crate::config::App, song_path: &String, song_queue_id: &uuid::Uuid, ) -> Result { @@ -14,10 +14,11 @@ pub async fn update_queued_song( .file_name("track01.flac"), ); - let url = format!("{base_url}/api/v2/song/queue/{song_queue_id}"); + let url = format!("{}/api/v2/song/queue/{song_queue_id}", app.uri); println!("Url: {url:?}"); - let request = client.patch(url).multipart(form); + let (key, header) = crate::api::auth_header(app).await; + let request = client.patch(url).multipart(form).header(key, header); let response = request.send().await?;