mirror of
https://github.com/lidarr/Lidarr
synced 2025-02-20 13:06:57 +00:00
Merge pull request #8 from mattman86/feature/trackRepository
Implemented Tracks
This commit is contained in:
commit
7acad802fb
13 changed files with 404 additions and 92 deletions
|
@ -48,16 +48,16 @@ protected override void MainDbUpgrade()
|
|||
.WithColumn("Overview").AsString();
|
||||
|
||||
Create.TableForModel("Tracks")
|
||||
.WithColumn("ItunesTrackId").AsInt32().Unique()
|
||||
.WithColumn("SpotifyTrackId").AsString().Nullable() // This shouldn't be nullable, but TrackRepository won't behave. Someone please fix this.
|
||||
.WithColumn("AlbumId").AsString()
|
||||
.WithColumn("ArtistsId").AsString().Nullable()
|
||||
.WithColumn("ArtistId").AsString() // This may be a list of Ids in future for compilations
|
||||
.WithColumn("ArtistSpotifyId").AsString()
|
||||
.WithColumn("Compilation").AsBoolean()
|
||||
.WithColumn("TrackNumber").AsInt32()
|
||||
.WithColumn("Title").AsString().Nullable()
|
||||
.WithColumn("Ignored").AsBoolean().Nullable()
|
||||
.WithColumn("Explict").AsBoolean()
|
||||
.WithColumn("Monitored").AsBoolean()
|
||||
.WithColumn("TrackExplicitName").AsString().Nullable()
|
||||
.WithColumn("TrackCensoredName").AsString().Nullable()
|
||||
.WithColumn("TrackFileId").AsInt32().Nullable()
|
||||
.WithColumn("ReleaseDate").AsDateTime().Nullable();
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ public static void Map()
|
|||
.Relationships.AutoMapICollectionOrComplexProperties()
|
||||
.For("Tracks")
|
||||
.LazyLoad(condition: parent => parent.Id > 0,
|
||||
query: (db, parent) => db.Query<Track>().Where(c => c.SpotifyTrackId == parent.Id).ToList())
|
||||
query: (db, parent) => db.Query<Track>().Where(c => c.ArtistId == parent.Id).ToList()) // TODO: Figure what the hell to do here
|
||||
.HasOne(file => file.Artist, file => file.AlbumId);
|
||||
|
||||
Mapper.Entity<Track>().RegisterModel("Tracks")
|
||||
|
@ -110,6 +110,7 @@ public static void Map()
|
|||
.Ignore(e => e.Album)
|
||||
.Ignore(e => e.HasFile)
|
||||
.Relationship()
|
||||
// TODO: Need to implement ArtistId to Artist.Id here
|
||||
.HasOne(track => track.TrackFile, track => track.TrackFileId); // TODO: Check lazy load for artists
|
||||
|
||||
Mapper.Entity<QualityDefinition>().RegisterModel("QualityDefinitions")
|
||||
|
|
|
@ -68,7 +68,7 @@ public void Handle(ApplicationStartedEvent message)
|
|||
//new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
||||
new ScheduledTask{ Interval = 6*60, TypeName = typeof(CheckHealthCommand).FullName},
|
||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshArtistCommand).FullName},
|
||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName}, // TODO: Remove
|
||||
//new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName}, // TODO: Remove
|
||||
new ScheduledTask{ Interval = 24*60, TypeName = typeof(HousekeepingCommand).FullName},
|
||||
new ScheduledTask{ Interval = 7*24*60, TypeName = typeof(BackupCommand).FullName},
|
||||
|
||||
|
|
18
src/NzbDrone.Core/MediaFiles/Events/TrackFileAddedEvent.cs
Normal file
18
src/NzbDrone.Core/MediaFiles/Events/TrackFileAddedEvent.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
public class TrackFileAddedEvent : IEvent
|
||||
{
|
||||
public TrackFile TrackFile { get; private set; }
|
||||
|
||||
public TrackFileAddedEvent(TrackFile trackFile)
|
||||
{
|
||||
TrackFile = trackFile;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,15 +115,15 @@ public Tuple<Artist, List<Track>> GetArtistInfo(string spotifyId)
|
|||
artist.SpotifyId = httpResponse.Resource.Id;
|
||||
artist.Genres = httpResponse.Resource.Genres;
|
||||
|
||||
var albumRet = MapAlbums(artist);
|
||||
artist = albumRet.Item1;
|
||||
|
||||
artist = MapAlbums(artist);
|
||||
|
||||
|
||||
// TODO: implement tracks api call
|
||||
return new Tuple<Artist, List<Track>>(artist, new List<Track>());
|
||||
|
||||
return new Tuple<Artist, List<Track>>(albumRet.Item1, albumRet.Item2);
|
||||
}
|
||||
|
||||
private Artist MapAlbums(Artist artist)
|
||||
private Tuple<Artist, List<Track>> MapAlbums(Artist artist)
|
||||
{
|
||||
|
||||
// Find all albums for the artist and all tracks for said album
|
||||
|
@ -141,21 +141,23 @@ private Artist MapAlbums(Artist artist)
|
|||
throw new HttpException(httpRequest, httpResponse);
|
||||
}
|
||||
|
||||
List<Track> masterTracks = new List<Track>();
|
||||
List<Album> albums = new List<Album>();
|
||||
foreach(var albumResource in httpResponse.Resource.Items)
|
||||
{
|
||||
Album album = new Album();
|
||||
album.AlbumId = albumResource.Id;
|
||||
album.Title = albumResource.Name;
|
||||
album.ArtworkUrl = albumResource.Images[0].Url;
|
||||
album.ArtworkUrl = albumResource.Images.Count > 0 ? albumResource.Images[0].Url : "";
|
||||
album.Tracks = MapTracksToAlbum(album);
|
||||
masterTracks.InsertRange(masterTracks.Count, album.Tracks);
|
||||
albums.Add(album);
|
||||
}
|
||||
|
||||
// TODO: We now need to get all tracks for each album
|
||||
|
||||
artist.Albums = albums;
|
||||
return artist;
|
||||
return new Tuple<Artist, List<Track>>(artist, masterTracks);
|
||||
}
|
||||
|
||||
private List<Track> MapTracksToAlbum(Album album)
|
||||
|
@ -183,11 +185,12 @@ private List<Track> MapTracksToAlbum(Album album)
|
|||
// TODO: Implement more track mapping
|
||||
//track.Artist = trackResource.Artists
|
||||
//track.ArtistId = album.
|
||||
track.SpotifyTrackId = trackResource.Id;
|
||||
track.ArtistSpotifyId = trackResource.Artists.Count > 0 ? trackResource.Artists[0].Id : null;
|
||||
track.Explict = trackResource.Explicit;
|
||||
track.Compilation = trackResource.Artists.Count > 1;
|
||||
track.TrackNumber = trackResource.TrackNumber;
|
||||
track.TrackExplicitName = trackResource.Name;
|
||||
track.TrackCensoredName = trackResource.Name;
|
||||
track.Title = trackResource.Name;
|
||||
tracks.Add(track);
|
||||
}
|
||||
|
||||
|
@ -272,7 +275,7 @@ private List<Artist> MapArtists(ArtistResource resource)
|
|||
artist.ArtistName = artistResource.Name;
|
||||
artist.SpotifyId = artistResource.Id;
|
||||
artist.Genres = artistResource.Genres;
|
||||
//artist.ArtistSlug = a//TODO implement artistSlug mapping;
|
||||
artist.ArtistSlug = Parser.Parser.CleanArtistTitle(artist.ArtistName);
|
||||
artists.Add(artist);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,8 @@ public class RefreshArtistService : IExecute<RefreshArtistCommand>
|
|||
private readonly IArtistService _artistService;
|
||||
private readonly IRefreshTrackService _refreshTrackService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
//private readonly IDailySeriesService _dailySeriesService;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
//private readonly ICheckIfArtistShouldBeRefreshed _checkIfArtistShouldBeRefreshed;
|
||||
private readonly ICheckIfArtistShouldBeRefreshed _checkIfArtistShouldBeRefreshed;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RefreshArtistService(IProvideArtistInfo artistInfo,
|
||||
|
@ -32,7 +31,7 @@ public RefreshArtistService(IProvideArtistInfo artistInfo,
|
|||
IRefreshTrackService refreshTrackService,
|
||||
IEventAggregator eventAggregator,
|
||||
IDiskScanService diskScanService,
|
||||
//ICheckIfArtistShouldBeRefreshed checkIfArtistShouldBeRefreshed,
|
||||
ICheckIfArtistShouldBeRefreshed checkIfArtistShouldBeRefreshed,
|
||||
Logger logger)
|
||||
{
|
||||
_artistInfo = artistInfo;
|
||||
|
@ -40,7 +39,7 @@ public RefreshArtistService(IProvideArtistInfo artistInfo,
|
|||
_refreshTrackService = refreshTrackService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_diskScanService = diskScanService;
|
||||
//_checkIfArtistShouldBeRefreshed = checkIfArtistShouldBeRefreshed;
|
||||
_checkIfArtistShouldBeRefreshed = checkIfArtistShouldBeRefreshed;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -75,7 +74,6 @@ private void RefreshArtistInfo(Artist artist)
|
|||
artist.CleanTitle = artistInfo.CleanTitle;
|
||||
artist.LastInfoSync = DateTime.UtcNow;
|
||||
artist.Images = artistInfo.Images;
|
||||
//artist.Actors = artistInfo.Actors;
|
||||
artist.Genres = artistInfo.Genres;
|
||||
|
||||
try
|
||||
|
@ -142,7 +140,7 @@ public void Execute(RefreshArtistCommand message)
|
|||
|
||||
foreach (var artist in allArtists)
|
||||
{
|
||||
if (message.Trigger == CommandTrigger.Manual /*|| _checkIfArtistShouldBeRefreshed.ShouldRefresh(artist)*/)
|
||||
if (message.Trigger == CommandTrigger.Manual || _checkIfArtistShouldBeRefreshed.ShouldRefresh(artist))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ public void RefreshTrackInfo(Artist artist, IEnumerable<Track> remoteTracks)
|
|||
var successCount = 0;
|
||||
var failCount = 0;
|
||||
|
||||
var existingTracks = _trackService.GetTrackByArtist(artist.SpotifyId);
|
||||
var existingTracks = _trackService.GetTracksByArtist(artist.SpotifyId);
|
||||
var albums = artist.Albums;
|
||||
|
||||
var updateList = new List<Track>();
|
||||
|
@ -57,13 +57,26 @@ public void RefreshTrackInfo(Artist artist, IEnumerable<Track> remoteTracks)
|
|||
trackToUpdate.Monitored = GetMonitoredStatus(track, albums);
|
||||
newList.Add(trackToUpdate);
|
||||
}
|
||||
trackToUpdate.ArtistId = artist.SpotifyId; // TODO: Ensure LazyLoaded<Artist> field gets updated.
|
||||
|
||||
trackToUpdate.SpotifyTrackId = track.SpotifyTrackId;
|
||||
trackToUpdate.TrackNumber = track.TrackNumber;
|
||||
trackToUpdate.Title = track.Title ?? "Unknown";
|
||||
|
||||
trackToUpdate.AlbumId = track.AlbumId;
|
||||
trackToUpdate.Album = track.Album;
|
||||
trackToUpdate.Explict = track.Explict;
|
||||
if (track.ArtistSpotifyId.IsNullOrWhiteSpace())
|
||||
{
|
||||
trackToUpdate.ArtistSpotifyId = artist.SpotifyId;
|
||||
} else
|
||||
{
|
||||
trackToUpdate.ArtistSpotifyId = track.ArtistSpotifyId;
|
||||
}
|
||||
trackToUpdate.ArtistId = track.ArtistId;
|
||||
trackToUpdate.Compilation = track.Compilation;
|
||||
|
||||
// TODO: Implement rest of [RefreshTrackService] fields
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
successCount++;
|
||||
}
|
||||
|
|
43
src/NzbDrone.Core/Music/ShouldRefreshArtist.cs
Normal file
43
src/NzbDrone.Core/Music/ShouldRefreshArtist.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public interface ICheckIfArtistShouldBeRefreshed
|
||||
{
|
||||
bool ShouldRefresh(Artist artist);
|
||||
}
|
||||
|
||||
public class CheckIfArtistShouldBeRefreshed : ICheckIfArtistShouldBeRefreshed
|
||||
{
|
||||
private readonly ITrackService _trackService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public CheckIfArtistShouldBeRefreshed(ITrackService trackService, Logger logger)
|
||||
{
|
||||
_trackService = trackService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool ShouldRefresh(Artist artist)
|
||||
{
|
||||
if (artist.LastInfoSync < DateTime.UtcNow.AddDays(-30))
|
||||
{
|
||||
_logger.Trace("Artist {0} last updated more than 30 days ago, should refresh.", artist.ArtistName);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (artist.LastInfoSync >= DateTime.UtcNow.AddHours(-6))
|
||||
{
|
||||
_logger.Trace("Artist {0} last updated less than 6 hours ago, should not be refreshed.", artist.ArtistName);
|
||||
return false;
|
||||
}
|
||||
|
||||
//_logger.Trace("Artist {0} ended long ago, should not be refreshed.", artist.Title);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,26 +17,20 @@ public Track()
|
|||
|
||||
public const string RELEASE_DATE_FORMAT = "yyyy-MM-dd";
|
||||
|
||||
public int SpotifyTrackId { get; set; }
|
||||
public string SpotifyTrackId { get; set; }
|
||||
public string AlbumId { get; set; }
|
||||
public LazyLoaded<Artist> Artist { get; set; }
|
||||
public string ArtistId { get; set; }
|
||||
public int CompilationId { get; set; }
|
||||
public string ArtistSpotifyId { get; set; }
|
||||
public long ArtistId { get; set; } // This is the DB Id of the Artist, not the SpotifyId
|
||||
//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 bool Monitored { get; set; }
|
||||
public int TrackFileId { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
/*
|
||||
public Ratings Ratings { get; set; } // This might be aplicable as can be pulled from IDv3 tags
|
||||
public List<MediaCover.MediaCover> Images { get; set; }*/
|
||||
|
||||
//public string SeriesTitle { get; private set; }
|
||||
|
||||
public LazyLoaded<TrackFile> TrackFile { get; set; }
|
||||
|
||||
|
|
165
src/NzbDrone.Core/Music/TrackRepository.cs
Normal file
165
src/NzbDrone.Core/Music/TrackRepository.cs
Normal file
|
@ -0,0 +1,165 @@
|
|||
using NzbDrone.Core.Datastore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using Marr.Data.QGen;
|
||||
using NzbDrone.Core.Datastore.Extensions;
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Core.Music
|
||||
{
|
||||
public interface ITrackRepository : IBasicRepository<Track>
|
||||
{
|
||||
Track Find(string artistId, string albumId, int trackNumber);
|
||||
List<Track> GetTracks(string artistId);
|
||||
List<Track> GetTracks(string artistId, string albumId);
|
||||
List<Track> GetTracksByFileId(int fileId);
|
||||
List<Track> TracksWithFiles(string artistId);
|
||||
PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec);
|
||||
PagingSpec<Track> TracksWhereCutoffUnmet(PagingSpec<Track> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff);
|
||||
void SetMonitoredFlat(Track episode, bool monitored);
|
||||
void SetMonitoredByAlbum(string artistId, string albumId, bool monitored);
|
||||
void SetFileId(int trackId, int fileId);
|
||||
}
|
||||
|
||||
public class TrackRepository : BasicRepository<Track>, ITrackRepository
|
||||
{
|
||||
private readonly IMainDatabase _database;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public TrackRepository(IMainDatabase database, IEventAggregator eventAggregator, Logger logger)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Track Find(string artistId, string albumId, int trackNumber)
|
||||
{
|
||||
return Query.Where(s => s.ArtistSpotifyId == artistId)
|
||||
.AndWhere(s => s.AlbumId == albumId)
|
||||
.AndWhere(s => s.TrackNumber == trackNumber)
|
||||
.SingleOrDefault();
|
||||
}
|
||||
|
||||
|
||||
public List<Track> GetTracks(string artistId)
|
||||
{
|
||||
return Query.Where(s => s.ArtistSpotifyId == artistId).ToList();
|
||||
}
|
||||
|
||||
public List<Track> GetTracks(string artistId, string albumId)
|
||||
{
|
||||
return Query.Where(s => s.ArtistSpotifyId == artistId)
|
||||
.AndWhere(s => s.AlbumId == albumId)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<Track> GetTracksByFileId(int fileId)
|
||||
{
|
||||
return Query.Where(e => e.TrackFileId == fileId).ToList();
|
||||
}
|
||||
|
||||
public List<Track> TracksWithFiles(string artistId)
|
||||
{
|
||||
return Query.Join<Track, TrackFile>(JoinType.Inner, e => e.TrackFile, (e, ef) => e.TrackFileId == ef.Id)
|
||||
.Where(e => e.ArtistSpotifyId == artistId);
|
||||
}
|
||||
|
||||
public PagingSpec<Track> TracksWhereCutoffUnmet(PagingSpec<Track> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
|
||||
{
|
||||
pagingSpec.TotalRecords = EpisodesWhereCutoffUnmetQuery(pagingSpec, qualitiesBelowCutoff).GetRowCount();
|
||||
pagingSpec.Records = EpisodesWhereCutoffUnmetQuery(pagingSpec, qualitiesBelowCutoff).ToList();
|
||||
|
||||
return pagingSpec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void SetMonitoredFlat(Track track, bool monitored)
|
||||
{
|
||||
track.Monitored = monitored;
|
||||
SetFields(track, p => p.Monitored);
|
||||
}
|
||||
|
||||
public void SetMonitoredByAlbum(string artistId, string albumId, bool monitored)
|
||||
{
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
mapper.AddParameter("artistId", artistId);
|
||||
mapper.AddParameter("albumId", albumId);
|
||||
mapper.AddParameter("monitored", monitored);
|
||||
|
||||
const string sql = "UPDATE Tracks " +
|
||||
"SET Monitored = @monitored " +
|
||||
"WHERE ArtistId = @artistId " +
|
||||
"AND AlbumId = @albumId";
|
||||
|
||||
mapper.ExecuteNonQuery(sql);
|
||||
}
|
||||
|
||||
public void SetFileId(int episodeId, int fileId)
|
||||
{
|
||||
SetFields(new Track { Id = episodeId, TrackFileId = fileId }, track => track.TrackFileId);
|
||||
}
|
||||
|
||||
public PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec)
|
||||
{
|
||||
var currentTime = DateTime.UtcNow;
|
||||
|
||||
pagingSpec.TotalRecords = GetMissingEpisodesQuery(pagingSpec, currentTime).GetRowCount();
|
||||
pagingSpec.Records = GetMissingEpisodesQuery(pagingSpec, currentTime).ToList();
|
||||
|
||||
return pagingSpec;
|
||||
}
|
||||
|
||||
private SortBuilder<Track> GetMissingEpisodesQuery(PagingSpec<Track> pagingSpec, DateTime currentTime)
|
||||
{
|
||||
return Query.Join<Track, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistSpotifyId == s.SpotifyId)
|
||||
.Where(pagingSpec.FilterExpression)
|
||||
.AndWhere(e => e.TrackFileId == 0)
|
||||
.AndWhere(BuildAirDateUtcCutoffWhereClause(currentTime))
|
||||
.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
|
||||
.Skip(pagingSpec.PagingOffset())
|
||||
.Take(pagingSpec.PageSize);
|
||||
}
|
||||
|
||||
|
||||
private SortBuilder<Track> EpisodesWhereCutoffUnmetQuery(PagingSpec<Track> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
|
||||
{
|
||||
return Query.Join<Track, Artist>(JoinType.Inner, e => e.Artist, (e, s) => e.ArtistSpotifyId == s.SpotifyId)
|
||||
.Join<Track, TrackFile>(JoinType.Left, e => e.TrackFile, (e, s) => e.TrackFileId == s.Id)
|
||||
.Where(pagingSpec.FilterExpression)
|
||||
.AndWhere(e => e.TrackFileId != 0)
|
||||
.AndWhere(BuildQualityCutoffWhereClause(qualitiesBelowCutoff))
|
||||
.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
|
||||
.Skip(pagingSpec.PagingOffset())
|
||||
.Take(pagingSpec.PageSize);
|
||||
}
|
||||
|
||||
private string BuildAirDateUtcCutoffWhereClause(DateTime currentTime)
|
||||
{
|
||||
return string.Format("WHERE datetime(strftime('%s', [t0].[AirDateUtc]) + [t1].[RunTime] * 60, 'unixepoch') <= '{0}'",
|
||||
currentTime.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
|
||||
private string BuildQualityCutoffWhereClause(List<QualitiesBelowCutoff> qualitiesBelowCutoff)
|
||||
{
|
||||
var clauses = new List<string>();
|
||||
|
||||
foreach (var profile in qualitiesBelowCutoff)
|
||||
{
|
||||
foreach (var belowCutoff in profile.QualityIds)
|
||||
{
|
||||
clauses.Add(string.Format("([t1].[ProfileId] = {0} AND [t2].[Quality] LIKE '%_quality_: {1},%')", profile.ProfileId, belowCutoff));
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format("({0})", string.Join(" OR ", clauses));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,9 @@
|
|||
using NzbDrone.Core.Datastore;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -12,12 +17,12 @@ public interface ITrackService
|
|||
List<Track> GetTracks(IEnumerable<int> ids);
|
||||
Track FindTrack(string artistId, string albumId, int trackNumber);
|
||||
Track FindTrackByTitle(string artistId, string albumId, string releaseTitle);
|
||||
List<Track> GetTrackByArtist(string artistId);
|
||||
List<Track> GetTracksByAlbum(string artistId, string albumId);
|
||||
List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle);
|
||||
List<Track> GetTracksByArtist(string artistId);
|
||||
//List<Track> GetTracksByAlbum(string artistId, string albumId);
|
||||
//List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle);
|
||||
List<Track> TracksWithFiles(string artistId);
|
||||
PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec);
|
||||
List<Track> GeTracksByFileId(int trackFileId);
|
||||
//PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec);
|
||||
List<Track> GetTracksByFileId(int trackFileId);
|
||||
void UpdateTrack(Track track);
|
||||
void SetTrackMonitored(int trackId, bool monitored);
|
||||
void UpdateTracks(List<Track> tracks);
|
||||
|
@ -29,89 +34,158 @@ public interface ITrackService
|
|||
|
||||
public class TrackService : ITrackService
|
||||
{
|
||||
public void DeleteMany(List<Track> tracks)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
private readonly ITrackRepository _trackRepository;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public Track FindTrack(string artistId, string albumId, int trackNumber)
|
||||
public TrackService(ITrackRepository trackRepository, IConfigService configService, Logger logger)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Track FindTrackByTitle(string artistId, string albumId, string releaseTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Track> GeTracksByFileId(int trackFileId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_trackRepository = trackRepository;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Track GetTrack(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Track> GetTrackByArtist(string artistId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _trackRepository.Get(id);
|
||||
}
|
||||
|
||||
public List<Track> GetTracks(IEnumerable<int> ids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _trackRepository.Get(ids).ToList();
|
||||
}
|
||||
|
||||
public Track FindTrack(string artistId, string albumId, int episodeNumber)
|
||||
{
|
||||
return _trackRepository.Find(artistId, albumId, episodeNumber);
|
||||
}
|
||||
|
||||
public List<Track> GetTracksByArtist(string artistId)
|
||||
{
|
||||
return _trackRepository.GetTracks(artistId).ToList();
|
||||
}
|
||||
|
||||
public List<Track> GetTracksByAlbum(string artistId, string albumId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _trackRepository.GetTracks(artistId, albumId);
|
||||
}
|
||||
|
||||
public List<Track> GetTracksByAlbumTitle(string artistId, string albumTitle)
|
||||
public Track FindTrackByTitle(string artistId, string albumId, string releaseTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
// TODO: can replace this search mechanism with something smarter/faster/better
|
||||
var normalizedReleaseTitle = Parser.Parser.NormalizeEpisodeTitle(releaseTitle).Replace(".", " ");
|
||||
var tracks = _trackRepository.GetTracks(artistId, albumId);
|
||||
|
||||
public void InsertMany(List<Track> tracks)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
var matches = tracks.Select(
|
||||
track => new
|
||||
{
|
||||
Position = normalizedReleaseTitle.IndexOf(Parser.Parser.NormalizeEpisodeTitle(track.Title), StringComparison.CurrentCultureIgnoreCase),
|
||||
Length = Parser.Parser.NormalizeEpisodeTitle(track.Title).Length,
|
||||
Track = track
|
||||
})
|
||||
.Where(e => e.Track.Title.Length > 0 && e.Position >= 0)
|
||||
.OrderBy(e => e.Position)
|
||||
.ThenByDescending(e => e.Length)
|
||||
.ToList();
|
||||
|
||||
public void SetTrackMonitored(int trackId, bool monitored)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
if (matches.Any())
|
||||
{
|
||||
return matches.First().Track;
|
||||
}
|
||||
|
||||
public void SetTrackMonitoredByAlbum(string artistId, string albumId, bool monitored)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Track> TracksWithFiles(string artistId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _trackRepository.TracksWithFiles(artistId);
|
||||
}
|
||||
|
||||
|
||||
public PagingSpec<Track> TracksWithoutFiles(PagingSpec<Track> pagingSpec)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var episodeResult = _trackRepository.TracksWithoutFiles(pagingSpec);
|
||||
|
||||
return episodeResult;
|
||||
}
|
||||
|
||||
public void UpdateMany(List<Track> tracks)
|
||||
public List<Track> GetTracksByFileId(int trackFileId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _trackRepository.GetTracksByFileId(trackFileId);
|
||||
}
|
||||
|
||||
public void UpdateTrack(Track track)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_trackRepository.Update(track);
|
||||
}
|
||||
|
||||
public void SetTrackMonitored(int trackId, bool monitored)
|
||||
{
|
||||
var track = _trackRepository.Get(trackId);
|
||||
_trackRepository.SetMonitoredFlat(track, monitored);
|
||||
|
||||
_logger.Debug("Monitored flag for Track:{0} was set to {1}", trackId, monitored);
|
||||
}
|
||||
|
||||
public void SetTrackMonitoredByAlbum(string artistId, string albumId, bool monitored)
|
||||
{
|
||||
_trackRepository.SetMonitoredByAlbum(artistId, albumId, monitored);
|
||||
}
|
||||
|
||||
public void UpdateEpisodes(List<Track> tracks)
|
||||
{
|
||||
_trackRepository.UpdateMany(tracks);
|
||||
}
|
||||
|
||||
public void InsertMany(List<Track> tracks)
|
||||
{
|
||||
_trackRepository.InsertMany(tracks);
|
||||
}
|
||||
|
||||
public void UpdateMany(List<Track> tracks)
|
||||
{
|
||||
_trackRepository.UpdateMany(tracks);
|
||||
}
|
||||
|
||||
public void DeleteMany(List<Track> tracks)
|
||||
{
|
||||
_trackRepository.DeleteMany(tracks);
|
||||
}
|
||||
|
||||
public void HandleAsync(ArtistDeletedEvent message)
|
||||
{
|
||||
var tracks = GetTracksByArtist(message.Artist.SpotifyId);
|
||||
_trackRepository.DeleteMany(tracks);
|
||||
}
|
||||
|
||||
public void Handle(TrackFileDeletedEvent message)
|
||||
{
|
||||
foreach (var track in GetTracksByFileId(message.TrackFile.Id))
|
||||
{
|
||||
_logger.Debug("Detaching track {0} from file.", track.Id);
|
||||
track.TrackFileId = 0;
|
||||
|
||||
if (message.Reason != DeleteMediaFileReason.Upgrade && _configService.AutoUnmonitorPreviouslyDownloadedEpisodes)
|
||||
{
|
||||
track.Monitored = false;
|
||||
}
|
||||
|
||||
UpdateTrack(track);
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(TrackFileAddedEvent message)
|
||||
{
|
||||
foreach (var track in message.TrackFile.Tracks.Value)
|
||||
{
|
||||
_trackRepository.SetFileId(track.Id, message.TrackFile.Id);
|
||||
_logger.Debug("Linking [{0}] > [{1}]", message.TrackFile.RelativePath, track);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateTracks(List<Track> tracks)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_trackRepository.UpdateMany(tracks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -769,6 +769,7 @@
|
|||
<Compile Include="MediaFiles\Events\SeriesRenamedEvent.cs" />
|
||||
<Compile Include="MediaFiles\Events\SeriesScanSkippedEvent.cs" />
|
||||
<Compile Include="MediaFiles\Events\SeriesScannedEvent.cs" />
|
||||
<Compile Include="MediaFiles\Events\TrackFileAddedEvent.cs" />
|
||||
<Compile Include="MediaFiles\Events\TrackFileDeletedEvent.cs" />
|
||||
<Compile Include="MediaFiles\Events\TrackImportedEvent.cs" />
|
||||
<Compile Include="MediaFiles\FileDateType.cs" />
|
||||
|
@ -868,7 +869,9 @@
|
|||
<Compile Include="Music\Events\TrackInfoRefreshedEvent.cs" />
|
||||
<Compile Include="Music\RefreshArtistService.cs" />
|
||||
<Compile Include="Music\RefreshTrackService.cs" />
|
||||
<Compile Include="Music\ShouldRefreshArtist.cs" />
|
||||
<Compile Include="Music\Track.cs" />
|
||||
<Compile Include="Music\TrackRepository.cs" />
|
||||
<Compile Include="Music\TrackService.cs" />
|
||||
<Compile Include="Notifications\Join\JoinAuthException.cs" />
|
||||
<Compile Include="Notifications\Join\JoinInvalidDeviceException.cs" />
|
||||
|
|
|
@ -9,14 +9,14 @@ module.exports = Marionette.ItemView.extend({
|
|||
|
||||
events : {
|
||||
'click .x-edit' : '_editSeries',
|
||||
'click .x-refresh' : '_refreshSeries'
|
||||
'click .x-refresh' : '_refreshArtist'
|
||||
},
|
||||
|
||||
onRender : function() {
|
||||
CommandController.bindToCommand({
|
||||
element : this.ui.refresh,
|
||||
command : {
|
||||
name : 'refreshSeries',
|
||||
name : 'refreshArtist',
|
||||
seriesId : this.model.get('id')
|
||||
}
|
||||
});
|
||||
|
@ -26,9 +26,9 @@ module.exports = Marionette.ItemView.extend({
|
|||
vent.trigger(vent.Commands.EditSeriesCommand, { series : this.model });
|
||||
},
|
||||
|
||||
_refreshSeries : function() {
|
||||
CommandController.Execute('refreshSeries', {
|
||||
name : 'refreshSeries',
|
||||
_refreshArtist : function() {
|
||||
CommandController.Execute('refreshArtist', {
|
||||
name : 'refreshArtist',
|
||||
seriesId : this.model.id
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue