look right in IE, all episodes are ajax loaded.

commited somewhere between vancouver and vegas @ 2135ft. Alt and 480mph.
This commit is contained in:
Keivan 2010-10-29 20:46:32 -06:00
parent c9bc063a9c
commit bf1ff29519
31 changed files with 323 additions and 364 deletions

View File

@ -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)
{

View File

@ -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<IRepository>();
repository.Setup(c => c.Update(It.IsAny<EpisodeInfo>())).Verifiable();
var diskProvider = MockLib.GetStandardDisk(1, 2);
var kernel = new MockingKernel();
kernel.Bind<IDiskProvider>().ToConstant(diskProvider);
kernel.Bind<IRepository>().ToConstant(repository.Object);
kernel.Bind<IMediaFileProvider>().To<MediaFileProvider>();
var fakeSeries = new Series()
{
Path = MockLib.StandardSeries[0]
};
//Act
kernel.Get<IMediaFileProvider>().Scan(fakeSeries);
//Assert
repository.Verify(c => c.Update(It.IsAny<EpisodeInfo>()), 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());
}
}
}

View File

@ -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<IConfigProvider>();
fakeConfig.Setup(c => c.EpisodeNameFormat).Returns(patern);
var kernel = new MockingKernel();
kernel.Bind<IConfigProvider>().ToConstant(fakeConfig.Object);
kernel.Bind<IMediaFileProvider>().To<MediaFileProvider>();
var fakeEpisode = new EpisodeModel
{
SeasonNumber = 6,
EpisodeNumber = 8,
EpisodeTitle = "Lethal Inspection",
Quality = QualityTypes.HDTV,
SeriesTitle = "Futurama"
};
//Act
var result = kernel.Get<IMediaFileProvider>().GenerateEpisodePath(fakeEpisode);
//Assert
Assert.AreEqual(path.ToLowerInvariant(), result.ToLowerInvariant());
}
}

View File

@ -49,7 +49,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" />
<Reference Include="NLog">
<HintPath>..\NzbDrone.Core\Libraries\NLog.dll</HintPath>
</Reference>
<Reference Include="SubSonic.Core, Version=3.0.0.3, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\SubSonic.Core.dll</HintPath>

View File

@ -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);

View File

@ -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<ISeriesProvider>().To<SeriesProvider>().InSingletonScope();
_kernel.Bind<ISeasonProvider>().To<SeasonProvider>();
_kernel.Bind<IEpisodeProvider>().To<EpisodeProvider>();
@ -48,6 +50,7 @@ namespace NzbDrone.Core
_kernel.Bind<ISyncProvider>().To<SyncProvider>().InSingletonScope();
_kernel.Bind<INotificationProvider>().To<NotificationProvider>().InSingletonScope();
_kernel.Bind<ILogProvider>().To<LogProvider>().InSingletonScope();
_kernel.Bind<IMediaFileProvider>().To<MediaFileProvider>().InSingletonScope();
_kernel.Bind<IRepository>().ToMethod(c => new SimpleRepository(dbProvider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(logRepository).WhenInjectedInto<SubsonicTarget>().InSingletonScope();

View File

@ -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<SubsonicTarget>();
LogManager.Configuration.AddTarget("DbLogger", sonicTarget);

View File

@ -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; }

View File

@ -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);
}
}
}

View File

@ -144,6 +144,7 @@
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.XML" />
<Reference Include="System.Xml.Linq" />
<Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL" />

View File

@ -17,7 +17,7 @@ namespace NzbDrone.Core
private static readonly Regex[] ReportTitleRegex = new[]
{
new Regex(@"(?<title>.+?)?\W(S)?(?<season>\d+)\w(?<episode>\d+)\W", RegexOptions.IgnoreCase | RegexOptions.Compiled)
new Regex(@"(?<title>.+?)?\W(S)?(?<season>\d+)\w(?<episode>\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;
}

View File

@ -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); }

View File

@ -43,6 +43,11 @@ namespace NzbDrone.Core.Providers
return _sonicRepo.Find<Episode>(e => e.SeriesId == seriesId);
}
public IList<Episode> GetEpisodeBySeason(long seasonId)
{
return _sonicRepo.Find<Episode>(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<Episode>();
var newList = new List<Episode>();
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);
}
}
}

View File

@ -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);

View File

@ -20,5 +20,6 @@ namespace NzbDrone.Core.Providers
bool IsNeeded(EpisodeModel episode);
void RefreshEpisodeInfo(int seriesId);
IList<Episode> GetEpisodeBySeason(long seasonId);
}
}

View File

@ -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);
}
}

View File

@ -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<string> GetMediaFileList(string path)
{
Logger.Info("Scanning '{0}' for episodes", path);
Logger.Debug("Scanning '{0}' for episodes", path);
var mediaFileList = new List<string>();
@ -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;
}
}
}

View File

@ -31,11 +31,10 @@ namespace NzbDrone.Core.Providers
if (_sonicRepo.Exists<Season>(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,

View File

@ -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
{

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository

View File

@ -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<Episode> Episodes { get; private set; }

View File

@ -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;
}
/*fix telerik grid missing boarder*/
.t-grid .t-last
{
border-bottom: 1px solid #EEEEEE;
border-color: #EEEEEE;
}

View File

@ -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));
}
}
}

View File

@ -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 = "<span class='MediaRenderer XBMC'><span class='Play'>Play</span><span class='Pause'>Pause</span><span class='Stop'>Stop</span></span>" }, 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<Episode> 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<Episode> GetData(GridCommand command)
{
return null;
/*
IQueryable<Episode> data = .Orders;
//Apply filtering
if (command.FilterDescriptors.Any())
{
data = data.Where(ExpressionBuilder.Expression<Order>(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<Order, int>(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;*/
}
//

View File

@ -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; }
}
}

View File

@ -86,6 +86,7 @@
</Compile>
<Compile Include="Helpers\IsCurrentActionHelper.cs" />
<Compile Include="Models\AccountModels.cs" />
<Compile Include="Models\EpisodeModel.cs" />
<Compile Include="Models\SettingsModels.cs" />
<Compile Include="Ninject.Web.Mvc\ControllerMissingBindingResolver.cs" />
<Compile Include="Ninject.Web.Mvc\FilterInjector.cs" />

View File

@ -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(
"<div><#= Logger #></div>" +
"<div><#= ExceptionType #></div>" +
"<div><#= ExceptionMessage #></div>" +
"<div><#= ExceptionString #></div>"
))
"<div class='stackframe'><#= ExceptionString #></div>"
)).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();
%>
</asp:Content>

View File

@ -2,6 +2,7 @@
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<%@ Import Namespace="NzbDrone.Core.Repository" %>
<%@ Import Namespace="NzbDrone.Web.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%: Model.Title %>
</asp:Content>
@ -42,18 +43,23 @@
Season
<%: season.SeasonNumber %></h3>
<%
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<EpisodeModel>().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("<div id ='ep_<#= EpisodeId #>'/>"))
.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") %>
</p>
</asp:Content>
<asp:Content ContentPlaceHolderID="Scripts" runat="server">
<script type="text/javascript">
function episodeDetailExpanded(e) {
$console.log("OnDetailViewExpand :: " + e.masterRow.cells[1].innerHTML);
}
</script>
</asp:Content>

View File

@ -1,7 +1,7 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NzbDrone.Core.Repository.Episode>" %>
<%@ 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)
%>
%>--%>

View File

@ -1,40 +1,28 @@
<!--
Design by Free CSS Templates
http://www.freecsstemplates.org
Released for free under a Creative Commons Attribution 2.5 License
Name : Concurrence
Description: A two-column, fixed-width design for 1024x768 screen resolutions.
Version : 1.0
Released : 20100727
-->
<%@ 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" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<asp:ContentPlaceHolder runat="server" ID="Scripts" />
<title>NZBDrone</title>
<%
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();
%>
<link href="../../Content/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<a href="http://github.com/kayone/NzbDrone">
<img style="position: absolute; top: 0; left: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png"
alt="Fork me on GitHub" />
<img style="position: absolute; top: 0; left: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png" />
</a>
<div id="msgBox" style="visibility: hidden">
<span id="msgText">Scanning Series Folder...</span>
</div>
<div id="header">
<div id="msgBox">
<span id="msgText">Scanning Series Folder...</span>
</div>
<div id="menu">
<ul>
<%=Html.CurrentActionLink("Series", "Index", "Series") %>
@ -51,21 +39,16 @@ Released : 20100727
</h1>
</div>
<hr />
<!-- end #logo -->
<div id="page">
<asp:ContentPlaceHolder ID="ActionMenu" runat="server" />
<div id="content">
<div class="post">
<div class="entry">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</div>
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
<% Html.Telerik().ScriptRegistrar().Scripts(
</body>
<asp:contentplaceholder runat="server" id="Scripts" />
<% Html.Telerik().ScriptRegistrar().Scripts(
c => c.Add("jquery-ui-1.8.5.custom.min.js")
.Add("jquery.jgrowl.js")
.Add("Notification.js")
).Render(); %>
</body>
.Add("Notification.js"))
.Render();
%>
</html>

View File

@ -40,7 +40,7 @@ namespace NzbDrone
}
#region private
#region private
private readonly Dictionary<AttachType, string> _attachTypesMap;
private readonly DTE2 _dte;
@ -49,7 +49,7 @@ namespace NzbDrone
#endregion
#region ctor
#region ctor
private ProcessAttacher(DTE2 dte, string processName, int waitTimeout)
{
@ -63,7 +63,7 @@ namespace NzbDrone
#endregion
#region private methods
#region private methods
private AttachResult Attach(AttachType attachType)
{
@ -130,7 +130,7 @@ namespace NzbDrone
#endregion
#region public methods
#region public methods
public void OptimisticAttachManaged()
@ -146,6 +146,7 @@ namespace NzbDrone
#endregion
}
#endif
}
#endif