From d849a4ab4813cd9f0578e38638fdb977441f039a Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 19 Dec 2014 17:21:03 -0800 Subject: [PATCH] New: Show source/seed info in manual search --- src/NzbDrone.Api/Indexers/ReleaseModule.cs | 17 +++- src/NzbDrone.Api/Indexers/ReleaseResource.cs | 5 + .../BitMeTvTests/BitMeTVFixture.cs | 2 +- .../BroadcastheNetFixture.cs | 2 +- .../IndexerTests/EztvTests/EztvFixture.cs | 2 +- .../IPTorrentsTests/IPTorrentsFixture.cs | 2 +- .../KickassTorrentsFixture.cs | 2 +- .../IndexerTests/NyaaTests/NyaaFixture.cs | 2 +- .../TorrentleechTests/TorrentleechFixture.cs | 2 +- .../Search/TorrentSeedingSpecification.cs | 6 +- .../BroadcastheNet/BroadcastheNetParser.cs | 2 +- .../Indexers/TorrentRssParser.cs | 2 +- src/NzbDrone.Core/Parser/Model/TorrentInfo.cs | 4 +- src/UI/Content/theme.less | 96 +++++++++++-------- src/UI/Episode/Search/ManualLayout.js | 15 ++- src/UI/Release/PeersCell.js | 34 +++++++ src/UI/Release/ProtocolCell.js | 28 ++++++ src/UI/Release/ReleaseCollection.js | 4 +- 18 files changed, 170 insertions(+), 57 deletions(-) create mode 100644 src/UI/Release/PeersCell.js create mode 100644 src/UI/Release/ProtocolCell.js diff --git a/src/NzbDrone.Api/Indexers/ReleaseModule.cs b/src/NzbDrone.Api/Indexers/ReleaseModule.cs index bc2f18038..e151cfc7f 100644 --- a/src/NzbDrone.Api/Indexers/ReleaseModule.cs +++ b/src/NzbDrone.Api/Indexers/ReleaseModule.cs @@ -54,7 +54,7 @@ namespace NzbDrone.Api.Indexers private Response DownloadRelease(ReleaseResource release) { var remoteEpisode = _remoteEpisodeCache.Find(release.Guid); - + if (remoteEpisode == null) { _logger.Debug("Couldn't find requested release in cache, cache timeout probably expired."); @@ -142,6 +142,21 @@ namespace NzbDrone.Api.Indexers release.QualityWeight += release.Quality.Revision.Real * 10; release.QualityWeight += release.Quality.Revision.Version; + + var torrentRelease = downloadDecision.RemoteEpisode.Release as TorrentInfo; + + if (torrentRelease != null) + { + release.Protocol = DownloadProtocol.Torrent; + release.Seeders = torrentRelease.Seeders; + //TODO: move this up the chains + release.Leechers = torrentRelease.Peers - torrentRelease.Seeders; + } + else + { + release.Protocol = DownloadProtocol.Usenet; + } + result.Add(release); } diff --git a/src/NzbDrone.Api/Indexers/ReleaseResource.cs b/src/NzbDrone.Api/Indexers/ReleaseResource.cs index 3086113c5..f6490f188 100644 --- a/src/NzbDrone.Api/Indexers/ReleaseResource.cs +++ b/src/NzbDrone.Api/Indexers/ReleaseResource.cs @@ -42,6 +42,11 @@ namespace NzbDrone.Api.Indexers public DownloadProtocol DownloadProtocol { get; set; } public Int32 ReleaseWeight { get; set; } + + public int? Seeders { get; set; } + public int? Leechers { get; set; } + public DownloadProtocol Protocol { get; set; } + public Boolean IsDaily { get; set; } public Boolean IsAbsoluteNumbering { get; set; } public Boolean IsPossibleSpecialEpisode { get; set; } diff --git a/src/NzbDrone.Core.Test/IndexerTests/BitMeTvTests/BitMeTVFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/BitMeTvTests/BitMeTVFixture.cs index a6b1b6278..9ec01f30a 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/BitMeTvTests/BitMeTVFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/BitMeTvTests/BitMeTVFixture.cs @@ -52,7 +52,7 @@ namespace NzbDrone.Core.Test.IndexerTests.BitMeTvTests torrentInfo.InfoHash.Should().Be(null); torrentInfo.MagnetUrl.Should().Be(null); torrentInfo.Peers.Should().Be(null); - torrentInfo.Seeds.Should().Be(null); + torrentInfo.Seeders.Should().Be(null); } } } diff --git a/src/NzbDrone.Core.Test/IndexerTests/BroadcastheNetTests/BroadcastheNetFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/BroadcastheNetTests/BroadcastheNetFixture.cs index fc1ec0af5..fefd10da5 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/BroadcastheNetTests/BroadcastheNetFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/BroadcastheNetTests/BroadcastheNetFixture.cs @@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.IndexerTests.BroadcastheNetTests torrentInfo.TvRageId.Should().Be(4055); torrentInfo.MagnetUrl.Should().BeNullOrEmpty(); torrentInfo.Peers.Should().Be(9); - torrentInfo.Seeds.Should().Be(40); + torrentInfo.Seeders.Should().Be(40); } private void VerifyBackOff() diff --git a/src/NzbDrone.Core.Test/IndexerTests/EztvTests/EztvFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/EztvTests/EztvFixture.cs index af2e680df..ac350320f 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/EztvTests/EztvFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/EztvTests/EztvFixture.cs @@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.EztvTests torrentInfo.InfoHash.Should().Be("20FC4FBFA88272274AC671F857CC15144E9AA83E"); torrentInfo.MagnetUrl.Should().Be("magnet:?xt=urn:btih:ED6E7P5IQJZCOSWGOH4FPTAVCRHJVKB6&dn=S4C.I.Grombil.Cyfandir.Pell.American.Interior.PDTV.x264-MVGroup"); torrentInfo.Peers.Should().NotHaveValue(); - torrentInfo.Seeds.Should().NotHaveValue(); + torrentInfo.Seeders.Should().NotHaveValue(); } } } diff --git a/src/NzbDrone.Core.Test/IndexerTests/IPTorrentsTests/IPTorrentsFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/IPTorrentsTests/IPTorrentsFixture.cs index 3fd02c0fd..4cf4bda66 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/IPTorrentsTests/IPTorrentsFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/IPTorrentsTests/IPTorrentsFixture.cs @@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.IPTorrentsTests torrentInfo.InfoHash.Should().Be(null); torrentInfo.MagnetUrl.Should().Be(null); torrentInfo.Peers.Should().Be(null); - torrentInfo.Seeds.Should().Be(null); + torrentInfo.Seeders.Should().Be(null); } } } diff --git a/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs index 728f75dd1..4fa34b012 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/KickassTorrentsTests/KickassTorrentsFixture.cs @@ -52,7 +52,7 @@ namespace NzbDrone.Core.Test.IndexerTests.KickassTorrentsTests torrentInfo.InfoHash.Should().Be("208C4F7866612CC88BFEBC7C496FA72C2368D1C0"); torrentInfo.MagnetUrl.Should().Be("magnet:?xt=urn:btih:208C4F7866612CC88BFEBC7C496FA72C2368D1C0&dn=doctor+stranger+e03+140512+hdtv+h264+720p+ipop+avi+ctrg&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce"); torrentInfo.Peers.Should().Be(311); - torrentInfo.Seeds.Should().Be(206); + torrentInfo.Seeders.Should().Be(206); } [Test] diff --git a/src/NzbDrone.Core.Test/IndexerTests/NyaaTests/NyaaFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/NyaaTests/NyaaFixture.cs index 6d48a6b42..e2f4f3b14 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/NyaaTests/NyaaFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/NyaaTests/NyaaFixture.cs @@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests torrentInfo.InfoHash.Should().Be(null); torrentInfo.MagnetUrl.Should().Be(null); torrentInfo.Peers.Should().Be(2); - torrentInfo.Seeds.Should().Be(1); + torrentInfo.Seeders.Should().Be(1); } } } diff --git a/src/NzbDrone.Core.Test/IndexerTests/TorrentleechTests/TorrentleechFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/TorrentleechTests/TorrentleechFixture.cs index cb9d2bc02..6c1a44d07 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/TorrentleechTests/TorrentleechFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/TorrentleechTests/TorrentleechFixture.cs @@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentleechTests torrentInfo.InfoHash.Should().Be(null); torrentInfo.MagnetUrl.Should().Be(null); torrentInfo.Peers.Should().Be(7); - torrentInfo.Seeds.Should().Be(1); + torrentInfo.Seeders.Should().Be(1); } } } diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/Search/TorrentSeedingSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/Search/TorrentSeedingSpecification.cs index 12ac5e7ab..ab8571cdb 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/Search/TorrentSeedingSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/Search/TorrentSeedingSpecification.cs @@ -31,10 +31,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search return Decision.Accept(); } - if (torrentInfo.Seeds != null && torrentInfo.Seeds < 1) + if (torrentInfo.Seeders != null && torrentInfo.Seeders < 1) { - _logger.Debug("Not enough seeders. ({0})", torrentInfo.Seeds); - return Decision.Reject("Not enough seeders. ({0})", torrentInfo.Seeds); + _logger.Debug("Not enough seeders. ({0})", torrentInfo.Seeders); + return Decision.Reject("Not enough seeders. ({0})", torrentInfo.Seeders); } return Decision.Accept(); diff --git a/src/NzbDrone.Core/Indexers/BroadcastheNet/BroadcastheNetParser.cs b/src/NzbDrone.Core/Indexers/BroadcastheNet/BroadcastheNetParser.cs index 6e1b94bdf..96ab86226 100644 --- a/src/NzbDrone.Core/Indexers/BroadcastheNet/BroadcastheNetParser.cs +++ b/src/NzbDrone.Core/Indexers/BroadcastheNet/BroadcastheNetParser.cs @@ -58,7 +58,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet torrentInfo.PublishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime().AddSeconds(torrent.Time); //torrentInfo.MagnetUrl = torrentInfo.InfoHash = torrent.InfoHash; - torrentInfo.Seeds = torrent.Seeders; + torrentInfo.Seeders = torrent.Seeders; torrentInfo.Peers = torrent.Leechers; results.Add(torrentInfo); diff --git a/src/NzbDrone.Core/Indexers/TorrentRssParser.cs b/src/NzbDrone.Core/Indexers/TorrentRssParser.cs index 14ea6eea3..7de611fa0 100644 --- a/src/NzbDrone.Core/Indexers/TorrentRssParser.cs +++ b/src/NzbDrone.Core/Indexers/TorrentRssParser.cs @@ -26,7 +26,7 @@ namespace NzbDrone.Core.Indexers result.InfoHash = GetInfoHash(item); result.MagnetUrl = GetMagnetUrl(item); - result.Seeds = GetSeeders(item); + result.Seeders = GetSeeders(item); result.Peers = GetPeers(item); return result; diff --git a/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs b/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs index 889a1acad..e8c1c79cf 100644 --- a/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs +++ b/src/NzbDrone.Core/Parser/Model/TorrentInfo.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Parser.Model { public string MagnetUrl { get; set; } public string InfoHash { get; set; } - public Int32? Seeds { get; set; } + public Int32? Seeders { get; set; } public Int32? Peers { get; set; } public static Int32? GetSeeders(ReleaseInfo release) @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Parser.Model { return null; } - return torrentInfo.Seeds; + return torrentInfo.Seeders; } } } \ No newline at end of file diff --git a/src/UI/Content/theme.less b/src/UI/Content/theme.less index a3b03dbd4..16a30ac70 100644 --- a/src/UI/Content/theme.less +++ b/src/UI/Content/theme.less @@ -19,7 +19,7 @@ @import "../Hotkeys/hotkeys"; .main-region { - @media (min-width: @screen-lg-min) { + @media (min-width : @screen-lg-min) { padding-left : 30px; padding-right : 30px; } @@ -28,12 +28,12 @@ .toolbar { &:after { - visibility: hidden; - display: block; - font-size: 0; - content: " "; - clear: both; - height: 0; + visibility : hidden; + display : block; + font-size : 0; + content : " "; + clear : both; + height : 0; } .page-toolbar { @@ -41,13 +41,13 @@ margin-bottom : 30px; .toolbar-group { - display: inline-block; + display : inline-block; } .sorting-buttons { .sorting-title { - display: inline-block; - width: 110px; + display : inline-block; + width : 110px; } } } @@ -86,7 +86,7 @@ .control-panel-visible { #scroll-up { - bottom: 100px; + bottom : 100px; } } @@ -101,7 +101,7 @@ } .label-disabled { - opacity: 0.5; + opacity : 0.5; } th { @@ -123,10 +123,9 @@ a, .btn { } body { - background: - url('../Content/Images/background/logo.png') 50px center no-repeat fixed,#272727; + background : url('../Content/Images/background/logo.png') 50px center no-repeat fixed, #272727; - margin-bottom : 100px; + margin-bottom : 100px; p { font-size : 0.9em; } @@ -163,10 +162,10 @@ body { .card(#aaaaaa); /* width : 1210px; min-width : 1210px; */ - max-width : 1210px; - margin : auto; -// margin-top : -70px; - padding : 20px 0px; + max-width : 1210px; + margin : auto; + // margin-top : -70px; + padding : 20px 0px; .header { padding-bottom : 10px; @@ -203,15 +202,15 @@ body { } .error { - background: #FF0000; + background : #FF0000; } -#errors{ +#errors { display : none; } .mono-space { - font-family: "ubuntu mono" + font-family : "ubuntu mono" } .file-path { @@ -221,26 +220,26 @@ body { .control-panel { .card(#333333); - color: #f5f5f5; - background-color: #333333; - margin: 0px; - margin-bottom: -100px; - position: fixed; - left: 0; - bottom: 0; - width: 100%; - height: 80px; - opacity: 0; - - @media (max-width: @screen-sm-max) { - height: initial; - position: static; + color : #f5f5f5; + background-color : #333333; + margin : 0px; + margin-bottom : -100px; + position : fixed; + left : 0; + bottom : 0; + width : 100%; + height : 80px; + opacity : 0; + + @media (max-width : @screen-sm-max) { + height : initial; + position : static; } } .tab-content { .tab-pane { - padding-top: 10px; + padding-top : 10px; } } @@ -251,6 +250,17 @@ body { } } +.modal-body { + table { + font-size : 12px; + font-weight : bold; + + i { + font-size : 14px; + } + } +} + .tooltip { .tooltip-inner { max-width : 250px; @@ -259,6 +269,16 @@ body { dl.info { dt, dd { - padding-bottom: 5px; + padding-bottom : 5px; } } + +.label { + &.protocol-torrent { + background-color : #00853D; + } + + &.protocol-usenet { + background-color : #17B1D9; + } +} \ No newline at end of file diff --git a/src/UI/Episode/Search/ManualLayout.js b/src/UI/Episode/Search/ManualLayout.js index 81388dc9f..31f8c6766 100644 --- a/src/UI/Episode/Search/ManualLayout.js +++ b/src/UI/Episode/Search/ManualLayout.js @@ -8,8 +8,10 @@ define( 'Cells/QualityCell', 'Cells/ApprovalStatusCell', 'Release/DownloadReportCell', - 'Release/AgeCell' - ], function (Marionette, Backgrid, ReleaseTitleCell, FileSizeCell, QualityCell, ApprovalStatusCell, DownloadReportCell, AgeCell) { + 'Release/AgeCell', + 'Release/ProtocolCell', + 'Release/PeersCell' + ], function (Marionette, Backgrid, ReleaseTitleCell, FileSizeCell, QualityCell, ApprovalStatusCell, DownloadReportCell, AgeCell, ProtocolCell, PeersCell) { return Marionette.Layout.extend({ template: 'Episode/Search/ManualLayoutTemplate', @@ -21,6 +23,10 @@ define( columns: [ { + name : 'protocol', + label : 'Source', + cell : ProtocolCell + }, { name : 'age', label : 'Age', cell : AgeCell @@ -40,6 +46,11 @@ define( label : 'Size', cell : FileSizeCell }, + { + name : 'seeders', + label : 'Peers', + cell : PeersCell + }, { name : 'quality', label : 'Quality', diff --git a/src/UI/Release/PeersCell.js b/src/UI/Release/PeersCell.js new file mode 100644 index 000000000..1ac08e1f4 --- /dev/null +++ b/src/UI/Release/PeersCell.js @@ -0,0 +1,34 @@ +'use strict'; + +define(['backgrid'], function (Backgrid) { + return Backgrid.Cell.extend({ + + className : 'peers-cell', + + render : function () { + + if (this.model.get('protocol') === 'torrent') { + + var seeders = this.model.get('seeders') || 0; + var leechers = this.model.get('leechers') || 0; + + var level = 'danger'; + + if(seeders > 0){ + level='warning'; + } + if(seeders > 10){ + level = 'info'; + } + if(seeders > 50){ + level = 'primary'; + } + + this.$el.html('
{0} / {1}
'.format(seeders, leechers, level)); + } + + this.delegateEvents(); + return this; + } + }); +}); \ No newline at end of file diff --git a/src/UI/Release/ProtocolCell.js b/src/UI/Release/ProtocolCell.js new file mode 100644 index 000000000..13645a6d8 --- /dev/null +++ b/src/UI/Release/ProtocolCell.js @@ -0,0 +1,28 @@ +'use strict'; + +define(['backgrid'], function (Backgrid) { + return Backgrid.Cell.extend({ + + className : 'protocol-cell', + + render : function () { + var protocol = this.model.get('protocol') || 'Unknown'; + + var label = '??'; + + if (protocol) { + if (protocol === 'torrent') { + label = 'torrent'; + } + else if (protocol === 'usenet') { + label = 'nzb'; + } + + this.$el.html('
{1}
'.format(protocol, label)); + } + + this.delegateEvents(); + return this; + } + }); +}); \ No newline at end of file diff --git a/src/UI/Release/ReleaseCollection.js b/src/UI/Release/ReleaseCollection.js index 796144502..0093e0022 100644 --- a/src/UI/Release/ReleaseCollection.js +++ b/src/UI/Release/ReleaseCollection.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict'; define( [ 'backbone.pageable', @@ -19,7 +19,7 @@ define( sortMappings: { 'quality' : { sortKey: 'qualityWeight' }, - 'rejections' : { sortValue: function (model, attr) { + 'rejections' : { sortValue: function (model) { var rejections = model.get('rejections'); var releaseWeight = model.get('releaseWeight');