diff --git a/NzbDrone.Core.Test/Fixtures.cs b/NzbDrone.Core.Test/Fixtures.cs
index 609518e78..ae4af6754 100644
--- a/NzbDrone.Core.Test/Fixtures.cs
+++ b/NzbDrone.Core.Test/Fixtures.cs
@@ -43,6 +43,7 @@ namespace NzbDrone.Core.Test
try
{
LogManager.Configuration = new XmlLoggingConfiguration(Path.Combine(CentralDispatch.AppPath, "log.config"), false);
+ LogManager.ThrowExceptions = true;
}
catch (Exception e)
{
diff --git a/NzbDrone.Core.Test/MediaFileProviderTests (X201's conflicted copy 2010-10-19).cs b/NzbDrone.Core.Test/MediaFileProviderTests (X201's conflicted copy 2010-10-19).cs
deleted file mode 100644
index a8825b3f6..000000000
--- a/NzbDrone.Core.Test/MediaFileProviderTests (X201's conflicted copy 2010-10-19).cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Text;
-using Gallio.Framework;
-using MbUnit.Framework;
-using MbUnit.Framework.ContractVerifiers;
-using Moq;
-using Ninject;
-using Ninject.Moq;
-using NzbDrone.Core.Entities;
-using NzbDrone.Core.Entities.Episode;
-using NzbDrone.Core.Entities.Quality;
-using NzbDrone.Core.Providers;
-using SubSonic.Repository;
-
-namespace NzbDrone.Core.Test
-{
- [TestFixture]
- // ReSharper disable InconsistentNaming
- public class MediaFileProviderTests
- {
- [Test]
- public void scan_test()
- {
- //Arrange
- var repository = new Mock();
- repository.Setup(c => c.Update(It.IsAny())).Verifiable();
-
- var diskProvider = MockLib.GetStandardDisk(1, 2);
-
- var kernel = new MockingKernel();
- kernel.Bind().ToConstant(diskProvider);
- kernel.Bind().ToConstant(repository.Object);
- kernel.Bind().To();
-
- var fakeSeries = new Series()
- {
- Path = MockLib.StandardSeries[0]
- };
-
- //Act
- kernel.Get().Scan(fakeSeries);
-
- //Assert
- repository.Verify(c => c.Update(It.IsAny()), Times.Exactly(1 * 2));
-
-
- }
-
- [Test]
- [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)]
- [Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)]
- [Row("Chuck.4x05.HDTV.XviD-LOL", 4, 5)]
- [Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", 3, 6)]
- [Row("Degrassi.S10E27.WS.DSR.XviD-2HD", 10, 27)]
- public void episode_parse(string path, int season, int episode)
- {
- var result = Parser.ParseBasicEpisode(path);
- Assert.AreEqual(season, result.SeasonNumber);
- Assert.AreEqual(episode, result.EpisodeNumber);
- }
-
- [Test]
- [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.DVD)]
- [Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.Bluray)]
- [Row("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", QualityTypes.HDTV)]
- [Row("Chuck.S04E05.HDTV.XviD-LOL", QualityTypes.TV)]
- [Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", QualityTypes.DVD)]
- [Row("Degrassi.S10E27.WS.DSR.XviD-2HD", QualityTypes.TV)]
- [Row("Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", QualityTypes.WEBDL)]
- [Row("Sonny.With.a.Chance.S02E15.720p", QualityTypes.HDTV)]
- [Row("Sonny.With.a.Chance.S02E15.mkv", QualityTypes.HDTV)]
- [Row("Sonny.With.a.Chance.S02E15.avi", QualityTypes.TV)]
- [Row("Sonny.With.a.Chance.S02E15.xvid", QualityTypes.TV)]
- [Row("Sonny.With.a.Chance.S02E15.divx", QualityTypes.TV)]
- [Row("Sonny.With.a.Chance.S02E15", QualityTypes.Unknown)]
- public void quality_parse(string path, object quality)
- {
- var result = Parser.ParseQuality(path);
- Assert.AreEqual(quality, result);
- }
-
- [Test]
- [Timeout(2)]
- public void quality_parse()
- {
- var sw = Stopwatch.StartNew();
- var name = "WEEDSawdawdadawdawd\\awdawdawdadadad.mkv";
- var quality = QualityTypes.HDTV;
-
- for (int i = 0; i < 100000; i++)
- {
- Assert.AreEqual(quality, Parser.ParseQuality(name));
- }
-
- Console.WriteLine(sw.Elapsed.ToString());
-
-
- }
-
- }
-
-
-}
diff --git a/NzbDrone.Core.Test/MediaFileProviderTests.cs b/NzbDrone.Core.Test/MediaFileProviderTests.cs
index 2c2fc1be3..a74ef8ea8 100644
--- a/NzbDrone.Core.Test/MediaFileProviderTests.cs
+++ b/NzbDrone.Core.Test/MediaFileProviderTests.cs
@@ -9,6 +9,7 @@ using MbUnit.Framework.ContractVerifiers;
using Moq;
using Ninject;
using Ninject.Moq;
+using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
@@ -29,7 +30,7 @@ namespace NzbDrone.Core.Test
/////////////////////////////////////////
//Constants
- const string fileName = "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi";
+ const string fileName = @"WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi";
const int seasonNumber = 3;
const int episodeNumner = 01;
const int size = 12345;
@@ -157,7 +158,34 @@ namespace NzbDrone.Core.Test
}
+ [Test]
+ [Row("Season {season}\\S{season:00}E{episode:00} - {title} - {quality}", "Season 6\\S06E08 - Lethal Inspection - hdtv")]
+ [Row("Season {season}\\{series} - {season:##}{episode:00} - {title} - {quality}", "Season 6\\Futurama - 608 - Lethal Inspection - hdtv")]
+ [Row("Season {season}\\{series} - {season:##}{episode:00} - {title}", "Season 6\\Futurama - 608 - Lethal Inspection")]
+ public void test_file_path_generation(string patern, string path)
+ {
+ var fakeConfig = new Mock();
+ fakeConfig.Setup(c => c.EpisodeNameFormat).Returns(patern);
+ var kernel = new MockingKernel();
+ kernel.Bind().ToConstant(fakeConfig.Object);
+ kernel.Bind().To();
+
+ var fakeEpisode = new EpisodeModel
+ {
+ SeasonNumber = 6,
+ EpisodeNumber = 8,
+ EpisodeTitle = "Lethal Inspection",
+ Quality = QualityTypes.HDTV,
+ SeriesTitle = "Futurama"
+ };
+
+ //Act
+ var result = kernel.Get().GenerateEpisodePath(fakeEpisode);
+
+ //Assert
+ Assert.AreEqual(path.ToLowerInvariant(), result.ToLowerInvariant());
+ }
}
diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 64ed87f4e..4eb6565e2 100644
--- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -49,7 +49,9 @@
False
..\NzbDrone.Core\Libraries\Ninject.dll
-
+
+ ..\NzbDrone.Core\Libraries\NLog.dll
+
False
..\NzbDrone.Core\Libraries\SubSonic.Core.dll
diff --git a/NzbDrone.Core.Test/ParserTest.cs b/NzbDrone.Core.Test/ParserTest.cs
index 53e686d0d..dad7b1a87 100644
--- a/NzbDrone.Core.Test/ParserTest.cs
+++ b/NzbDrone.Core.Test/ParserTest.cs
@@ -18,6 +18,9 @@ namespace NzbDrone.Core.Test
[Row("Chuck.4x05.HDTV.XviD-LOL", 4, 5)]
[Row("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", 3, 6)]
[Row("Degrassi.S10E27.WS.DSR.XviD-2HD", 10, 27)]
+ [Row(@"z:\tv shows\battlestar galactica (2003)\Season 3\S03E05 - Collaborators.mkv", 3, 5)]
+ [Row(@"z:\tv shows\modern marvels\Season 16\S16E03 - The Potato.mkv", 16, 3)]
+ [Row(@"z:\tv shows\robot chicken\Specials\S00E16 - Dear Consumer - SD TV.avi", 0, 16)]
public void episode_parse(string path, int season, int episode)
{
var result = Parser.ParseEpisodeInfo(path);
@@ -40,6 +43,10 @@ namespace NzbDrone.Core.Test
[Row("Sonny.With.a.Chance.S02E15.xvid", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15.divx", QualityTypes.TV)]
[Row("Sonny.With.a.Chance.S02E15", QualityTypes.Unknown)]
+ [Row("S01E04 - So Old - Playdate - 720p TV.mkv", QualityTypes.HDTV)]
+ [Row("S22E03 - MoneyBART - HD TV.mkv", QualityTypes.HDTV)]
+ [Row("S01E03 - Come Fly With Me - 720p BluRay.mkv", QualityTypes.Bluray)]
+ [Row("S11E06 - D-Yikes! - 720p WEB-DL.mkv", QualityTypes.WEBDL)]
public void quality_parse(string path, object quality)
{
var result = Parser.ParseQuality(path);
diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs
index 6e02ea2e8..2a6bd44a7 100644
--- a/NzbDrone.Core/CentralDispatch.cs
+++ b/NzbDrone.Core/CentralDispatch.cs
@@ -10,6 +10,7 @@ using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Fakes;
using NzbDrone.Core.Repository;
using SubSonic.DataProviders;
+using SubSonic.Query;
using SubSonic.Repository;
using NLog;
using System.Linq;
@@ -31,14 +32,15 @@ namespace NzbDrone.Core
string connectionString = String.Format("Data Source={0};Version=3;", Path.Combine(AppPath, "nzbdrone.db"));
var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
-
+
string logConnectionString = String.Format("Data Source={0};Version=3;", Path.Combine(AppPath, "log.db"));
var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SQLite");
var logRepository = new SimpleRepository(logDbProvider, SimpleRepositoryOptions.RunMigrations);
+ //dbProvider.ExecuteQuery(new QueryCommand("VACUUM", dbProvider));
dbProvider.Log = new NlogWriter();
dbProvider.LogParams = true;
-
+
_kernel.Bind().To().InSingletonScope();
_kernel.Bind().To();
_kernel.Bind().To();
@@ -48,6 +50,7 @@ namespace NzbDrone.Core
_kernel.Bind().To().InSingletonScope();
_kernel.Bind().To().InSingletonScope();
_kernel.Bind().To().InSingletonScope();
+ _kernel.Bind().To().InSingletonScope();
_kernel.Bind().ToMethod(c => new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope();
_kernel.Bind().ToConstant(logRepository).WhenInjectedInto().InSingletonScope();
diff --git a/NzbDrone.Core/Instrumentation/LogConfiguration.cs b/NzbDrone.Core/Instrumentation/LogConfiguration.cs
index aaf807324..19e0f84ff 100644
--- a/NzbDrone.Core/Instrumentation/LogConfiguration.cs
+++ b/NzbDrone.Core/Instrumentation/LogConfiguration.cs
@@ -22,9 +22,12 @@ namespace NzbDrone.Core.Instrumentation
private static void BindCustomLoggers()
{
+#if Release
var exTarget = new ExceptioneerTarget();
LogManager.Configuration.AddTarget("Exceptioneer", exTarget);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Error, exTarget));
+#endif
+
var sonicTarget = CentralDispatch.NinjectKernel.Get();
LogManager.Configuration.AddTarget("DbLogger", sonicTarget);
diff --git a/NzbDrone.Core/Model/EpisodeModel.cs b/NzbDrone.Core/Model/EpisodeModel.cs
index 7656d89cb..caa4ed596 100644
--- a/NzbDrone.Core/Model/EpisodeModel.cs
+++ b/NzbDrone.Core/Model/EpisodeModel.cs
@@ -6,6 +6,7 @@ namespace NzbDrone.Core.Model
public class EpisodeModel
{
public string SeriesTitle { get; set; }
+ public string EpisodeTitle { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public QualityTypes Quality { get; set; }
diff --git a/NzbDrone.Core/Model/EpisodeParseResult.cs b/NzbDrone.Core/Model/EpisodeParseResult.cs
index d280f539b..ab9638421 100644
--- a/NzbDrone.Core/Model/EpisodeParseResult.cs
+++ b/NzbDrone.Core/Model/EpisodeParseResult.cs
@@ -3,10 +3,16 @@ using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Model
{
- internal struct EpisodeParseResult
+ internal class EpisodeParseResult
{
internal string SeriesTitle { get; set; }
internal int SeasonNumber { get; set; }
internal int EpisodeNumber { get; set; }
+
+ public override string ToString()
+ {
+ return string.Format("Series:{0} Season:{1} Episode:{2}", SeriesTitle, SeasonNumber, EpisodeNumber);
+ }
+
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj
index 695502a22..873ae09db 100644
--- a/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/NzbDrone.Core/NzbDrone.Core.csproj
@@ -144,6 +144,7 @@
+
diff --git a/NzbDrone.Core/Parser.cs b/NzbDrone.Core/Parser.cs
index faa32613f..df2d18618 100644
--- a/NzbDrone.Core/Parser.cs
+++ b/NzbDrone.Core/Parser.cs
@@ -17,7 +17,7 @@ namespace NzbDrone.Core
private static readonly Regex[] ReportTitleRegex = new[]
{
- new Regex(@"(?.+?)?\W(S)?(?\d+)\w(?\d+)\W", RegexOptions.IgnoreCase | RegexOptions.Compiled)
+ new Regex(@"(?.+?)?\W(S)?(?\d+)\w(?\d+)\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled)
};
private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
@@ -43,22 +43,20 @@ namespace NzbDrone.Core
foreach (Match matchGroup in match)
{
- var tuple = new EpisodeParseResult
+ var parsedEpisode = new EpisodeParseResult
{
SeriesTitle = seriesName,
SeasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value),
EpisodeNumber = Convert.ToInt32(matchGroup.Groups["episode"].Value)
};
- result.Add(tuple);
+ result.Add(parsedEpisode);
- Logger.Trace("Episode Parsed. {0}", tuple);
+ Logger.Trace("Episode Parsed. {0}", parsedEpisode);
}
}
}
- Logger.Trace("{0} episodes parsed from string.", result.Count);
-
return result;
}
diff --git a/NzbDrone.Core/Providers/ConfigProvider.cs b/NzbDrone.Core/Providers/ConfigProvider.cs
index 748cc06f2..1bbbd7b65 100644
--- a/NzbDrone.Core/Providers/ConfigProvider.cs
+++ b/NzbDrone.Core/Providers/ConfigProvider.cs
@@ -8,6 +8,8 @@ namespace NzbDrone.Core.Providers
public class ConfigProvider : IConfigProvider
{
private const string SERIES_ROOTS = "SeriesRoots";
+ private const string EPISODE_NAME_FORMAT = "EpisodeNameFormat";
+
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IRepository _sonicRepo;
@@ -21,6 +23,13 @@ namespace NzbDrone.Core.Providers
return GetValue(key, String.Empty, false);
}
+ public String EpisodeNameFormat
+ {
+ get { return GetValue(EPISODE_NAME_FORMAT); }
+
+ set { SetValue(EPISODE_NAME_FORMAT, value); }
+ }
+
public String SeriesRoot
{
get { return GetValue(SERIES_ROOTS); }
diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs
index 42aa0f300..7bbd808d3 100644
--- a/NzbDrone.Core/Providers/EpisodeProvider.cs
+++ b/NzbDrone.Core/Providers/EpisodeProvider.cs
@@ -43,6 +43,11 @@ namespace NzbDrone.Core.Providers
return _sonicRepo.Find(e => e.SeriesId == seriesId);
}
+ public IList GetEpisodeBySeason(long seasonId)
+ {
+ return _sonicRepo.Find(e => e.SeasonId == seasonId);
+ }
+
public String GetSabTitle(Episode episode)
{
var series = _series.GetSeries(episode.SeriesId);
@@ -72,7 +77,7 @@ namespace NzbDrone.Core.Providers
var updateList = new List();
var newList = new List();
- Logger.Debug("Updating season info for series:{0}", seriesId);
+ Logger.Debug("Updating season info for series:{0}", targetSeries.SeriesName);
targetSeries.Episodes.Select(e => new { e.SeasonId, e.SeasonNumber })
.Distinct().ToList()
.ForEach(s => _seasons.EnsureSeason(seriesId, s.SeasonId, s.SeasonNumber));
@@ -81,7 +86,7 @@ namespace NzbDrone.Core.Providers
{
try
{
- Logger.Debug("Updating info for series:{0} - episode:{1}", seriesId, episode.Id);
+ Logger.Trace("Updating info for series:{0} - episode:{1}", targetSeries.SeriesName, episode.EpisodeNumber);
var newEpisode = new Episode()
{
AirDate = episode.FirstAired,
@@ -116,7 +121,7 @@ namespace NzbDrone.Core.Providers
_sonicRepo.AddMany(newList);
_sonicRepo.UpdateMany(updateList);
- Logger.Info("Finished episode refresh for series:{0}. Success:{1} - Fail:{2} ", seriesId, successCount, failCount);
+ Logger.Debug("Finished episode refresh for series:{0}. Successful:{1} - Failed:{2} ", targetSeries.SeriesName, successCount, failCount);
}
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Providers/IConfigProvider.cs b/NzbDrone.Core/Providers/IConfigProvider.cs
index 649249fbb..e34998a63 100644
--- a/NzbDrone.Core/Providers/IConfigProvider.cs
+++ b/NzbDrone.Core/Providers/IConfigProvider.cs
@@ -5,6 +5,7 @@ namespace NzbDrone.Core.Providers
public interface IConfigProvider
{
String SeriesRoot { get; set; }
+ String EpisodeNameFormat { get; set; }
string GetValue(string key, object defaultValue, bool makePermanent);
void SetValue(string key, string value);
diff --git a/NzbDrone.Core/Providers/IEpisodeProvider.cs b/NzbDrone.Core/Providers/IEpisodeProvider.cs
index 758c3cdf8..30f3054d1 100644
--- a/NzbDrone.Core/Providers/IEpisodeProvider.cs
+++ b/NzbDrone.Core/Providers/IEpisodeProvider.cs
@@ -20,5 +20,6 @@ namespace NzbDrone.Core.Providers
bool IsNeeded(EpisodeModel episode);
void RefreshEpisodeInfo(int seriesId);
+ IList GetEpisodeBySeason(long seasonId);
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Providers/IMediaFileProvider.cs b/NzbDrone.Core/Providers/IMediaFileProvider.cs
index 651e59fcc..c9c19ed9d 100644
--- a/NzbDrone.Core/Providers/IMediaFileProvider.cs
+++ b/NzbDrone.Core/Providers/IMediaFileProvider.cs
@@ -1,3 +1,4 @@
+using NzbDrone.Core.Model;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers
@@ -11,5 +12,6 @@ namespace NzbDrone.Core.Providers
void Scan(Series series);
EpisodeFile ImportFile(Series series, string filePath);
+ string GenerateEpisodePath(EpisodeModel episode);
}
}
\ No newline at end of file
diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs
index dc6fad676..07aadc607 100644
--- a/NzbDrone.Core/Providers/MediaFileProvider.cs
+++ b/NzbDrone.Core/Providers/MediaFileProvider.cs
@@ -14,15 +14,17 @@ namespace NzbDrone.Core.Providers
public class MediaFileProvider : IMediaFileProvider
{
private readonly IRepository _repository;
+ private readonly IConfigProvider _configProvider;
private readonly IDiskProvider _diskProvider;
private readonly IEpisodeProvider _episodeProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly string[] MediaExtentions = new[] { "*.mkv", "*.avi", "*.wmv" };
- public MediaFileProvider(IRepository repository, IDiskProvider diskProvider, IEpisodeProvider episodeProvider)
+ public MediaFileProvider(IRepository repository, IConfigProvider _configProvider, IDiskProvider diskProvider, IEpisodeProvider episodeProvider)
{
_repository = repository;
+ this._configProvider = _configProvider;
_diskProvider = diskProvider;
_episodeProvider = episodeProvider;
}
@@ -55,21 +57,21 @@ namespace NzbDrone.Core.Providers
var episode = _episodeProvider.GetEpisode(series.SeriesId, closureEpisode.SeasonNumber, closureEpisode.EpisodeNumber);
if (episode != null)
{
- var epFile = new EpisodeFile();
- epFile.DateAdded = DateTime.Now;
- epFile.SeriesId = series.SeriesId;
- epFile.EpisodeId = episode.EpisodeId;
- epFile.Path = Parser.NormalizePath(filePath);
- epFile.Size = _diskProvider.GetSize(filePath);
- epFile.Quality = Parser.ParseQuality(filePath);
- epFile.Proper = Parser.ParseProper(filePath);
- _repository.Add(epFile);
- Logger.Info("File '{0}' successfully attached to {1}", episode.EpisodeId);
+ var episodeFile = new EpisodeFile();
+ episodeFile.DateAdded = DateTime.Now;
+ episodeFile.SeriesId = series.SeriesId;
+ episodeFile.EpisodeId = episode.EpisodeId;
+ episodeFile.Path = Parser.NormalizePath(filePath);
+ episodeFile.Size = _diskProvider.GetSize(filePath);
+ episodeFile.Quality = Parser.ParseQuality(filePath);
+ episodeFile.Proper = Parser.ParseProper(filePath);
+ _repository.Add(episodeFile);
+ Logger.Trace("File {0}:{1} attached to '{2}'", episodeFile.FileId, filePath, episode.EpisodeId);
- return epFile;
+ return episodeFile;
}
- Logger.Warn("Unable to find Series:{0} Season:{1} Episode:{2} in the database.", series.Title, closureEpisode.SeasonNumber, closureEpisode.EpisodeNumber);
+ Logger.Warn("Unable to find Series:{0} Season:{1} Episode:{2} in the database. File:{3}", series.Title, closureEpisode.SeasonNumber, closureEpisode.EpisodeNumber, filePath);
}
}
else
@@ -96,9 +98,23 @@ namespace NzbDrone.Core.Providers
}
}
+
+ public string GenerateEpisodePath(EpisodeModel episode)
+ {
+ var episodeNamePattern = _configProvider.EpisodeNameFormat;
+
+ episodeNamePattern = episodeNamePattern.Replace("{series}", "{0}");
+ episodeNamePattern = episodeNamePattern.Replace("{episode", "{1");
+ episodeNamePattern = episodeNamePattern.Replace("{season", "{2");
+ episodeNamePattern = episodeNamePattern.Replace("{title}", "{3}");
+ episodeNamePattern = episodeNamePattern.Replace("{quality}", "{4}");
+
+ return String.Format(episodeNamePattern, episode.SeriesTitle, episode.EpisodeNumber, episode.SeasonNumber, episode.EpisodeTitle, episode.Quality);
+ }
+
private List GetMediaFileList(string path)
{
- Logger.Info("Scanning '{0}' for episodes", path);
+ Logger.Debug("Scanning '{0}' for episodes", path);
var mediaFileList = new List();
@@ -107,8 +123,9 @@ namespace NzbDrone.Core.Providers
mediaFileList.AddRange(_diskProvider.GetFiles(path, ext, SearchOption.AllDirectories));
}
- Logger.Info("{0} media files were found in {1}", mediaFileList.Count, path);
+ Logger.Trace("{0} media files were found in {1}", mediaFileList.Count, path);
return mediaFileList;
}
+
}
}
diff --git a/NzbDrone.Core/Providers/SeasonProvider.cs b/NzbDrone.Core/Providers/SeasonProvider.cs
index bb97862c8..85a22d85e 100644
--- a/NzbDrone.Core/Providers/SeasonProvider.cs
+++ b/NzbDrone.Core/Providers/SeasonProvider.cs
@@ -31,11 +31,10 @@ namespace NzbDrone.Core.Providers
if (_sonicRepo.Exists(s => s.SeasonId == seasonId))
return;
//TODO: Calculate Season Folder
- Logger.Debug("Adding Season To DB. [SeriesID:{0} SeasonID:{1} SeasonNumber:{2} Folder:{3}]", seriesId, seasonId, seasonNumber, "????");
+ Logger.Trace("Adding Season To DB. [SeriesID:{0} SeasonID:{1} SeasonNumber:{2}]", seriesId, seasonId, seasonNumber, "????");
var newSeason = new Season()
{
- Folder = String.Empty,
Monitored = true,
SeasonId = seasonId,
SeasonNumber = seasonNumber,
diff --git a/NzbDrone.Core/Providers/SyncProvider.cs b/NzbDrone.Core/Providers/SyncProvider.cs
index 8c8644598..99e518a2e 100644
--- a/NzbDrone.Core/Providers/SyncProvider.cs
+++ b/NzbDrone.Core/Providers/SyncProvider.cs
@@ -14,6 +14,7 @@ namespace NzbDrone.Core.Providers
{
private readonly ISeriesProvider _seriesProvider;
private readonly IEpisodeProvider _episodeProvider;
+ private readonly IMediaFileProvider _mediaFileProvider;
private readonly INotificationProvider _notificationProvider;
private ProgressNotification _seriesSyncNotification;
@@ -21,10 +22,11 @@ namespace NzbDrone.Core.Providers
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
- public SyncProvider(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider, INotificationProvider notificationProvider)
+ public SyncProvider(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider, IMediaFileProvider mediaFileProvider, INotificationProvider notificationProvider)
{
_seriesProvider = seriesProvider;
_episodeProvider = episodeProvider;
+ _mediaFileProvider = mediaFileProvider;
_notificationProvider = notificationProvider;
}
@@ -65,7 +67,7 @@ namespace NzbDrone.Core.Providers
{
try
{
- _seriesSyncNotification.CurrentStatus = String.Format("Analysing Folder: {0}", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(new DirectoryInfo(seriesFolder).Name));
+ _seriesSyncNotification.CurrentStatus = String.Format("Searching For: {0}", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(new DirectoryInfo(seriesFolder).Name));
Logger.Debug("Folder '{0}' isn't mapped in the database. Trying to map it.'", seriesFolder);
var mappedSeries = _seriesProvider.MapPathToSeries(seriesFolder);
@@ -79,9 +81,12 @@ namespace NzbDrone.Core.Providers
//Check if series is mapped to another folder
if (_seriesProvider.GetSeries(mappedSeries.Id) == null)
{
- _seriesSyncNotification.CurrentStatus = String.Format("Downloading Info for '{0}'", mappedSeries.SeriesName);
+ _seriesSyncNotification.CurrentStatus = String.Format("{0}: downloading series info...", mappedSeries.SeriesName);
_seriesProvider.AddSeries(seriesFolder, mappedSeries);
_episodeProvider.RefreshEpisodeInfo(mappedSeries.Id);
+ _seriesSyncNotification.CurrentStatus = String.Format("{0}: finding episodes on disk...", mappedSeries.SeriesName);
+ _mediaFileProvider.Scan(_seriesProvider.GetSeries(mappedSeries.Id));
+
}
else
{
diff --git a/NzbDrone.Core/Repository/Episode.cs b/NzbDrone.Core/Repository/Episode.cs
index bfebd5fea..27a58e713 100644
--- a/NzbDrone.Core/Repository/Episode.cs
+++ b/NzbDrone.Core/Repository/Episode.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Web.Script.Serialization;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
diff --git a/NzbDrone.Core/Repository/Season.cs b/NzbDrone.Core/Repository/Season.cs
index 42e5ad1fd..aaeb11a90 100644
--- a/NzbDrone.Core/Repository/Season.cs
+++ b/NzbDrone.Core/Repository/Season.cs
@@ -10,8 +10,7 @@ namespace NzbDrone.Core.Repository
public long SeriesId { get; set; }
public int SeasonNumber { get; set; }
public bool Monitored { get; set; }
- public string Folder { get; set; }
-
+
[SubSonicToManyRelation]
public virtual List Episodes { get; private set; }
diff --git a/NzbDrone.Web/Content/style.css b/NzbDrone.Web/Content/style.css
index 6a2accce0..bb626824d 100644
--- a/NzbDrone.Web/Content/style.css
+++ b/NzbDrone.Web/Content/style.css
@@ -1,4 +1,3 @@
-
/*
Design by Free CSS Templates
http://www.freecsstemplates.org
@@ -6,7 +5,6 @@ Released for free under a Creative Commons Attribution 2.5 License
*/
body
{
- margin: 20px 0px 0px 0px;
padding: 0;
background: #191919 url(images/img07.jpg) no-repeat right top;
font-family: Segoe UI, Tahoma, Geneva, sans-serif;
@@ -19,7 +17,7 @@ h1, h2, h3
{
margin: 0;
color: #549900;
- font-family: Segoe UI Light;
+ font-family: Segoe UI Light,Tahoma, Geneva, sans-serif;
text-transform: lowercase;
}
@@ -173,63 +171,16 @@ hr
{
}
-/* Search */
-
-#search
-{
- float: right;
- padding: 10px 10px 0px 0px;
-}
-
-#search form
-{
- float: right;
- margin: 0;
- padding: 4px 0px 0 0;
-}
-
-#search fieldset
-{
- margin: 0;
- padding: 0;
- border: none;
-}
-
-#search input
-{
- float: left;
- font: 12px Georgia, "Times New Roman" , Times, serif;
-}
-
-#search-text
-{
- width: 213px;
- height: 28px;
- padding: 6px 0 0 7px;
- border: none;
- background: url(images/img02.jpg) no-repeat left top;
- color: #000000;
-}
-
-#search-submit
-{
- width: 82px;
- height: 28px;
- margin-left: 10px;
- padding: 0px 5px;
- background: url(images/img03.jpg) no-repeat left top;
- border: none;
- text-indent: -9999px;
- color: #FFFFFF;
-}
/* Page */
#page
{
- width: 950px;
margin: 0 auto 60px;
overflow: hidden;
+ background-color: White;
+ padding: 10px 20px 20px 20px;
+ width: 910px;
}
@@ -293,79 +244,9 @@ hr
background: #FFFFFF no-repeat;
float: left;
width: 100%;
- padding: 0px 0px 0px 0px;
-}
-
-/* Post */
-
-.post
-{
padding: 0px 30px 20px 30px;
}
-.post .title
-{
- height: 44px;
- margin: 0px;
- padding: 36px 0px 0px 0px;
- width: 576px;
-}
-
-.post .title a
-{
- letter-spacing: -2px;
- text-decoration: none;
- text-transform: lowercase;
- font-size: 36px;
- color: #424242;
-}
-
-.post .title a:hover
-{
- color: #065EFE;
-}
-
-.post .meta
-{
- margin-left: 2px;
- padding: 4px 30px 2px 0px;
- text-transform: uppercase;
- font-weight: bold;
- font-size: 11px;
- color: #66665E;
-}
-
-.post .meta span
-{
- margin: 0px;
-}
-
-.post .meta a
-{
- text-decoration: none;
-}
-
-.post .entry
-{
- padding: 10px 0px 0px 0px;
-}
-
-.post .comments
-{
- display: block;
- width: 120px;
- height: 18px;
- margin: 0px;
- padding: 3px 0px 0px 40px;
- background: #90BF35;
- border: 1px solid #5F817E;
- text-decoration: none;
- font-size: 11px;
- text-decoration: none;
- font-weight: bold;
- color: #FFFFFF;
-}
-
/* Footer */
#footer
@@ -376,10 +257,6 @@ hr
padding: 0;
}
-#footer-bgcontent
-{
-}
-
#footer p
{
margin: 0;
@@ -393,8 +270,14 @@ hr
{
}
+.stackframe
+{
+ font-family: Consolas, Monospace;
+}
-.t-grid .t-last {
-border-bottom:1px solid #EEEEEE;
-border-color:#EEEEEE;
-}
\ No newline at end of file
+/*fix telerik grid missing boarder*/
+.t-grid .t-last
+{
+ border-bottom: 1px solid #EEEEEE;
+ border-color: #EEEEEE;
+}
diff --git a/NzbDrone.Web/Controllers/LogController.cs b/NzbDrone.Web/Controllers/LogController.cs
index 69ad51452..49727a190 100644
--- a/NzbDrone.Web/Controllers/LogController.cs
+++ b/NzbDrone.Web/Controllers/LogController.cs
@@ -38,6 +38,26 @@ namespace NzbDrone.Web.Controllers
}
+ [GridAction]
+ public ActionResult _AjaxBinding2()
+ {
+ var l= _logProvider.GetAllLogs().Select(c => new {
+ c.DisplayLevel,
+ c.ExceptionMessage,
+ c.ExceptionString,
+ c.ExceptionType,
+ //c.Level,
+ c.Logger,
+ c.LogId,
+ c.Message,
+ c.Stack,
+ c.Time
+ });
+
+ return View(new GridModel(l));
+ }
+
+
}
}
diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs
index e0bc6471e..9eb42c5dd 100644
--- a/NzbDrone.Web/Controllers/SeriesController.cs
+++ b/NzbDrone.Web/Controllers/SeriesController.cs
@@ -1,9 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
using System.Web;
using System.Web.Mvc;
using NzbDrone.Core.Providers;
+using NzbDrone.Core.Repository;
+using NzbDrone.Web.Models;
+using Telerik.Web.Mvc;
namespace NzbDrone.Web.Controllers
{
@@ -52,38 +56,93 @@ namespace NzbDrone.Web.Controllers
});
}
- public JsonResult MediaDetect()
+
+ [GridAction]
+ public ActionResult _AjaxSeasonGrid(int seasonId)
{
- Core.Providers.IMediaDiscoveryProvider disco = new Core.Providers.MediaDiscoveryProvider();
- return Json(new { Discovered = disco.DiscoveredMedia }, JsonRequestBehavior.AllowGet);
+ var episodes = _episodeProvider.GetEpisodeBySeason(seasonId).Select(c => new EpisodeModel()
+ {
+ EpisodeId = c.EpisodeId,
+ EpisodeNumber = c.EpisodeNumber,
+ SeasonNumber = c.SeasonNumber,
+ Title = c.Title,
+ Overview = c.Overview,
+ AirDate = c.AirDate
+ });
+ return View(new GridModel(episodes));
}
- public JsonResult LightUpMedia()
+
+
+ [GridAction]
+ public ActionResult _CustomBinding(GridCommand command, int seasonId)
{
- Core.Providers.IMediaDiscoveryProvider disco = new Core.Providers.MediaDiscoveryProvider();
- IMediaProvider p = disco.Providers[0];
- return Json(new { ID = 0, HTML = "PlayPauseStop" }, JsonRequestBehavior.AllowGet);
- }
- public JsonResult ControlMedia()
- {
- Core.Providers.IMediaDiscoveryProvider disco = new Core.Providers.MediaDiscoveryProvider();
- IMediaProvider p = disco.Providers[0];
- string action = Request["Action"];
- switch (action)
+ IEnumerable data = GetData(command);
+ return View(new GridModel
{
- case "Play":
- p.Play();
- break;
- case "Pause":
- p.Pause();
- break;
- case "Stop":
- p.Stop();
- break;
- default:
- break;
+ Data = data,
+ Total = data.Count()
+ });
+ }
+ private IEnumerable GetData(GridCommand command)
+ {
+
+ return null;
+ /*
+ IQueryable data = .Orders;
+ //Apply filtering
+ if (command.FilterDescriptors.Any())
+ {
+ data = data.Where(ExpressionBuilder.Expression(command.FilterDescriptors));
}
- return Json(new { Success = true }, JsonRequestBehavior.AllowGet);
+ // Apply sorting
+ foreach (SortDescriptor sortDescriptor in command.SortDescriptors)
+ {
+ if (sortDescriptor.SortDirection == ListSortDirection.Ascending)
+ {
+ switch (sortDescriptor.Member)
+ {
+ case "OrderID":
+ data = data.OrderBy(ExpressionBuilder.Expression(sortDescriptor.Member));
+ break;
+ case "Customer.ContactName":
+ data = data.OrderBy(order => order.Customer.ContactName);
+ break;
+ case "ShipAddress":
+ data = data.OrderBy(order => order.ShipAddress);
+ break;
+ case "OrderDate":
+ data = data.OrderBy(order => order.OrderDate);
+ break;
+ }
+ }
+ else
+ {
+ switch (sortDescriptor.Member)
+ {
+ case "OrderID":
+ data = data.OrderByDescending(order => order.OrderID);
+ break;
+ case "Customer.ContactName":
+ data = data.OrderByDescending(order => order.Customer.ContactName);
+ break;
+ case "ShipAddress":
+ data = data.OrderByDescending(order => order.ShipAddress);
+ break;
+ case "OrderDate":
+ data = data.OrderByDescending(order => order.OrderDate);
+ break;
+ }
+ }
+ }
+ count = data.Count();
+ // ... and paging
+ if (command.PageSize > 0)
+ {
+ data = data.Skip((command.Page - 1) * command.PageSize);
+ }
+ data = data.Take(command.PageSize);
+ return data;*/
}
//
diff --git a/NzbDrone.Web/Models/EpisodeModel.cs b/NzbDrone.Web/Models/EpisodeModel.cs
new file mode 100644
index 000000000..6447a3702
--- /dev/null
+++ b/NzbDrone.Web/Models/EpisodeModel.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace NzbDrone.Web.Models
+{
+ public class EpisodeModel
+ {
+ public string Title { get; set; }
+ public int EpisodeId { get; set; }
+ public int EpisodeNumber { get; set; }
+ public int SeasonNumber { get; set; }
+ public string Overview { get; set; }
+
+ public DateTime AirDate { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj
index 1a5742c00..f9ec2b48b 100644
--- a/NzbDrone.Web/NzbDrone.Web.csproj
+++ b/NzbDrone.Web/NzbDrone.Web.csproj
@@ -86,6 +86,7 @@
+
diff --git a/NzbDrone.Web/Views/Log/Index.aspx b/NzbDrone.Web/Views/Log/Index.aspx
index f56e389ee..6e331f120 100644
--- a/NzbDrone.Web/Views/Log/Index.aspx
+++ b/NzbDrone.Web/Views/Log/Index.aspx
@@ -15,7 +15,7 @@
}
else if (e.dataItem.Level == 5) {
e.row.style.backgroundColor = "black";
- e.row.style.Color = "white";
+ e.row.style.color = "red";
}
//e.row.style.color = 'blue';
}
@@ -34,25 +34,21 @@
.Columns(columns =>
{
columns.Bound(c => c.Time).Title("Time").Width(190);
- //columns.Bound(c => c.Time).Title("Time").Template(c => c.Time.ToShortTimeString()).Groupable(false);
columns.Bound(c => c.DisplayLevel).Title("Level").Width(0);
columns.Bound(c => c.Message);
})
- .DataBinding(dataBinding => dataBinding.Ajax().Select("_AjaxBinding", "Log"))
- .DetailView(detailView => detailView.ClientTemplate(
-
+ .DetailView(detailView => detailView.ClientTemplate(
+
"<#= Logger #>
" +
"<#= ExceptionType #>
" +
"<#= ExceptionMessage #>
" +
- "<#= ExceptionString #>
"
-
- ))
+ "<#= ExceptionString #>
"
+
+ )).DataBinding(data => data.Ajax().Select("_AjaxBinding", "Log"))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.Time).Descending()).Enabled(true))
- .Pageable(c => c.PageSize(50).Position(GridPagerPosition.Both).Style(GridPagerStyles.PageInput | GridPagerStyles.NextPreviousAndNumeric))
- //.Groupable()
+ .Pageable(c => c.PageSize(20).Position(GridPagerPosition.Both).Style(GridPagerStyles.PageInput | GridPagerStyles.NextPreviousAndNumeric))
.Filterable()
.ClientEvents(c => c.OnRowDataBound("onRowDataBound"))
- //.Groupable(grouping => grouping.Groups(groups => groups.Add(c => c.Time.Date)).Enabled(true))
.Render();
%>
diff --git a/NzbDrone.Web/Views/Series/Details.aspx b/NzbDrone.Web/Views/Series/Details.aspx
index ed60f15dd..833183ef0 100644
--- a/NzbDrone.Web/Views/Series/Details.aspx
+++ b/NzbDrone.Web/Views/Series/Details.aspx
@@ -2,6 +2,7 @@
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<%@ Import Namespace="NzbDrone.Core.Repository" %>
+<%@ Import Namespace="NzbDrone.Web.Models" %>
<%: Model.Title %>
@@ -42,18 +43,23 @@
Season
<%: season.SeasonNumber %>
<%
- Html.Telerik().Grid(season.Episodes).Name("seasons_" + season.SeasonNumber)
- .Columns(columns =>
- {
- columns.Bound(c => c.SeasonNumber).Width(0).Title("Seasons");
- columns.Bound(c => c.EpisodeNumber).Width(0).Title("Episode");
- columns.Bound(c => c.Title);
- columns.Bound(c => c.AirDate).Format("{0:d}").Width(0);
- })
- .DetailView(detailView => detailView.Template(e => Html.RenderPartial("EpisodeDetail", e)))
- .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber)).Enabled(false))
- .Footer(false)
- .Render();
+ Season season1 = season;
+ Html.Telerik().Grid().Name("seasons_" + season.SeasonNumber)
+ .Columns(columns =>
+ {
+ columns.Bound(c => c.SeasonNumber).Width(0).Title("Seasons");
+ columns.Bound(c => c.EpisodeNumber).Width(0).Title("Episode");
+ columns.Bound(c => c.Title).Title("Title");
+ columns.Bound(c => c.AirDate).Format("{0:d}").Width(0);
+ })
+ //.DetailView(detailView => detailView.Template(e => Html.RenderPartial("EpisodeDetail", e)))
+ .DetailView(detailView => detailView.ClientTemplate(""))
+ .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber)).Enabled(false))
+ .Footer(false)
+ .DataBinding(d => d.Ajax().Select("_AjaxSeasonGrid", "Series", new RouteValueDictionary { { "seasonId", season1.SeasonId.ToString() } }))
+ //.EnableCustomBinding(true)
+ .ClientEvents(e => e.OnDetailViewExpand("episodeDetailExpanded"))
+ .Render();
}
//Specials
@@ -74,8 +80,7 @@ Html.Telerik().Grid(specialSeasons.Episodes).Name("seasons_specials")
columns.Bound(c => c.Title);
columns.Bound(c => c.AirDate).Format("{0:d}").Width(0);
})
- .DetailView(detailView => detailView.Template(e => Html.RenderPartial("EpisodeDetail", e)))
- .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber)).Enabled(false))
+ .Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber)).Enabled(false))
.Footer(false)
.Render();
}
@@ -85,3 +90,12 @@ Html.Telerik().Grid(specialSeasons.Episodes).Name("seasons_specials")
<%: Html.ActionLink("Back to Series", "Index") %>
+
+
+
diff --git a/NzbDrone.Web/Views/Series/EpisodeDetail.ascx b/NzbDrone.Web/Views/Series/EpisodeDetail.ascx
index 6f31877e2..67d7fc94a 100644
--- a/NzbDrone.Web/Views/Series/EpisodeDetail.ascx
+++ b/NzbDrone.Web/Views/Series/EpisodeDetail.ascx
@@ -1,7 +1,7 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<%: Model.Overview %>
-<%:
+<%--<%:
Html.Telerik().Grid(Model.Files)
.Name("files_" + Model.EpisodeId)
.Columns(columns =>
@@ -11,4 +11,4 @@
columns.Bound(c => c.DateAdded);
})
.Footer(false)
-%>
\ No newline at end of file
+%>--%>
\ No newline at end of file
diff --git a/NzbDrone.Web/Views/Shared/Site.Master b/NzbDrone.Web/Views/Shared/Site.Master
index 7e1ed0b1d..0076a0ec0 100644
--- a/NzbDrone.Web/Views/Shared/Site.Master
+++ b/NzbDrone.Web/Views/Shared/Site.Master
@@ -1,40 +1,28 @@
-
-
-<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
-
+<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<%@ Import Namespace="Helpers" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
+
-
NZBDrone
<%
Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("telerik.common.css")
- .Add("telerik.sitefinity.css")
- .Add("style.css")
- .Add("notibar.css")).Render();
+ .Add("telerik.sitefinity.css")
+ .Add("notibar.css"))
+ .Render();
%>
+
-
+
+
+ Scanning Series Folder...
+