lyrics
This commit is contained in:
parent
70d45e42a8
commit
d309c5d8c1
3 changed files with 59 additions and 2 deletions
|
@ -1,7 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use sqlx::prelude::FromRow;
|
||||
use std::str::FromStr;
|
||||
use std::{io::Read, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
get_pg,
|
||||
|
@ -325,6 +325,47 @@ impl Track {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn get_lyrics(&self) -> Option<serde_json::Value> {
|
||||
let base_path = std::path::Path::new(&self.path).with_extension("");
|
||||
let extensions = vec!["lrc", "txt"];
|
||||
|
||||
for ext in &extensions {
|
||||
let candidate = base_path.with_extension(ext);
|
||||
if candidate.exists() {
|
||||
if let Ok(mut file) = std::fs::File::open(&candidate) {
|
||||
let mut contents = String::new();
|
||||
if file.read_to_string(&mut contents).is_ok() {
|
||||
// Determine if it's timed lyrics or plain text
|
||||
let lyrics_type = if ext == &"lrc" { "timed" } else { "plain" };
|
||||
|
||||
return Some(json!({
|
||||
"lyrics": contents,
|
||||
"source": "file",
|
||||
"type": lyrics_type
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(lyrics) = self.meta.as_ref()?.get("lyrics").and_then(|l| l.as_str()) {
|
||||
// Check if lyrics seem to be timed or plain text
|
||||
let lyrics_type = if lyrics.contains('[') && lyrics.contains(']') {
|
||||
"timed" // A rough check for LRC-style brackets indicating timing
|
||||
} else {
|
||||
"plain"
|
||||
};
|
||||
|
||||
return Some(json!({
|
||||
"lyrics": lyrics,
|
||||
"type": lyrics_type
|
||||
}));
|
||||
}
|
||||
|
||||
// No lyrics found
|
||||
None
|
||||
}
|
||||
|
||||
/// Finds the first track of a given album.
|
||||
pub async fn find_first_of_album(album: &uuid::Uuid) -> Option<Self> {
|
||||
sqlx::query_as("SELECT * FROM track WHERE album = $1 LIMIT 1")
|
||||
|
|
|
@ -90,7 +90,8 @@ async fn rocket() -> _ {
|
|||
route::admin::get_orphans_route,
|
||||
route::admin::get_singles_route,
|
||||
route::event::event_report_route,
|
||||
route::search::search_route
|
||||
route::search::search_route,
|
||||
route::track::track_lyrics_route
|
||||
],
|
||||
)
|
||||
.manage(lib)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use super::api_error;
|
||||
use super::no_uuid_error;
|
||||
use super::to_uuid;
|
||||
use super::FallibleApiResponse;
|
||||
use super::ToAPI;
|
||||
|
@ -60,3 +61,17 @@ pub async fn track_audio_aac128_route(track_id: &str, lib: &State<Libary>) -> Op
|
|||
.await?;
|
||||
NamedFile::open(track.get_aac(128)?).await.ok()
|
||||
}
|
||||
|
||||
#[get("/track/<track_id>/lyrics")]
|
||||
pub async fn track_lyrics_route(track_id: &str, lib: &State<Libary>) -> FallibleApiResponse {
|
||||
let track = lib
|
||||
.get_track_by_id(&uuid::Uuid::from_str(track_id).map_err(|_| no_uuid_error())?)
|
||||
.await
|
||||
.ok_or_else(|| api_error("No such track"))?;
|
||||
|
||||
if let Some(lyrics) = track.get_lyrics().await {
|
||||
return Ok(lyrics);
|
||||
}
|
||||
|
||||
Ok(json!({}))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue