use std::str::FromStr;
use serde::{Deserialize, Serialize};
use crate::{REQWEST_CLIENT, library::track::lyric_data::PlainLyrics, synced_lyrics::SyncedLyrics};
const LRCLIB_SEARCH_ORIGIN: &str = "https://lrclib.net/api/search";
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SearchRecord {
pub id: u64,
pub name: String,
pub track_name: String,
pub artist_name: String,
pub album_name: String,
pub duration: Option<f64>,
pub instrumental: bool,
pub plain_lyrics: Option<String>,
pub synced_lyrics: Option<String>,
}
#[derive(Serialize)]
pub struct SearchQuery<'a> {
#[serde(rename = "track_name")]
track_title: &'a str,
#[serde(rename = "artist_name", skip_serializing_if = "Option::is_none")]
main_artist: Option<&'a str>,
#[serde(rename = "album_name", skip_serializing_if = "Option::is_none")]
album_title: Option<&'a str>,
}
impl<'a> SearchQuery<'a> {
pub fn new(track_title: &'a str) -> Self {
Self {
track_title,
main_artist: None,
album_title: None,
}
}
pub fn main_artist(mut self, artist: Option<&'a str>) -> Self {
self.main_artist = artist;
self
}
pub fn album_title(mut self, title: Option<&'a str>) -> Self {
self.album_title = title;
self
}
pub fn run(self) -> Result<Vec<SearchRecord>, reqwest::Error> {
let response = REQWEST_CLIENT
.get(LRCLIB_SEARCH_ORIGIN)
.query(&self)
.send()?;
response.json()
}
}
impl SearchRecord {
pub fn is_instrumental(&self) -> bool {
self.instrumental
}
pub fn plain_lyrics(&self) -> Option<PlainLyrics> {
self.plain_lyrics
.as_deref()
.map(|lyrics| PlainLyrics::from_str(lyrics).unwrap())
}
pub fn synced_lyrics(&self) -> Option<SyncedLyrics> {
self.synced_lyrics
.as_deref()
.and_then(|lyrics| SyncedLyrics::from_synced_lyrics(lyrics).ok())
}
}