Blacklisting torrents and using more info to evaluate matches
New: Blacklisting torrents manually New: Details on why a release was blacklisted in the UI New: Blacklist matching take into account indexer, size, date and name
This commit is contained in:
parent
14f49489a7
commit
bc03ad2a18
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Blacklist
|
namespace NzbDrone.Api.Blacklist
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,9 @@ namespace NzbDrone.Api.Blacklist
|
||||||
public string SourceTitle { get; set; }
|
public string SourceTitle { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
|
public DownloadProtocol Protocol { get; set; }
|
||||||
|
public string Indexer { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
public SeriesResource Series { get; set; }
|
public SeriesResource Series { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ namespace NzbDrone.Api.History
|
||||||
public Boolean QualityCutoffNotMet { get; set; }
|
public Boolean QualityCutoffNotMet { get; set; }
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
public string Indexer { get; set; }
|
public string Indexer { get; set; }
|
||||||
public string NzbInfoUrl { get; set; }
|
|
||||||
public string ReleaseGroup { get; set; }
|
public string ReleaseGroup { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace NzbDrone.Core.Test.Blacklisting
|
||||||
{
|
{
|
||||||
Subject.Insert(_blacklist);
|
Subject.Insert(_blacklist);
|
||||||
|
|
||||||
Subject.Blacklisted(_blacklist.SeriesId, _blacklist.SourceTitle.ToUpperInvariant()).Should().HaveCount(1);
|
Subject.BlacklistedByTitle(_blacklist.SeriesId, _blacklist.SourceTitle.ToUpperInvariant()).Should().HaveCount(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,12 @@ namespace NzbDrone.Core.Test.Blacklisting
|
||||||
};
|
};
|
||||||
|
|
||||||
_event.Data.Add("publishedDate", DateTime.UtcNow.ToString("s") + "Z");
|
_event.Data.Add("publishedDate", DateTime.UtcNow.ToString("s") + "Z");
|
||||||
|
_event.Data.Add("size", "1000");
|
||||||
|
_event.Data.Add("indexer", "nzbs.org");
|
||||||
|
_event.Data.Add("protocol", "1");
|
||||||
|
_event.Data.Add("message", "Marked as failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_add_to_repository()
|
public void should_add_to_repository()
|
||||||
{
|
{
|
||||||
|
@ -39,5 +42,17 @@ namespace NzbDrone.Core.Test.Blacklisting
|
||||||
Mocker.GetMock<IBlacklistRepository>()
|
Mocker.GetMock<IBlacklistRepository>()
|
||||||
.Verify(v => v.Insert(It.Is<Blacklist>(b => b.EpisodeIds == _event.EpisodeIds)), Times.Once());
|
.Verify(v => v.Insert(It.Is<Blacklist>(b => b.EpisodeIds == _event.EpisodeIds)), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_add_to_repository_missing_size_and_protocol()
|
||||||
|
{
|
||||||
|
Subject.Handle(_event);
|
||||||
|
|
||||||
|
_event.Data.Remove("size");
|
||||||
|
_event.Data.Remove("protocol");
|
||||||
|
|
||||||
|
Mocker.GetMock<IBlacklistRepository>()
|
||||||
|
.Verify(v => v.Insert(It.Is<Blacklist>(b => b.EpisodeIds == _event.EpisodeIds)), Times.Once());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
@ -8,12 +9,17 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
{
|
{
|
||||||
public class Blacklist : ModelBase
|
public class Blacklist : ModelBase
|
||||||
{
|
{
|
||||||
public Int32 SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
public Series Series { get; set; }
|
public Series Series { get; set; }
|
||||||
public List<Int32> EpisodeIds { get; set; }
|
public List<int> EpisodeIds { get; set; }
|
||||||
public String SourceTitle { get; set; }
|
public string SourceTitle { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
public DateTime? PublishedDate { get; set; }
|
public DateTime? PublishedDate { get; set; }
|
||||||
|
public long? Size { get; set; }
|
||||||
|
public DownloadProtocol Protocol { get; set; }
|
||||||
|
public string Indexer { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public string TorrentInfoHash { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
{
|
{
|
||||||
public interface IBlacklistRepository : IBasicRepository<Blacklist>
|
public interface IBlacklistRepository : IBasicRepository<Blacklist>
|
||||||
{
|
{
|
||||||
List<Blacklist> Blacklisted(int seriesId, string sourceTitle);
|
List<Blacklist> BlacklistedByTitle(int seriesId, string sourceTitle);
|
||||||
|
List<Blacklist> BlacklistedByTorrentInfoHash(int seriesId, string torrentInfoHash);
|
||||||
List<Blacklist> BlacklistedBySeries(int seriesId);
|
List<Blacklist> BlacklistedBySeries(int seriesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,12 +20,18 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Blacklist> Blacklisted(int seriesId, string sourceTitle)
|
public List<Blacklist> BlacklistedByTitle(int seriesId, string sourceTitle)
|
||||||
{
|
{
|
||||||
return Query.Where(e => e.SeriesId == seriesId)
|
return Query.Where(e => e.SeriesId == seriesId)
|
||||||
.AndWhere(e => e.SourceTitle.Contains(sourceTitle));
|
.AndWhere(e => e.SourceTitle.Contains(sourceTitle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Blacklist> BlacklistedByTorrentInfoHash(int seriesId, string torrentInfoHash)
|
||||||
|
{
|
||||||
|
return Query.Where(e => e.SeriesId == seriesId)
|
||||||
|
.AndWhere(e => e.TorrentInfoHash.Contains(torrentInfoHash));
|
||||||
|
}
|
||||||
|
|
||||||
public List<Blacklist> BlacklistedBySeries(int seriesId)
|
public List<Blacklist> BlacklistedBySeries(int seriesId)
|
||||||
{
|
{
|
||||||
return Query.Where(b => b.SeriesId == seriesId);
|
return Query.Where(b => b.SeriesId == seriesId);
|
||||||
|
|
|
@ -3,20 +3,22 @@ using System.Linq;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Tv.Events;
|
using NzbDrone.Core.Tv.Events;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Blacklisting
|
namespace NzbDrone.Core.Blacklisting
|
||||||
{
|
{
|
||||||
public interface IBlacklistService
|
public interface IBlacklistService
|
||||||
{
|
{
|
||||||
bool Blacklisted(int seriesId, string sourceTitle, DateTime publishedDate);
|
bool Blacklisted(int seriesId, ReleaseInfo release);
|
||||||
PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec);
|
PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec);
|
||||||
void Delete(int id);
|
void Delete(int id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlacklistService : IBlacklistService,
|
public class BlacklistService : IBlacklistService,
|
||||||
|
|
||||||
IExecute<ClearBlacklistCommand>,
|
IExecute<ClearBlacklistCommand>,
|
||||||
IHandle<DownloadFailedEvent>,
|
IHandle<DownloadFailedEvent>,
|
||||||
IHandleAsync<SeriesDeletedEvent>
|
IHandleAsync<SeriesDeletedEvent>
|
||||||
|
@ -28,11 +30,29 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
_blacklistRepository = blacklistRepository;
|
_blacklistRepository = blacklistRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Blacklisted(int seriesId, string sourceTitle, DateTime publishedDate)
|
public bool Blacklisted(int seriesId, ReleaseInfo release)
|
||||||
{
|
{
|
||||||
var blacklisted = _blacklistRepository.Blacklisted(seriesId, sourceTitle);
|
var blacklistedByTitle = _blacklistRepository.BlacklistedByTitle(seriesId, release.Title);
|
||||||
|
|
||||||
|
if (release.DownloadProtocol == DownloadProtocol.Torrent)
|
||||||
|
{
|
||||||
|
var torrentInfo = release as TorrentInfo;
|
||||||
|
|
||||||
return blacklisted.Any(item => HasSamePublishedDate(item, publishedDate));
|
if (torrentInfo == null) return false;
|
||||||
|
|
||||||
|
if (torrentInfo.InfoHash.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return blacklistedByTitle.Where(b => b.Protocol == DownloadProtocol.Torrent)
|
||||||
|
.Any(b => SameTorrent(b, torrentInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blacklistedByTorrentInfohash = _blacklistRepository.BlacklistedByTitle(seriesId, torrentInfo.InfoHash);
|
||||||
|
|
||||||
|
return blacklistedByTorrentInfohash.Any(b => SameTorrent(b, torrentInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
return blacklistedByTitle.Where(b => b.Protocol == DownloadProtocol.Usenet)
|
||||||
|
.Any(b => SameNzb(b, release));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec)
|
public PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec)
|
||||||
|
@ -45,12 +65,58 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
_blacklistRepository.Delete(id);
|
_blacklistRepository.Delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasSamePublishedDate(Blacklist item, DateTime publishedDate)
|
private bool SameNzb(Blacklist item, ReleaseInfo release)
|
||||||
|
{
|
||||||
|
if (item.PublishedDate == release.PublishDate)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasSameIndexer(item, release.Indexer) &&
|
||||||
|
HasSamePublishedDate(item, release.PublishDate) &&
|
||||||
|
HasSameSize(item, release.Size))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SameTorrent(Blacklist item, TorrentInfo release)
|
||||||
|
{
|
||||||
|
if (release.InfoHash.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return release.InfoHash.Equals(item.TorrentInfoHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.Indexer.Equals(release.Indexer, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasSameIndexer(Blacklist item, string indexer)
|
||||||
|
{
|
||||||
|
if (item.Indexer.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.Indexer.Equals(indexer, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasSamePublishedDate(Blacklist item, DateTime publishedDate)
|
||||||
{
|
{
|
||||||
if (!item.PublishedDate.HasValue) return true;
|
if (!item.PublishedDate.HasValue) return true;
|
||||||
|
|
||||||
return item.PublishedDate.Value.AddDays(-2) <= publishedDate &&
|
return item.PublishedDate.Value.AddMinutes(-2) <= publishedDate &&
|
||||||
item.PublishedDate.Value.AddDays(2) >= publishedDate;
|
item.PublishedDate.Value.AddMinutes(2) >= publishedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasSameSize(Blacklist item, long size)
|
||||||
|
{
|
||||||
|
if (!item.Size.HasValue) return true;
|
||||||
|
|
||||||
|
var difference = Math.Abs(item.Size.Value - size);
|
||||||
|
|
||||||
|
return difference <= 2.Megabytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute(ClearBlacklistCommand message)
|
public void Execute(ClearBlacklistCommand message)
|
||||||
|
@ -67,7 +133,12 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
SourceTitle = message.SourceTitle,
|
SourceTitle = message.SourceTitle,
|
||||||
Quality = message.Quality,
|
Quality = message.Quality,
|
||||||
Date = DateTime.UtcNow,
|
Date = DateTime.UtcNow,
|
||||||
PublishedDate = DateTime.Parse(message.Data.GetValueOrDefault("publishedDate"))
|
PublishedDate = DateTime.Parse(message.Data.GetValueOrDefault("publishedDate")),
|
||||||
|
Size = Int64.Parse(message.Data.GetValueOrDefault("size", "0")),
|
||||||
|
Indexer = message.Data.GetValueOrDefault("indexer"),
|
||||||
|
Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")),
|
||||||
|
Message = message.Message,
|
||||||
|
TorrentInfoHash = message.Data.GetValueOrDefault("torrentInfoHash")
|
||||||
};
|
};
|
||||||
|
|
||||||
_blacklistRepository.Insert(blacklist);
|
_blacklistRepository.Insert(blacklist);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(83)]
|
||||||
|
public class additonal_blacklist_columns : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Blacklist").AddColumn("Size").AsInt64().Nullable();
|
||||||
|
Alter.Table("Blacklist").AddColumn("Protocol").AsInt32().Nullable();
|
||||||
|
Alter.Table("Blacklist").AddColumn("Indexer").AsString().Nullable();
|
||||||
|
Alter.Table("Blacklist").AddColumn("Message").AsString().Nullable();
|
||||||
|
Alter.Table("Blacklist").AddColumn("TorrentInfoHash").AsString().Nullable();
|
||||||
|
|
||||||
|
Update.Table("Blacklist")
|
||||||
|
.Set(new { Protocol = 1 })
|
||||||
|
.AllRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,14 +20,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
public RejectionType Type { get { return RejectionType.Permanent; } }
|
public RejectionType Type { get { return RejectionType.Permanent; } }
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
if (subject.Release.DownloadProtocol == DownloadProtocol.Torrent)
|
if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release))
|
||||||
{
|
|
||||||
return Decision.Accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release.Title, subject.Release.PublishDate))
|
|
||||||
{
|
{
|
||||||
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
|
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
|
||||||
return Decision.Reject("Release is blacklisted");
|
return Decision.Reject("Release is blacklisted");
|
||||||
|
|
|
@ -6,9 +6,11 @@ using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
@ -78,77 +80,6 @@ namespace NzbDrone.Core.History
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(EpisodeGrabbedEvent message)
|
|
||||||
{
|
|
||||||
foreach (var episode in message.Episode.Episodes)
|
|
||||||
{
|
|
||||||
var history = new History
|
|
||||||
{
|
|
||||||
EventType = HistoryEventType.Grabbed,
|
|
||||||
Date = DateTime.UtcNow,
|
|
||||||
Quality = message.Episode.ParsedEpisodeInfo.Quality,
|
|
||||||
SourceTitle = message.Episode.Release.Title,
|
|
||||||
SeriesId = episode.SeriesId,
|
|
||||||
EpisodeId = episode.Id,
|
|
||||||
DownloadId = message.DownloadId
|
|
||||||
};
|
|
||||||
|
|
||||||
history.Data.Add("Indexer", message.Episode.Release.Indexer);
|
|
||||||
history.Data.Add("NzbInfoUrl", message.Episode.Release.InfoUrl);
|
|
||||||
history.Data.Add("ReleaseGroup", message.Episode.ParsedEpisodeInfo.ReleaseGroup);
|
|
||||||
history.Data.Add("Age", message.Episode.Release.Age.ToString());
|
|
||||||
history.Data.Add("AgeHours", message.Episode.Release.AgeHours.ToString());
|
|
||||||
history.Data.Add("AgeMinutes", message.Episode.Release.AgeMinutes.ToString());
|
|
||||||
history.Data.Add("PublishedDate", message.Episode.Release.PublishDate.ToString("s") + "Z");
|
|
||||||
history.Data.Add("DownloadClient", message.DownloadClient);
|
|
||||||
|
|
||||||
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
history.Data.Add("ReleaseHash", message.Episode.ParsedEpisodeInfo.ReleaseHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
_historyRepository.Insert(history);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(EpisodeImportedEvent message)
|
|
||||||
{
|
|
||||||
if (!message.NewDownload)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var downloadId = message.DownloadId;
|
|
||||||
|
|
||||||
if (downloadId.IsNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
downloadId = FindDownloadId(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var episode in message.EpisodeInfo.Episodes)
|
|
||||||
{
|
|
||||||
var history = new History
|
|
||||||
{
|
|
||||||
EventType = HistoryEventType.DownloadFolderImported,
|
|
||||||
Date = DateTime.UtcNow,
|
|
||||||
Quality = message.EpisodeInfo.Quality,
|
|
||||||
SourceTitle = message.ImportedEpisode.SceneName ?? Path.GetFileNameWithoutExtension(message.EpisodeInfo.Path),
|
|
||||||
SeriesId = message.ImportedEpisode.SeriesId,
|
|
||||||
EpisodeId = episode.Id,
|
|
||||||
DownloadId = downloadId
|
|
||||||
};
|
|
||||||
|
|
||||||
//Won't have a value since we publish this event before saving to DB.
|
|
||||||
//history.Data.Add("FileId", message.ImportedEpisode.Id.ToString());
|
|
||||||
history.Data.Add("DroppedPath", message.EpisodeInfo.Path);
|
|
||||||
history.Data.Add("ImportedPath", Path.Combine(message.EpisodeInfo.Series.Path, message.ImportedEpisode.RelativePath));
|
|
||||||
history.Data.Add("DownloadClient", message.DownloadClient);
|
|
||||||
|
|
||||||
_historyRepository.Insert(history);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private string FindDownloadId(EpisodeImportedEvent trackedDownload)
|
private string FindDownloadId(EpisodeImportedEvent trackedDownload)
|
||||||
{
|
{
|
||||||
_logger.Debug("Trying to find downloadId for {0} from history", trackedDownload.ImportedEpisode.Path);
|
_logger.Debug("Trying to find downloadId for {0} from history", trackedDownload.ImportedEpisode.Path);
|
||||||
|
@ -194,6 +125,88 @@ namespace NzbDrone.Core.History
|
||||||
return downloadId;
|
return downloadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Handle(EpisodeGrabbedEvent message)
|
||||||
|
{
|
||||||
|
foreach (var episode in message.Episode.Episodes)
|
||||||
|
{
|
||||||
|
var history = new History
|
||||||
|
{
|
||||||
|
EventType = HistoryEventType.Grabbed,
|
||||||
|
Date = DateTime.UtcNow,
|
||||||
|
Quality = message.Episode.ParsedEpisodeInfo.Quality,
|
||||||
|
SourceTitle = message.Episode.Release.Title,
|
||||||
|
SeriesId = episode.SeriesId,
|
||||||
|
EpisodeId = episode.Id,
|
||||||
|
DownloadId = message.DownloadId
|
||||||
|
};
|
||||||
|
|
||||||
|
history.Data.Add("Indexer", message.Episode.Release.Indexer);
|
||||||
|
history.Data.Add("NzbInfoUrl", message.Episode.Release.InfoUrl);
|
||||||
|
history.Data.Add("ReleaseGroup", message.Episode.ParsedEpisodeInfo.ReleaseGroup);
|
||||||
|
history.Data.Add("Age", message.Episode.Release.Age.ToString());
|
||||||
|
history.Data.Add("AgeHours", message.Episode.Release.AgeHours.ToString());
|
||||||
|
history.Data.Add("AgeMinutes", message.Episode.Release.AgeMinutes.ToString());
|
||||||
|
history.Data.Add("PublishedDate", message.Episode.Release.PublishDate.ToString("s") + "Z");
|
||||||
|
history.Data.Add("DownloadClient", message.DownloadClient);
|
||||||
|
history.Data.Add("Size", message.Episode.Release.Size.ToString());
|
||||||
|
history.Data.Add("DownloadUrl", message.Episode.Release.DownloadUrl);
|
||||||
|
history.Data.Add("Guid", message.Episode.Release.Guid);
|
||||||
|
history.Data.Add("TvRageId", message.Episode.Release.TvRageId.ToString());
|
||||||
|
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
|
||||||
|
|
||||||
|
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
history.Data.Add("ReleaseHash", message.Episode.ParsedEpisodeInfo.ReleaseHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
var torrentRelease = message.Episode.Release as TorrentInfo;
|
||||||
|
|
||||||
|
if (torrentRelease != null)
|
||||||
|
{
|
||||||
|
history.Data.Add("TorrentInfoHash", torrentRelease.InfoHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
_historyRepository.Insert(history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(EpisodeImportedEvent message)
|
||||||
|
{
|
||||||
|
if (!message.NewDownload)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var downloadId = message.DownloadId;
|
||||||
|
|
||||||
|
if (downloadId.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
downloadId = FindDownloadId(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var episode in message.EpisodeInfo.Episodes)
|
||||||
|
{
|
||||||
|
var history = new History
|
||||||
|
{
|
||||||
|
EventType = HistoryEventType.DownloadFolderImported,
|
||||||
|
Date = DateTime.UtcNow,
|
||||||
|
Quality = message.EpisodeInfo.Quality,
|
||||||
|
SourceTitle = message.ImportedEpisode.SceneName ?? Path.GetFileNameWithoutExtension(message.EpisodeInfo.Path),
|
||||||
|
SeriesId = message.ImportedEpisode.SeriesId,
|
||||||
|
EpisodeId = episode.Id,
|
||||||
|
DownloadId = downloadId
|
||||||
|
};
|
||||||
|
|
||||||
|
//Won't have a value since we publish this event before saving to DB.
|
||||||
|
//history.Data.Add("FileId", message.ImportedEpisode.Id.ToString());
|
||||||
|
history.Data.Add("DroppedPath", message.EpisodeInfo.Path);
|
||||||
|
history.Data.Add("ImportedPath", Path.Combine(message.EpisodeInfo.Series.Path, message.ImportedEpisode.RelativePath));
|
||||||
|
history.Data.Add("DownloadClient", message.DownloadClient);
|
||||||
|
|
||||||
|
_historyRepository.Insert(history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Handle(DownloadFailedEvent message)
|
public void Handle(DownloadFailedEvent message)
|
||||||
{
|
{
|
||||||
foreach (var episodeId in message.EpisodeIds)
|
foreach (var episodeId in message.EpisodeIds)
|
||||||
|
|
|
@ -254,6 +254,7 @@
|
||||||
<Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_category.cs" />
|
<Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_category.cs" />
|
||||||
<Compile Include="Datastore\Migration\079_dedupe_tags.cs" />
|
<Compile Include="Datastore\Migration\079_dedupe_tags.cs" />
|
||||||
<Compile Include="Datastore\Migration\070_delay_profile.cs" />
|
<Compile Include="Datastore\Migration\070_delay_profile.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\083_additonal_blacklist_columns.cs" />
|
||||||
<Compile Include="Datastore\Migration\082_add_fanzub_settings.cs" />
|
<Compile Include="Datastore\Migration\082_add_fanzub_settings.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||||
|
|
|
@ -1,19 +1,27 @@
|
||||||
|
var vent = require('vent');
|
||||||
var NzbDroneCell = require('../../Cells/NzbDroneCell');
|
var NzbDroneCell = require('../../Cells/NzbDroneCell');
|
||||||
|
var BlacklistDetailsLayout = require('./Details/BlacklistDetailsLayout');
|
||||||
|
|
||||||
module.exports = NzbDroneCell.extend({
|
module.exports = NzbDroneCell.extend({
|
||||||
className : 'blacklist-controls-cell',
|
className : 'blacklist-actions-cell',
|
||||||
|
|
||||||
events : {
|
events : {
|
||||||
'click' : '_delete'
|
'click .x-details' : '_details',
|
||||||
|
'click .x-delete' : '_delete'
|
||||||
},
|
},
|
||||||
|
|
||||||
render : function() {
|
render : function() {
|
||||||
this.$el.empty();
|
this.$el.empty();
|
||||||
this.$el.html('<i class="icon-sonarr-delete"></i>');
|
this.$el.html('<i class="icon-sonarr-info x-details"></i>' +
|
||||||
|
'<i class="icon-sonarr-delete x-delete"></i>');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_details : function() {
|
||||||
|
vent.trigger(vent.Commands.OpenModalCommand, new BlacklistDetailsLayout({ model : this.model }));
|
||||||
|
},
|
||||||
|
|
||||||
_delete : function() {
|
_delete : function() {
|
||||||
this.model.destroy();
|
this.model.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
var Marionette = require('marionette');
|
||||||
|
var BlacklistDetailsView = require('./BlacklistDetailsView');
|
||||||
|
|
||||||
|
module.exports = Marionette.Layout.extend({
|
||||||
|
template : 'Activity/Blacklist/Details/BlacklistDetailsLayoutTemplate',
|
||||||
|
|
||||||
|
regions : {
|
||||||
|
bodyRegion : '.modal-body'
|
||||||
|
},
|
||||||
|
|
||||||
|
onShow : function() {
|
||||||
|
this.bodyRegion.show(new BlacklistDetailsView({ model : this.model }));
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="history-detail-modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Blacklisted
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn" data-dismiss="modal">close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,5 @@
|
||||||
|
var Marionette = require('marionette');
|
||||||
|
|
||||||
|
module.exports = Marionette.ItemView.extend({
|
||||||
|
template : 'Activity/Blacklist/Details/BlacklistDetailsViewTemplate'
|
||||||
|
});
|
|
@ -0,0 +1,23 @@
|
||||||
|
<dl class="dl-horizontal info">
|
||||||
|
|
||||||
|
<dt>Name:</dt>
|
||||||
|
<dd>{{sourceTitle}}</dd>
|
||||||
|
|
||||||
|
{{#if protocol}}
|
||||||
|
{{#unless_eq protocol compare="unknown"}}
|
||||||
|
<dt>Protocol:</dt>
|
||||||
|
<dd>{{protocol}}</dd>
|
||||||
|
{{/unless_eq}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if indexer}}
|
||||||
|
<dt>Indexer:</dt>
|
||||||
|
<dd>{{indexer}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
|
||||||
|
{{#if message}}
|
||||||
|
<dt>Message:</dt>
|
||||||
|
<dd>{{message}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
</dl>
|
|
@ -236,3 +236,15 @@ td.delete-episode-file-cell {
|
||||||
.age-cell {
|
.age-cell {
|
||||||
cursor : default;
|
cursor : default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blacklist-actions-cell {
|
||||||
|
min-width : 55px;
|
||||||
|
width : 55px;
|
||||||
|
text-align : right !important;
|
||||||
|
|
||||||
|
i {
|
||||||
|
.clickable();
|
||||||
|
margin-left : 2px;
|
||||||
|
margin-right : 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue