Added code
This commit is contained in:
+160
-1
@@ -122,10 +122,36 @@ mod song_queue {
|
|||||||
Err(_err) => Err(sqlx::Error::RowNotFound),
|
Err(_err) => Err(sqlx::Error::RowNotFound),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_data(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result<Vec<u8>, sqlx::Error> {
|
||||||
|
let result = sqlx::query(
|
||||||
|
r#"
|
||||||
|
SELECT data FROM "songQueue"
|
||||||
|
WHERE id = $1;
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Error inserting: {}", e);
|
||||||
|
});
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(row) => {
|
||||||
|
let data = row
|
||||||
|
.try_get("data")
|
||||||
|
.map_err(|_e| sqlx::Error::RowNotFound)
|
||||||
|
.unwrap();
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
Err(_err) => Err(sqlx::Error::RowNotFound),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod endpoint {
|
pub mod endpoint {
|
||||||
use axum::{Json, http::StatusCode};
|
use axum::{Json, http::StatusCode, response::IntoResponse};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use crate::callers::song::song_queue;
|
use crate::callers::song::song_queue;
|
||||||
@@ -197,4 +223,137 @@ pub mod endpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
use axum::{
|
||||||
|
response::{Response, IntoResponse},
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
extract::Path,
|
||||||
|
http::{header, StatusCode, Uri},
|
||||||
|
};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use tokio::fs::File;
|
||||||
|
use tokio_util::io::ReaderStream;
|
||||||
|
use mime_guess::from_path;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
// Configuration constants
|
||||||
|
const MEDIA_DIRECTORY: &str = "./media";
|
||||||
|
const ALLOWED_EXTENSION: &str = "flac";
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub async fn download_flac(
|
||||||
|
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||||
|
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>) -> (StatusCode, axum::response::Response) {
|
||||||
|
pritnln!("Id: {:?}", id);
|
||||||
|
|
||||||
|
match song_queue::get_data(&pool, &id).await {
|
||||||
|
Ok(data) => {
|
||||||
|
let by = axum::body::Bytes::from(data);
|
||||||
|
/*
|
||||||
|
match axum::response::Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.header(
|
||||||
|
axum::http::header::CONTENT_TYPE,
|
||||||
|
"audio/flac",
|
||||||
|
)
|
||||||
|
.header(
|
||||||
|
axum::http::header::CONTENT_DISPOSITION,
|
||||||
|
format!("attachment; filename=\"{}.flac\"", id),
|
||||||
|
)
|
||||||
|
.header(axum::http::header::CONTENT_LENGTH, by.len())
|
||||||
|
.body(by) {
|
||||||
|
Ok(resp) => {
|
||||||
|
(StatusCode::OK, resp)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
let mut response = by.into_response();
|
||||||
|
let headers = response.headers_mut();
|
||||||
|
headers.insert(
|
||||||
|
axum::http::header::CONTENT_TYPE,
|
||||||
|
"audio/flac".parse().unwrap(),
|
||||||
|
);
|
||||||
|
headers.insert(
|
||||||
|
axum::http::header::CONTENT_DISPOSITION,
|
||||||
|
format!("attachment; filename=\"{}.flac\"", id).parse().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
(StatusCode::OK, response)
|
||||||
|
}
|
||||||
|
Err(_err) => {
|
||||||
|
(StatusCode::BAD_REQUEST, axum::response::Response::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Construct the file path
|
||||||
|
/*
|
||||||
|
let file_name = format!("{}.{}", id, ALLOWED_EXTENSION);
|
||||||
|
let file_path = PathBuf::from(MEDIA_DIRECTORY).join(&file_name);
|
||||||
|
|
||||||
|
// Security check: prevent path traversal
|
||||||
|
if !file_path.starts_with(MEDIA_DIRECTORY) {
|
||||||
|
return Err((
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"Invalid file path".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file metadata
|
||||||
|
let metadata = match tokio::fs::metadata(&file_path).await {
|
||||||
|
Ok(meta) => meta,
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||||
|
return Err((
|
||||||
|
StatusCode::NOT_FOUND,
|
||||||
|
"File not found".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("Failed to read file: {}", err),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify this is a FLAC file (extension check)
|
||||||
|
if file_path.extension().map(|ext| ext != ALLOWED_EXTENSION).unwrap_or(true) {
|
||||||
|
return Err((
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"Invalid file type".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file
|
||||||
|
let file = match File::open(&file_path).await {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(err) => {
|
||||||
|
return Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("Failed to open file: {}", err),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create stream from file
|
||||||
|
let stream = ReaderStream::new(file);
|
||||||
|
|
||||||
|
// Build response
|
||||||
|
axum::response::Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.header(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
"audio/flac", // Specific MIME type for FLAC
|
||||||
|
)
|
||||||
|
.header(
|
||||||
|
header::CONTENT_DISPOSITION,
|
||||||
|
format!("attachment; filename=\"{}\"", file_name),
|
||||||
|
)
|
||||||
|
.header(header::CONTENT_LENGTH, metadata.len())
|
||||||
|
.body(axum::body::Body::from_stream(stream))
|
||||||
|
.unwrap())
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ pub mod init {
|
|||||||
crate::callers::endpoints::QUEUESONG,
|
crate::callers::endpoints::QUEUESONG,
|
||||||
post(crate::callers::song::endpoint::queue_song),
|
post(crate::callers::song::endpoint::queue_song),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
crate::callers::endpoints::QUEUESONG,
|
||||||
|
get(crate::callers::song::endpoint::download_flac),
|
||||||
|
)
|
||||||
.route(
|
.route(
|
||||||
crate::callers::endpoints::NEXTQUEUESONG,
|
crate::callers::endpoints::NEXTQUEUESONG,
|
||||||
get(crate::callers::song::endpoint::fetch_queue_song),
|
get(crate::callers::song::endpoint::fetch_queue_song),
|
||||||
|
|||||||
Reference in New Issue
Block a user