Files
allstarr/allstarr/Models/Domain/Song.cs
Josh Patra 565cb46b72 feat: add proper multi-artist support with ArtistIds list
- Add ArtistIds list to Song model to store IDs for all artists
- Update SquidWTF ParseTidalTrack and ParseTidalTrackFull to populate ArtistIds from artists array
- Update Deezer ParseDeezerTrackFull to populate ArtistIds from contributors
- Update JellyfinResponseBuilder to use real ArtistIds instead of fake IDs
- Fixes UnprocessableEntity errors when clicking on secondary artists
- Enables proper navigation to all artist pages in Jellyfin clients
2026-02-09 12:22:40 -05:00

120 lines
3.5 KiB
C#

namespace allstarr.Models.Domain;
/// <summary>
/// Represents a song (local or external)
/// </summary>
public class Song
{
/// <summary>
/// Unique ID. For external songs, prefixed with "ext-" + provider + "-" + external id
/// Example: "ext-deezer-123456" or "local-789"
/// </summary>
public string Id { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string Artist { get; set; } = string.Empty;
public string? ArtistId { get; set; }
/// <summary>
/// All artists for this track (main + featured). For display in Jellyfin clients.
/// </summary>
public List<string> Artists { get; set; } = new();
/// <summary>
/// All artist IDs corresponding to the Artists list. Index-matched with Artists.
/// </summary>
public List<string> ArtistIds { get; set; } = new();
public string Album { get; set; } = string.Empty;
public string? AlbumId { get; set; }
public int? Duration { get; set; } // In seconds
public int? Track { get; set; }
public int? DiscNumber { get; set; }
public int? TotalTracks { get; set; }
public int? Year { get; set; }
public string? Genre { get; set; }
public string? CoverArtUrl { get; set; }
/// <summary>
/// High-resolution cover art URL (for embedding)
/// </summary>
public string? CoverArtUrlLarge { get; set; }
/// <summary>
/// BPM (beats per minute) if available
/// </summary>
public int? Bpm { get; set; }
/// <summary>
/// ISRC (International Standard Recording Code)
/// </summary>
public string? Isrc { get; set; }
/// <summary>
/// Spotify track ID (for lyrics and matching)
/// </summary>
public string? SpotifyId { get; set; }
/// <summary>
/// Full release date (format: YYYY-MM-DD)
/// </summary>
public string? ReleaseDate { get; set; }
/// <summary>
/// Album artist name (may differ from track artist)
/// </summary>
public string? AlbumArtist { get; set; }
/// <summary>
/// Composer(s)
/// </summary>
public string? Composer { get; set; }
/// <summary>
/// Album label
/// </summary>
public string? Label { get; set; }
/// <summary>
/// Copyright
/// </summary>
public string? Copyright { get; set; }
/// <summary>
/// Contributing artists (features, etc.)
/// </summary>
public List<string> Contributors { get; set; } = new();
/// <summary>
/// Indicates whether the song is available locally or needs to be downloaded
/// </summary>
public bool IsLocal { get; set; }
/// <summary>
/// External provider (deezer, spotify, etc.) - null if local
/// </summary>
public string? ExternalProvider { get; set; }
/// <summary>
/// ID on the external provider (for downloading)
/// </summary>
public string? ExternalId { get; set; }
/// <summary>
/// Local file path (if available)
/// </summary>
public string? LocalPath { get; set; }
/// <summary>
/// Deezer explicit content lyrics value
/// 0 = Naturally clean, 1 = Explicit, 2 = Not applicable, 3 = Clean/edited version, 6/7 = Unknown
/// </summary>
public int? ExplicitContentLyrics { get; set; }
/// <summary>
/// Raw Jellyfin metadata (MediaSources, etc.) for local tracks
/// Preserved to maintain bitrate and other technical details
/// </summary>
public Dictionary<string, object?>? JellyfinMetadata { get; set; }
}