394 lines
9.5 KiB
Rust
394 lines
9.5 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
// --- Auth ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct UserInfo {
|
|
pub id: i32,
|
|
pub username: String,
|
|
pub role: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct SetupRequired {
|
|
pub required: bool,
|
|
}
|
|
|
|
// --- Library entities ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
|
pub struct Artist {
|
|
pub id: i32,
|
|
pub name: String,
|
|
pub musicbrainz_id: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct ArtistListItem {
|
|
pub id: i32,
|
|
pub name: String,
|
|
pub musicbrainz_id: Option<String>,
|
|
pub total_watched: usize,
|
|
pub total_owned: usize,
|
|
pub total_items: usize,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct FullAlbumInfo {
|
|
pub mbid: String,
|
|
pub title: String,
|
|
pub release_type: Option<String>,
|
|
pub date: Option<String>,
|
|
pub track_count: u32,
|
|
pub local_album_id: Option<i32>,
|
|
pub watched_tracks: u32,
|
|
pub downloaded_tracks: u32,
|
|
pub owned_tracks: u32,
|
|
pub total_local_tracks: u32,
|
|
pub status: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct FullArtistDetail {
|
|
pub artist: Artist,
|
|
pub albums: Vec<FullAlbumInfo>,
|
|
pub artist_status: String,
|
|
#[serde(default)]
|
|
pub total_available_tracks: u32,
|
|
#[serde(default)]
|
|
pub total_watched_tracks: u32,
|
|
#[serde(default)]
|
|
pub total_owned_tracks: u32,
|
|
#[serde(default)]
|
|
pub enriched: bool,
|
|
#[serde(default)]
|
|
pub artist_info: Option<ArtistInfoFe>,
|
|
#[serde(default)]
|
|
pub artist_photo: Option<String>,
|
|
#[serde(default)]
|
|
pub artist_bio: Option<String>,
|
|
#[serde(default)]
|
|
pub artist_banner: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
|
pub struct ArtistInfoFe {
|
|
pub name: String,
|
|
#[serde(default)]
|
|
pub disambiguation: Option<String>,
|
|
#[serde(default)]
|
|
pub country: Option<String>,
|
|
#[serde(default)]
|
|
pub artist_type: Option<String>,
|
|
#[serde(default)]
|
|
pub begin_year: Option<String>,
|
|
#[serde(default)]
|
|
pub urls: Vec<ArtistUrlFe>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
|
pub struct ArtistUrlFe {
|
|
pub url: String,
|
|
pub link_type: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct LyricsResult {
|
|
pub found: bool,
|
|
pub lyrics: Option<String>,
|
|
pub synced_lyrics: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
|
pub struct Track {
|
|
pub id: i32,
|
|
pub file_path: String,
|
|
pub title: Option<String>,
|
|
pub artist: Option<String>,
|
|
pub album: Option<String>,
|
|
pub track_number: Option<i32>,
|
|
pub year: Option<i32>,
|
|
pub genre: Option<String>,
|
|
pub codec: Option<String>,
|
|
}
|
|
|
|
/// Album detail from MusicBrainz (the primary album view).
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct MbAlbumDetail {
|
|
pub mbid: String,
|
|
pub tracks: Vec<MbAlbumTrack>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct MbAlbumTrack {
|
|
pub recording_mbid: String,
|
|
pub title: String,
|
|
pub track_number: Option<i32>,
|
|
pub disc_number: Option<i32>,
|
|
pub duration_ms: Option<u64>,
|
|
pub status: Option<String>,
|
|
}
|
|
|
|
// --- Search results ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct ArtistResult {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub disambiguation: Option<String>,
|
|
pub country: Option<String>,
|
|
pub artist_type: Option<String>,
|
|
pub score: u8,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct AlbumResult {
|
|
pub id: String,
|
|
pub title: String,
|
|
pub artist: String,
|
|
pub artist_id: Option<String>,
|
|
pub year: Option<String>,
|
|
pub track_count: Option<i32>,
|
|
pub score: u8,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct TrackResult {
|
|
pub id: String,
|
|
pub title: String,
|
|
pub artist: String,
|
|
pub artist_id: Option<String>,
|
|
pub album: Option<String>,
|
|
pub score: u8,
|
|
}
|
|
|
|
// --- YouTube Auth ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct YtAuthStatus {
|
|
pub authenticated: bool,
|
|
pub cookie_age_hours: Option<f64>,
|
|
pub cookie_count: Option<i64>,
|
|
pub refresh_enabled: bool,
|
|
pub login_session_active: bool,
|
|
pub vnc_url: Option<String>,
|
|
#[serde(default)]
|
|
pub ytdlp_version: Option<String>,
|
|
#[serde(default)]
|
|
pub ytdlp_latest: Option<String>,
|
|
#[serde(default)]
|
|
pub ytdlp_update_available: bool,
|
|
#[serde(default)]
|
|
pub lastfm_api_key_set: bool,
|
|
#[serde(default)]
|
|
pub fanart_api_key_set: bool,
|
|
}
|
|
|
|
// --- Downloads ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct DownloadItem {
|
|
pub id: i32,
|
|
pub query: String,
|
|
pub status: String,
|
|
pub source_url: Option<String>,
|
|
pub error_message: Option<String>,
|
|
pub retry_count: i32,
|
|
}
|
|
|
|
// --- Tasks ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct TaskProgress {
|
|
pub current: u64,
|
|
pub total: u64,
|
|
pub message: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct TaskInfo {
|
|
pub id: String,
|
|
pub task_type: String,
|
|
pub status: String,
|
|
pub progress: Option<TaskProgress>,
|
|
pub result: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct TaskRef {
|
|
pub task_id: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct PipelineRef {
|
|
pub task_ids: Vec<String>,
|
|
}
|
|
|
|
// --- Status ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct TaggingStatus {
|
|
pub needs_tagging: usize,
|
|
#[serde(default)]
|
|
pub items: Vec<Track>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct Status {
|
|
pub library: LibrarySummary,
|
|
pub queue: QueueStatus,
|
|
#[serde(default)]
|
|
pub tagging: Option<TaggingStatus>,
|
|
pub tasks: Vec<TaskInfo>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct LibrarySummary {
|
|
pub total_items: u64,
|
|
pub wanted: u64,
|
|
pub available: u64,
|
|
pub downloaded: u64,
|
|
pub owned: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct QueueStatus {
|
|
pub pending: usize,
|
|
pub downloading: usize,
|
|
#[serde(default)]
|
|
pub failed: usize,
|
|
#[serde(default)]
|
|
pub items: Vec<DownloadItem>,
|
|
}
|
|
|
|
// --- API responses ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct AddSummary {
|
|
pub tracks_added: u64,
|
|
pub tracks_already_owned: u64,
|
|
pub errors: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub struct SyncStats {
|
|
pub found: u64,
|
|
pub enqueued: u64,
|
|
pub skipped: u64,
|
|
}
|
|
|
|
// --- Config ---
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub struct AppConfig {
|
|
pub library_path: String,
|
|
pub database_url: String,
|
|
pub download_path: String,
|
|
pub organization_format: String,
|
|
#[serde(default)]
|
|
pub allowed_secondary_types: Vec<String>,
|
|
#[serde(default)]
|
|
pub web: WebConfigFe,
|
|
#[serde(default)]
|
|
pub tagging: TaggingConfigFe,
|
|
#[serde(default)]
|
|
pub download: DownloadConfigFe,
|
|
#[serde(default)]
|
|
pub indexing: IndexingConfigFe,
|
|
#[serde(default)]
|
|
pub metadata: MetadataConfigFe,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
|
pub struct WebConfigFe {
|
|
#[serde(default)]
|
|
pub port: u16,
|
|
#[serde(default)]
|
|
pub bind: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
|
pub struct TaggingConfigFe {
|
|
#[serde(default)]
|
|
pub auto_tag: bool,
|
|
#[serde(default)]
|
|
pub write_tags: bool,
|
|
#[serde(default)]
|
|
pub confidence: f64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
|
pub struct DownloadConfigFe {
|
|
#[serde(default)]
|
|
pub format: String,
|
|
#[serde(default)]
|
|
pub search_source: String,
|
|
#[serde(default)]
|
|
pub cookies_path: Option<String>,
|
|
#[serde(default)]
|
|
pub rate_limit: u32,
|
|
#[serde(default)]
|
|
pub rate_limit_auth: u32,
|
|
#[serde(default)]
|
|
pub cookie_refresh_enabled: bool,
|
|
#[serde(default = "default_cookie_refresh_hours")]
|
|
pub cookie_refresh_hours: u32,
|
|
#[serde(default = "default_vnc_port")]
|
|
pub vnc_port: u16,
|
|
}
|
|
|
|
fn default_cookie_refresh_hours() -> u32 {
|
|
6
|
|
}
|
|
fn default_vnc_port() -> u16 {
|
|
6080
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
|
pub struct IndexingConfigFe {
|
|
#[serde(default)]
|
|
pub concurrency: usize,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub struct MetadataConfigFe {
|
|
#[serde(default = "default_metadata_source")]
|
|
pub metadata_source: String,
|
|
#[serde(default = "default_artist_image_source")]
|
|
pub artist_image_source: String,
|
|
#[serde(default = "default_artist_bio_source")]
|
|
pub artist_bio_source: String,
|
|
#[serde(default = "default_lyrics_source")]
|
|
pub lyrics_source: String,
|
|
#[serde(default = "default_cover_art_source")]
|
|
pub cover_art_source: String,
|
|
}
|
|
|
|
impl Default for MetadataConfigFe {
|
|
fn default() -> Self {
|
|
Self {
|
|
metadata_source: default_metadata_source(),
|
|
artist_image_source: default_artist_image_source(),
|
|
artist_bio_source: default_artist_bio_source(),
|
|
lyrics_source: default_lyrics_source(),
|
|
cover_art_source: default_cover_art_source(),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn default_metadata_source() -> String {
|
|
"musicbrainz".into()
|
|
}
|
|
fn default_artist_image_source() -> String {
|
|
"wikipedia".into()
|
|
}
|
|
fn default_artist_bio_source() -> String {
|
|
"wikipedia".into()
|
|
}
|
|
fn default_lyrics_source() -> String {
|
|
"lrclib".into()
|
|
}
|
|
fn default_cover_art_source() -> String {
|
|
"coverartarchive".into()
|
|
}
|