mirror of
https://github.com/Radarr/Radarr.git
synced 2024-08-16 23:39:44 +02:00
Merge branch 'master' of git://github.com/kayone/NzbDrone
This commit is contained in:
commit
a977443676
@ -1,10 +1,13 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq.Expressions;
|
||||
using AutoMoq;
|
||||
using FizzWare.NBuilder;
|
||||
using MbUnit.Framework;
|
||||
using Moq;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
@ -54,42 +57,142 @@ public void RefreshEpisodeInfo()
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsNeededTrue()
|
||||
|
||||
//Should Download
|
||||
[Row(QualityTypes.TV, true, QualityTypes.TV, false, true)]
|
||||
[Row(QualityTypes.DVD, true, QualityTypes.TV, true, true)]
|
||||
[Row(QualityTypes.DVD, true, QualityTypes.TV, true, true)]
|
||||
//Should Skip
|
||||
[Row(QualityTypes.Bluray720, true, QualityTypes.Bluray1080, false, false)]
|
||||
[Row(QualityTypes.TV, true, QualityTypes.HDTV, true, false)]
|
||||
public void Is_Needed_Tv_Dvd_BluRay_BluRay720_Is_Cutoff(QualityTypes reportQuality, Boolean isReportProper, QualityTypes fileQuality, Boolean isFileProper, bool excpected)
|
||||
{
|
||||
//Setup
|
||||
var season = new Mock<SeasonProvider>();
|
||||
var series = new Mock<SeriesProvider>();
|
||||
//var history = new Mock<IHistoryProvider>();
|
||||
//var quality = new Mock<IQualityProvider>();
|
||||
var repo = new Mock<IRepository>();
|
||||
var parseResult = new EpisodeParseResult
|
||||
{
|
||||
SeriesId = 12,
|
||||
SeasonNumber = 2,
|
||||
Episodes = new List<int> { 3 },
|
||||
Quality = reportQuality,
|
||||
Proper = isReportProper
|
||||
};
|
||||
|
||||
var epInDb = new Episode
|
||||
{
|
||||
AirDate = DateTime.Today,
|
||||
EpisodeId = 55555,
|
||||
EpisodeNumber = 5,
|
||||
Language = "en",
|
||||
SeasonId = 4444,
|
||||
SeasonNumber = 1
|
||||
};
|
||||
var epFile = new EpisodeFile()
|
||||
{
|
||||
Proper = isFileProper,
|
||||
Quality = fileQuality
|
||||
};
|
||||
|
||||
season.Setup(s => s.IsIgnored(12345, 1)).Returns(false);
|
||||
series.Setup(s => s.QualityWanted(12345, QualityTypes.TV)).Returns(true);
|
||||
repo.Setup(s => s.Single<Episode>(c => c.SeriesId == 12345 && c.SeasonNumber == 1 && c.EpisodeNumber == 5)).
|
||||
Returns(epInDb);
|
||||
var episodeInfo = new Episode
|
||||
{
|
||||
SeriesId = 12,
|
||||
SeasonNumber = 2,
|
||||
EpisodeNumber = 3,
|
||||
Series = new Series() { QualityProfileId = 1 },
|
||||
EpisodeFile = epFile
|
||||
|
||||
//repo.Setup(s => s.All<EpisodeFile>()).Returns();
|
||||
//repo.All<EpisodeFile>().Where(c => c.EpisodeId == episode.EpisodeId);
|
||||
};
|
||||
|
||||
var seriesQualityProfile = new QualityProfile()
|
||||
{
|
||||
Allowed = new List<QualityTypes> { QualityTypes.TV, QualityTypes.DVD, QualityTypes.Bluray720, QualityTypes.Bluray1080 },
|
||||
Cutoff = QualityTypes.Bluray720,
|
||||
Name = "TV/DVD",
|
||||
};
|
||||
|
||||
|
||||
|
||||
var mocker = new AutoMoqer();
|
||||
mocker.GetMock<IRepository>()
|
||||
.Setup(r => r.Single(It.IsAny<Expression<Func<Episode, Boolean>>>()))
|
||||
.Returns(episodeInfo);
|
||||
|
||||
mocker.GetMock<QualityProvider>()
|
||||
.Setup(q => q.Find(1))
|
||||
.Returns(seriesQualityProfile);
|
||||
|
||||
var result = mocker.Resolve<EpisodeProvider>().IsNeeded(parseResult);
|
||||
|
||||
Assert.AreEqual(excpected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Missing_episode_should_be_added()
|
||||
{
|
||||
//Setup
|
||||
var parseResult1 = new EpisodeParseResult
|
||||
{
|
||||
SeriesId = 12,
|
||||
SeasonNumber = 2,
|
||||
Episodes = new List<int> { 3 },
|
||||
Quality = QualityTypes.DVD
|
||||
|
||||
};
|
||||
|
||||
var parseResult2 = new EpisodeParseResult
|
||||
{
|
||||
SeriesId = 12,
|
||||
SeasonNumber = 3,
|
||||
Episodes = new List<int> { 3 },
|
||||
Quality = QualityTypes.DVD
|
||||
|
||||
};
|
||||
|
||||
var mocker = new AutoMoqer();
|
||||
mocker.SetConstant(MockLib.GetEmptyRepository());
|
||||
|
||||
var episodeProvider = mocker.Resolve<EpisodeProvider>();
|
||||
var result1 = episodeProvider.IsNeeded(parseResult1);
|
||||
var result2 = episodeProvider.IsNeeded(parseResult2);
|
||||
var episodes = episodeProvider.GetEpisodeBySeries(12);
|
||||
Assert.IsTrue(result1);
|
||||
Assert.IsTrue(result2);
|
||||
Assert.IsNotEmpty(episodes);
|
||||
Assert.Count(2, episodes);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Row(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, false, "My Series Name - 1x2 - My Episode Title DVD")]
|
||||
[Row(1, new[] { 2 }, "My Episode Title", QualityTypes.DVD, true, "My Series Name - 1x2 - My Episode Title DVD [Proper]")]
|
||||
[Row(1, new[] { 2 }, "", QualityTypes.DVD, true, "My Series Name - 1x2 - DVD [Proper]")]
|
||||
[Row(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, false, "My Series Name - 1x2-1x4 - My Episode Title HDTV")]
|
||||
[Row(1, new[] { 2, 4 }, "My Episode Title", QualityTypes.HDTV, true, "My Series Name - 1x2-1x4 - My Episode Title HDTV [Proper]")]
|
||||
[Row(1, new[] { 2, 4 }, "", QualityTypes.HDTV, true, "My Series Name - 1x2-1x4 - HDTV [Proper]")]
|
||||
public void sab_title(int seasons, int[] episodes, string title, QualityTypes quality, bool proper, string excpected)
|
||||
{
|
||||
//Arrange
|
||||
var fakeSeries = new Series()
|
||||
{
|
||||
SeriesId = 12,
|
||||
Path = "C:\\TV Shows\\My Series Name"
|
||||
};
|
||||
|
||||
var mocker = new AutoMoqer();
|
||||
mocker.GetMock<SeriesProvider>(MockBehavior.Strict)
|
||||
.Setup(c => c.GetSeries(12))
|
||||
.Returns(fakeSeries);
|
||||
|
||||
var parsResult = new EpisodeParseResult()
|
||||
{
|
||||
SeriesId = 12,
|
||||
AirDate = DateTime.Now,
|
||||
Episodes = episodes.ToList(),
|
||||
Proper = proper,
|
||||
Quality = quality,
|
||||
SeasonNumber = seasons,
|
||||
EpisodeTitle = title
|
||||
};
|
||||
|
||||
//Act
|
||||
|
||||
var actual = mocker.Resolve<EpisodeProvider>().GetSabTitle(parsResult);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(excpected, actual);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Explicit]
|
||||
public void Add_daily_show_episodes()
|
||||
{
|
||||
var mocker = new AutoMoqer();
|
||||
|
@ -62,7 +62,7 @@ public MockIndexerProvider(SeriesProvider seriesProvider, SeasonProvider seasonP
|
||||
{
|
||||
}
|
||||
|
||||
protected override string[] Url
|
||||
protected override string[] Urls
|
||||
{
|
||||
get { return new[] { "www.google.com" }; }
|
||||
}
|
||||
|
@ -50,6 +50,27 @@ public void can_run_job_again()
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
//This test will confirm that the concurrency checks are rest
|
||||
//after execution so the job can successfully run.
|
||||
public void can_run_broken_job_again()
|
||||
{
|
||||
IEnumerable<IJob> fakeTimers = new List<IJob> { new BrokenJob() };
|
||||
var mocker = new AutoMoqer();
|
||||
|
||||
mocker.SetConstant(MockLib.GetEmptyRepository());
|
||||
mocker.SetConstant(fakeTimers);
|
||||
|
||||
var timerProvider = mocker.Resolve<JobProvider>();
|
||||
timerProvider.Initialize();
|
||||
var firstRun = timerProvider.RunScheduled();
|
||||
var secondRun = timerProvider.RunScheduled();
|
||||
|
||||
Assert.IsTrue(firstRun);
|
||||
Assert.IsTrue(secondRun);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
//This test will confirm that the concurrency checks are rest
|
||||
//after execution so the job can successfully run.
|
||||
@ -73,6 +94,28 @@ public void can_run_async_job_again()
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
//This test will confirm that the concurrency checks are rest
|
||||
//after execution so the job can successfully run.
|
||||
public void can_run_broken_async_job_again()
|
||||
{
|
||||
IEnumerable<IJob> fakeTimers = new List<IJob> { new BrokenJob() };
|
||||
var mocker = new AutoMoqer();
|
||||
|
||||
mocker.SetConstant(MockLib.GetEmptyRepository());
|
||||
mocker.SetConstant(fakeTimers);
|
||||
|
||||
var timerProvider = mocker.Resolve<JobProvider>();
|
||||
timerProvider.Initialize();
|
||||
var firstRun = timerProvider.BeginExecute(typeof(FakeJob));
|
||||
Thread.Sleep(2000);
|
||||
var secondRun = timerProvider.BeginExecute(typeof(FakeJob));
|
||||
|
||||
Assert.IsTrue(firstRun);
|
||||
Assert.IsTrue(secondRun);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
//This test will confirm that the concurrency checks are rest
|
||||
//after execution so the job can successfully run.
|
||||
@ -183,6 +226,24 @@ public void Start(ProgressNotification notification, int targetId)
|
||||
}
|
||||
}
|
||||
|
||||
public class BrokenJob : IJob
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return "FakeJob"; }
|
||||
}
|
||||
|
||||
public int DefaultInterval
|
||||
{
|
||||
get { return 15; }
|
||||
}
|
||||
|
||||
public void Start(ProgressNotification notification, int targetId)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public class SlowJob : IJob
|
||||
{
|
||||
public string Name
|
||||
@ -197,7 +258,7 @@ public int DefaultInterval
|
||||
|
||||
public void Start(ProgressNotification notification, int targetId)
|
||||
{
|
||||
Thread.Sleep(10000);
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@ public class EpisodeParseResult
|
||||
internal List<int> Episodes { get; set; }
|
||||
internal int Year { get; set; }
|
||||
|
||||
internal string EpisodeTitle { get; set; }
|
||||
|
||||
internal DateTime AirDate { get; set; }
|
||||
|
||||
public bool Proper { get; set; }
|
||||
|
@ -139,7 +139,6 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>Libraries\NLog.Extended.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NzbDrone.Core, Version=0.2.0.35870, Culture=neutral, processorArchitecture=MSIL" />
|
||||
<Reference Include="SubSonic.Core, Version=3.0.0.3, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>Libraries\SubSonic.Core.dll</HintPath>
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
@ -58,13 +59,29 @@ public virtual IList<Episode> GetEpisodeBySeason(long seasonId)
|
||||
return _sonicRepo.Find<Episode>(e => e.SeasonId == seasonId);
|
||||
}
|
||||
|
||||
public virtual String GetSabTitle(Episode episode)
|
||||
public virtual String GetSabTitle(EpisodeParseResult parseResult)
|
||||
{
|
||||
var series = _series.GetSeries(episode.SeriesId);
|
||||
if (series == null) throw new ArgumentException("Unknown series. ID: " + episode.SeriesId);
|
||||
//Show Name - 1x01-1x02 - Episode Name
|
||||
//Show Name - 1x01 - Episode Name
|
||||
var episodeString = new List<String>();
|
||||
|
||||
//TODO: This method should return a standard title for the sab episode.
|
||||
throw new NotImplementedException();
|
||||
foreach (var episode in parseResult.Episodes)
|
||||
{
|
||||
episodeString.Add(String.Format("{0}x{1}", parseResult.SeasonNumber, episode));
|
||||
}
|
||||
|
||||
var epNumberString = String.Join("-", episodeString);
|
||||
var series = _series.GetSeries(parseResult.SeriesId);
|
||||
var folderName = new DirectoryInfo(series.Path).Name;
|
||||
|
||||
var result = String.Format("{0} - {1} - {2} {3}", folderName, epNumberString, parseResult.EpisodeTitle, parseResult.Quality);
|
||||
|
||||
if (parseResult.Proper)
|
||||
{
|
||||
result += " [Proper]";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -80,10 +97,23 @@ public virtual bool IsNeeded(EpisodeParseResult parsedReport)
|
||||
|
||||
if (episodeInfo == null)
|
||||
{
|
||||
|
||||
//Todo: How do we want to handle this really? Episode could be released before information is on TheTvDB
|
||||
//(Parks and Rec did this a lot in the first season, from experience)
|
||||
//Keivan: Should automatically add the episode to db with minimal information. then update the description/title when avilable.
|
||||
throw new NotImplementedException("Episode was not found in the database");
|
||||
//Keivan: Should automatically add the episode to db with minimal information. then update the description/title when available.
|
||||
episodeInfo = new Episode()
|
||||
{
|
||||
SeriesId = parsedReport.SeriesId,
|
||||
AirDate = DateTime.Now.Date,
|
||||
EpisodeNumber = episode,
|
||||
SeasonNumber = parsedReport.SeasonNumber,
|
||||
Title = String.Empty,
|
||||
Overview = String.Empty,
|
||||
Language = "en"
|
||||
};
|
||||
|
||||
_sonicRepo.Add(episodeInfo);
|
||||
|
||||
}
|
||||
|
||||
var file = episodeInfo.EpisodeFile;
|
||||
@ -221,6 +251,8 @@ public virtual void RefreshEpisodeInfo(Season season)
|
||||
Title = episode.EpisodeName
|
||||
};
|
||||
|
||||
|
||||
//TODO: Replace this db check with a local check. Should make things even faster
|
||||
if (_sonicRepo.Exists<Episode>(e => e.EpisodeId == newEpisode.EpisodeId))
|
||||
{
|
||||
updateList.Add(newEpisode);
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.ServiceModel.Syndication;
|
||||
using System.ServiceModel.Syndication;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
@ -32,57 +32,23 @@ public IndexerProviderBase(SeriesProvider seriesProvider, SeasonProvider seasonP
|
||||
_indexerProvider = indexerProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the source URL for the feed
|
||||
/// </summary>
|
||||
protected abstract string[] Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name for the feed
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates direct link to download an NZB
|
||||
/// Gets the source URL for the feed
|
||||
/// </summary>
|
||||
/// <param name = "item">RSS Feed item to generate the link for</param>
|
||||
/// <returns>Download link URL</returns>
|
||||
protected abstract string NzbDownloadUrl(SyndicationItem item);
|
||||
protected abstract string[] Urls { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses the RSS feed item and.
|
||||
/// </summary>
|
||||
/// <param name = "item">RSS feed item to parse</param>
|
||||
/// <returns>Detailed episode info</returns>
|
||||
protected EpisodeParseResult ParseFeed(SyndicationItem item)
|
||||
|
||||
protected IndexerSetting Settings
|
||||
{
|
||||
var episodeParseResult = Parser.ParseEpisodeInfo(item.Title.Text);
|
||||
if (episodeParseResult == null) return null;
|
||||
|
||||
episodeParseResult = CustomParser(item, episodeParseResult);
|
||||
|
||||
var seriesInfo = _seriesProvider.FindSeries(episodeParseResult.SeriesTitle);
|
||||
|
||||
if (seriesInfo != null)
|
||||
get
|
||||
{
|
||||
episodeParseResult.SeriesId = seriesInfo.SeriesId;
|
||||
episodeParseResult.SeriesTitle = seriesInfo.Title;
|
||||
return episodeParseResult;
|
||||
return _indexerProvider.GetSettings(GetType());
|
||||
}
|
||||
|
||||
Logger.Debug("Unable to map {0} to any of series in database", episodeParseResult.SeriesTitle);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can be overwritten to provide indexer specific info parsing
|
||||
/// </summary>
|
||||
/// <param name="item">RSS item that needs to be parsed</param>
|
||||
/// <param name="currentResult">Result of the built in parse function.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
|
||||
{
|
||||
return currentResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -92,7 +58,7 @@ public void Fetch()
|
||||
{
|
||||
Logger.Info("Fetching feeds from " + Settings.Name);
|
||||
|
||||
foreach (var url in Url)
|
||||
foreach (var url in Urls)
|
||||
{
|
||||
Logger.Debug("Downloading RSS " + url);
|
||||
var feed = SyndicationFeed.Load(_httpProvider.DownloadXml(url)).Items;
|
||||
@ -142,16 +108,45 @@ private void ProcessItem(SyndicationItem feedItem)
|
||||
}
|
||||
}
|
||||
|
||||
protected IndexerSetting Settings
|
||||
/// <summary>
|
||||
/// Parses the RSS feed item and.
|
||||
/// </summary>
|
||||
/// <param name = "item">RSS feed item to parse</param>
|
||||
/// <returns>Detailed episode info</returns>
|
||||
protected EpisodeParseResult ParseFeed(SyndicationItem item)
|
||||
{
|
||||
get
|
||||
var episodeParseResult = Parser.ParseEpisodeInfo(item.Title.Text);
|
||||
if (episodeParseResult == null) return CustomParser(item, null);
|
||||
|
||||
var seriesInfo = _seriesProvider.FindSeries(episodeParseResult.SeriesTitle);
|
||||
|
||||
if (seriesInfo != null)
|
||||
{
|
||||
return _indexerProvider.GetSettings(GetType());
|
||||
episodeParseResult.SeriesId = seriesInfo.SeriesId;
|
||||
episodeParseResult.SeriesTitle = seriesInfo.Title;
|
||||
return CustomParser(item, episodeParseResult);
|
||||
}
|
||||
|
||||
Logger.Debug("Unable to map {0} to any of series in database", episodeParseResult.SeriesTitle);
|
||||
return CustomParser(item, episodeParseResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can be overwritten to provide indexer specific info parsing
|
||||
/// </summary>
|
||||
/// <param name="item">RSS item that needs to be parsed</param>
|
||||
/// <param name="currentResult">Result of the built in parse function.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual EpisodeParseResult CustomParser(SyndicationItem item, EpisodeParseResult currentResult)
|
||||
{
|
||||
return currentResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Generates direct link to download an NZB
|
||||
/// </summary>
|
||||
/// <param name = "item">RSS Feed item to generate the link for</param>
|
||||
/// <returns>Download link URL</returns>
|
||||
protected abstract string NzbDownloadUrl(SyndicationItem item);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ public NewzbinProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvi
|
||||
{
|
||||
}
|
||||
|
||||
protected override string[] Url
|
||||
protected override string[] Urls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ public NzbMatrixProvider(SeriesProvider seriesProvider, SeasonProvider seasonPro
|
||||
{
|
||||
}
|
||||
|
||||
protected override string[] Url
|
||||
protected override string[] Urls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ public NzbsOrgProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvi
|
||||
{
|
||||
}
|
||||
|
||||
protected override string[] Url
|
||||
protected override string[] Urls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ public NzbsRUsProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvi
|
||||
{
|
||||
}
|
||||
|
||||
protected override string[] Url
|
||||
protected override string[] Urls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -127,7 +127,18 @@ public bool BeginExecute(Type jobType, int targetId = 0)
|
||||
{
|
||||
Logger.Debug("Initializing background thread");
|
||||
|
||||
ThreadStart starter = () => Execute(jobType, targetId);
|
||||
ThreadStart starter = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Execute(jobType, targetId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
_jobThread = new Thread(starter) { Name = "TimerThread", Priority = ThreadPriority.BelowNormal };
|
||||
_jobThread.Start();
|
||||
|
||||
@ -169,14 +180,7 @@ private void Execute(Type jobType, int targetId = 0)
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.ErrorException("An error has occurred while executing timer job" + timerClass.Name, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_jobThread == Thread.CurrentThread)
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
Logger.ErrorException("An error has occurred while executing timer job " + timerClass.Name, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,14 +198,13 @@ public virtual void Initialize()
|
||||
var timerProviderLocal = timer;
|
||||
if (!currentTimer.Exists(c => c.TypeName == timerProviderLocal.GetType().ToString()))
|
||||
{
|
||||
var settings = new JobSetting()
|
||||
var settings = new JobSetting
|
||||
{
|
||||
Enable = true,
|
||||
TypeName = timer.GetType().ToString(),
|
||||
Name = timerProviderLocal.Name,
|
||||
Interval = timerProviderLocal.DefaultInterval,
|
||||
LastExecution = DateTime.MinValue
|
||||
|
||||
};
|
||||
|
||||
SaveSettings(settings);
|
||||
|
@ -32,10 +32,10 @@ public class Episode
|
||||
public virtual Season Season { get; set; }
|
||||
|
||||
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
|
||||
public virtual Series Series { get; private set; }
|
||||
public virtual Series Series { get; set; }
|
||||
|
||||
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
|
||||
public virtual EpisodeFile EpisodeFile { get; private set; }
|
||||
public virtual EpisodeFile EpisodeFile { get; set; }
|
||||
|
||||
[SubSonicToManyRelation]
|
||||
public virtual List<History> Histories { get; private set; }
|
||||
|
@ -36,7 +36,7 @@
|
||||
.Columns(columns =>
|
||||
{
|
||||
columns.Bound(c => c.Time).Title("Time").Width(190);
|
||||
columns.Bound(c => c.DisplayLevel).Title("Level").Width(0);
|
||||
columns.Bound(c => c.Level).Title("Level").Width(0);
|
||||
columns.Bound(c => c.Message);
|
||||
})
|
||||
.DetailView(detailView => detailView.ClientTemplate(
|
||||
|
@ -9,18 +9,22 @@
|
||||
<parameter name="stacktrace" layout="${stacktrace:topFrames=99}" xsi:type="NLogViewerParameterInfo" />
|
||||
<parameter name="ThreadName" layout="${threadname}" xsi:type="NLogViewerParameterInfo" />
|
||||
</target>
|
||||
|
||||
<target name="file" xsi:type="File"
|
||||
layout="${longdate} [${level}] ${logger}: ${message} ${exception:ToString}"
|
||||
fileName="${basedir}/App_Data/logs/${shortdate}.txt" />
|
||||
</targets>
|
||||
|
||||
|
||||
|
||||
|
||||
<rules>
|
||||
|
||||
<logger name="IIS*" minlevel="Trace" writeTo="consoleTarget"/>
|
||||
<logger name="Application" minlevel="Trace" writeTo="consoleTarget"/>
|
||||
<logger name="*" minlevel="Trace" writeTo="udpTarget"/>
|
||||
<!--<logger name="*" minlevel="Off" writeTo="debugTarget"/>-->
|
||||
|
||||
|
||||
<logger name="*" minlevel="Trace" writeTo="file">
|
||||
<filters>
|
||||
<when condition="logger == 'NzbDrone.SubSonic'" action="Ignore" />
|
||||
</filters>
|
||||
</logger>
|
||||
<logger name="*" minlevel="Off" writeTo="debugTarget"/>
|
||||
</rules>
|
||||
</nlog>
|
Loading…
Reference in New Issue
Block a user