mirror of https://github.com/lidarr/Lidarr
Refactored most code for track parsing.
This commit is contained in:
parent
d1eb9ff16c
commit
76db95947c
|
@ -4,6 +4,7 @@ using System.Text.RegularExpressions;
|
|||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Music;
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
{
|
||||
|
@ -19,6 +20,9 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
|||
public virtual bool MonitoredEpisodesOnly { get; set; }
|
||||
public virtual bool UserInvokedSearch { get; set; }
|
||||
|
||||
public Artist Artist { get; set; }
|
||||
public List<Track> Tracks { get; set; }
|
||||
|
||||
public List<string> QueryTitles => SceneTitles.Select(GetQueryTitle).ToList();
|
||||
|
||||
public static string GetQueryTitle(string title)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Messaging.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
public class RescanArtistCommand : Command
|
||||
{
|
||||
|
||||
public string ArtistId { get; set; }
|
||||
|
||||
public override bool SendUpdatesToClient => true;
|
||||
|
||||
public RescanArtistCommand()
|
||||
{
|
||||
ArtistId = "";
|
||||
}
|
||||
|
||||
public RescanArtistCommand(string artistId)
|
||||
{
|
||||
ArtistId = artistId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,12 +16,15 @@ using NzbDrone.Core.Messaging.Commands;
|
|||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IDiskScanService
|
||||
{
|
||||
void Scan(Series series);
|
||||
void Scan(Artist artist);
|
||||
string[] GetVideoFiles(string path, bool allDirectories = true);
|
||||
string[] GetNonVideoFiles(string path, bool allDirectories = true);
|
||||
List<string> FilterFiles(Series series, IEnumerable<string> files);
|
||||
|
@ -30,13 +33,16 @@ namespace NzbDrone.Core.MediaFiles
|
|||
public class DiskScanService :
|
||||
IDiskScanService,
|
||||
IHandle<SeriesUpdatedEvent>,
|
||||
IExecute<RescanSeriesCommand>
|
||||
IExecute<RescanSeriesCommand>,
|
||||
IHandle<ArtistUpdatedEvent>,
|
||||
IExecute<RescanArtistCommand>
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IMakeImportDecision _importDecisionMaker;
|
||||
private readonly IImportApprovedEpisodes _importApprovedEpisodes;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IArtistService _artistService;
|
||||
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
@ -46,6 +52,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
IImportApprovedEpisodes importApprovedEpisodes,
|
||||
IConfigService configService,
|
||||
ISeriesService seriesService,
|
||||
IArtistService artistService,
|
||||
IMediaFileTableCleanupService mediaFileTableCleanupService,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
|
@ -55,6 +62,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_importApprovedEpisodes = importApprovedEpisodes;
|
||||
_configService = configService;
|
||||
_seriesService = seriesService;
|
||||
_artistService = artistService;
|
||||
_mediaFileTableCleanupService = mediaFileTableCleanupService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
|
@ -63,6 +71,58 @@ namespace NzbDrone.Core.MediaFiles
|
|||
private static readonly Regex ExcludedSubFoldersRegex = new Regex(@"(?:\\|\/|^)(extras|@eadir|extrafanart|plex\sversions|\..+)(?:\\|\/)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private static readonly Regex ExcludedFilesRegex = new Regex(@"^\._|Thumbs\.db", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public void Scan(Artist artist)
|
||||
{
|
||||
var rootFolder = _diskProvider.GetParentFolder(artist.Path);
|
||||
|
||||
if (!_diskProvider.FolderExists(rootFolder))
|
||||
{
|
||||
_logger.Warn("Artist' root folder ({0}) doesn't exist.", rootFolder);
|
||||
_eventAggregator.PublishEvent(new ArtistScanSkippedEvent(artist, ArtistScanSkippedReason.RootFolderDoesNotExist));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_diskProvider.GetDirectories(rootFolder).Empty())
|
||||
{
|
||||
_logger.Warn("Artist' root folder ({0}) is empty.", rootFolder);
|
||||
_eventAggregator.PublishEvent(new ArtistScanSkippedEvent(artist, ArtistScanSkippedReason.RootFolderIsEmpty));
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.ProgressInfo("Scanning disk for {0}", artist.ArtistName);
|
||||
|
||||
if (!_diskProvider.FolderExists(artist.Path))
|
||||
{
|
||||
if (_configService.CreateEmptySeriesFolders)
|
||||
{
|
||||
_logger.Debug("Creating missing artist folder: {0}", artist.Path);
|
||||
_diskProvider.CreateFolder(artist.Path);
|
||||
SetPermissions(artist.Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Artist folder doesn't exist: {0}", artist.Path);
|
||||
}
|
||||
CleanMediaFiles(artist, new List<string>());
|
||||
CompletedScanning(artist);
|
||||
return;
|
||||
}
|
||||
|
||||
var musicFilesStopwatch = Stopwatch.StartNew();
|
||||
var mediaFileList = FilterFiles(artist, GetMusicFiles(artist.Path)).ToList();
|
||||
musicFilesStopwatch.Stop();
|
||||
_logger.Trace("Finished getting track files for: {0} [{1}]", artist, musicFilesStopwatch.Elapsed);
|
||||
|
||||
CleanMediaFiles(artist, mediaFileList);
|
||||
|
||||
var decisionsStopwatch = Stopwatch.StartNew();
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, artist);
|
||||
decisionsStopwatch.Stop();
|
||||
_logger.Trace("Import decisions complete for: {0} [{1}]", artist, decisionsStopwatch.Elapsed);
|
||||
_importApprovedTracks.Import(decisions, false);
|
||||
|
||||
CompletedScanning(artist);
|
||||
}
|
||||
public void Scan(Series series)
|
||||
{
|
||||
var rootFolder = _diskProvider.GetParentFolder(series.Path);
|
||||
|
@ -122,12 +182,24 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_mediaFileTableCleanupService.Clean(series, mediaFileList);
|
||||
}
|
||||
|
||||
private void CleanMediaFiles(Artist artist, List<string> mediaFileList)
|
||||
{
|
||||
_logger.Debug("{0} Cleaning up media files in DB", artist);
|
||||
_mediaFileTableCleanupService.Clean(artist, mediaFileList);
|
||||
}
|
||||
|
||||
private void CompletedScanning(Series series)
|
||||
{
|
||||
_logger.Info("Completed scanning disk for {0}", series.Title);
|
||||
_eventAggregator.PublishEvent(new SeriesScannedEvent(series));
|
||||
}
|
||||
|
||||
private void CompletedScanning(Artist artist)
|
||||
{
|
||||
_logger.Info("Completed scanning disk for {0}", artist.ArtistName);
|
||||
_eventAggregator.PublishEvent(new ArtistScannedEvent(artist));
|
||||
}
|
||||
|
||||
public string[] GetVideoFiles(string path, bool allDirectories = true)
|
||||
{
|
||||
_logger.Debug("Scanning '{0}' for video files", path);
|
||||
|
@ -143,9 +215,24 @@ namespace NzbDrone.Core.MediaFiles
|
|||
return mediaFileList.ToArray();
|
||||
}
|
||||
|
||||
public string[] GetMusicFiles(string path, bool allDirectories = true)
|
||||
{
|
||||
_logger.Debug("Scanning '{0}' for music files", path);
|
||||
|
||||
var searchOption = allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
var filesOnDisk = _diskProvider.GetFiles(path, searchOption).ToList();
|
||||
|
||||
var mediaFileList = filesOnDisk.Where(file => MediaFileExtensions.Extensions.Contains(Path.GetExtension(file).ToLower()))
|
||||
.ToList();
|
||||
|
||||
_logger.Trace("{0} files were found in {1}", filesOnDisk.Count, path);
|
||||
_logger.Debug("{0} video files were found in {1}", mediaFileList.Count, path);
|
||||
return mediaFileList.ToArray();
|
||||
}
|
||||
|
||||
public string[] GetNonVideoFiles(string path, bool allDirectories = true)
|
||||
{
|
||||
_logger.Debug("Scanning '{0}' for non-video files", path);
|
||||
_logger.Debug("Scanning '{0}' for non-music files", path);
|
||||
|
||||
var searchOption = allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
var filesOnDisk = _diskProvider.GetFiles(path, searchOption).ToList();
|
||||
|
@ -154,7 +241,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
.ToList();
|
||||
|
||||
_logger.Trace("{0} files were found in {1}", filesOnDisk.Count, path);
|
||||
_logger.Debug("{0} non-video files were found in {1}", mediaFileList.Count, path);
|
||||
_logger.Debug("{0} non-music files were found in {1}", mediaFileList.Count, path);
|
||||
return mediaFileList.ToArray();
|
||||
}
|
||||
|
||||
|
@ -165,6 +252,13 @@ namespace NzbDrone.Core.MediaFiles
|
|||
.ToList();
|
||||
}
|
||||
|
||||
public List<string> FilterFiles(Artist artist, IEnumerable<string> files)
|
||||
{
|
||||
return files.Where(file => !ExcludedSubFoldersRegex.IsMatch(artist.Path.GetRelativePath(file)))
|
||||
.Where(file => !ExcludedFilesRegex.IsMatch(Path.GetFileName(file)))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private void SetPermissions(string path)
|
||||
{
|
||||
if (!_configService.SetPermissionsLinux)
|
||||
|
@ -191,6 +285,11 @@ namespace NzbDrone.Core.MediaFiles
|
|||
Scan(message.Series);
|
||||
}
|
||||
|
||||
public void Handle(ArtistUpdatedEvent message)
|
||||
{
|
||||
Scan(message.Artist);
|
||||
}
|
||||
|
||||
public void Execute(RescanSeriesCommand message)
|
||||
{
|
||||
if (message.SeriesId.HasValue)
|
||||
|
@ -209,5 +308,24 @@ namespace NzbDrone.Core.MediaFiles
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(RescanArtistCommand message)
|
||||
{
|
||||
if (message.ArtistId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var artist = _artistService.FindById(message.ArtistId);
|
||||
Scan(artist);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
var allArtists = _artistService.GetAllArtists();
|
||||
|
||||
foreach (var artist in allArtists)
|
||||
{
|
||||
Scan(artist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,14 +11,16 @@ using NzbDrone.Core.Parser.Model;
|
|||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
|
||||
using NzbDrone.Core.Music;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
{
|
||||
public interface IMakeImportDecision
|
||||
{
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
||||
//List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
|
||||
List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist);
|
||||
//List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
||||
List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo);
|
||||
}
|
||||
|
||||
public class ImportDecisionMaker : IMakeImportDecision
|
||||
|
@ -48,65 +50,87 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series)
|
||||
//public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series)
|
||||
//{
|
||||
// return GetImportDecisions(videoFiles, series, null, false);
|
||||
//}
|
||||
|
||||
//public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Artist series, ParsedEpisodeInfo folderInfo, bool sceneSource)
|
||||
//{
|
||||
// var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), series);
|
||||
|
||||
// _logger.Debug("Analyzing {0}/{1} files.", newFiles.Count, videoFiles.Count());
|
||||
|
||||
// var shouldUseFolderName = ShouldUseFolderName(videoFiles, series, folderInfo);
|
||||
// var decisions = new List<ImportDecision>();
|
||||
|
||||
// foreach (var file in newFiles)
|
||||
// {
|
||||
// decisions.AddIfNotNull(GetDecision(file, series, folderInfo, sceneSource, shouldUseFolderName));
|
||||
// }
|
||||
|
||||
// return decisions;
|
||||
//}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist)
|
||||
{
|
||||
return GetImportDecisions(videoFiles, series, null, false);
|
||||
return GetImportDecisions(musicFiles, artist, null);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource)
|
||||
public List<ImportDecision> GetImportDecisions(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo)
|
||||
{
|
||||
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), series);
|
||||
var newFiles = _mediaFileService.FilterExistingFiles(musicFiles.ToList(), artist);
|
||||
|
||||
_logger.Debug("Analyzing {0}/{1} files.", newFiles.Count, videoFiles.Count());
|
||||
_logger.Debug("Analyzing {0}/{1} files.", newFiles.Count, musicFiles.Count());
|
||||
|
||||
var shouldUseFolderName = ShouldUseFolderName(videoFiles, series, folderInfo);
|
||||
var shouldUseFolderName = ShouldUseFolderName(musicFiles, artist, folderInfo);
|
||||
var decisions = new List<ImportDecision>();
|
||||
|
||||
foreach (var file in newFiles)
|
||||
{
|
||||
decisions.AddIfNotNull(GetDecision(file, series, folderInfo, sceneSource, shouldUseFolderName));
|
||||
decisions.AddIfNotNull(GetDecision(file, artist, folderInfo, shouldUseFolderName));
|
||||
}
|
||||
|
||||
return decisions;
|
||||
}
|
||||
|
||||
private ImportDecision GetDecision(string file, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
|
||||
private ImportDecision GetDecision(string file, Artist artist, ParsedTrackInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
|
||||
{
|
||||
ImportDecision decision = null;
|
||||
|
||||
try
|
||||
{
|
||||
var localEpisode = _parsingService.GetLocalEpisode(file, series, shouldUseFolderName ? folderInfo : null, sceneSource);
|
||||
var localTrack = _parsingService.GetLocalTrack(file, artist, shouldUseFolderName ? folderInfo : null);
|
||||
|
||||
if (localEpisode != null)
|
||||
if (localTrack != null)
|
||||
{
|
||||
localEpisode.Quality = GetQuality(folderInfo, localEpisode.Quality, series);
|
||||
localEpisode.Size = _diskProvider.GetFileSize(file);
|
||||
localTrack.Quality = GetQuality(folderInfo, localTrack.Quality, artist);
|
||||
localTrack.Size = _diskProvider.GetFileSize(file);
|
||||
|
||||
_logger.Debug("Size: {0}", localEpisode.Size);
|
||||
_logger.Debug("Size: {0}", localTrack.Size);
|
||||
|
||||
//TODO: make it so media info doesn't ruin the import process of a new series
|
||||
if (sceneSource)
|
||||
{
|
||||
localEpisode.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
||||
localTrack.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
||||
}
|
||||
|
||||
if (localEpisode.Episodes.Empty())
|
||||
if (localTrack.Tracks.Empty())
|
||||
{
|
||||
decision = new ImportDecision(localEpisode, new Rejection("Invalid season or episode"));
|
||||
decision = new ImportDecision(localTrack, new Rejection("Invalid album or track"));
|
||||
}
|
||||
else
|
||||
{
|
||||
decision = GetDecision(localEpisode);
|
||||
decision = GetDecision(localTrack);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
localEpisode = new LocalEpisode();
|
||||
localEpisode.Path = file;
|
||||
localTrack = new LocalTrack();
|
||||
localTrack.Path = file;
|
||||
|
||||
decision = new ImportDecision(localEpisode, new Rejection("Unable to parse file"));
|
||||
decision = new ImportDecision(localTrack, new Rejection("Unable to parse file"));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -150,28 +174,28 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
return null;
|
||||
}
|
||||
|
||||
private bool ShouldUseFolderName(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo)
|
||||
private bool ShouldUseFolderName(List<string> musicFiles, Artist artist, ParsedTrackInfo folderInfo)
|
||||
{
|
||||
if (folderInfo == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (folderInfo.FullSeason)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//if (folderInfo.FullSeason)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
return videoFiles.Count(file =>
|
||||
return musicFiles.Count(file =>
|
||||
{
|
||||
var size = _diskProvider.GetFileSize(file);
|
||||
var fileQuality = QualityParser.ParseQuality(file);
|
||||
var sample = _detectSample.IsSample(series, GetQuality(folderInfo, fileQuality, series), file, size, folderInfo.IsPossibleSpecialEpisode);
|
||||
//var sample = _detectSample.IsSample(artist, GetQuality(folderInfo, fileQuality, artist), file, size, folderInfo.IsPossibleSpecialEpisode);
|
||||
|
||||
if (sample)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//if (sample)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if (SceneChecker.IsSceneTitle(Path.GetFileName(file)))
|
||||
{
|
||||
|
@ -182,9 +206,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
}) == 1;
|
||||
}
|
||||
|
||||
private QualityModel GetQuality(ParsedEpisodeInfo folderInfo, QualityModel fileQuality, Series series)
|
||||
private QualityModel GetQuality(ParsedTrackInfo folderInfo, QualityModel fileQuality, Artist artist)
|
||||
{
|
||||
if (UseFolderQuality(folderInfo, fileQuality, series))
|
||||
if (UseFolderQuality(folderInfo, fileQuality, artist))
|
||||
{
|
||||
_logger.Debug("Using quality from folder: {0}", folderInfo.Quality);
|
||||
return folderInfo.Quality;
|
||||
|
@ -193,7 +217,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
return fileQuality;
|
||||
}
|
||||
|
||||
private bool UseFolderQuality(ParsedEpisodeInfo folderInfo, QualityModel fileQuality, Series series)
|
||||
private bool UseFolderQuality(ParsedTrackInfo folderInfo, QualityModel fileQuality, Artist artist)
|
||||
{
|
||||
if (folderInfo == null)
|
||||
{
|
||||
|
@ -210,7 +234,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||
return true;
|
||||
}
|
||||
|
||||
if (new QualityModelComparer(series.Profile).Compare(folderInfo.Quality, fileQuality) > 0)
|
||||
if (new QualityModelComparer(artist.Profile).Compare(folderInfo.Quality, fileQuality) > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Music;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
public class ArtistScanSkippedEvent : IEvent
|
||||
{
|
||||
public Artist Artist { get; private set; }
|
||||
public ArtistScanSkippedReason Reason { get; private set; }
|
||||
|
||||
public ArtistScanSkippedEvent(Artist artist, ArtistScanSkippedReason reason)
|
||||
{
|
||||
Artist = artist;
|
||||
Reason = reason;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ArtistScanSkippedReason
|
||||
{
|
||||
RootFolderDoesNotExist,
|
||||
RootFolderIsEmpty
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Music;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
public class ArtistScannedEvent : IEvent
|
||||
{
|
||||
public Artist Artist { get; private set; }
|
||||
|
||||
public ArtistScannedEvent(Artist artist)
|
||||
{
|
||||
Artist = artist;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
@ -5,36 +6,28 @@ using NzbDrone.Core.Messaging.Events;
|
|||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IMediaFileRepository : IBasicRepository<EpisodeFile>
|
||||
public interface IMediaFileRepository : IBasicRepository<TrackFile>
|
||||
{
|
||||
List<EpisodeFile> GetFilesBySeries(int seriesId);
|
||||
List<EpisodeFile> GetFilesBySeason(int seriesId, int seasonNumber);
|
||||
List<EpisodeFile> GetFilesWithoutMediaInfo();
|
||||
List<TrackFile> GetFilesByArtist(string artistId);
|
||||
List<TrackFile> GetFilesWithoutMediaInfo();
|
||||
}
|
||||
|
||||
|
||||
public class MediaFileRepository : BasicRepository<EpisodeFile>, IMediaFileRepository
|
||||
public class MediaFileRepository : BasicRepository<TrackFile>, IMediaFileRepository
|
||||
{
|
||||
public MediaFileRepository(IMainDatabase database, IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public List<EpisodeFile> GetFilesBySeries(int seriesId)
|
||||
{
|
||||
return Query.Where(c => c.SeriesId == seriesId).ToList();
|
||||
}
|
||||
|
||||
public List<EpisodeFile> GetFilesBySeason(int seriesId, int seasonNumber)
|
||||
{
|
||||
return Query.Where(c => c.SeriesId == seriesId)
|
||||
.AndWhere(c => c.SeasonNumber == seasonNumber)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<EpisodeFile> GetFilesWithoutMediaInfo()
|
||||
public List<TrackFile> GetFilesWithoutMediaInfo()
|
||||
{
|
||||
return Query.Where(c => c.MediaInfo == null).ToList();
|
||||
}
|
||||
|
||||
public List<TrackFile> GetFilesByArtist(string artistId)
|
||||
{
|
||||
return Query.Where(c => c.SpotifyTrackId == artistId).ToList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,24 +7,26 @@ using NzbDrone.Core.Messaging.Events;
|
|||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Music;
|
||||
using System;
|
||||
using NzbDrone.Core.Music.Events;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IMediaFileService
|
||||
{
|
||||
EpisodeFile Add(EpisodeFile episodeFile);
|
||||
void Update(EpisodeFile episodeFile);
|
||||
void Delete(EpisodeFile episodeFile, DeleteMediaFileReason reason);
|
||||
List<EpisodeFile> GetFilesBySeries(int seriesId);
|
||||
List<EpisodeFile> GetFilesBySeason(int seriesId, int seasonNumber);
|
||||
List<EpisodeFile> GetFilesWithoutMediaInfo();
|
||||
List<string> FilterExistingFiles(List<string> files, Series series);
|
||||
EpisodeFile Get(int id);
|
||||
List<EpisodeFile> Get(IEnumerable<int> ids);
|
||||
TrackFile Add(TrackFile trackFile);
|
||||
void Update(TrackFile trackFile);
|
||||
void Delete(TrackFile trackFile, DeleteMediaFileReason reason);
|
||||
List<TrackFile> GetFilesByArtist(string artistId);
|
||||
List<TrackFile> GetFilesWithoutMediaInfo();
|
||||
List<string> FilterExistingFiles(List<string> files, Artist artist);
|
||||
TrackFile Get(int id);
|
||||
List<TrackFile> Get(IEnumerable<int> ids);
|
||||
|
||||
}
|
||||
|
||||
public class MediaFileService : IMediaFileService, IHandleAsync<SeriesDeletedEvent>
|
||||
public class MediaFileService : IMediaFileService, IHandleAsync<ArtistDeletedEvent>
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IMediaFileRepository _mediaFileRepository;
|
||||
|
@ -37,66 +39,63 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public EpisodeFile Add(EpisodeFile episodeFile)
|
||||
public TrackFile Add(TrackFile trackFile)
|
||||
{
|
||||
var addedFile = _mediaFileRepository.Insert(episodeFile);
|
||||
_eventAggregator.PublishEvent(new EpisodeFileAddedEvent(addedFile));
|
||||
var addedFile = _mediaFileRepository.Insert(trackFile);
|
||||
_eventAggregator.PublishEvent(new TrackFileAddedEvent(addedFile));
|
||||
return addedFile;
|
||||
}
|
||||
|
||||
public void Update(EpisodeFile episodeFile)
|
||||
public void Update(TrackFile trackFile)
|
||||
{
|
||||
_mediaFileRepository.Update(episodeFile);
|
||||
_mediaFileRepository.Update(trackFile);
|
||||
}
|
||||
|
||||
public void Delete(EpisodeFile episodeFile, DeleteMediaFileReason reason)
|
||||
public void Delete(TrackFile trackFile, DeleteMediaFileReason reason)
|
||||
{
|
||||
//Little hack so we have the episodes and series attached for the event consumers
|
||||
episodeFile.Episodes.LazyLoad();
|
||||
episodeFile.Path = Path.Combine(episodeFile.Series.Value.Path, episodeFile.RelativePath);
|
||||
//Little hack so we have the tracks and artist attached for the event consumers
|
||||
trackFile.Episodes.LazyLoad();
|
||||
trackFile.Path = Path.Combine(trackFile.Artist.Value.Path, trackFile.RelativePath);
|
||||
|
||||
_mediaFileRepository.Delete(episodeFile);
|
||||
_eventAggregator.PublishEvent(new EpisodeFileDeletedEvent(episodeFile, reason));
|
||||
_mediaFileRepository.Delete(trackFile);
|
||||
_eventAggregator.PublishEvent(new TrackFileDeletedEvent(trackFile, reason));
|
||||
}
|
||||
|
||||
public List<EpisodeFile> GetFilesBySeries(int seriesId)
|
||||
{
|
||||
return _mediaFileRepository.GetFilesBySeries(seriesId);
|
||||
}
|
||||
|
||||
public List<EpisodeFile> GetFilesBySeason(int seriesId, int seasonNumber)
|
||||
{
|
||||
return _mediaFileRepository.GetFilesBySeason(seriesId, seasonNumber);
|
||||
}
|
||||
|
||||
public List<EpisodeFile> GetFilesWithoutMediaInfo()
|
||||
public List<TrackFile> GetFilesWithoutMediaInfo()
|
||||
{
|
||||
return _mediaFileRepository.GetFilesWithoutMediaInfo();
|
||||
}
|
||||
|
||||
public List<string> FilterExistingFiles(List<string> files, Series series)
|
||||
public List<string> FilterExistingFiles(List<string> files, Artist artist)
|
||||
{
|
||||
var seriesFiles = GetFilesBySeries(series.Id).Select(f => Path.Combine(series.Path, f.RelativePath)).ToList();
|
||||
var artistFiles = GetFilesByArtist(artist.SpotifyId).Select(f => Path.Combine(artist.Path, f.RelativePath)).ToList();
|
||||
|
||||
if (!seriesFiles.Any()) return files;
|
||||
if (!artistFiles.Any()) return files;
|
||||
|
||||
return files.Except(seriesFiles, PathEqualityComparer.Instance).ToList();
|
||||
return files.Except(artistFiles, PathEqualityComparer.Instance).ToList();
|
||||
}
|
||||
|
||||
public EpisodeFile Get(int id)
|
||||
public TrackFile Get(int id)
|
||||
{
|
||||
// TODO: Should this be spotifyID or DB Id?
|
||||
return _mediaFileRepository.Get(id);
|
||||
}
|
||||
|
||||
public List<EpisodeFile> Get(IEnumerable<int> ids)
|
||||
public List<TrackFile> Get(IEnumerable<int> ids)
|
||||
{
|
||||
return _mediaFileRepository.Get(ids).ToList();
|
||||
}
|
||||
|
||||
public void HandleAsync(SeriesDeletedEvent message)
|
||||
public void HandleAsync(ArtistDeletedEvent message)
|
||||
{
|
||||
var files = GetFilesBySeries(message.Series.Id);
|
||||
var files = GetFilesByArtist(message.Artist.SpotifyId);
|
||||
_mediaFileRepository.DeleteMany(files);
|
||||
}
|
||||
|
||||
public List<TrackFile> GetFilesByArtist(string artistId)
|
||||
{
|
||||
return _mediaFileRepository.GetFilesByArtist(artistId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
{
|
||||
public class TrackFile : ModelBase
|
||||
{
|
||||
public int ItunesTrackId { get; set; }
|
||||
public string SpotifyTrackId { get; set; }
|
||||
public int AlbumId { get; set; }
|
||||
public string RelativePath { get; set; }
|
||||
public string Path { get; set; }
|
||||
|
|
|
@ -89,11 +89,12 @@ namespace NzbDrone.Core.Music
|
|||
return _artistRepository.All().ToList();
|
||||
}
|
||||
|
||||
public Artist GetArtist(int artistId)
|
||||
public Artist GetArtist(int artistDBId)
|
||||
{
|
||||
return _artistRepository.Get(artistId);
|
||||
return _artistRepository.Get(artistDBId);
|
||||
}
|
||||
|
||||
|
||||
public List<Artist> GetArtists(IEnumerable<int> artistIds)
|
||||
{
|
||||
return _artistRepository.Get(artistIds).ToList();
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace NzbDrone.Core.Music
|
|||
try
|
||||
{
|
||||
_logger.Info("Skipping refresh of artist: {0}", artist.ArtistName);
|
||||
//TODO: _diskScanService.Scan(artist);
|
||||
_diskScanService.Scan(artist);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Parser.Model
|
||||
{
|
||||
public class ArtistTitleInfo
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string TitleWithoutYear { get; set; }
|
||||
public int Year { get; set; }
|
||||
}
|
||||
}
|
|
@ -9,87 +9,34 @@ namespace NzbDrone.Core.Parser.Model
|
|||
{
|
||||
public class ParsedTrackInfo
|
||||
{
|
||||
// [TODO]: Properly fill this out
|
||||
public string ArtistTitle { get; set; }
|
||||
public string AlbumTitle { get; set; }
|
||||
public SeriesTitleInfo SeriesTitleInfo { get; set; }
|
||||
public ArtistTitleInfo ArtistTitleInfo { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public int[] EpisodeNumbers { get; set; }
|
||||
public int[] AbsoluteEpisodeNumbers { get; set; }
|
||||
public string AirDate { get; set; }
|
||||
public Language Language { get; set; }
|
||||
public bool FullSeason { get; set; }
|
||||
public bool Special { get; set; }
|
||||
public string AlbumId { get; set; } // maybe
|
||||
public int[] TrackNumbers { get; set; }
|
||||
//public Language Language { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
public string ReleaseHash { get; set; }
|
||||
|
||||
public ParsedTrackInfo()
|
||||
{
|
||||
EpisodeNumbers = new int[0];
|
||||
AbsoluteEpisodeNumbers = new int[0];
|
||||
TrackNumbers = new int[0];
|
||||
}
|
||||
|
||||
public bool IsDaily
|
||||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(AirDate);
|
||||
}
|
||||
|
||||
//This prevents manually downloading a release from blowing up in mono
|
||||
//TODO: Is there a better way?
|
||||
private set { }
|
||||
}
|
||||
|
||||
public bool IsAbsoluteNumbering
|
||||
{
|
||||
get
|
||||
{
|
||||
return AbsoluteEpisodeNumbers.Any();
|
||||
}
|
||||
|
||||
//This prevents manually downloading a release from blowing up in mono
|
||||
//TODO: Is there a better way?
|
||||
private set { }
|
||||
}
|
||||
|
||||
public bool IsPossibleSpecialEpisode
|
||||
{
|
||||
get
|
||||
{
|
||||
// if we don't have eny episode numbers we are likely a special episode and need to do a search by episode title
|
||||
return (AirDate.IsNullOrWhiteSpace() &&
|
||||
ArtistTitle.IsNullOrWhiteSpace() &&
|
||||
(EpisodeNumbers.Length == 0 || SeasonNumber == 0) ||
|
||||
!ArtistTitle.IsNullOrWhiteSpace() && Special);
|
||||
}
|
||||
|
||||
//This prevents manually downloading a release from blowing up in mono
|
||||
//TODO: Is there a better way?
|
||||
private set { }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string episodeString = "[Unknown Episode]";
|
||||
string episodeString = "[Unknown Track]";
|
||||
|
||||
if (IsDaily && EpisodeNumbers.Empty())
|
||||
|
||||
if (TrackNumbers != null && TrackNumbers.Any())
|
||||
{
|
||||
episodeString = string.Format("{0}", AirDate);
|
||||
}
|
||||
else if (FullSeason)
|
||||
{
|
||||
episodeString = string.Format("Season {0:00}", SeasonNumber);
|
||||
}
|
||||
else if (EpisodeNumbers != null && EpisodeNumbers.Any())
|
||||
{
|
||||
episodeString = string.Format("S{0:00}E{1}", SeasonNumber, string.Join("-", EpisodeNumbers.Select(c => c.ToString("00"))));
|
||||
}
|
||||
else if (AbsoluteEpisodeNumbers != null && AbsoluteEpisodeNumbers.Any())
|
||||
{
|
||||
episodeString = string.Format("{0}", string.Join("-", AbsoluteEpisodeNumbers.Select(c => c.ToString("000"))));
|
||||
episodeString = string.Format("T{1}", string.Join("-", TrackNumbers.Select(c => c.ToString("00"))));
|
||||
}
|
||||
|
||||
|
||||
return string.Format("{0} - {1} {2}", ArtistTitle, episodeString, Quality);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
// Music stuff here
|
||||
LocalTrack GetLocalTrack(string filename, Artist artist);
|
||||
LocalTrack GetLocalTrack(string filename, Artist artist, ParsedTrackInfo folderInfo, bool sceneSource);
|
||||
LocalTrack GetLocalTrack(string filename, Artist artist, ParsedTrackInfo folderInfo);
|
||||
|
||||
}
|
||||
|
||||
|
@ -40,12 +40,14 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
public ParsingService(IEpisodeService episodeService,
|
||||
ISeriesService seriesService,
|
||||
ITrackService trackService,
|
||||
// ISceneMappingService sceneMappingService,
|
||||
Logger logger)
|
||||
{
|
||||
_episodeService = episodeService;
|
||||
_seriesService = seriesService;
|
||||
// _sceneMappingService = sceneMappingService;
|
||||
_trackService = trackService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -407,6 +409,73 @@ namespace NzbDrone.Core.Parser
|
|||
return result;
|
||||
}
|
||||
|
||||
private List<Track> GetStandardTracks(Artist artist, ParsedTrackInfo parsedTrackInfo, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var result = new List<Track>();
|
||||
|
||||
if (parsedTrackInfo.TrackNumbers == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var trackNumber in parsedTrackInfo.TrackNumbers)
|
||||
{
|
||||
//if (series.UseSceneNumbering && sceneSource)
|
||||
//{
|
||||
// List<Episode> episodes = new List<Episode>();
|
||||
|
||||
// if (searchCriteria != null)
|
||||
// {
|
||||
// episodes = searchCriteria.Episodes.Where(e => e.SceneSeasonNumber == parsedTrackInfo.SeasonNumber &&
|
||||
// e.SceneEpisodeNumber == trackNumber).ToList();
|
||||
// }
|
||||
|
||||
// if (!episodes.Any())
|
||||
// {
|
||||
// episodes = _episodeService.FindEpisodesBySceneNumbering(series.Id, seasonNumber, trackNumber);
|
||||
// }
|
||||
|
||||
// if (episodes != null && episodes.Any())
|
||||
// {
|
||||
// _logger.Debug("Using Scene to TVDB Mapping for: {0} - Scene: {1}x{2:00} - TVDB: {3}",
|
||||
// series.Title,
|
||||
// episodes.First().SceneSeasonNumber,
|
||||
// episodes.First().SceneEpisodeNumber,
|
||||
// string.Join(", ", episodes.Select(e => string.Format("{0}x{1:00}", e.SeasonNumber, e.EpisodeNumber))));
|
||||
|
||||
// result.AddRange(episodes);
|
||||
// continue;
|
||||
// }
|
||||
//}
|
||||
|
||||
Track trackInfo = null;
|
||||
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
trackInfo = searchCriteria.Tracks.SingleOrDefault(e => e.TrackNumber == trackNumber); //e => e.SeasonNumber == seasonNumber && e.TrackNumber == trackNumber
|
||||
}
|
||||
|
||||
if (trackInfo == null)
|
||||
{
|
||||
trackInfo = _trackService.FindTrack(artist.SpotifyId, trackNumber);
|
||||
}
|
||||
|
||||
if (trackInfo != null)
|
||||
{
|
||||
result.Add(trackInfo);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_logger.Debug("Unable to find {0}", parsedEpisodeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Episode> GetStandardEpisodes(Series series, ParsedEpisodeInfo parsedEpisodeInfo, bool sceneSource, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var result = new List<Episode>();
|
||||
|
@ -486,10 +555,10 @@ namespace NzbDrone.Core.Parser
|
|||
|
||||
public LocalTrack GetLocalTrack(string filename, Artist artist)
|
||||
{
|
||||
return GetLocalTrack(filename, artist, null, false);
|
||||
return GetLocalTrack(filename, artist, null);
|
||||
}
|
||||
|
||||
public LocalTrack GetLocalTrack(string filename, Artist artist, ParsedTrackInfo folderInfo, bool sceneSource)
|
||||
public LocalTrack GetLocalTrack(string filename, Artist artist, ParsedTrackInfo folderInfo)
|
||||
{
|
||||
ParsedTrackInfo parsedTrackInfo;
|
||||
|
||||
|
@ -504,7 +573,7 @@ namespace NzbDrone.Core.Parser
|
|||
parsedTrackInfo = Parser.ParseMusicPath(filename);
|
||||
}
|
||||
|
||||
if (parsedTrackInfo == null || parsedTrackInfo.IsPossibleSpecialEpisode)
|
||||
if (parsedTrackInfo == null)
|
||||
{
|
||||
var title = Path.GetFileNameWithoutExtension(filename);
|
||||
//var specialEpisodeInfo = ParseSpecialEpisodeTitle(title, series);
|
||||
|
@ -525,7 +594,7 @@ namespace NzbDrone.Core.Parser
|
|||
return null;
|
||||
}
|
||||
|
||||
var tracks = GetTracks(parsedTrackInfo, artist, sceneSource);
|
||||
var tracks = GetTracks(parsedTrackInfo, artist);
|
||||
|
||||
return new LocalTrack
|
||||
{
|
||||
|
@ -538,10 +607,10 @@ namespace NzbDrone.Core.Parser
|
|||
};
|
||||
}
|
||||
|
||||
private List<Track> GetTracks(ParsedTrackInfo parsedTrackInfo, Artist artist, bool sceneSource)
|
||||
private List<Track> GetTracks(ParsedTrackInfo parsedTrackInfo, Artist artist)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
// TODO: Ensure GetTracks(parsedTrackInfo, artist) doesn't need any checks
|
||||
/*if (parsedTrackInfo.FullSeason) // IF Album
|
||||
{
|
||||
return _trackService.GetTracksByAlbumTitle(artist.Id, parsedTrackInfo.AlbumTitle);
|
||||
|
@ -566,6 +635,7 @@ namespace NzbDrone.Core.Parser
|
|||
}
|
||||
|
||||
return GetStandardEpisodes(artist, parsedTrackInfo, sceneSource, searchCriteria);*/
|
||||
return GetStandardTracks(artist, parsedTrackInfo, searchCriteria);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ var ReleaseLayout = require('./Release/ReleaseLayout');
|
|||
var SystemLayout = require('./System/SystemLayout');
|
||||
var SeasonPassLayout = require('./SeasonPass/SeasonPassLayout');
|
||||
var SeriesEditorLayout = require('./Series/Editor/SeriesEditorLayout');
|
||||
var SeriesDetailsLayout = require('./Series/Details/SeriesDetailsLayout');
|
||||
|
||||
module.exports = NzbDroneController.extend({
|
||||
addSeries : function(action) {
|
||||
|
@ -17,6 +18,11 @@ module.exports = NzbDroneController.extend({
|
|||
this.showMainRegion(new AddSeriesLayout({ action : action }));
|
||||
},
|
||||
|
||||
artistDetails: function(query) {
|
||||
this.setTitle('Artist Detail');
|
||||
this.showMainRegion(new SeriesDetailsLayout());
|
||||
},
|
||||
|
||||
calendar : function() {
|
||||
this.setTitle('Calendar');
|
||||
this.showMainRegion(new CalendarLayout());
|
||||
|
|
|
@ -18,6 +18,7 @@ module.exports = Marionette.AppRouter.extend({
|
|||
'rss' : 'rss',
|
||||
'system' : 'system',
|
||||
'system/:action' : 'system',
|
||||
'artist/:query' : 'artistDetails',
|
||||
'seasonpass' : 'seasonPass',
|
||||
'serieseditor' : 'seriesEditor',
|
||||
':whatever' : 'showNotFound'
|
||||
|
|
|
@ -48,9 +48,10 @@ module.exports = Marionette.Layout.extend({
|
|||
this.seriesCollection = ArtistCollection.clone();
|
||||
this.seriesCollection.shadowCollection.bindSignalR();
|
||||
|
||||
|
||||
this.listenTo(this.model, 'change:monitored', this._setMonitoredState);
|
||||
this.listenTo(this.model, 'remove', this._seriesRemoved);
|
||||
this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
|
||||
//this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
|
||||
|
||||
this.listenTo(this.model, 'change', function(model, options) {
|
||||
if (options && options.changeSource === 'signalr') {
|
||||
|
@ -59,6 +60,7 @@ module.exports = Marionette.Layout.extend({
|
|||
});
|
||||
|
||||
this.listenTo(this.model, 'change:images', this._updateImages);
|
||||
|
||||
},
|
||||
|
||||
onShow : function() {
|
||||
|
@ -81,15 +83,16 @@ module.exports = Marionette.Layout.extend({
|
|||
name : 'seriesSearch'
|
||||
}
|
||||
});
|
||||
console.log(this.model);
|
||||
|
||||
CommandController.bindToCommand({
|
||||
/*CommandController.bindToCommand({
|
||||
element : this.ui.rename,
|
||||
command : {
|
||||
name : 'renameFiles',
|
||||
seriesId : this.model.id,
|
||||
seriesId : this.model.spotifyId,
|
||||
seasonNumber : -1
|
||||
}
|
||||
});
|
||||
});*/
|
||||
},
|
||||
|
||||
onClose : function() {
|
||||
|
@ -164,6 +167,7 @@ module.exports = Marionette.Layout.extend({
|
|||
|
||||
_showSeasons : function() {
|
||||
var self = this;
|
||||
return;
|
||||
|
||||
this.seasons.show(new LoadingView());
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="col-md-10 col-xs-9">
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-xs-10">
|
||||
<a href="artist/{{artistNameSlug}}" target="_blank">
|
||||
<a href="artist/{{artistSlug}}" target="_blank">
|
||||
<h2>{{artistName}}</h2>
|
||||
</a>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue