1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-16 11:37:58 +02:00

Set episode file modified date to local or utc air date

This commit is contained in:
Mark McDowall 2014-03-12 22:27:36 -07:00
parent 8478379ff4
commit a02108922f
26 changed files with 175 additions and 202 deletions

View File

@ -275,6 +275,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@ -101,6 +101,7 @@
</ItemGroup> </ItemGroup>
<Import Project="..\Common\Microsoft.AspNet.SignalR.targets" /> <Import Project="..\Common\Microsoft.AspNet.SignalR.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@ -1,15 +1,16 @@
using System; using System;
using NzbDrone.Api.REST; using NzbDrone.Api.REST;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Api.Config 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; }
public FileDateType FileDate { get; set; }
public Boolean SetPermissionsLinux { get; set; } public Boolean SetPermissionsLinux { get; set; }
public String FileChmod { get; set; } public String FileChmod { get; set; }

View File

@ -35,7 +35,7 @@ private List<LogFileResource> GetLogFiles()
{ {
Id = i + 1, Id = i + 1,
Filename = Path.GetFileName(file), Filename = Path.GetFileName(file),
LastWriteTime = _diskProvider.GetLastFileWriteUTC(file) LastWriteTime = _diskProvider.FileGetLastWriteUtc(file)
}); });
} }

View File

@ -144,7 +144,7 @@ public void move_read_only_file()
public void empty_folder_should_return_folder_modified_date() public void empty_folder_should_return_folder_modified_date()
{ {
var tempfolder = new DirectoryInfo(TempFolder); var tempfolder = new DirectoryInfo(TempFolder);
Subject.GetLastFolderWrite(TempFolder).Should().Be(tempfolder.LastWriteTimeUtc); Subject.FolderGetLastWrite(TempFolder).Should().Be(tempfolder.LastWriteTimeUtc);
} }
[Test] [Test]
@ -159,8 +159,8 @@ public void folder_should_return_correct_value_for_last_write()
Subject.WriteAllText(testFile, "Test"); Subject.WriteAllText(testFile, "Test");
Subject.GetLastFolderWrite(SandboxFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1)); Subject.FolderGetLastWrite(SandboxFolder).Should().BeOnOrAfter(DateTime.UtcNow.AddMinutes(-1));
Subject.GetLastFolderWrite(SandboxFolder).Should().BeBefore(DateTime.UtcNow.AddMinutes(1)); Subject.FolderGetLastWrite(SandboxFolder).Should().BeBefore(DateTime.UtcNow.AddMinutes(1));
} }
[Test] [Test]
@ -208,7 +208,7 @@ public void should_be_able_to_set_permission_from_parrent()
[Explicit] [Explicit]
public void check_last_write() public void check_last_write()
{ {
Console.WriteLine(Subject.GetLastFolderWrite(_binFolder.FullName)); Console.WriteLine(Subject.FolderGetLastWrite(_binFolder.FullName));
Console.WriteLine(_binFolder.LastWriteTimeUtc); Console.WriteLine(_binFolder.LastWriteTimeUtc);
} }

View File

@ -56,7 +56,7 @@ public static bool IsParent(string parentPath, string childPath)
return false; return false;
} }
public DateTime GetLastFolderWrite(string path) public DateTime FolderGetLastWrite(string path)
{ {
Ensure.That(path, () => path).IsValidPath(); Ensure.That(path, () => path).IsValidPath();
@ -76,14 +76,14 @@ public DateTime GetLastFolderWrite(string path)
.Max(c => c.LastWriteTimeUtc); .Max(c => c.LastWriteTimeUtc);
} }
public DateTime GetLastFileWrite(string path) public DateTime FileGetLastWrite(string path)
{ {
PathEnsureFileExists(path); PathEnsureFileExists(path);
return new FileInfo(path).LastWriteTime; return new FileInfo(path).LastWriteTime;
} }
public DateTime GetLastFileWriteUTC(string path) public DateTime FileGetLastWriteUtc(string path)
{ {
PathEnsureFileExists(path); PathEnsureFileExists(path);

View File

@ -12,9 +12,9 @@ public interface IDiskProvider
void SetPermissions(string path, string mask, string user, string group); void SetPermissions(string path, string mask, string user, string group);
long? GetTotalSize(string path); long? GetTotalSize(string path);
DateTime GetLastFolderWrite(string path); DateTime FolderGetLastWrite(string path);
DateTime GetLastFileWrite(string path); DateTime FileGetLastWrite(string path);
DateTime GetLastFileWriteUTC(string path); DateTime FileGetLastWriteUtc(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);

View File

@ -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.GetLastFileWriteUTC(It.IsAny<string>())) Mocker.GetMock<IDiskProvider>().Setup(c => c.FileGetLastWriteUtc(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>()))

View File

@ -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.GetLastFileWriteUTC(It.IsAny<string>())) .Setup(s => s.FileGetLastWriteUtc(It.IsAny<string>()))
.Returns(time); .Returns(time);
} }

View File

@ -18,19 +18,19 @@ public class CleanupFixture : CoreTest
private void WithExpired() private void WithExpired()
{ {
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFolderWrite(It.IsAny<String>())) Mocker.GetMock<IDiskProvider>().Setup(s => s.FolderGetLastWrite(It.IsAny<String>()))
.Returns(DateTime.UtcNow.AddDays(-10)); .Returns(DateTime.UtcNow.AddDays(-10));
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFileWriteUTC(It.IsAny<String>())) Mocker.GetMock<IDiskProvider>().Setup(s => s.FileGetLastWriteUtc(It.IsAny<String>()))
.Returns(DateTime.UtcNow.AddDays(-10)); .Returns(DateTime.UtcNow.AddDays(-10));
} }
private void WithNonExpired() private void WithNonExpired()
{ {
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFolderWrite(It.IsAny<String>())) Mocker.GetMock<IDiskProvider>().Setup(s => s.FolderGetLastWrite(It.IsAny<String>()))
.Returns(DateTime.UtcNow.AddDays(-3)); .Returns(DateTime.UtcNow.AddDays(-3));
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetLastFileWriteUTC(It.IsAny<String>())) Mocker.GetMock<IDiskProvider>().Setup(s => s.FileGetLastWriteUtc(It.IsAny<String>()))
.Returns(DateTime.UtcNow.AddDays(-3)); .Returns(DateTime.UtcNow.AddDays(-3));
} }

View File

@ -4,9 +4,7 @@
using NLog; using NLog;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
using NzbDrone.Core.Configuration.Events; using NzbDrone.Core.Configuration.Events;
using NzbDrone.Core.Download; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@ -86,12 +84,6 @@ 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); }
@ -147,12 +139,18 @@ public Boolean EnableFailedDownloadHandling
public Boolean CreateEmptySeriesFolders public Boolean CreateEmptySeriesFolders
{ {
//TODO: only create if the parent folder exists (check first)
get { return GetValueBoolean("CreateEmptySeriesFolders", false); } get { return GetValueBoolean("CreateEmptySeriesFolders", false); }
set { SetValue("CreateEmptySeriesFolders", value); } set { SetValue("CreateEmptySeriesFolders", value); }
} }
public FileDateType FileDate
{
get { return GetValueEnum("FileDate", FileDateType.None); }
set { SetValue("FileDate", value); }
}
public String DownloadClientWorkingFolders public String DownloadClientWorkingFolders
{ {
get { return GetValue("DownloadClientWorkingFolders", "_UNPACK_|_FAILED_"); } get { return GetValue("DownloadClientWorkingFolders", "_UNPACK_|_FAILED_"); }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Configuration namespace NzbDrone.Core.Configuration
{ {
@ -20,10 +21,10 @@ 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; }
FileDateType FileDate { get; set; }
//Permissions (Media Management) //Permissions (Media Management)
Boolean SetPermissionsLinux { get; set; } Boolean SetPermissionsLinux { get; set; }

View File

@ -67,7 +67,7 @@ public void ConvertToLocalUrls(int seriesId, IEnumerable<MediaCover> covers)
if (_diskProvider.FileExists(filePath)) if (_diskProvider.FileExists(filePath))
{ {
var lastWrite = _diskProvider.GetLastFileWriteUTC(filePath); var lastWrite = _diskProvider.FileGetLastWriteUtc(filePath);
mediaCover.Url += "?lastWrite=" + lastWrite.Ticks; mediaCover.Url += "?lastWrite=" + lastWrite.Ticks;
} }
} }

View File

@ -1,18 +0,0 @@
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;
}
}
}
}

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using NLog; using NLog;
@ -51,7 +52,7 @@ public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series)
_logger.Trace("Renaming episode file: {0} to {1}", episodeFile, filePath); _logger.Trace("Renaming episode file: {0} to {1}", episodeFile, filePath);
return MoveFile(episodeFile, series, filePath); return MoveFile(episodeFile, series, episodes, filePath);
} }
public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode)
@ -61,10 +62,10 @@ public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEp
_logger.Trace("Moving episode file: {0} to {1}", episodeFile, filePath); _logger.Trace("Moving episode file: {0} to {1}", episodeFile, filePath);
return MoveFile(episodeFile, localEpisode.Series, filePath); return MoveFile(episodeFile, localEpisode.Series, localEpisode.Episodes, filePath);
} }
private EpisodeFile MoveFile(EpisodeFile episodeFile, Series series, string destinationFilename) private EpisodeFile MoveFile(EpisodeFile episodeFile, Series series, List<Episode> episodes, string destinationFilename)
{ {
Ensure.That(episodeFile, () => episodeFile).IsNotNull(); Ensure.That(episodeFile, () => episodeFile).IsNotNull();
Ensure.That(series,() => series).IsNotNull(); Ensure.That(series,() => series).IsNotNull();
@ -105,10 +106,7 @@ 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.ChangeFileDateForFile(episodeFile, series, episodes);
{
_updateEpisodeFileService.ChangeFileDateToAirdate(episodeFile, series);
}
try try
{ {

View File

@ -42,7 +42,7 @@ public bool IsSatisfiedBy(LocalEpisode localEpisode)
return false; return false;
} }
if (_diskProvider.GetLastFileWriteUTC(localEpisode.Path) > DateTime.UtcNow.AddMinutes(-5)) if (_diskProvider.FileGetLastWriteUtc(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;

View File

@ -1,15 +0,0 @@
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;
}
}
}

View File

@ -0,0 +1,9 @@
namespace NzbDrone.Core.MediaFiles
{
public enum FileDateType
{
None = 0,
LocalAirDate = 1,
UtcAirDate = 2
}
}

View File

@ -128,7 +128,7 @@ public void Cleanup()
foreach (var folder in _diskProvider.GetDirectories(_configService.RecycleBin)) foreach (var folder in _diskProvider.GetDirectories(_configService.RecycleBin))
{ {
if (_diskProvider.GetLastFolderWrite(folder).AddDays(7) > DateTime.UtcNow) if (_diskProvider.FolderGetLastWrite(folder).AddDays(7) > DateTime.UtcNow)
{ {
logger.Trace("Folder hasn't expired yet, skipping: {0}", folder); logger.Trace("Folder hasn't expired yet, skipping: {0}", folder);
continue; continue;
@ -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.GetLastFileWriteUTC(file).AddDays(7) > DateTime.UtcNow) if (_diskProvider.FileGetLastWriteUtc(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;

View File

@ -1,16 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Instrumentation;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.MediaFiles.Commands;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
@ -18,124 +14,119 @@ namespace NzbDrone.Core.MediaFiles
{ {
public interface IUpdateEpisodeFileService public interface IUpdateEpisodeFileService
{ {
void ChangeFileDateToAirdate(EpisodeFile episodeFile, Series series); void ChangeFileDateForFile(EpisodeFile episodeFile, Series series, List<Episode> episodes);
} }
public class UpdateEpisodeFileService : IUpdateEpisodeFileService, public class UpdateEpisodeFileService : IUpdateEpisodeFileService,
IExecute<AirDateSeriesCommand>,
IHandle<SeriesScannedEvent> IHandle<SeriesScannedEvent>
{ {
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly ISeriesService _seriesService;
private readonly IEpisodeService _episodeService; private readonly IEpisodeService _episodeService;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger; private readonly Logger _logger;
public UpdateEpisodeFileService(IDiskProvider diskProvider, public UpdateEpisodeFileService(IDiskProvider diskProvider,
IConfigService configService, IConfigService configService,
ISeriesService seriesService,
IEpisodeService episodeService, IEpisodeService episodeService,
IEventAggregator eventAggregator,
Logger logger) Logger logger)
{ {
_diskProvider = diskProvider; _diskProvider = diskProvider;
_configService = configService; _configService = configService;
_seriesService = seriesService;
_episodeService = episodeService; _episodeService = episodeService;
_eventAggregator = eventAggregator;
_logger = logger; _logger = logger;
} }
public void ChangeFileDateToAirdate(EpisodeFile episodeFile, Series series) public void ChangeFileDateForFile(EpisodeFile episodeFile, Series series, List<Episode> episodes)
{ {
var episode = new Episode(); ChangeFileDate(episodeFile, series, episodes);
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) private bool ChangeFileDate(EpisodeFile episodeFile, Series series, List<Episode> episodes)
{ {
if (!episodes.Any()) switch (_configService.FileDate)
{ {
_logger.ProgressDebug("{0} has no media files available to update with air dates", series.Title); case FileDateType.LocalAirDate:
}
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 var airDate = episodes.First().AirDate;
&& episode.EpisodeFile.IsLoaded var airTime = series.AirTime;
&& ChangeFileDate(episode.EpisodeFile.Value.Path, episode.AirDate, series.AirTime))
if (airDate.IsNullOrWhiteSpace() || airTime.IsNullOrWhiteSpace())
{ {
done.Add(episode); return false;
} }
return ChangeFileDateToLocalAirDate(episodeFile.Path, airDate, airTime);
} }
if (done.Any()) case FileDateType.UtcAirDate:
{ {
_eventAggregator.PublishEvent(new SeriesAirDatedEvent(series)); var airDateUtc = episodes.First().AirDateUtc;
_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 if (!airDateUtc.HasValue)
{ {
_logger.ProgressDebug("{0} has all its media file dates matching the date each aired", series.Title); return false;
}
return ChangeFileDateToUtcAirDate(episodeFile.Path, airDateUtc.Value);
} }
} }
}
public void Execute(AirDateSeriesCommand message) return false;
{
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) public void Handle(SeriesScannedEvent message)
{ {
if (_configService.FileDateAiredDate) if (_configService.FileDate == FileDateType.None)
{ {
var episodes = _episodeService.EpisodesWithFiles(message.Series.Id); return;
}
ChangeFileDateToAirdate(episodes, message.Series); var episodes = _episodeService.EpisodesWithFiles(message.Series.Id);
}
var episodeFiles = new List<EpisodeFile>();
var updated = new List<EpisodeFile>();
foreach (var group in episodes.GroupBy(e => e.EpisodeFileId))
{
var episodesInFile = group.Select(e => e).ToList();
var episodeFile = episodesInFile.First().EpisodeFile;
episodeFiles.Add(episodeFile);
if (ChangeFileDate(episodeFile, message.Series, episodesInFile))
{
updated.Add(episodeFile);
}
}
if (updated.Any())
{
_logger.ProgressDebug("Changed file date for {0} files of {1} in {2}", updated.Count, episodeFiles.Count, message.Series.Title);
}
else
{
_logger.ProgressDebug("No file dates changed for {0}", message.Series.Title);
}
} }
private bool ChangeFileDate(String filePath, String fileDate, String fileTime) private bool ChangeFileDateToLocalAirDate(string filePath, string fileDate, string fileTime)
{ {
DateTime dateTime, oldDateTime; DateTime airDate;
bool result = false;
if (DateTime.TryParse(fileDate + ' ' + fileTime, out dateTime)) if (DateTime.TryParse(fileDate + ' ' + fileTime, out airDate))
{ {
// avoiding false +ve checks and set date skewing by not using UTC (Windows) // avoiding false +ve checks and set date skewing by not using UTC (Windows)
oldDateTime = _diskProvider.GetLastFileWrite(filePath); DateTime oldDateTime = _diskProvider.FileGetLastWriteUtc(filePath);
if (!DateTime.Equals(dateTime, oldDateTime)) if (!DateTime.Equals(airDate, oldDateTime))
{ {
try try
{ {
_diskProvider.FileSetLastWriteTime(filePath, dateTime); _diskProvider.FileSetLastWriteTime(filePath, airDate);
_diskProvider.FileSetLastAccessTime(filePath, dateTime); _logger.Debug("Date of file [{0}] changed from '{1}' to '{2}'", filePath, oldDateTime, airDate);
_logger.Info("Date of file [{0}] changed from \"{1}\" to \"{2}\"", filePath, oldDateTime, dateTime);
result = true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -147,10 +138,33 @@ private bool ChangeFileDate(String filePath, String fileDate, String fileTime)
else else
{ {
_logger.Warn("Could not create valid date to set [{0}]", filePath); _logger.Debug("Could not create valid date to change file [{0}]", filePath);
} }
return result; return false;
}
private bool ChangeFileDateToUtcAirDate(string filePath, DateTime airDateUtc)
{
DateTime oldLastWrite = _diskProvider.FileGetLastWriteUtc(filePath);
if (!DateTime.Equals(airDateUtc, oldLastWrite))
{
try
{
_diskProvider.FileSetLastWriteTime(filePath, airDateUtc);
_logger.Debug("Date of file [{0}] changed from '{1}' to '{2}'", filePath, oldLastWrite, airDateUtc);
return true;
}
catch (Exception ex)
{
_logger.WarnException("Unable to set date of file [" + filePath + "]", ex);
}
}
return false;
} }
} }
} }

View File

@ -308,7 +308,6 @@
<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" />
@ -319,7 +318,7 @@
<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\FileDateType.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" />

View File

@ -9,11 +9,10 @@ define(
], function (_, vent, Backbone, Marionette, CommandController) { ], function (_, vent, Backbone, Marionette, CommandController) {
return Marionette.ItemView.extend({ return Marionette.ItemView.extend({
template: 'Series/Editor/UpdateFiles/UpdateFilesSeriesViewTemplate', template: 'Series/Editor/Organize/OrganizeFilesViewTemplate',
events: { events: {
'click .x-confirm-rename': '_rename', 'click .x-confirm-organize': '_organize'
'click .x-confirm-airdate': '_setFileAirDate'
}, },
initialize: function (options) { initialize: function (options) {
@ -22,7 +21,7 @@ define(
this.templateHelpers = { numberOfSeries: this.series.length, series: new Backbone.Collection(this.series).toJSON() }; this.templateHelpers = { numberOfSeries: this.series.length, series: new Backbone.Collection(this.series).toJSON() };
}, },
_rename: function () { _organize: function () {
var seriesIds = _.pluck(this.series, 'id'); var seriesIds = _.pluck(this.series, 'id');
CommandController.Execute('renameSeries', { CommandController.Execute('renameSeries', {
@ -30,19 +29,7 @@ define(
seriesIds : seriesIds seriesIds : seriesIds
}); });
this.trigger('updatingFiles'); this.trigger('organizingFiles');
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);
} }
}); });

View File

@ -1,6 +1,6 @@
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>Update Files of Selected Series</h3> <h3>Organize of Selected Series</h3>
</div> </div>
<div class="modal-body update-files-series-modal"> <div class="modal-body update-files-series-modal">
<div class="alert alert-info"> <div class="alert alert-info">
@ -19,6 +19,5 @@
</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-organize">organize</button>
<button class="btn btn-danger x-confirm-airdate">set file date to air date</button>
</div> </div>

View File

@ -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/UpdateFiles/UpdateFilesSeriesView', 'Series/Editor/Organize/OrganizeFilesView',
'Config' 'Config'
], function (_, ], function (_,
Marionette, Marionette,
@ -27,20 +27,20 @@ define(
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',
updateFilesButton: '.x-update-files', organizeFilesButton : '.x-organize-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-update-files': '_updateFiles' 'click .x-organize-files' : '_organizeFiles'
}, },
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.updateFilesButton.attr('disabled', ''); this.ui.organizeFilesButton.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.updateFilesButton.removeAttr('disabled', ''); this.ui.organizeFilesButton.removeAttr('disabled', '');
} }
}, },
@ -162,7 +162,7 @@ define(
}); });
}, },
_updateFiles: function () { _organizeFiles: function () {
var selected = this.editorGrid.getSelectedModels(); var selected = this.editorGrid.getSelectedModels();
var updateFilesSeriesView = new UpdateFilesSeriesView({ series: selected }); var updateFilesSeriesView = new UpdateFilesSeriesView({ series: selected });
this.listenToOnce(updateFilesSeriesView, 'updatingFiles', this._afterSave); this.listenToOnce(updateFilesSeriesView, 'updatingFiles', this._afterSave);

View File

@ -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-update-files">Update Files</button> <button class="btn btn-danger x-organize-files">Organize</button>
</span> </span>
</div> </div>
</div> </div>

View File

@ -21,23 +21,6 @@
</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>
@ -68,4 +51,19 @@
</span> </span>
</div> </div>
</div> </div>
<div class="control-group">
<label class="control-label">Change File Date</label>
<div class="controls">
<select class="inputClass" name="fileDate">
<option value="none">None</option>
<option value="localAirDate">Local Air Date</option>
<option value="utcAirDate">UTC Air Date</option>
</select>
<span class="help-inline">
<i class="icon-nd-form-info" title="Change file date on import/rescan"/>
</span>
</div>
</div>
</fieldset> </fieldset>