mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
Merge branch 'AirDate' of https://github.com/JackDandy/NzbDrone into set-file-date
This commit is contained in:
commit
8478379ff4
@ -6,6 +6,7 @@ namespace NzbDrone.Api.Config
|
|||||||
public class MediaManagementConfigResource : RestResource
|
public class MediaManagementConfigResource : RestResource
|
||||||
{
|
{
|
||||||
public Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
|
public Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
|
||||||
|
public Boolean FileDateAiredDate { get; set; }
|
||||||
public String RecycleBin { get; set; }
|
public String RecycleBin { get; set; }
|
||||||
public Boolean AutoDownloadPropers { get; set; }
|
public Boolean AutoDownloadPropers { get; set; }
|
||||||
public Boolean CreateEmptySeriesFolders { get; set; }
|
public Boolean CreateEmptySeriesFolders { get; set; }
|
||||||
|
@ -35,7 +35,7 @@ private List<LogFileResource> GetLogFiles()
|
|||||||
{
|
{
|
||||||
Id = i + 1,
|
Id = i + 1,
|
||||||
Filename = Path.GetFileName(file),
|
Filename = Path.GetFileName(file),
|
||||||
LastWriteTime = _diskProvider.GetLastFileWrite(file)
|
LastWriteTime = _diskProvider.GetLastFileWriteUTC(file)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,20 @@ public DateTime GetLastFolderWrite(string path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DateTime GetLastFileWrite(string path)
|
public DateTime GetLastFileWrite(string path)
|
||||||
|
{
|
||||||
|
PathEnsureFileExists(path);
|
||||||
|
|
||||||
|
return new FileInfo(path).LastWriteTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime GetLastFileWriteUTC(string path)
|
||||||
|
{
|
||||||
|
PathEnsureFileExists(path);
|
||||||
|
|
||||||
|
return new FileInfo(path).LastWriteTimeUtc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PathEnsureFileExists(string path)
|
||||||
{
|
{
|
||||||
Ensure.That(path, () => path).IsValidPath();
|
Ensure.That(path, () => path).IsValidPath();
|
||||||
|
|
||||||
@ -84,8 +98,6 @@ public DateTime GetLastFileWrite(string path)
|
|||||||
{
|
{
|
||||||
throw new FileNotFoundException("File doesn't exist: " + path);
|
throw new FileNotFoundException("File doesn't exist: " + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FileInfo(path).LastWriteTimeUtc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureFolder(string path)
|
public void EnsureFolder(string path)
|
||||||
@ -305,6 +317,26 @@ public void FolderSetLastWriteTimeUtc(string path, DateTime dateTime)
|
|||||||
Directory.SetLastWriteTimeUtc(path, dateTime);
|
Directory.SetLastWriteTimeUtc(path, dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void FileSetLastWriteTime(string path, DateTime dateTime)
|
||||||
|
{
|
||||||
|
Ensure.That(path, () => path).IsValidPath();
|
||||||
|
|
||||||
|
File.SetLastWriteTime(path, dateTime);
|
||||||
|
}
|
||||||
|
public void FileSetLastAccessTime(string path, DateTime dateTime)
|
||||||
|
{
|
||||||
|
Ensure.That(path, () => path).IsValidPath();
|
||||||
|
|
||||||
|
File.SetLastAccessTimeUtc(path, dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FileSetLastAccessTimeUtc(string path, DateTime dateTime)
|
||||||
|
{
|
||||||
|
Ensure.That(path, () => path).IsValidPath();
|
||||||
|
|
||||||
|
File.SetLastAccessTimeUtc(path, dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsFileLocked(string file)
|
public bool IsFileLocked(string file)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -14,6 +14,7 @@ public interface IDiskProvider
|
|||||||
|
|
||||||
DateTime GetLastFolderWrite(string path);
|
DateTime GetLastFolderWrite(string path);
|
||||||
DateTime GetLastFileWrite(string path);
|
DateTime GetLastFileWrite(string path);
|
||||||
|
DateTime GetLastFileWriteUTC(string path);
|
||||||
void EnsureFolder(string path);
|
void EnsureFolder(string path);
|
||||||
bool FolderExists(string path);
|
bool FolderExists(string path);
|
||||||
bool FileExists(string path);
|
bool FileExists(string path);
|
||||||
@ -33,6 +34,8 @@ public interface IDiskProvider
|
|||||||
void WriteAllText(string filename, string contents);
|
void WriteAllText(string filename, string contents);
|
||||||
void FileSetLastWriteTimeUtc(string path, DateTime dateTime);
|
void FileSetLastWriteTimeUtc(string path, DateTime dateTime);
|
||||||
void FolderSetLastWriteTimeUtc(string path, DateTime dateTime);
|
void FolderSetLastWriteTimeUtc(string path, DateTime dateTime);
|
||||||
|
void FileSetLastWriteTime(string path, DateTime dateTime);
|
||||||
|
void FileSetLastAccessTime(string path, DateTime dateTime);
|
||||||
bool IsFileLocked(string path);
|
bool IsFileLocked(string path);
|
||||||
string GetPathRoot(string path);
|
string GetPathRoot(string path);
|
||||||
string GetParentFolder(string path);
|
string GetParentFolder(string path);
|
||||||
|
@ -29,7 +29,7 @@ public void should_convert_trakts_urls_to_local()
|
|||||||
new MediaCover.MediaCover {CoverType = MediaCoverTypes.Banner}
|
new MediaCover.MediaCover {CoverType = MediaCoverTypes.Banner}
|
||||||
};
|
};
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetLastFileWrite(It.IsAny<string>()))
|
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetLastFileWriteUTC(It.IsAny<string>()))
|
||||||
.Returns(new DateTime(1234));
|
.Returns(new DateTime(1234));
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileExists(It.IsAny<string>()))
|
Mocker.GetMock<IDiskProvider>().Setup(c => c.FileExists(It.IsAny<string>()))
|
||||||
|
@ -42,7 +42,7 @@ private void GivenInWorkingFolder()
|
|||||||
private void GivenLastWriteTimeUtc(DateTime time)
|
private void GivenLastWriteTimeUtc(DateTime time)
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Setup(s => s.GetLastFileWrite(It.IsAny<string>()))
|
.Setup(s => s.GetLastFileWriteUTC(It.IsAny<string>()))
|
||||||
.Returns(time);
|
.Returns(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ private void WithExpired()
|
|||||||
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFolderWrite(It.IsAny<String>()))
|
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFolderWrite(It.IsAny<String>()))
|
||||||
.Returns(DateTime.UtcNow.AddDays(-10));
|
.Returns(DateTime.UtcNow.AddDays(-10));
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFileWrite(It.IsAny<String>()))
|
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFileWriteUTC(It.IsAny<String>()))
|
||||||
.Returns(DateTime.UtcNow.AddDays(-10));
|
.Returns(DateTime.UtcNow.AddDays(-10));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ private void WithNonExpired()
|
|||||||
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFolderWrite(It.IsAny<String>()))
|
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFolderWrite(It.IsAny<String>()))
|
||||||
.Returns(DateTime.UtcNow.AddDays(-3));
|
.Returns(DateTime.UtcNow.AddDays(-3));
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFileWrite(It.IsAny<String>()))
|
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFileWriteUTC(It.IsAny<String>()))
|
||||||
.Returns(DateTime.UtcNow.AddDays(-3));
|
.Returns(DateTime.UtcNow.AddDays(-3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,12 @@ public bool AutoUnmonitorPreviouslyDownloadedEpisodes
|
|||||||
set { SetValue("AutoUnmonitorPreviouslyDownloadedEpisodes", value); }
|
set { SetValue("AutoUnmonitorPreviouslyDownloadedEpisodes", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool FileDateAiredDate
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("FileDateAiredDate"); }
|
||||||
|
set { SetValue("FileDateAiredDate", value); }
|
||||||
|
}
|
||||||
|
|
||||||
public int Retention
|
public int Retention
|
||||||
{
|
{
|
||||||
get { return GetValueInt("Retention", 0); }
|
get { return GetValueInt("Retention", 0); }
|
||||||
|
@ -20,6 +20,7 @@ public interface IConfigService
|
|||||||
|
|
||||||
//Media Management
|
//Media Management
|
||||||
Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
|
Boolean AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
|
||||||
|
Boolean FileDateAiredDate { get; set; }
|
||||||
String RecycleBin { get; set; }
|
String RecycleBin { get; set; }
|
||||||
Boolean AutoDownloadPropers { get; set; }
|
Boolean AutoDownloadPropers { get; set; }
|
||||||
Boolean CreateEmptySeriesFolders { get; set; }
|
Boolean CreateEmptySeriesFolders { get; set; }
|
||||||
|
@ -67,7 +67,7 @@ public void ConvertToLocalUrls(int seriesId, IEnumerable<MediaCover> covers)
|
|||||||
|
|
||||||
if (_diskProvider.FileExists(filePath))
|
if (_diskProvider.FileExists(filePath))
|
||||||
{
|
{
|
||||||
var lastWrite = _diskProvider.GetLastFileWrite(filePath);
|
var lastWrite = _diskProvider.GetLastFileWriteUTC(filePath);
|
||||||
mediaCover.Url += "?lastWrite=" + lastWrite.Ticks;
|
mediaCover.Url += "?lastWrite=" + lastWrite.Ticks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
|
{
|
||||||
|
public class AirDateSeriesCommand : Command
|
||||||
|
{
|
||||||
|
public List<int> SeriesIds { get; set; }
|
||||||
|
|
||||||
|
public override bool SendUpdatesToClient
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,18 +22,21 @@ public interface IMoveEpisodeFiles
|
|||||||
public class EpisodeFileMovingService : IMoveEpisodeFiles
|
public class EpisodeFileMovingService : IMoveEpisodeFiles
|
||||||
{
|
{
|
||||||
private readonly IEpisodeService _episodeService;
|
private readonly IEpisodeService _episodeService;
|
||||||
|
private readonly IUpdateEpisodeFileService _updateEpisodeFileService;
|
||||||
private readonly IBuildFileNames _buildFileNames;
|
private readonly IBuildFileNames _buildFileNames;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public EpisodeFileMovingService(IEpisodeService episodeService,
|
public EpisodeFileMovingService(IEpisodeService episodeService,
|
||||||
|
IUpdateEpisodeFileService updateEpisodeFileService,
|
||||||
IBuildFileNames buildFileNames,
|
IBuildFileNames buildFileNames,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
|
_updateEpisodeFileService = updateEpisodeFileService;
|
||||||
_buildFileNames = buildFileNames;
|
_buildFileNames = buildFileNames;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
@ -102,6 +105,11 @@ private EpisodeFile MoveFile(EpisodeFile episodeFile, Series series, string dest
|
|||||||
_diskProvider.MoveFile(episodeFile.Path, destinationFilename);
|
_diskProvider.MoveFile(episodeFile.Path, destinationFilename);
|
||||||
episodeFile.Path = destinationFilename;
|
episodeFile.Path = destinationFilename;
|
||||||
|
|
||||||
|
if (_configService.FileDateAiredDate)
|
||||||
|
{
|
||||||
|
_updateEpisodeFileService.ChangeFileDateToAirdate(episodeFile, series);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.Trace("Setting last write time on series folder: {0}", series.Path);
|
_logger.Trace("Setting last write time on series folder: {0}", series.Path);
|
||||||
|
@ -42,7 +42,7 @@ public bool IsSatisfiedBy(LocalEpisode localEpisode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_diskProvider.GetLastFileWrite(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5))
|
if (_diskProvider.GetLastFileWriteUTC(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5))
|
||||||
{
|
{
|
||||||
_logger.Trace("{0} appears to be unpacking still", localEpisode.Path);
|
_logger.Trace("{0} appears to be unpacking still", localEpisode.Path);
|
||||||
return false;
|
return false;
|
||||||
|
15
src/NzbDrone.Core/MediaFiles/Events/SeriesAirDatedEvent.cs
Normal file
15
src/NzbDrone.Core/MediaFiles/Events/SeriesAirDatedEvent.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.Events
|
||||||
|
{
|
||||||
|
public class SeriesAirDatedEvent : IEvent
|
||||||
|
{
|
||||||
|
public Series Series { get; private set; }
|
||||||
|
|
||||||
|
public SeriesAirDatedEvent(Series series)
|
||||||
|
{
|
||||||
|
Series = series;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -139,7 +139,7 @@ public void Cleanup()
|
|||||||
|
|
||||||
foreach (var file in _diskProvider.GetFiles(_configService.RecycleBin, SearchOption.TopDirectoryOnly))
|
foreach (var file in _diskProvider.GetFiles(_configService.RecycleBin, SearchOption.TopDirectoryOnly))
|
||||||
{
|
{
|
||||||
if (_diskProvider.GetLastFileWrite(file).AddDays(7) > DateTime.UtcNow)
|
if (_diskProvider.GetLastFileWriteUTC(file).AddDays(7) > DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
logger.Trace("File hasn't expired yet, skipping: {0}", file);
|
logger.Trace("File hasn't expired yet, skipping: {0}", file);
|
||||||
continue;
|
continue;
|
||||||
|
156
src/NzbDrone.Core/MediaFiles/UpdateEpisodeFileService.cs
Normal file
156
src/NzbDrone.Core/MediaFiles/UpdateEpisodeFileService.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Instrumentation;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Instrumentation;
|
||||||
|
using NzbDrone.Core.MediaFiles.Commands;
|
||||||
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
{
|
||||||
|
public interface IUpdateEpisodeFileService
|
||||||
|
{
|
||||||
|
void ChangeFileDateToAirdate(EpisodeFile episodeFile, Series series);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateEpisodeFileService : IUpdateEpisodeFileService,
|
||||||
|
IExecute<AirDateSeriesCommand>,
|
||||||
|
IHandle<SeriesScannedEvent>
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
private readonly ISeriesService _seriesService;
|
||||||
|
private readonly IEpisodeService _episodeService;
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public UpdateEpisodeFileService(IDiskProvider diskProvider,
|
||||||
|
IConfigService configService,
|
||||||
|
ISeriesService seriesService,
|
||||||
|
IEpisodeService episodeService,
|
||||||
|
IEventAggregator eventAggregator,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_configService = configService;
|
||||||
|
_seriesService = seriesService;
|
||||||
|
_episodeService = episodeService;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeFileDateToAirdate(EpisodeFile episodeFile, Series series)
|
||||||
|
{
|
||||||
|
var episode = new Episode();
|
||||||
|
episode.AirDate = episodeFile.Episodes.Value.First().AirDate;
|
||||||
|
episode.EpisodeFile = episodeFile;
|
||||||
|
episode.EpisodeFileId = 1;
|
||||||
|
|
||||||
|
var episodes = new List<Episode>();
|
||||||
|
episodes.Add(episode);
|
||||||
|
|
||||||
|
ChangeFileDateToAirdate(episodes, series);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeFileDateToAirdate(List<Episode> episodes, Series series)
|
||||||
|
{
|
||||||
|
if (!episodes.Any())
|
||||||
|
{
|
||||||
|
_logger.ProgressDebug("{0} has no media files available to update with air dates", series.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var done = new List<Episode>();
|
||||||
|
|
||||||
|
_logger.ProgressDebug("{0} ... checking {1} media file dates match air date", series.Title, episodes.Count);
|
||||||
|
|
||||||
|
foreach (var episode in episodes)
|
||||||
|
{
|
||||||
|
if (episode.HasFile
|
||||||
|
&& episode.EpisodeFile.IsLoaded
|
||||||
|
&& ChangeFileDate(episode.EpisodeFile.Value.Path, episode.AirDate, series.AirTime))
|
||||||
|
{
|
||||||
|
done.Add(episode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done.Any())
|
||||||
|
{
|
||||||
|
_eventAggregator.PublishEvent(new SeriesAirDatedEvent(series));
|
||||||
|
_logger.ProgressDebug("{0} had {1} of {2} media file dates changed to the date and time the episode aired", series.Title, done.Count, episodes.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.ProgressDebug("{0} has all its media file dates matching the date each aired", series.Title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(AirDateSeriesCommand message)
|
||||||
|
{
|
||||||
|
var seriesToAirDate = _seriesService.GetSeries(message.SeriesIds);
|
||||||
|
|
||||||
|
foreach (var series in seriesToAirDate)
|
||||||
|
{
|
||||||
|
var episodes = _episodeService.EpisodesWithFiles(series.Id);
|
||||||
|
|
||||||
|
ChangeFileDateToAirdate(episodes, series);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(SeriesScannedEvent message)
|
||||||
|
{
|
||||||
|
if (_configService.FileDateAiredDate)
|
||||||
|
{
|
||||||
|
var episodes = _episodeService.EpisodesWithFiles(message.Series.Id);
|
||||||
|
|
||||||
|
ChangeFileDateToAirdate(episodes, message.Series);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ChangeFileDate(String filePath, String fileDate, String fileTime)
|
||||||
|
{
|
||||||
|
DateTime dateTime, oldDateTime;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (DateTime.TryParse(fileDate + ' ' + fileTime, out dateTime))
|
||||||
|
{
|
||||||
|
// avoiding false +ve checks and set date skewing by not using UTC (Windows)
|
||||||
|
oldDateTime = _diskProvider.GetLastFileWrite(filePath);
|
||||||
|
|
||||||
|
if (!DateTime.Equals(dateTime, oldDateTime))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_diskProvider.FileSetLastWriteTime(filePath, dateTime);
|
||||||
|
_diskProvider.FileSetLastAccessTime(filePath, dateTime);
|
||||||
|
_logger.Info("Date of file [{0}] changed from \"{1}\" to \"{2}\"", filePath, oldDateTime, dateTime);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.WarnException("Unable to set date of file [" + filePath + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Warn("Could not create valid date to set [{0}]", filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -78,7 +78,7 @@ private static Series MapSeries(Show show)
|
|||||||
series.Overview = show.overview;
|
series.Overview = show.overview;
|
||||||
series.Runtime = show.runtime;
|
series.Runtime = show.runtime;
|
||||||
series.Network = show.network;
|
series.Network = show.network;
|
||||||
series.AirTime = show.air_time_utc;
|
series.AirTime = show.air_time;
|
||||||
series.TitleSlug = show.url.ToLower().Replace("http://trakt.tv/show/", "");
|
series.TitleSlug = show.url.ToLower().Replace("http://trakt.tv/show/", "");
|
||||||
series.Status = GetSeriesStatus(show.status, show.ended);
|
series.Status = GetSeriesStatus(show.status, show.ended);
|
||||||
series.Ratings = GetRatings(show.ratings);
|
series.Ratings = GetRatings(show.ratings);
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
<Compile Include="Instrumentation\Commands\DeleteLogFilesCommand.cs" />
|
<Compile Include="Instrumentation\Commands\DeleteLogFilesCommand.cs" />
|
||||||
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
||||||
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
||||||
|
<Compile Include="MediaFiles\Commands\AirDateSeriesCommand.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RenameSeriesCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RenameSeriesCommand.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RescanSeriesCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RescanSeriesCommand.cs" />
|
||||||
<Compile Include="Lifecycle\Commands\ShutdownCommand.cs" />
|
<Compile Include="Lifecycle\Commands\ShutdownCommand.cs" />
|
||||||
@ -318,9 +319,11 @@
|
|||||||
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\Events\SeriesScannedEvent.cs" />
|
<Compile Include="MediaFiles\Events\SeriesScannedEvent.cs" />
|
||||||
|
<Compile Include="MediaFiles\Events\SeriesAirDatedEvent.cs" />
|
||||||
<Compile Include="MediaFiles\MediaFileExtensions.cs" />
|
<Compile Include="MediaFiles\MediaFileExtensions.cs" />
|
||||||
<Compile Include="MediaFiles\MediaInfo\VideoFileInfoReader.cs" />
|
<Compile Include="MediaFiles\MediaInfo\VideoFileInfoReader.cs" />
|
||||||
<Compile Include="MediaFiles\RenameEpisodeFilePreview.cs" />
|
<Compile Include="MediaFiles\RenameEpisodeFilePreview.cs" />
|
||||||
|
<Compile Include="MediaFiles\UpdateEpisodeFileService.cs" />
|
||||||
<Compile Include="Messaging\Commands\CommandExecutor.cs" />
|
<Compile Include="Messaging\Commands\CommandExecutor.cs" />
|
||||||
<Compile Include="Messaging\Commands\ICommandExecutor.cs" />
|
<Compile Include="Messaging\Commands\ICommandExecutor.cs" />
|
||||||
<Compile Include="Messaging\Commands\IExecute.cs" />
|
<Compile Include="Messaging\Commands\IExecute.cs" />
|
||||||
|
@ -10,7 +10,7 @@ define(
|
|||||||
'AddSeries/RootFolders/RootFolderCollection',
|
'AddSeries/RootFolders/RootFolderCollection',
|
||||||
'Shared/Toolbar/ToolbarLayout',
|
'Shared/Toolbar/ToolbarLayout',
|
||||||
'AddSeries/RootFolders/RootFolderLayout',
|
'AddSeries/RootFolders/RootFolderLayout',
|
||||||
'Series/Editor/Rename/RenameSeriesView',
|
'Series/Editor/UpdateFiles/UpdateFilesSeriesView',
|
||||||
'Config'
|
'Config'
|
||||||
], function (_,
|
], function (_,
|
||||||
Marionette,
|
Marionette,
|
||||||
@ -21,26 +21,26 @@ define(
|
|||||||
RootFolders,
|
RootFolders,
|
||||||
ToolbarLayout,
|
ToolbarLayout,
|
||||||
RootFolderLayout,
|
RootFolderLayout,
|
||||||
RenameSeriesView,
|
UpdateFilesSeriesView,
|
||||||
Config) {
|
Config) {
|
||||||
return Marionette.ItemView.extend({
|
return Marionette.ItemView.extend({
|
||||||
template: 'Series/Editor/SeriesEditorFooterViewTemplate',
|
template: 'Series/Editor/SeriesEditorFooterViewTemplate',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
monitored : '.x-monitored',
|
monitored : '.x-monitored',
|
||||||
qualityProfile: '.x-quality-profiles',
|
qualityProfile : '.x-quality-profiles',
|
||||||
seasonFolder : '.x-season-folder',
|
seasonFolder : '.x-season-folder',
|
||||||
rootFolder : '.x-root-folder',
|
rootFolder : '.x-root-folder',
|
||||||
selectedCount : '.x-selected-count',
|
selectedCount : '.x-selected-count',
|
||||||
saveButton : '.x-save',
|
saveButton : '.x-save',
|
||||||
renameButton : '.x-rename',
|
updateFilesButton: '.x-update-files',
|
||||||
container : '.series-editor-footer'
|
container : '.series-editor-footer'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click .x-save' : '_updateAndSave',
|
'click .x-save' : '_updateAndSave',
|
||||||
'change .x-root-folder': '_rootFolderChanged',
|
'change .x-root-folder': '_rootFolderChanged',
|
||||||
'click .x-rename' : '_rename'
|
'click .x-update-files': '_updateFiles'
|
||||||
},
|
},
|
||||||
|
|
||||||
templateHelpers: function () {
|
templateHelpers: function () {
|
||||||
@ -119,7 +119,7 @@ define(
|
|||||||
this.ui.seasonFolder.attr('disabled', '');
|
this.ui.seasonFolder.attr('disabled', '');
|
||||||
this.ui.rootFolder.attr('disabled', '');
|
this.ui.rootFolder.attr('disabled', '');
|
||||||
this.ui.saveButton.attr('disabled', '');
|
this.ui.saveButton.attr('disabled', '');
|
||||||
this.ui.renameButton.attr('disabled', '');
|
this.ui.updateFilesButton.attr('disabled', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
@ -128,7 +128,7 @@ define(
|
|||||||
this.ui.seasonFolder.removeAttr('disabled', '');
|
this.ui.seasonFolder.removeAttr('disabled', '');
|
||||||
this.ui.rootFolder.removeAttr('disabled', '');
|
this.ui.rootFolder.removeAttr('disabled', '');
|
||||||
this.ui.saveButton.removeAttr('disabled', '');
|
this.ui.saveButton.removeAttr('disabled', '');
|
||||||
this.ui.renameButton.removeAttr('disabled', '');
|
this.ui.updateFilesButton.removeAttr('disabled', '');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -162,12 +162,12 @@ define(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_rename: function () {
|
_updateFiles: function () {
|
||||||
var selected = this.editorGrid.getSelectedModels();
|
var selected = this.editorGrid.getSelectedModels();
|
||||||
var renameSeriesView = new RenameSeriesView({ series: selected });
|
var updateFilesSeriesView = new UpdateFilesSeriesView({ series: selected });
|
||||||
this.listenToOnce(renameSeriesView, 'seriesRenamed', this._afterSave);
|
this.listenToOnce(updateFilesSeriesView, 'updatingFiles', this._afterSave);
|
||||||
|
|
||||||
vent.trigger(vent.Commands.OpenModalCommand, renameSeriesView);
|
vent.trigger(vent.Commands.OpenModalCommand, updateFilesSeriesView);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
<span class="selected-count x-selected-count">0 series selected</span>
|
<span class="selected-count x-selected-count">0 series selected</span>
|
||||||
<button class="btn btn-primary x-save">Save</button>
|
<button class="btn btn-primary x-save">Save</button>
|
||||||
<button class="btn btn-danger x-rename">Rename</button>
|
<button class="btn btn-danger x-update-files">Update Files</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -9,10 +9,11 @@ define(
|
|||||||
], function (_, vent, Backbone, Marionette, CommandController) {
|
], function (_, vent, Backbone, Marionette, CommandController) {
|
||||||
|
|
||||||
return Marionette.ItemView.extend({
|
return Marionette.ItemView.extend({
|
||||||
template: 'Series/Editor/Rename/RenameSeriesViewTemplate',
|
template: 'Series/Editor/UpdateFiles/UpdateFilesSeriesViewTemplate',
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click .x-confirm-rename': '_rename'
|
'click .x-confirm-rename': '_rename',
|
||||||
|
'click .x-confirm-airdate': '_setFileAirDate'
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
@ -29,7 +30,19 @@ define(
|
|||||||
seriesIds : seriesIds
|
seriesIds : seriesIds
|
||||||
});
|
});
|
||||||
|
|
||||||
this.trigger('seriesRenamed');
|
this.trigger('updatingFiles');
|
||||||
|
vent.trigger(vent.Commands.CloseModalCommand);
|
||||||
|
},
|
||||||
|
|
||||||
|
_setFileAirDate: function () {
|
||||||
|
var seriesIds = _.pluck(this.series, 'id');
|
||||||
|
|
||||||
|
CommandController.Execute('AirDateSeries', {
|
||||||
|
name: 'AirDateSeries',
|
||||||
|
seriesIds: seriesIds
|
||||||
|
});
|
||||||
|
|
||||||
|
this.trigger('updatingFiles');
|
||||||
vent.trigger(vent.Commands.CloseModalCommand);
|
vent.trigger(vent.Commands.CloseModalCommand);
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -1,23 +1,24 @@
|
|||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3>Rename Selected Series</h3>
|
<h3>Update Files of Selected Series</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body rename-series-modal">
|
<div class="modal-body update-files-series-modal">
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
You can use the rename function for an individual series to preview the rename
|
Tip: To preview a rename... select "Cancel" then any series title and use the <i data-original-title="" class="icon-nd-rename" title=""></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Are you sure you want to rename all files in the {{numberOfSeries}} selected series?
|
Are you sure you want to update all files in the {{numberOfSeries}} selected series?
|
||||||
|
|
||||||
{{debug}}
|
{{debug}}
|
||||||
<ul class="selected-series">
|
<ul class="selected-series">
|
||||||
{{#each series}}
|
{{#each series}}
|
||||||
<li>{{title}}</li>
|
<li>{{title}}</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn" data-dismiss="modal">cancel</button>
|
<button class="btn" data-dismiss="modal">cancel</button>
|
||||||
<button class="btn btn-danger x-confirm-rename">rename</button>
|
<button class="btn btn-danger x-confirm-rename">rename</button>
|
||||||
|
<button class="btn btn-danger x-confirm-airdate">set file date to air date</button>
|
||||||
</div>
|
</div>
|
@ -314,9 +314,13 @@
|
|||||||
.row {
|
.row {
|
||||||
margin-left: -40px;
|
margin-left: -40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.span2 {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rename-series-modal {
|
.update-files-series-modal {
|
||||||
.selected-series {
|
.selected-series {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">Set File Date to Airdate</label>
|
||||||
|
<div class="controls">
|
||||||
|
<label class="checkbox toggle well">
|
||||||
|
<input type="checkbox" name="fileDateAiredDate" />
|
||||||
|
<p>
|
||||||
|
<span>Yes</span>
|
||||||
|
<span>No</span>
|
||||||
|
</p>
|
||||||
|
<div class="btn btn-primary slide-button" />
|
||||||
|
</label>
|
||||||
|
<span class="help-inline-checkbox">
|
||||||
|
<i class="icon-nd-form-info" title="Adjust added media file dates to the original episode aired date" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label">Download Propers</label>
|
<label class="control-label">Download Propers</label>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user