mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-16 21:16:24 -04:00
Merge branch 'develop'
Conflicts: src/UI/app.js
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(22)]
|
||||
public class move_indexer_to_generic_provider : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Indexers").AddColumn("ConfigContract").AsString().Nullable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(22)]
|
||||
public class move_indexer_to_generic_provider : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Indexers").AddColumn("ConfigContract").AsString().Nullable();
|
||||
|
||||
//Execute.WithConnection(ConvertSeasons);
|
||||
}
|
||||
|
||||
private void ConvertSeasons(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand allSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
allSeriesCmd.Transaction = tran;
|
||||
allSeriesCmd.CommandText = @"SELECT Id FROM Series";
|
||||
using (IDataReader allSeriesReader = allSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (allSeriesReader.Read())
|
||||
{
|
||||
int seriesId = allSeriesReader.GetInt32(0);
|
||||
var seasons = new List<dynamic>();
|
||||
|
||||
using (IDbCommand seasonsCmd = conn.CreateCommand())
|
||||
{
|
||||
seasonsCmd.Transaction = tran;
|
||||
seasonsCmd.CommandText = String.Format(@"SELECT SeasonNumber, Monitored FROM Seasons WHERE SeriesId = {0}", seriesId);
|
||||
|
||||
using (IDataReader seasonReader = seasonsCmd.ExecuteReader())
|
||||
{
|
||||
while (seasonReader.Read())
|
||||
{
|
||||
int seasonNumber = seasonReader.GetInt32(0);
|
||||
bool monitored = seasonReader.GetBoolean(1);
|
||||
|
||||
if (seasonNumber == 0)
|
||||
{
|
||||
monitored = false;
|
||||
}
|
||||
|
||||
seasons.Add(new { seasonNumber, monitored });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
var text = String.Format("UPDATE Series SET Seasons = '{0}' WHERE Id = {1}", seasons.ToJson(), seriesId);
|
||||
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = text;
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(24)]
|
||||
public class drop_tvdb_episodeid : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
SqLiteAlter.DropColumns("Episodes", new[] { "TvDbEpisodeId" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(25)]
|
||||
public class move_notification_to_generic_provider : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Notifications").AddColumn("ConfigContract").AsString().Nullable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(26)]
|
||||
public class add_config_contract_to_notifications : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "EmailSettings" }).Where(new { Implementation = "Email" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "GrowlSettings" }).Where(new { Implementation = "Growl" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "NotifyMyAndroidSettings" }).Where(new { Implementation = "NotifyMyAndroid" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "PlexClientSettings" }).Where(new { Implementation = "PlexClient" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "PlexServerSettings" }).Where(new { Implementation = "PlexServer" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "ProwlSettings" }).Where(new { Implementation = "Prowl" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "PushBulletSettings" }).Where(new { Implementation = "PushBullet" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "PushoverSettings" }).Where(new { Implementation = "Pushover" });
|
||||
Update.Table("Notifications").Set(new { ConfigContract = "XbmcSettings" }).Where(new { Implementation = "Xbmc" });
|
||||
|
||||
Delete.FromTable("Notifications").IsNull("ConfigContract");
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/NzbDrone.Core/Datastore/Migration/027_fix_omgwtfnzbs.cs
Normal file
24
src/NzbDrone.Core/Datastore/Migration/027_fix_omgwtfnzbs.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(27)]
|
||||
public class fix_omgwtfnzbs : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Update.Table("Indexers")
|
||||
.Set(new {ConfigContract = "OmgwtfnzbsSettings"})
|
||||
.Where(new {Implementation = "Omgwtfnzbs"});
|
||||
|
||||
Update.Table("Indexers")
|
||||
.Set(new {Settings = "{}"})
|
||||
.Where(new {Implementation = "Omgwtfnzbs", Settings = (string) null});
|
||||
|
||||
Update.Table("Indexers")
|
||||
.Set(new { Settings = "{}" })
|
||||
.Where(new { Implementation = "Omgwtfnzbs", Settings = "" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,12 +35,13 @@ namespace NzbDrone.Core.Datastore
|
||||
|
||||
Mapper.Entity<IndexerDefinition>().RegisterModel("Indexers");
|
||||
Mapper.Entity<ScheduledTask>().RegisterModel("ScheduledTasks");
|
||||
Mapper.Entity<NotificationDefinition>().RegisterModel("Notifications");
|
||||
Mapper.Entity<NotificationDefinition>()
|
||||
.RegisterModel("Notifications");
|
||||
|
||||
Mapper.Entity<SceneMapping>().RegisterModel("SceneMappings");
|
||||
|
||||
Mapper.Entity<History.History>().RegisterModel("History")
|
||||
.AutoMapChildModels();
|
||||
.AutoMapChildModels();
|
||||
|
||||
Mapper.Entity<Series>().RegisterModel("Series")
|
||||
.Ignore(s => s.RootFolderPath)
|
||||
@@ -96,7 +97,6 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
var embeddedTypes = typeof(IEmbeddedDocument).Assembly.ImplementationsOf<IEmbeddedDocument>();
|
||||
|
||||
|
||||
var embeddedConvertor = new EmbeddedDocumentConverter();
|
||||
var genericListDefinition = typeof(List<>).GetGenericTypeDefinition();
|
||||
foreach (var embeddedType in embeddedTypes)
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
@@ -38,31 +39,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
return true;
|
||||
}
|
||||
|
||||
var queue = downloadClient.GetQueue().Select(queueItem => Parser.Parser.ParseTitle(queueItem.Title)).Where(episodeInfo => episodeInfo != null);
|
||||
var queue = downloadClient.GetQueue().Select(q => q.RemoteEpisode);
|
||||
|
||||
return !IsInQueue(subject, queue);
|
||||
}
|
||||
|
||||
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<ParsedEpisodeInfo> queue)
|
||||
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<RemoteEpisode> queue)
|
||||
{
|
||||
var matchingTitle = queue.Where(q => String.Equals(q.SeriesTitle, newEpisode.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));
|
||||
var matchingSeries = queue.Where(q => q.Series.Id == newEpisode.Series.Id);
|
||||
var matchingSeriesAndQuality = matchingSeries.Where(q => q.ParsedEpisodeInfo.Quality >= newEpisode.ParsedEpisodeInfo.Quality);
|
||||
|
||||
var matchingTitleWithQuality = matchingTitle.Where(q => q.Quality >= newEpisode.ParsedEpisodeInfo.Quality);
|
||||
|
||||
if (newEpisode.Series.SeriesType == SeriesTypes.Daily)
|
||||
{
|
||||
return matchingTitleWithQuality.Any(q => q.AirDate.Value.Date == newEpisode.ParsedEpisodeInfo.AirDate.Value.Date);
|
||||
}
|
||||
|
||||
var matchingSeason = matchingTitleWithQuality.Where(q => q.SeasonNumber == newEpisode.ParsedEpisodeInfo.SeasonNumber);
|
||||
|
||||
if (newEpisode.ParsedEpisodeInfo.FullSeason)
|
||||
{
|
||||
return matchingSeason.Any();
|
||||
}
|
||||
|
||||
return matchingSeason.Any(q => q.EpisodeNumbers != null && q.EpisodeNumbers.Any(e => newEpisode.ParsedEpisodeInfo.EpisodeNumbers.Contains(e)));
|
||||
return matchingSeriesAndQuality.Any(q => q.Episodes.Select(e => e.Id).Intersect(newEpisode.Episodes.Select(e => e.Id)).Any());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
12
src/NzbDrone.Core/DiskSpace/DiskSpace.cs
Normal file
12
src/NzbDrone.Core/DiskSpace/DiskSpace.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Core.DiskSpace
|
||||
{
|
||||
public class DiskSpace
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public String Label { get; set; }
|
||||
public long FreeSpace { get; set; }
|
||||
public long TotalSpace { get; set; }
|
||||
}
|
||||
}
|
||||
96
src/NzbDrone.Core/DiskSpace/DiskSpaceService.cs
Normal file
96
src/NzbDrone.Core/DiskSpace/DiskSpaceService.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.DiskSpace
|
||||
{
|
||||
public interface IDiskSpaceService
|
||||
{
|
||||
List<DiskSpace> GetFreeSpace();
|
||||
}
|
||||
|
||||
public class DiskSpaceService : IDiskSpaceService
|
||||
{
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DiskSpaceService(ISeriesService seriesService, IConfigService configService, IDiskProvider diskProvider, Logger logger)
|
||||
{
|
||||
_seriesService = seriesService;
|
||||
_configService = configService;
|
||||
_diskProvider = diskProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<DiskSpace> GetFreeSpace()
|
||||
{
|
||||
var diskSpace = new List<DiskSpace>();
|
||||
diskSpace.AddRange(GetSeriesFreeSpace());
|
||||
diskSpace.AddRange(GetDroneFactoryFreeSpace());
|
||||
diskSpace.AddRange(GetFixedDisksFreeSpace());
|
||||
|
||||
return diskSpace.DistinctBy(d => d.Path).ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<DiskSpace> GetSeriesFreeSpace()
|
||||
{
|
||||
var seriesRootPaths = _seriesService.GetAllSeries().Select(s => _diskProvider.GetPathRoot(s.Path)).Distinct();
|
||||
|
||||
return GetDiskSpace(seriesRootPaths);
|
||||
}
|
||||
|
||||
private IEnumerable<DiskSpace> GetDroneFactoryFreeSpace()
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(_configService.DownloadedEpisodesFolder))
|
||||
{
|
||||
return GetDiskSpace(new[] { _diskProvider.GetPathRoot(_configService.DownloadedEpisodesFolder) });
|
||||
}
|
||||
|
||||
return new List<DiskSpace>();
|
||||
}
|
||||
|
||||
private IEnumerable<DiskSpace> GetFixedDisksFreeSpace()
|
||||
{
|
||||
return GetDiskSpace(_diskProvider.GetFixedDrives());
|
||||
}
|
||||
|
||||
private IEnumerable<DiskSpace> GetDiskSpace(IEnumerable<String> paths)
|
||||
{
|
||||
foreach (var path in paths)
|
||||
{
|
||||
DiskSpace diskSpace = null;
|
||||
|
||||
try
|
||||
{
|
||||
var freeSpace = _diskProvider.GetAvailableSpace(path).Value;
|
||||
var totalSpace = _diskProvider.GetTotalSize(path).Value;
|
||||
|
||||
diskSpace = new DiskSpace
|
||||
{
|
||||
Path = path,
|
||||
FreeSpace = freeSpace,
|
||||
TotalSpace = totalSpace
|
||||
};
|
||||
|
||||
diskSpace.Label = _diskProvider.GetVolumeLabel(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.WarnException("Unable to get free space for: " + path, ex);
|
||||
}
|
||||
|
||||
if (diskSpace != null)
|
||||
{
|
||||
yield return diskSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
@@ -12,12 +13,14 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NzbgetClient(IConfigService configService, IHttpProvider httpProvider, Logger logger)
|
||||
public NzbgetClient(IConfigService configService, IHttpProvider httpProvider, IParsingService parsingService, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_httpProvider = httpProvider;
|
||||
_parsingService = parsingService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -75,6 +78,14 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
queueItem.Size = nzbGetQueueItem.FileSizeMb;
|
||||
queueItem.Sizeleft = nzbGetQueueItem.RemainingSizeMb;
|
||||
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
|
||||
if (parsedEpisodeInfo == null) continue;
|
||||
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
|
||||
if (remoteEpisode.Series == null) continue;
|
||||
|
||||
queueItem.RemoteEpisode = remoteEpisode;
|
||||
|
||||
yield return queueItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using NzbDrone.Common;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using RestSharp;
|
||||
|
||||
@@ -53,13 +54,19 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly ICached<IEnumerable<QueueItem>> _queueCache;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SabnzbdClient(IConfigService configService, IHttpProvider httpProvider, ICacheManger cacheManger, Logger logger)
|
||||
public SabnzbdClient(IConfigService configService,
|
||||
IHttpProvider httpProvider,
|
||||
ICacheManger cacheManger,
|
||||
IParsingService parsingService,
|
||||
Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_httpProvider = httpProvider;
|
||||
_parsingService = parsingService;
|
||||
_queueCache = cacheManger.GetCache<IEnumerable<QueueItem>>(GetType(), "queue");
|
||||
_logger = logger;
|
||||
}
|
||||
@@ -121,6 +128,14 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
queueItem.Timeleft = sabQueueItem.Timeleft;
|
||||
queueItem.Status = sabQueueItem.Status;
|
||||
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
|
||||
if (parsedEpisodeInfo == null) continue;
|
||||
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
|
||||
if (remoteEpisode.Series == null) continue;
|
||||
|
||||
queueItem.RemoteEpisode = remoteEpisode;
|
||||
|
||||
queueItems.Add(queueItem);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,5 +9,4 @@ namespace NzbDrone.Core.Download
|
||||
bool IsConfigured { get; }
|
||||
IEnumerable<QueueItem> GetQueue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
@@ -10,5 +11,6 @@ namespace NzbDrone.Core.Download
|
||||
public decimal Sizeleft { get; set; }
|
||||
public TimeSpan Timeleft { get; set; }
|
||||
public String Status { get; set; }
|
||||
public RemoteEpisode RemoteEpisode { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupOrphanedEpisodeFiles : IHousekeepingTask
|
||||
{
|
||||
private readonly IDatabase _database;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public CleanupOrphanedEpisodeFiles(IDatabase database, Logger logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
_logger.Trace("Running orphaned episode files cleanup");
|
||||
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM EpisodeFiles
|
||||
WHERE Id IN (
|
||||
SELECT EpisodeFiles.Id FROM EpisodeFiles
|
||||
LEFT OUTER JOIN Episodes
|
||||
ON EpisodeFiles.Id = Episodes.EpisodeFileId
|
||||
WHERE Episodes.Id IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping
|
||||
{
|
||||
public class HousekeepingService : IExecute<HousekeepingCommand>
|
||||
public class HousekeepingService : IExecute<HousekeepingCommand>, IHandleAsync<ApplicationStartedEvent>
|
||||
{
|
||||
private readonly IEnumerable<IHousekeepingTask> _housekeepers;
|
||||
private readonly Logger _logger;
|
||||
@@ -16,7 +18,7 @@ namespace NzbDrone.Core.Housekeeping
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Execute(HousekeepingCommand message)
|
||||
private void Clean()
|
||||
{
|
||||
_logger.Info("Running housecleaning tasks");
|
||||
|
||||
@@ -32,5 +34,15 @@ namespace NzbDrone.Core.Housekeeping
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(HousekeepingCommand message)
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
public void HandleAsync(ApplicationStartedEvent message)
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace NzbDrone.Core.Indexers
|
||||
|
||||
_logger.Debug("Available indexers {0}", indexers.Count);
|
||||
|
||||
|
||||
var taskList = new List<Task>();
|
||||
var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
}
|
||||
|
||||
public ProviderDefinition Definition { get; set; }
|
||||
public virtual ProviderDefinition Definition { get; set; }
|
||||
|
||||
public abstract DownloadProtocol Protocol { get; }
|
||||
|
||||
@@ -49,7 +49,6 @@ namespace NzbDrone.Core.Indexers
|
||||
public abstract IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date);
|
||||
public abstract IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset);
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GetType().Name;
|
||||
|
||||
@@ -4,5 +4,6 @@ namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
public class IndexerDefinition : ProviderDefinition
|
||||
{
|
||||
public bool Enable { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Composition;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Indexers
|
||||
@@ -14,12 +16,14 @@ namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
private readonly IIndexerRepository _providerRepository;
|
||||
private readonly IEnumerable<IIndexer> _providers;
|
||||
private readonly INewznabTestService _newznabTestService;
|
||||
|
||||
public IndexerFactory(IIndexerRepository providerRepository, IEnumerable<IIndexer> providers, Logger logger)
|
||||
: base(providerRepository, providers, logger)
|
||||
public IndexerFactory(IIndexerRepository providerRepository, IEnumerable<IIndexer> providers, IContainer container, INewznabTestService newznabTestService, Logger logger)
|
||||
: base(providerRepository, providers, container, logger)
|
||||
{
|
||||
_providerRepository = providerRepository;
|
||||
_providers = providers;
|
||||
_newznabTestService = newznabTestService;
|
||||
}
|
||||
|
||||
protected override void InitializeProviders()
|
||||
@@ -31,11 +35,26 @@ namespace NzbDrone.Core.Indexers
|
||||
|
||||
var newProviders = definitions.Where(def => currentProviders.All(c => c.Implementation != def.Implementation)).ToList();
|
||||
|
||||
|
||||
if (newProviders.Any())
|
||||
{
|
||||
_providerRepository.InsertMany(newProviders.Cast<IndexerDefinition>().ToList());
|
||||
}
|
||||
}
|
||||
|
||||
protected override List<IndexerDefinition> Active()
|
||||
{
|
||||
return base.Active().Where(c => c.Enable).ToList();
|
||||
}
|
||||
|
||||
public override IndexerDefinition Create(IndexerDefinition definition)
|
||||
{
|
||||
if (definition.Implementation == typeof(Newznab.Newznab).Name)
|
||||
{
|
||||
var indexer = GetInstance(definition);
|
||||
_newznabTestService.Test(indexer);
|
||||
}
|
||||
|
||||
return base.Create(definition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,8 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
}
|
||||
}
|
||||
|
||||
public override ProviderDefinition Definition { get; set; }
|
||||
|
||||
private NewznabSettings GetSettings(string url, List<int> categories)
|
||||
{
|
||||
var settings = new NewznabSettings { Url = url };
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class NewznabSettings : IProviderConfig
|
||||
{
|
||||
private static readonly NewznabSettingsValidator Validator = new NewznabSettingsValidator();
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
{
|
||||
return decisions.Where(c => c.Approved)
|
||||
.OrderByDescending(c => c.LocalEpisode.Quality)
|
||||
.ThenByDescending(c => c.LocalEpisode.Size)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,6 @@ namespace NzbDrone.Core.MetadataSource
|
||||
episode.SeasonNumber = traktEpisode.season;
|
||||
episode.EpisodeNumber = traktEpisode.episode;
|
||||
episode.EpisodeNumber = traktEpisode.number;
|
||||
episode.TvDbEpisodeId = traktEpisode.tvdb_id;
|
||||
episode.Title = traktEpisode.title;
|
||||
episode.AirDate = FromIsoToString(traktEpisode.first_aired_iso);
|
||||
episode.AirDateUtc = FromIso(traktEpisode.first_aired_iso);
|
||||
|
||||
@@ -12,16 +12,6 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
_smtpProvider = smtpProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Email"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "Email"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return null; }
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Email
|
||||
{
|
||||
public class EmailSettingsValidator : AbstractValidator<EmailSettings>
|
||||
{
|
||||
public EmailSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Server).NotEmpty();
|
||||
RuleFor(c => c.Port).GreaterThan(0);
|
||||
RuleFor(c => c.From).NotEmpty();
|
||||
RuleFor(c => c.To).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class EmailSettings : IProviderConfig
|
||||
{
|
||||
private static readonly EmailSettingsValidator Validator = new EmailSettingsValidator();
|
||||
|
||||
public EmailSettings()
|
||||
{
|
||||
Port = 25;
|
||||
@@ -43,7 +57,7 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Growl
|
||||
_growlProvider = growlProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Growl"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "Growl"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "http://growl.info/"; }
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Growl
|
||||
{
|
||||
public class GrowlSettingsValidator : AbstractValidator<GrowlSettings>
|
||||
{
|
||||
public GrowlSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Host).NotEmpty();
|
||||
RuleFor(c => c.Port).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class GrowlSettings : IProviderConfig
|
||||
{
|
||||
private static readonly GrowlSettingsValidator Validator = new GrowlSettingsValidator();
|
||||
|
||||
public GrowlSettings()
|
||||
{
|
||||
Port = 23053;
|
||||
@@ -31,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Growl
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public interface INotification
|
||||
public interface INotification : IProvider
|
||||
{
|
||||
string Name { get; }
|
||||
string ImplementationName { get; }
|
||||
string Link { get; }
|
||||
|
||||
NotificationDefinition InstanceDefinition { get; set; }
|
||||
|
||||
void OnGrab(string message);
|
||||
void OnDownload(string message, Series series);
|
||||
void AfterRename(Series series);
|
||||
|
||||
@@ -1,28 +1,47 @@
|
||||
using NzbDrone.Common.Serializer;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public abstract class NotificationBase<TSetting> : INotification where TSetting : class, IProviderConfig, new()
|
||||
public abstract class NotificationBase<TSettings> : INotification where TSettings : IProviderConfig, new()
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
public abstract string ImplementationName { get; }
|
||||
public abstract string Link { get; }
|
||||
public Type ConfigContract
|
||||
{
|
||||
get
|
||||
{
|
||||
return typeof(TSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public NotificationDefinition InstanceDefinition { get; set; }
|
||||
public IEnumerable<ProviderDefinition> DefaultDefinitions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<ProviderDefinition>();
|
||||
}
|
||||
}
|
||||
|
||||
public ProviderDefinition Definition { get; set; }
|
||||
|
||||
public abstract string Link { get; }
|
||||
|
||||
public abstract void OnGrab(string message);
|
||||
public abstract void OnDownload(string message, Series series);
|
||||
public abstract void AfterRename(Series series);
|
||||
|
||||
public TSetting Settings { get; private set; }
|
||||
|
||||
public TSetting ImportSettingsFromJson(string json)
|
||||
protected TSettings Settings
|
||||
{
|
||||
Settings = Json.Deserialize<TSetting>(json) ?? new TSetting();
|
||||
get
|
||||
{
|
||||
return (TSettings)Definition.Settings;
|
||||
}
|
||||
}
|
||||
|
||||
return Settings;
|
||||
public override string ToString()
|
||||
{
|
||||
return GetType().Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
using System;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public class NotificationDefinition : ModelBase
|
||||
{
|
||||
public String Name { get; set; }
|
||||
public Boolean OnGrab { get; set; }
|
||||
public Boolean OnDownload { get; set; }
|
||||
public String Settings { get; set; }
|
||||
public String Implementation { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class NotificationProviderModel : ProviderDefinition
|
||||
public class NotificationDefinition : ProviderDefinition
|
||||
{
|
||||
public Boolean OnGrab { get; set; }
|
||||
public Boolean OnDownload { get; set; }
|
||||
|
||||
35
src/NzbDrone.Core/Notifications/NotificationFactory.cs
Normal file
35
src/NzbDrone.Core/Notifications/NotificationFactory.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Composition;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public interface INotificationFactory : IProviderFactory<INotification, NotificationDefinition>
|
||||
{
|
||||
List<INotification> OnGrabEnabled();
|
||||
List<INotification> OnDownloadEnabled();
|
||||
}
|
||||
|
||||
public class NotificationFactory : ProviderFactory<INotification, NotificationDefinition>, INotificationFactory
|
||||
{
|
||||
private IEnumerable<INotification> _providers;
|
||||
|
||||
public NotificationFactory(INotificationRepository providerRepository, IEnumerable<INotification> providers, IContainer container, Logger logger)
|
||||
: base(providerRepository, providers, container, logger)
|
||||
{
|
||||
_providers = providers;
|
||||
}
|
||||
|
||||
public List<INotification> OnGrabEnabled()
|
||||
{
|
||||
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnGrab).ToList();
|
||||
}
|
||||
|
||||
public List<INotification> OnDownloadEnabled()
|
||||
{
|
||||
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnDownload).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,20 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public interface INotificationRepository : IBasicRepository<NotificationDefinition>
|
||||
public interface INotificationRepository : IProviderRepository<NotificationDefinition>
|
||||
{
|
||||
NotificationDefinition Get(string name);
|
||||
NotificationDefinition Find(string name);
|
||||
|
||||
}
|
||||
|
||||
public class NotificationRepository : BasicRepository<NotificationDefinition>, INotificationRepository
|
||||
public class NotificationRepository : ProviderRepository<NotificationDefinition>, INotificationRepository
|
||||
{
|
||||
public NotificationRepository(IDatabase database, IEventAggregator eventAggregator)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
}
|
||||
|
||||
public NotificationDefinition Get(string name)
|
||||
{
|
||||
return Query.Single(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public NotificationDefinition Find(string name)
|
||||
{
|
||||
return Query.SingleOrDefault(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,126 +13,20 @@ using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public interface INotificationService
|
||||
{
|
||||
List<Notification> All();
|
||||
Notification Get(int id);
|
||||
List<Notification> Schema();
|
||||
Notification Create(Notification notification);
|
||||
void Update(Notification notification);
|
||||
void Delete(int id);
|
||||
}
|
||||
|
||||
public class NotificationService
|
||||
: INotificationService,
|
||||
IHandle<EpisodeGrabbedEvent>,
|
||||
: IHandle<EpisodeGrabbedEvent>,
|
||||
IHandle<EpisodeDownloadedEvent>,
|
||||
IHandle<SeriesRenamedEvent>
|
||||
{
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
private readonly IContainer _container;
|
||||
private readonly List<INotification> _notifications;
|
||||
private readonly INotificationFactory _notificationFactory;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NotificationService(INotificationRepository notificationRepository,
|
||||
IEnumerable<INotification> notifications,
|
||||
IContainer container,
|
||||
Logger logger)
|
||||
public NotificationService(INotificationFactory notificationFactory, Logger logger)
|
||||
{
|
||||
_notificationRepository = notificationRepository;
|
||||
_container = container;
|
||||
_notifications = notifications.ToList();
|
||||
_notificationFactory = notificationFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<Notification> All()
|
||||
{
|
||||
return _notificationRepository.All().Select(ToNotification).ToList();
|
||||
}
|
||||
|
||||
public Notification Get(int id)
|
||||
{
|
||||
return ToNotification(_notificationRepository.Get(id));
|
||||
}
|
||||
|
||||
public List<Notification> Schema()
|
||||
{
|
||||
var notifications = new List<Notification>();
|
||||
|
||||
int i = 1;
|
||||
foreach (var notification in _notifications)
|
||||
{
|
||||
var type = notification.GetType();
|
||||
|
||||
var newNotification = new Notification();
|
||||
newNotification.Instance = (INotification)_container.Resolve(type);
|
||||
newNotification.Id = i;
|
||||
newNotification.ImplementationName = notification.ImplementationName;
|
||||
newNotification.Link = notification.Link;
|
||||
|
||||
var instanceType = newNotification.Instance.GetType();
|
||||
var baseGenArgs = instanceType.BaseType.GetGenericArguments();
|
||||
newNotification.Settings = (IProviderConfig)Activator.CreateInstance(baseGenArgs[0]);
|
||||
newNotification.Implementation = type.Name;
|
||||
|
||||
notifications.Add(newNotification);
|
||||
i++;
|
||||
}
|
||||
|
||||
return notifications.OrderBy(n => n.Name).ToList();
|
||||
}
|
||||
|
||||
public Notification Create(Notification notification)
|
||||
{
|
||||
var definition = new NotificationDefinition();
|
||||
definition.InjectFrom(notification);
|
||||
definition.Settings = notification.Settings.ToJson();
|
||||
|
||||
definition = _notificationRepository.Insert(definition);
|
||||
notification.Id = definition.Id;
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
public void Update(Notification notification)
|
||||
{
|
||||
var definition = _notificationRepository.Get(notification.Id);
|
||||
definition.InjectFrom(notification);
|
||||
definition.Settings = notification.Settings.ToJson();
|
||||
|
||||
_notificationRepository.Update(definition);
|
||||
}
|
||||
|
||||
public void Delete(int id)
|
||||
{
|
||||
_notificationRepository.Delete(id);
|
||||
}
|
||||
|
||||
private Notification ToNotification(NotificationDefinition definition)
|
||||
{
|
||||
var notification = new Notification();
|
||||
notification.Id = definition.Id;
|
||||
notification.OnGrab = definition.OnGrab;
|
||||
notification.OnDownload = definition.OnDownload;
|
||||
notification.Instance = GetInstance(definition);
|
||||
notification.Name = definition.Name;
|
||||
notification.Implementation = definition.Implementation;
|
||||
notification.ImplementationName = notification.Instance.ImplementationName;
|
||||
notification.Settings = ((dynamic)notification.Instance).ImportSettingsFromJson(definition.Settings);
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
private INotification GetInstance(NotificationDefinition indexerDefinition)
|
||||
{
|
||||
var type = _notifications.Single(c => c.GetType().Name.Equals(indexerDefinition.Implementation, StringComparison.InvariantCultureIgnoreCase)).GetType();
|
||||
|
||||
var instance = (INotification)_container.Resolve(type);
|
||||
|
||||
instance.InstanceDefinition = indexerDefinition;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private string GetMessage(Series series, List<Episode> episodes, QualityModel quality)
|
||||
{
|
||||
if (series.SeriesType == SeriesTypes.Daily)
|
||||
@@ -163,16 +57,16 @@ namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality);
|
||||
|
||||
foreach (var notification in All().Where(n => n.OnGrab))
|
||||
foreach (var notification in _notificationFactory.OnGrabEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
notification.Instance.OnGrab(messageBody);
|
||||
notification.OnGrab(messageBody);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Unable to send OnGrab notification to: " + notification.Name, ex);
|
||||
_logger.ErrorException("Unable to send OnGrab notification to: " + notification.Definition.Name, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,32 +75,32 @@ namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
var messageBody = GetMessage(message.Episode.Series, message.Episode.Episodes, message.Episode.ParsedEpisodeInfo.Quality);
|
||||
|
||||
foreach (var notification in All().Where(n => n.OnDownload))
|
||||
foreach (var notification in _notificationFactory.OnDownloadEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
notification.Instance.OnDownload(messageBody, message.Episode.Series);
|
||||
notification.OnDownload(messageBody, message.Episode.Series);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.WarnException("Unable to send OnDownload notification to: " + notification.Name, ex);
|
||||
_logger.WarnException("Unable to send OnDownload notification to: " + notification.Definition.Name, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SeriesRenamedEvent message)
|
||||
{
|
||||
foreach (var notification in All().Where(n => n.OnDownload))
|
||||
foreach (var notification in _notificationFactory.OnDownloadEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
notification.Instance.AfterRename(message.Series);
|
||||
notification.AfterRename(message.Series);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.WarnException("Unable to send AfterRename notification to: " + notification.Name, ex);
|
||||
_logger.WarnException("Unable to send AfterRename notification to: " + notification.Definition.Name, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public interface INotificationSettingsProvider
|
||||
{
|
||||
TSetting Get<TSetting>(INotification indexer) where TSetting : IProviderConfig, new();
|
||||
}
|
||||
|
||||
public class NotificationSettingsProvider : INotificationSettingsProvider
|
||||
{
|
||||
private readonly INotificationRepository _notificationRepository;
|
||||
|
||||
public NotificationSettingsProvider(INotificationRepository notificationRepository)
|
||||
{
|
||||
_notificationRepository = notificationRepository;
|
||||
}
|
||||
|
||||
public TSetting Get<TSetting>(INotification indexer) where TSetting : IProviderConfig, new()
|
||||
{
|
||||
var indexerDef = _notificationRepository.Find(indexer.Name);
|
||||
|
||||
if (indexerDef == null || string.IsNullOrWhiteSpace(indexerDef.Settings))
|
||||
{
|
||||
return new TSetting();
|
||||
}
|
||||
|
||||
return Json.Deserialize<TSetting>(indexerDef.Settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||
_notifyMyAndroidProxy = notifyMyAndroidProxy;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "NotifyMyAndroid"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "NotifyMyAndroid"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "http://www.notifymyandroid.com/"; }
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||
{
|
||||
public class NotifyMyAndroidSettingsValidator : AbstractValidator<NotifyMyAndroidSettings>
|
||||
{
|
||||
public NotifyMyAndroidSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.ApiKey).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class NotifyMyAndroidSettings : IProviderConfig
|
||||
{
|
||||
private static readonly NotifyMyAndroidSettingsValidator Validator = new NotifyMyAndroidSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "API Key", HelpLink = "http://www.notifymyandroid.com/")]
|
||||
public String ApiKey { get; set; }
|
||||
|
||||
@@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
_plexProvider = plexProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Plex Client"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "Plex Client"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "http://www.plexapp.com/"; }
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Plex
|
||||
{
|
||||
public class PlexClientSettingsValidator : AbstractValidator<PlexClientSettings>
|
||||
{
|
||||
public PlexClientSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Host).NotEmpty();
|
||||
RuleFor(c => c.Port).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class PlexClientSettings : IProviderConfig
|
||||
{
|
||||
private static readonly PlexClientSettingsValidator Validator = new PlexClientSettingsValidator();
|
||||
|
||||
public PlexClientSettings()
|
||||
{
|
||||
Port = 3000;
|
||||
@@ -34,7 +46,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
_plexProvider = plexProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Plex Server"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "Plex Server"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "http://www.plexapp.com/"; }
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Plex
|
||||
{
|
||||
public class PlexServerSettingsValidator : AbstractValidator<PlexServerSettings>
|
||||
{
|
||||
public PlexServerSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Host).NotEmpty();
|
||||
RuleFor(c => c.Port).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class PlexServerSettings : IProviderConfig
|
||||
{
|
||||
private static readonly PlexServerSettingsValidator Validator = new PlexServerSettingsValidator();
|
||||
|
||||
public PlexServerSettings()
|
||||
{
|
||||
Port = 32400;
|
||||
@@ -31,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,16 +12,6 @@ namespace NzbDrone.Core.Notifications.Prowl
|
||||
_prowlProvider = prowlProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Prowl"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "Prowl"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "http://www.prowlapp.com/"; }
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Prowl
|
||||
{
|
||||
public class ProwlSettingsValidator : AbstractValidator<ProwlSettings>
|
||||
{
|
||||
public ProwlSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.ApiKey).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class ProwlSettings : IProviderConfig
|
||||
{
|
||||
private static readonly ProwlSettingsValidator Validator = new ProwlSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.prowlapp.com/api_settings.php")]
|
||||
public String ApiKey { get; set; }
|
||||
|
||||
@@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Prowl
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
||||
_pushBulletProxy = pushBulletProxy;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "PushBullet"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "PushBullet"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "https://www.pushbullet.com/"; }
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.PushBullet
|
||||
{
|
||||
public class PushBulletSettingsValidator : AbstractValidator<PushBulletSettings>
|
||||
{
|
||||
public PushBulletSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.ApiKey).NotEmpty();
|
||||
RuleFor(c => c.DeviceId).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class PushBulletSettings : IProviderConfig
|
||||
{
|
||||
private static readonly PushBulletSettingsValidator Validator = new PushBulletSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "API Key", HelpLink = "https://www.pushbullet.com/")]
|
||||
public String ApiKey { get; set; }
|
||||
|
||||
@@ -23,7 +35,7 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Pushover
|
||||
_pushoverProxy = pushoverProxy;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Pushover"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "Pushover"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "https://pushover.net/"; }
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
using System;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Pushover
|
||||
{
|
||||
public class PushoverSettingsValidator : AbstractValidator<PushoverSettings>
|
||||
{
|
||||
public PushoverSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.UserKey).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class PushoverSettings : IProviderConfig
|
||||
{
|
||||
private static readonly PushoverSettingsValidator Validator = new PushoverSettingsValidator();
|
||||
|
||||
[FieldDefinition(0, Label = "User Key", HelpLink = "https://pushover.net/")]
|
||||
public String UserKey { get; set; }
|
||||
|
||||
@@ -23,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Pushover
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
||||
_xbmcProvider = xbmcProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "XBMC"; }
|
||||
}
|
||||
|
||||
public override string ImplementationName
|
||||
{
|
||||
get { return "XBMC"; }
|
||||
}
|
||||
|
||||
public override string Link
|
||||
{
|
||||
get { return "http://xbmc.org/"; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Annotations;
|
||||
@@ -7,8 +8,19 @@ using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Xbmc
|
||||
{
|
||||
public class XbmcSettingsValidator : AbstractValidator<XbmcSettings>
|
||||
{
|
||||
public XbmcSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Host).NotEmpty();
|
||||
RuleFor(c => c.DisplayTime).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class XbmcSettings : IProviderConfig
|
||||
{
|
||||
private static readonly XbmcSettingsValidator Validator = new XbmcSettingsValidator();
|
||||
|
||||
public XbmcSettings()
|
||||
{
|
||||
DisplayTime = 5;
|
||||
@@ -56,7 +68,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
||||
|
||||
public ValidationResult Validate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Validator.Validate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,8 +173,14 @@
|
||||
<Compile Include="Datastore\Migration\019_restore_unique_constraints.cs" />
|
||||
<Compile Include="Datastore\Migration\020_add_year_and_seasons_to_series.cs" />
|
||||
<Compile Include="Datastore\Migration\021_drop_seasons_table.cs" />
|
||||
<Compile Include="Datastore\Migration\022_move_notification_to_generic_provider.cs" />
|
||||
<Compile Include="Datastore\Migration\022_move_indexer_to_generic_provider.cs" />
|
||||
<Compile Include="Datastore\Migration\023_add_config_contract_to_indexers.cs" />
|
||||
<Compile Include="Datastore\Migration\024_drop_tvdb_episodeid.cs" />
|
||||
<Compile Include="Datastore\Migration\026_add_config_contract_to_notifications.cs" />
|
||||
<Compile Include="Datastore\Migration\025_move_notification_to_generic_provider.cs" />
|
||||
<Compile Include="Datastore\Migration\027_fix_omgwtfnzbs.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||
@@ -213,6 +219,8 @@
|
||||
<Compile Include="DecisionEngine\Specifications\Search\SingleEpisodeSearchMatchSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\UpgradeDiskSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\RssSync\UpgradeHistorySpecification.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpace.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpaceService.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\ConnectionInfoModel.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdPriorityTypeConverter.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdQueueTimeConverter.cs" />
|
||||
@@ -227,6 +235,7 @@
|
||||
<Compile Include="Exceptions\StatusCodeToExceptions.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodes.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedHistoryItems.cs" />
|
||||
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodeFiles.cs" />
|
||||
<Compile Include="Housekeeping\HousekeepingCommand.cs" />
|
||||
<Compile Include="Housekeeping\HousekeepingService.cs" />
|
||||
<Compile Include="Housekeeping\IHousekeepingTask.cs" />
|
||||
@@ -267,6 +276,8 @@
|
||||
<Compile Include="Messaging\Events\IEventAggregator.cs" />
|
||||
<Compile Include="Messaging\Events\IHandle.cs" />
|
||||
<Compile Include="MetadataSource\Trakt\TraktException.cs" />
|
||||
<Compile Include="Notifications\NotificationFactory.cs" />
|
||||
<Compile Include="Notifications\NotificationService.cs" />
|
||||
<Compile Include="Notifications\PushBullet\PushBullet.cs" />
|
||||
<Compile Include="Notifications\PushBullet\PushBulletProxy.cs" />
|
||||
<Compile Include="Notifications\PushBullet\PushBulletSettings.cs" />
|
||||
@@ -326,10 +337,8 @@
|
||||
<Compile Include="Notifications\Email\TestEmailCommand.cs" />
|
||||
<Compile Include="Notifications\Growl\GrowlSettings.cs" />
|
||||
<Compile Include="Notifications\Growl\TestGrowlCommand.cs" />
|
||||
<Compile Include="Notifications\NotificationSettingsProvider.cs" />
|
||||
<Compile Include="Notifications\INotification.cs" />
|
||||
<Compile Include="Notifications\Notification.cs" />
|
||||
<Compile Include="Notifications\NotificationService.cs" />
|
||||
<Compile Include="Notifications\NotificationRepository.cs" />
|
||||
<Compile Include="Fluent.cs" />
|
||||
<Compile Include="History\HistoryRepository.cs" />
|
||||
|
||||
@@ -15,13 +15,11 @@ namespace NzbDrone.Core.Queue
|
||||
public class QueueService : IQueueService
|
||||
{
|
||||
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public QueueService(IProvideDownloadClient downloadClientProvider, IParsingService parsingService, Logger logger)
|
||||
public QueueService(IProvideDownloadClient downloadClientProvider, Logger logger)
|
||||
{
|
||||
_downloadClientProvider = downloadClientProvider;
|
||||
_parsingService = parsingService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -39,31 +37,19 @@ namespace NzbDrone.Core.Queue
|
||||
|
||||
foreach (var queueItem in queueItems)
|
||||
{
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(queueItem.Title);
|
||||
|
||||
if (parsedEpisodeInfo != null && !string.IsNullOrWhiteSpace(parsedEpisodeInfo.SeriesTitle))
|
||||
foreach (var episode in queueItem.RemoteEpisode.Episodes)
|
||||
{
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
|
||||
|
||||
if (remoteEpisode.Series == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var episode in remoteEpisode.Episodes)
|
||||
{
|
||||
var queue = new Queue();
|
||||
queue.Id = queueItem.Id.GetHashCode();
|
||||
queue.Series = remoteEpisode.Series;
|
||||
queue.Episode = episode;
|
||||
queue.Quality = remoteEpisode.ParsedEpisodeInfo.Quality;
|
||||
queue.Title = queueItem.Title;
|
||||
queue.Size = queueItem.Size;
|
||||
queue.Sizeleft = queueItem.Sizeleft;
|
||||
queue.Timeleft = queueItem.Timeleft;
|
||||
queue.Status = queueItem.Status;
|
||||
queued.Add(queue);
|
||||
}
|
||||
var queue = new Queue();
|
||||
queue.Id = queueItem.Id.GetHashCode();
|
||||
queue.Series = queueItem.RemoteEpisode.Series;
|
||||
queue.Episode = episode;
|
||||
queue.Quality = queueItem.RemoteEpisode.ParsedEpisodeInfo.Quality;
|
||||
queue.Title = queueItem.Title;
|
||||
queue.Size = queueItem.Size;
|
||||
queue.Sizeleft = queueItem.Sizeleft;
|
||||
queue.Timeleft = queueItem.Timeleft;
|
||||
queue.Status = queueItem.Status;
|
||||
queued.Add(queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
private IProviderConfig _settings;
|
||||
public string Name { get; set; }
|
||||
public string Implementation { get; set; }
|
||||
public bool Enable { get; set; }
|
||||
|
||||
public string ConfigContract { get; set; }
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Composition;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
@@ -12,13 +13,18 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
where TProvider : IProvider
|
||||
{
|
||||
private readonly IProviderRepository<TProviderDefinition> _providerRepository;
|
||||
private readonly IContainer _container;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly List<TProvider> _providers;
|
||||
|
||||
protected ProviderFactory(IProviderRepository<TProviderDefinition> providerRepository, IEnumerable<TProvider> providers, Logger logger)
|
||||
protected ProviderFactory(IProviderRepository<TProviderDefinition> providerRepository,
|
||||
IEnumerable<TProvider> providers,
|
||||
IContainer container,
|
||||
Logger logger)
|
||||
{
|
||||
_providerRepository = providerRepository;
|
||||
_container = container;
|
||||
_providers = providers.ToList();
|
||||
_logger = logger;
|
||||
}
|
||||
@@ -40,8 +46,7 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
|
||||
public List<TProvider> GetAvailableProviders()
|
||||
{
|
||||
return All().Where(c => c.Enable && c.Settings.Validate().IsValid)
|
||||
.Select(GetInstance).ToList();
|
||||
return Active().Select(GetInstance).ToList();
|
||||
}
|
||||
|
||||
public TProviderDefinition Get(int id)
|
||||
@@ -49,12 +54,12 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
return _providerRepository.Get(id);
|
||||
}
|
||||
|
||||
public TProviderDefinition Create(TProviderDefinition provider)
|
||||
public virtual TProviderDefinition Create(TProviderDefinition definition)
|
||||
{
|
||||
return _providerRepository.Insert(provider);
|
||||
return _providerRepository.Insert(definition);
|
||||
}
|
||||
|
||||
public void Update(TProviderDefinition definition)
|
||||
public virtual void Update(TProviderDefinition definition)
|
||||
{
|
||||
_providerRepository.Update(definition);
|
||||
}
|
||||
@@ -64,10 +69,10 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
_providerRepository.Delete(id);
|
||||
}
|
||||
|
||||
private TProvider GetInstance(TProviderDefinition definition)
|
||||
protected TProvider GetInstance(TProviderDefinition definition)
|
||||
{
|
||||
var type = GetImplementation(definition);
|
||||
var instance = (TProvider)Activator.CreateInstance(type);
|
||||
var instance = (TProvider)_container.Resolve(type);
|
||||
instance.Definition = definition;
|
||||
return instance;
|
||||
}
|
||||
@@ -90,6 +95,11 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual List<TProviderDefinition> Active()
|
||||
{
|
||||
return All().Where(c => c.Settings.Validate().IsValid).ToList();
|
||||
}
|
||||
|
||||
private void RemoveMissingImplementations()
|
||||
{
|
||||
var storedProvider = _providerRepository.All();
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace NzbDrone.Core.Tv
|
||||
{
|
||||
public const string AIR_DATE_FORMAT = "yyyy-MM-dd";
|
||||
|
||||
public int TvDbEpisodeId { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int EpisodeFileId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
@@ -39,7 +38,7 @@ namespace NzbDrone.Core.Tv
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0}]{1}", TvDbEpisodeId, Title.NullSafe());
|
||||
return string.Format("[{0}]{1}", Id, Title.NullSafe());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,6 @@ namespace NzbDrone.Core.Tv
|
||||
}
|
||||
|
||||
episodeToUpdate.SeriesId = series.Id;
|
||||
episodeToUpdate.TvDbEpisodeId = episode.TvDbEpisodeId;
|
||||
episodeToUpdate.EpisodeNumber = episode.EpisodeNumber;
|
||||
episodeToUpdate.SeasonNumber = episode.SeasonNumber;
|
||||
episodeToUpdate.Title = episode.Title;
|
||||
|
||||
Reference in New Issue
Block a user