diff --git a/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs b/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs index b94578c32..7953de12d 100644 --- a/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs +++ b/src/NzbDrone.Core.Test/DataAugmentation/Scene/SceneMappingServiceFixture.cs @@ -9,6 +9,7 @@ using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; using FluentAssertions; using NzbDrone.Common.Extensions; +using NzbDrone.Core.DataAugmentation; namespace NzbDrone.Core.Test.DataAugmentation.Scene { diff --git a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs index 14ec8922d..1afaf456a 100644 --- a/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs +++ b/src/NzbDrone.Core/DataAugmentation/Scene/SceneMappingService.cs @@ -11,243 +11,243 @@ using NzbDrone.Core.Tv.Events; namespace NzbDrone.Core.DataAugmentation.Scene { - //public interface ISceneMappingService - //{ - // List GetSceneNames(int tvdbId, List seasonNumbers, List sceneSeasonNumbers); - // int? FindTvdbId(string title); - // List FindByTvdbId(int tvdbId); - // SceneMapping FindSceneMapping(string title); - // int? GetSceneSeasonNumber(string title); - // int? GetTvdbSeasonNumber(string title); - // int? GetSceneSeasonNumber(int tvdbId, int seasonNumber); - //} - - //public class SceneMappingService : ISceneMappingService, - // IHandle, - // IExecute - //{ - // private readonly ISceneMappingRepository _repository; - // private readonly IEnumerable _sceneMappingProviders; - // private readonly IEventAggregator _eventAggregator; - // private readonly Logger _logger; - // private readonly ICachedDictionary> _getTvdbIdCache; - // private readonly ICachedDictionary> _findByTvdbIdCache; - - //public SceneMappingService(ISceneMappingRepository repository, - // ICacheManager cacheManager, - // IEnumerable sceneMappingProviders, - // IEventAggregator eventAggregator, - // Logger logger) - //{ - // _repository = repository; - // _sceneMappingProviders = sceneMappingProviders; - // _eventAggregator = eventAggregator; - // _logger = logger; - - // _getTvdbIdCache = cacheManager.GetCacheDictionary>(GetType(), "tvdb_id"); - // _findByTvdbIdCache = cacheManager.GetCacheDictionary>(GetType(), "find_tvdb_id"); - //} - - // public List GetSceneNames(int tvdbId, List seasonNumbers, List sceneSeasonNumbers) - // { - // var mappings = FindByTvdbId(tvdbId); - - // if (mappings == null) - // { - // return new List(); - // } - - // var names = mappings.Where(n => n.SeasonNumber.HasValue && seasonNumbers.Contains(n.SeasonNumber.Value) || - // n.SceneSeasonNumber.HasValue && sceneSeasonNumbers.Contains(n.SceneSeasonNumber.Value) || - // (n.SeasonNumber ?? -1) == -1 && (n.SceneSeasonNumber ?? -1) == -1) - // .Select(n => n.SearchTerm).Distinct().ToList(); - - // return FilterNonEnglish(names); - // } - - // public int? FindTvdbId(string title) - // { - // var mapping = FindMapping(title); - - // if (mapping == null) - // return null; - - // return mapping.TvdbId; - // } - - // public List FindByTvdbId(int tvdbId) - // { - // if (_findByTvdbIdCache.Count == 0) - // { - // RefreshCache(); - // } - - // var mappings = _findByTvdbIdCache.Find(tvdbId.ToString()); - - // if (mappings == null) - // { - // return new List(); - // } - - // return mappings; - // } - - // public SceneMapping FindSceneMapping(string title) - // { - // return FindMapping(title); - // } - - // public int? GetSceneSeasonNumber(string title) - // { - // var mapping = FindMapping(title); - - // if (mapping == null) - // { - // return null; - // } - - // return mapping.SceneSeasonNumber; - // } - - // public int? GetTvdbSeasonNumber(string title) - // { - // var mapping = FindMapping(title); - - // if (mapping == null) - // { - // return null; - // } - - // return mapping.SeasonNumber; - // } - - // public int? GetSceneSeasonNumber(int tvdbId, int seasonNumber) - // { - // var mappings = FindByTvdbId(tvdbId); - - // if (mappings == null) - // { - // return null; - // } - - // var mapping = mappings.FirstOrDefault(e => e.SeasonNumber == seasonNumber && e.SceneSeasonNumber.HasValue); - - // if (mapping == null) - // { - // return null; - // } - - // return mapping.SceneSeasonNumber; - // } - - // private void UpdateMappings() - // { - // _logger.Info("Updating Scene mappings"); - - // foreach (var sceneMappingProvider in _sceneMappingProviders) - // { - // try - // { - // var mappings = sceneMappingProvider.GetSceneMappings(); - - // if (mappings.Any()) - // { - // _repository.Clear(sceneMappingProvider.GetType().Name); - - // mappings.RemoveAll(sceneMapping => - // { - // if (sceneMapping.Title.IsNullOrWhiteSpace() || - // sceneMapping.SearchTerm.IsNullOrWhiteSpace()) - // { - // _logger.Warn("Invalid scene mapping found for: {0}, skipping", sceneMapping.TvdbId); - // return true; - // } - - // return false; - // }); - - // foreach (var sceneMapping in mappings) - // { - // sceneMapping.ParseTerm = sceneMapping.Title.CleanSeriesTitle(); - // sceneMapping.Type = sceneMappingProvider.GetType().Name; - // } - - // _repository.InsertMany(mappings.ToList()); - // } - // else - // { - // _logger.Warn("Received empty list of mapping. will not update."); - // } - // } - // catch (Exception ex) - // { - // _logger.Error(ex, "Failed to Update Scene Mappings."); - // } - // } - - // RefreshCache(); - - // _eventAggregator.PublishEvent(new SceneMappingsUpdatedEvent()); - // } - - // private SceneMapping FindMapping(string title) - // { - // if (_getTvdbIdCache.Count == 0) - // { - // RefreshCache(); - // } - - // var candidates = _getTvdbIdCache.Find(title.CleanSeriesTitle()); - - // if (candidates == null) - // { - // return null; - // } - - // if (candidates.Count == 1) - // { - // return candidates.First(); - // } - - // var exactMatch = candidates.OrderByDescending(v => v.SeasonNumber) - // .FirstOrDefault(v => v.Title == title); - - // if (exactMatch != null) - // { - // return exactMatch; - // } - - // var closestMatch = candidates.OrderBy(v => title.LevenshteinDistance(v.Title, 10, 1, 10)) - // .ThenByDescending(v => v.SeasonNumber) - // .First(); - - // return closestMatch; - // } - - // private void RefreshCache() - // { - // var mappings = _repository.All().ToList(); - - // _getTvdbIdCache.Update(mappings.GroupBy(v => v.ParseTerm).ToDictionary(v => v.Key, v => v.ToList())); - // _findByTvdbIdCache.Update(mappings.GroupBy(v => v.TvdbId).ToDictionary(v => v.Key.ToString(), v => v.ToList())); - // } - - // private List FilterNonEnglish(List titles) - // { - // return titles.Where(title => title.All(c => c <= 255)).ToList(); - // } - - // public void Handle(SeriesRefreshStartingEvent message) - // { - // if (message.ManualTrigger && _findByTvdbIdCache.IsExpired(TimeSpan.FromMinutes(1))) - // { - // UpdateMappings(); - // } - // } - - // public void Execute(UpdateSceneMappingCommand message) - // { - // UpdateMappings(); - // } - //} + public interface ISceneMappingService + { + List GetSceneNames(int tvdbId, List seasonNumbers, List sceneSeasonNumbers); + int? FindTvdbId(string title); + List FindByTvdbId(int tvdbId); + SceneMapping FindSceneMapping(string title); + int? GetSceneSeasonNumber(string title); + int? GetTvdbSeasonNumber(string title); + int? GetSceneSeasonNumber(int tvdbId, int seasonNumber); + } + + public class SceneMappingService : ISceneMappingService, + IHandle, + IExecute + { + private readonly ISceneMappingRepository _repository; + private readonly IEnumerable _sceneMappingProviders; + private readonly IEventAggregator _eventAggregator; + private readonly Logger _logger; + private readonly ICachedDictionary> _getTvdbIdCache; + private readonly ICachedDictionary> _findByTvdbIdCache; + + public SceneMappingService(ISceneMappingRepository repository, + ICacheManager cacheManager, + IEnumerable sceneMappingProviders, + IEventAggregator eventAggregator, + Logger logger) + { + _repository = repository; + _sceneMappingProviders = sceneMappingProviders; + _eventAggregator = eventAggregator; + _logger = logger; + + _getTvdbIdCache = cacheManager.GetCacheDictionary>(GetType(), "tvdb_id"); + _findByTvdbIdCache = cacheManager.GetCacheDictionary>(GetType(), "find_tvdb_id"); + } + + public List GetSceneNames(int tvdbId, List seasonNumbers, List sceneSeasonNumbers) + { + var mappings = FindByTvdbId(tvdbId); + + if (mappings == null) + { + return new List(); + } + + var names = mappings.Where(n => n.SeasonNumber.HasValue && seasonNumbers.Contains(n.SeasonNumber.Value) || + n.SceneSeasonNumber.HasValue && sceneSeasonNumbers.Contains(n.SceneSeasonNumber.Value) || + (n.SeasonNumber ?? -1) == -1 && (n.SceneSeasonNumber ?? -1) == -1) + .Select(n => n.SearchTerm).Distinct().ToList(); + + return FilterNonEnglish(names); + } + + public int? FindTvdbId(string title) + { + var mapping = FindMapping(title); + + if (mapping == null) + return null; + + return mapping.TvdbId; + } + + public List FindByTvdbId(int tvdbId) + { + if (_findByTvdbIdCache.Count == 0) + { + RefreshCache(); + } + + var mappings = _findByTvdbIdCache.Find(tvdbId.ToString()); + + if (mappings == null) + { + return new List(); + } + + return mappings; + } + + public SceneMapping FindSceneMapping(string title) + { + return FindMapping(title); + } + + public int? GetSceneSeasonNumber(string title) + { + var mapping = FindMapping(title); + + if (mapping == null) + { + return null; + } + + return mapping.SceneSeasonNumber; + } + + public int? GetTvdbSeasonNumber(string title) + { + var mapping = FindMapping(title); + + if (mapping == null) + { + return null; + } + + return mapping.SeasonNumber; + } + + public int? GetSceneSeasonNumber(int tvdbId, int seasonNumber) + { + var mappings = FindByTvdbId(tvdbId); + + if (mappings == null) + { + return null; + } + + var mapping = mappings.FirstOrDefault(e => e.SeasonNumber == seasonNumber && e.SceneSeasonNumber.HasValue); + + if (mapping == null) + { + return null; + } + + return mapping.SceneSeasonNumber; + } + + private void UpdateMappings() + { + _logger.Info("Updating Scene mappings"); + + foreach (var sceneMappingProvider in _sceneMappingProviders) + { + try + { + var mappings = sceneMappingProvider.GetSceneMappings(); + + if (mappings.Any()) + { + _repository.Clear(sceneMappingProvider.GetType().Name); + + mappings.RemoveAll(sceneMapping => + { + if (sceneMapping.Title.IsNullOrWhiteSpace() || + sceneMapping.SearchTerm.IsNullOrWhiteSpace()) + { + _logger.Warn("Invalid scene mapping found for: {0}, skipping", sceneMapping.TvdbId); + return true; + } + + return false; + }); + + foreach (var sceneMapping in mappings) + { + sceneMapping.ParseTerm = sceneMapping.Title.CleanSeriesTitle(); + sceneMapping.Type = sceneMappingProvider.GetType().Name; + } + + _repository.InsertMany(mappings.ToList()); + } + else + { + _logger.Warn("Received empty list of mapping. will not update."); + } + } + catch (Exception ex) + { + _logger.Error(ex, "Failed to Update Scene Mappings."); + } + } + + RefreshCache(); + + _eventAggregator.PublishEvent(new SceneMappingsUpdatedEvent()); + } + + private SceneMapping FindMapping(string title) + { + if (_getTvdbIdCache.Count == 0) + { + RefreshCache(); + } + + var candidates = _getTvdbIdCache.Find(title.CleanSeriesTitle()); + + if (candidates == null) + { + return null; + } + + if (candidates.Count == 1) + { + return candidates.First(); + } + + var exactMatch = candidates.OrderByDescending(v => v.SeasonNumber) + .FirstOrDefault(v => v.Title == title); + + if (exactMatch != null) + { + return exactMatch; + } + + var closestMatch = candidates.OrderBy(v => title.LevenshteinDistance(v.Title, 10, 1, 10)) + .ThenByDescending(v => v.SeasonNumber) + .First(); + + return closestMatch; + } + + private void RefreshCache() + { + var mappings = _repository.All().ToList(); + + _getTvdbIdCache.Update(mappings.GroupBy(v => v.ParseTerm).ToDictionary(v => v.Key, v => v.ToList())); + _findByTvdbIdCache.Update(mappings.GroupBy(v => v.TvdbId).ToDictionary(v => v.Key.ToString(), v => v.ToList())); + } + + private List FilterNonEnglish(List titles) + { + return titles.Where(title => title.All(c => c <= 255)).ToList(); + } + + public void Handle(SeriesRefreshStartingEvent message) + { + if (message.ManualTrigger && _findByTvdbIdCache.IsExpired(TimeSpan.FromMinutes(1))) + { + UpdateMappings(); + } + } + + public void Execute(UpdateSceneMappingCommand message) + { + UpdateMappings(); + } + } } diff --git a/src/NzbDrone.Core/Datastore/Migration/111_setup_music.cs b/src/NzbDrone.Core/Datastore/Migration/111_setup_music.cs new file mode 100644 index 000000000..7fe64acfe --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/111_setup_music.cs @@ -0,0 +1,75 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(111)] + public class setup_music : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Create.TableForModel("Artists") + .WithColumn("ItunesId").AsInt32().Unique() + .WithColumn("ArtistName").AsString().Unique() + .WithColumn("ArtistSlug").AsString().Unique() + .WithColumn("CleanTitle").AsString() + .WithColumn("Monitored").AsBoolean() + .WithColumn("LastInfoSync").AsDateTime().Nullable() + .WithColumn("LastDiskSync").AsDateTime().Nullable() + .WithColumn("Overview").AsString() + .WithColumn("Status").AsInt32() + .WithColumn("Path").AsString() + .WithColumn("Images").AsString() + .WithColumn("QualityProfileId").AsInt32() + .WithColumn("AirTime").AsString().Nullable() // JVM: This might be DropDate instead + //.WithColumn("BacklogSetting").AsInt32() + ; + + Create.TableForModel("Albums") + .WithColumn("AlbumId").AsInt32() // Does this map to collectionId? + .WithColumn("CompilationId").AsInt32() + .WithColumn("Compilation").AsBoolean() + .WithColumn("Title").AsString() + .WithColumn("Year").AsInt32() + .WithColumn("Image").AsInt32() // Is this needed? + .WithColumn("TrackCount").AsInt32() + .WithColumn("DiscCount").AsInt32() + .WithColumn("Monitored").AsBoolean(); + + Create.TableForModel("Tracks") + .WithColumn("ItunesTrackId").AsInt32().Unique() + .WithColumn("AlbumId").AsInt32() + .WithColumn("CompilationId").AsInt32().Nullable() + .WithColumn("Compilation").AsBoolean().WithDefaultValue("False") + .WithColumn("TrackNumber").AsInt32() + .WithColumn("Title").AsString().Nullable() + .WithColumn("Ignored").AsBoolean().Nullable() + .WithColumn("Explict").AsBoolean() + .WithColumn("TrackExplicitName").AsString().Nullable() + .WithColumn("TrackCensoredName").AsString().Nullable() + .WithColumn("TrackFileId").AsInt32().Nullable() + .WithColumn("ReleaseDate").AsDateTime().Nullable(); + //.WithColumn("AbsoluteEpisodeNumber").AsInt32().Nullable() + //.WithColumn("SceneAbsoluteEpisodeNumber").AsInt32().Nullable() + //.WithColumn("SceneSeasonNumber").AsInt32().Nullable() + //.WithColumn("SceneEpisodeNumber").AsInt32().Nullable(); + + Create.TableForModel("TrackFiles") + .WithColumn("ArtistId").AsInt32() + .WithColumn("Path").AsString().Unique() + .WithColumn("Quality").AsString() + .WithColumn("Size").AsInt64() + .WithColumn("DateAdded").AsDateTime() + .WithColumn("AlbumId").AsInt32(); // How does this impact stand alone tracks? + + Create.TableForModel("Compilation") + .WithColumn("CompilationId").AsInt32().Unique() + .WithColumn("ArtistId").AsString().Nullable(); + } + + } +} diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 62f6aeb8b..ce619b72b 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -34,6 +34,7 @@ using NzbDrone.Core.Extras.Metadata.Files; using NzbDrone.Core.Extras.Others; using NzbDrone.Core.Extras.Subtitles; using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Music; namespace NzbDrone.Core.Datastore { @@ -91,6 +92,29 @@ namespace NzbDrone.Core.Datastore .Relationship() .HasOne(episode => episode.EpisodeFile, episode => episode.EpisodeFileId); + Mapper.Entity().RegisterModel("Artist") + .Ignore(s => s.RootFolderPath) + .Relationship() + .HasOne(s => s.Profile, s => s.ProfileId); + + Mapper.Entity().RegisterModel("TrackFiles") + .Ignore(f => f.Path) + .Relationships.AutoMapICollectionOrComplexProperties() + .For("Tracks") + .LazyLoad(condition: parent => parent.Id > 0, + query: (db, parent) => db.Query().Where(c => c.ItunesTrackId == parent.Id).ToList()) + .HasOne(file => file.Artist, file => file.AlbumId); + + Mapper.Entity().RegisterModel("Tracks") + //.Ignore(e => e.SeriesTitle) + .Ignore(e => e.Album) + .Ignore(e => e.HasFile) + .Relationship() + .HasOne(track => track.TrackFile, track => track.TrackFileId); + + Mapper.Entity().RegisterModel("Compilation") + .Relationships.AutoMapICollectionOrComplexProperties(); //TODO: Figure out how to map this Table + Mapper.Entity().RegisterModel("QualityDefinitions") .Ignore(d => d.Weight); diff --git a/src/NzbDrone.Core/MediaFiles/TrackFile.cs b/src/NzbDrone.Core/MediaFiles/TrackFile.cs new file mode 100644 index 000000000..9c2df9875 --- /dev/null +++ b/src/NzbDrone.Core/MediaFiles/TrackFile.cs @@ -0,0 +1,34 @@ +using Marr.Data; +using NzbDrone.Core.Datastore; +using NzbDrone.Core.MediaFiles.MediaInfo; +using NzbDrone.Core.Music; +using NzbDrone.Core.Qualities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.MediaFiles +{ + public class TrackFile : ModelBase + { + public int ItunesTrackId { get; set; } + public int AlbumId { get; set; } + public string RelativePath { get; set; } + public string Path { get; set; } + public long Size { get; set; } + public DateTime DateAdded { get; set; } + public string SceneName { get; set; } + public string ReleaseGroup { get; set; } + public QualityModel Quality { get; set; } + public MediaInfoModel MediaInfo { get; set; } + public LazyLoaded> Episodes { get; set; } + public LazyLoaded Artist { get; set; } + public LazyLoaded> Tracks { get; set; } + + public override string ToString() + { + return string.Format("[{0}] {1}", Id, RelativePath); + } + } +} diff --git a/src/NzbDrone.Core/Music/Album.cs b/src/NzbDrone.Core/Music/Album.cs new file mode 100644 index 000000000..0466e479f --- /dev/null +++ b/src/NzbDrone.Core/Music/Album.cs @@ -0,0 +1,26 @@ +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Tv; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Music +{ + public class Album : IEmbeddedDocument + { + public Album() + { + Images = new List(); + } + + public int AlbumId { get; set; } + public string Title { get; set; } + public int Year { get; set; } + public int TrackCount { get; set; } + public int DiscCount { get; set; } + public bool Monitored { get; set; } + public List Images { get; set; } + public List Actors { get; set; } // These are band members. TODO: Refactor + } +} diff --git a/src/NzbDrone.Core/Music/Artist.cs b/src/NzbDrone.Core/Music/Artist.cs new file mode 100644 index 000000000..f0faed6b1 --- /dev/null +++ b/src/NzbDrone.Core/Music/Artist.cs @@ -0,0 +1,83 @@ +using Marr.Data; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Profiles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Music +{ + public class Artist : ModelBase + { + public Artist() + { + Images = new List(); + Genres = new List(); + //Members = new List(); // Artist Band Member? (NOTE: This should be per album) + Albums = new List(); + Tags = new HashSet(); + + } + + public int ItunesId { get; set; } + //public int TvRageId { get; set; } + //public int TvMazeId { get; set; } + //public string ImdbId { get; set; } + public string ArtistName { get; set; } + public string ArtistSlug { get; set; } + public string CleanTitle { get; set; } + public string SortTitle { get; set; } + //public SeriesStatusType Status { get; set; } + public string Overview { get; set; } + public bool Monitored { get; set; } + //public int ProfileId { get; set; } + public bool AlbumFolder { get; set; } + public DateTime? LastInfoSync { get; set; } + //public int Runtime { get; set; } + public List Images { get; set; } + //public SeriesTypes SeriesType { get; set; } + //public string Network { get; set; } + //public bool UseSceneNumbering { get; set; } + //public string TitleSlug { get; set; } + public string Path { get; set; } + //public int Year { get; set; } + //public Ratings Ratings { get; set; } + public List Genres { get; set; } + //public List Actors { get; set; } // MOve to album? + public string Certification { get; set; } + public string RootFolderPath { get; set; } + public DateTime Added { get; set; } + public DateTime? FirstAired { get; set; } + public LazyLoaded Profile { get; set; } + public int ProfileId { get; set; } + + public List Albums { get; set; } + public HashSet Tags { get; set; } + //public AddSeriesOptions AddOptions { get; set; } // TODO: Learn what this does + + public override string ToString() + { + return string.Format("[{0}][{1}]", ItunesId, ArtistName.NullSafe()); + } + + public void ApplyChanges(Artist otherArtist) + { + //TODO: Implement + ItunesId = otherArtist.ItunesId; + + Albums = otherArtist.Albums; + Path = otherArtist.Path; + ProfileId = otherArtist.ProfileId; + + AlbumFolder = otherArtist.AlbumFolder; + Monitored = otherArtist.Monitored; + + //SeriesType = otherArtist.SeriesType; + RootFolderPath = otherArtist.RootFolderPath; + Tags = otherArtist.Tags; + //AddOptions = otherArtist.AddOptions; + } + } +} diff --git a/src/NzbDrone.Core/Music/Compilation.cs b/src/NzbDrone.Core/Music/Compilation.cs new file mode 100644 index 000000000..923e6d7f3 --- /dev/null +++ b/src/NzbDrone.Core/Music/Compilation.cs @@ -0,0 +1,19 @@ +using NzbDrone.Core.Datastore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Music +{ + public class Compilation : ModelBase + { + public Compilation() + { + + } + + public int CompilationId { get; set; } + public LazyList Artists { get; set; } + } +} diff --git a/src/NzbDrone.Core/Music/Track.cs b/src/NzbDrone.Core/Music/Track.cs new file mode 100644 index 000000000..89793d514 --- /dev/null +++ b/src/NzbDrone.Core/Music/Track.cs @@ -0,0 +1,51 @@ +using NzbDrone.Core.Datastore; +using NzbDrone.Core.MediaFiles; +using Marr.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Common.Extensions; + +namespace NzbDrone.Core.Music +{ + public class Track : ModelBase + { + public Track() + { + } + + public const string RELEASE_DATE_FORMAT = "yyyy-MM-dd"; + + public int ItunesTrackId { get; set; } + public int AlbumId { get; set; } + public int CompilationId { get; set; } + public bool Compilation { get; set; } + public int TrackNumber { get; set; } + public string Title { get; set; } + public bool Ignored { get; set; } + public bool Explict { get; set; } + public string TrackExplicitName { get; set; } + public string TrackCensoredName { get; set; } + public string Monitored { get; set; } + public int TrackFileId { get; set; } // JVM: Is this needed with TrackFile reference? + public DateTime? ReleaseDate { get; set; } + /*public int? SceneEpisodeNumber { get; set; } + public bool UnverifiedSceneNumbering { get; set; } + public Ratings Ratings { get; set; } // This might be aplicable as can be pulled from IDv3 tags + public List Images { get; set; }*/ + + //public string SeriesTitle { get; private set; } + + public LazyLoaded TrackFile { get; set; } + + public Album Album { get; set; } + + public bool HasFile => TrackFileId > 0; + + public override string ToString() + { + return string.Format("[{0}]{1}", ItunesTrackId, Title.NullSafe()); + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 9e238632b..d82211ee6 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -287,6 +287,7 @@ Code + @@ -781,6 +782,7 @@ + @@ -837,6 +839,9 @@ + + +