mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 20:12:41 +02:00
AHD, PTP and HDB support the new indexer flags too now! Indexer flags can be preferred over other releases.
This commit is contained in:
parent
10091b9454
commit
433ae019de
@ -8,9 +8,10 @@ public class IndexerConfigResource : RestResource
|
||||
public int MinimumAge { get; set; }
|
||||
public int Retention { get; set; }
|
||||
public int RssSyncInterval { get; set; }
|
||||
public int AvailabilityDelay { get; set; }
|
||||
public bool AllowHardcodedSubs { get; set; }
|
||||
public string WhitelistedHardcodedSubs { get; set; }
|
||||
public bool PreferIndexerFlags { get; set; }
|
||||
public int AvailabilityDelay { get; set; }
|
||||
public bool AllowHardcodedSubs { get; set; }
|
||||
public string WhitelistedHardcodedSubs { get; set; }
|
||||
}
|
||||
|
||||
public static class IndexerConfigResourceMapper
|
||||
@ -22,9 +23,10 @@ public static IndexerConfigResource ToResource(IConfigService model)
|
||||
MinimumAge = model.MinimumAge,
|
||||
Retention = model.Retention,
|
||||
RssSyncInterval = model.RssSyncInterval,
|
||||
AvailabilityDelay = model.AvailabilityDelay,
|
||||
AllowHardcodedSubs = model.AllowHardcodedSubs,
|
||||
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs,
|
||||
PreferIndexerFlags = model.PreferIndexerFlags,
|
||||
AvailabilityDelay = model.AvailabilityDelay,
|
||||
AllowHardcodedSubs = model.AllowHardcodedSubs,
|
||||
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs,
|
||||
|
||||
};
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
86
src/NzbDrone.Core.Test/IndexerTests/PTPTests/PTPFixture.cs
Normal file
86
src/NzbDrone.Core.Test/IndexerTests/PTPTests/PTPFixture.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.PassThePopcorn;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.PTPTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class PTPFixture : CoreTest<PassThePopcorn>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "PTP",
|
||||
Settings = new PassThePopcornSettings() { Passkey = "fakekey", Username = "asdf", Password = "sad" }
|
||||
};
|
||||
}
|
||||
|
||||
[TestCase("Files/Indexers/PTP/imdbsearch.json")]
|
||||
public void should_parse_feed_from_PTP(string fileName)
|
||||
{
|
||||
var authResponse = new PassThePopcornAuthResponse { Result = "Ok" };
|
||||
|
||||
System.IO.StringWriter authStream = new System.IO.StringWriter();
|
||||
Json.Serialize(authResponse, authStream);
|
||||
var responseJson = ReadAllText(fileName);
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r,new HttpHeader(), authStream.ToString()));
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader {ContentType = HttpAccept.Json.Value}, responseJson));
|
||||
|
||||
var torrents = Subject.FetchRecent();
|
||||
|
||||
torrents.Should().HaveCount(293);
|
||||
torrents.First().Should().BeOfType<PassThePopcornInfo>();
|
||||
|
||||
var first = torrents.First() as TorrentInfo;
|
||||
|
||||
first.Guid.Should().Be("PassThePopcorn-483521");
|
||||
first.Title.Should().Be("The.Night.Of.S01.720p.HDTV.x264-BTN");
|
||||
first.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
first.DownloadUrl.Should().Be("https://passthepopcorn.me/torrents.php?action=download&id=483521&authkey=00000000000000000000000000000000&torrent_pass=00000000000000000000000000000000");
|
||||
first.InfoUrl.Should().Be("https://passthepopcorn.me/torrents.php?id=148131&torrentid=483521");
|
||||
first.PublishDate.Should().Be(DateTime.Parse("2017-04-17T12:13:42+0000").ToUniversalTime());
|
||||
first.Size.Should().Be(9370933376);
|
||||
first.InfoHash.Should().BeNullOrEmpty();
|
||||
first.MagnetUrl.Should().BeNullOrEmpty();
|
||||
first.Peers.Should().Be(3);
|
||||
first.Seeders.Should().Be(1);
|
||||
|
||||
torrents.Any(t => t.IndexerFlags.HasFlag(IndexerFlags.G_Freeleech)).Should().Be(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_warn_on_wrong_passkey()
|
||||
{
|
||||
var responseJson = new { status = 5, message = "Invalid authentication credentials" }.ToJson();
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(),
|
||||
Encoding.UTF8.GetBytes(responseJson)));
|
||||
|
||||
var torrents = Subject.FetchRecent();
|
||||
|
||||
torrents.Should().BeEmpty();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
}
|
||||
}
|
@ -389,6 +389,10 @@
|
||||
<Content Include="Files\ArabicRomanNumeralDictionary.JSON">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Compile Include="IndexerTests\PTPTests\PTPFixture.cs" />
|
||||
<None Include="Files\Indexers\PTP\imdbsearch.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
||||
@ -574,6 +578,8 @@
|
||||
<Folder Include="DataAugmentation\SceneNumbering\" />
|
||||
<Folder Include="Providers\" />
|
||||
<Folder Include="ProviderTests\UpdateProviderTests\" />
|
||||
<Folder Include="IndexerTests\PTPTests\" />
|
||||
<Folder Include="Files\Indexers\PTP\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
|
@ -105,11 +105,11 @@ public int RssSyncInterval
|
||||
set { SetValue("RssSyncInterval", value); }
|
||||
}
|
||||
|
||||
public int AvailabilityDelay
|
||||
{
|
||||
get { return GetValueInt("AvailabilityDelay",0); }
|
||||
set { SetValue("AvailabilityDelay", value); }
|
||||
}
|
||||
public int AvailabilityDelay
|
||||
{
|
||||
get { return GetValueInt("AvailabilityDelay",0); }
|
||||
set { SetValue("AvailabilityDelay", value); }
|
||||
}
|
||||
|
||||
public int NetImportSyncInterval
|
||||
{
|
||||
@ -190,19 +190,26 @@ public bool EnableCompletedDownloadHandling
|
||||
set { SetValue("EnableCompletedDownloadHandling", value); }
|
||||
}
|
||||
|
||||
public bool AllowHardcodedSubs
|
||||
{
|
||||
get { return GetValueBoolean("AllowHardcodedSubs", false); }
|
||||
public bool PreferIndexerFlags
|
||||
{
|
||||
get { return GetValueBoolean("PreferIndexerFlags", false); }
|
||||
|
||||
set { SetValue("AllowHardcodedSubs", value); }
|
||||
}
|
||||
set {SetValue("PreferIndexerFlags", value);}
|
||||
}
|
||||
|
||||
public string WhitelistedHardcodedSubs
|
||||
{
|
||||
get { return GetValue("WhitelistedHardcodedSubs", ""); }
|
||||
public bool AllowHardcodedSubs
|
||||
{
|
||||
get { return GetValueBoolean("AllowHardcodedSubs", false); }
|
||||
|
||||
set { SetValue("WhitelistedHardcodedSubs", value); }
|
||||
}
|
||||
set { SetValue("AllowHardcodedSubs", value); }
|
||||
}
|
||||
|
||||
public string WhitelistedHardcodedSubs
|
||||
{
|
||||
get { return GetValue("WhitelistedHardcodedSubs", ""); }
|
||||
|
||||
set { SetValue("WhitelistedHardcodedSubs", value); }
|
||||
}
|
||||
|
||||
public bool RemoveCompletedDownloads
|
||||
{
|
||||
|
@ -46,20 +46,22 @@ public interface IConfigService
|
||||
int RssSyncInterval { get; set; }
|
||||
int MinimumAge { get; set; }
|
||||
|
||||
int AvailabilityDelay { get; set; }
|
||||
bool PreferIndexerFlags { get; set; }
|
||||
|
||||
bool AllowHardcodedSubs { get; set; }
|
||||
string WhitelistedHardcodedSubs { get; set; }
|
||||
int AvailabilityDelay { get; set; }
|
||||
|
||||
bool AllowHardcodedSubs { get; set; }
|
||||
string WhitelistedHardcodedSubs { get; set; }
|
||||
|
||||
int NetImportSyncInterval { get; set; }
|
||||
string ListSyncLevel { get; set; }
|
||||
string ImportExclusions { get; set; }
|
||||
string ListSyncLevel { get; set; }
|
||||
string ImportExclusions { get; set; }
|
||||
string TraktAuthToken { get; set; }
|
||||
string TraktRefreshToken { get; set; }
|
||||
int TraktTokenExpiry { get; set; }
|
||||
string NewTraktAuthToken { get; set; }
|
||||
string NewTraktRefreshToken {get; set; }
|
||||
int NewTraktTokenExpiry { get; set; }
|
||||
string NewTraktAuthToken { get; set; }
|
||||
string NewTraktRefreshToken {get; set; }
|
||||
int NewTraktTokenExpiry { get; set; }
|
||||
|
||||
//UI
|
||||
int FirstDayOfWeek { get; set; }
|
||||
|
@ -4,18 +4,21 @@
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Profiles.Delay;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public class DownloadDecisionComparer : IComparer<DownloadDecision>
|
||||
{
|
||||
private readonly IDelayProfileService _delayProfileService;
|
||||
private readonly IConfigService _configService;
|
||||
public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y);
|
||||
public delegate int CompareDelegate<TSubject, TValue>(DownloadDecision x, DownloadDecision y);
|
||||
|
||||
public DownloadDecisionComparer(IDelayProfileService delayProfileService)
|
||||
public DownloadDecisionComparer(IDelayProfileService delayProfileService, IConfigService configService)
|
||||
{
|
||||
_delayProfileService = delayProfileService;
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public int Compare(DownloadDecision x, DownloadDecision y)
|
||||
@ -24,6 +27,7 @@ public int Compare(DownloadDecision x, DownloadDecision y)
|
||||
{
|
||||
CompareQuality,
|
||||
ComparePreferredWords,
|
||||
CompareIndexerFlags,
|
||||
CompareProtocol,
|
||||
ComparePeersIfTorrent,
|
||||
CompareAgeIfUsenet,
|
||||
@ -84,7 +88,22 @@ private int ComparePreferredWords(DownloadDecision x, DownloadDecision y)
|
||||
return num;
|
||||
|
||||
});
|
||||
; }
|
||||
}
|
||||
|
||||
private int CompareIndexerFlags(DownloadDecision x, DownloadDecision y)
|
||||
{
|
||||
var releaseX = x.RemoteMovie.Release;
|
||||
var releaseY = y.RemoteMovie.Release;
|
||||
|
||||
if (_configService.PreferIndexerFlags)
|
||||
{
|
||||
return CompareBy(x.RemoteMovie.Release, y.RemoteMovie.Release, release => ScoreFlags(release.IndexerFlags));
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
||||
{
|
||||
@ -185,5 +204,34 @@ private int CompareSize(DownloadDecision x, DownloadDecision y)
|
||||
|
||||
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
|
||||
}
|
||||
|
||||
private int ScoreFlags(IndexerFlags flags)
|
||||
{
|
||||
var flagValues = Enum.GetValues(typeof(IndexerFlags));
|
||||
|
||||
var score = 0;
|
||||
|
||||
foreach (IndexerFlags value in flagValues)
|
||||
{
|
||||
if ((flags & value) == value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case IndexerFlags.G_DoubleUpload:
|
||||
case IndexerFlags.G_Freeleech:
|
||||
case IndexerFlags.PTP_Approved:
|
||||
case IndexerFlags.PTP_Golden:
|
||||
case IndexerFlags.HDB_Internal:
|
||||
score += 2;
|
||||
break;
|
||||
case IndexerFlags.G_Halfleech:
|
||||
score += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Profiles.Delay;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
@ -13,10 +14,12 @@ public interface IPrioritizeDownloadDecision
|
||||
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
|
||||
{
|
||||
private readonly IDelayProfileService _delayProfileService;
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService)
|
||||
public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService, IConfigService configService)
|
||||
{
|
||||
_delayProfileService = delayProfileService;
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
|
||||
@ -24,7 +27,7 @@ public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisio
|
||||
return decisions.Where(c => c.RemoteEpisode.Series != null)
|
||||
.GroupBy(c => c.RemoteEpisode.Series.Id, (seriesId, downloadDecisions) =>
|
||||
{
|
||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
|
||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService, _configService));
|
||||
})
|
||||
.SelectMany(c => c)
|
||||
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
|
||||
@ -36,7 +39,7 @@ public List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision
|
||||
return decisions.Where(c => c.RemoteMovie.Movie != null)
|
||||
.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
|
||||
{
|
||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
|
||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService, _configService));
|
||||
})
|
||||
.SelectMany(c => c)
|
||||
.Union(decisions.Where(c => c.RemoteMovie.Movie == null))
|
||||
|
@ -69,6 +69,12 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
{
|
||||
var id = torrent.Id;
|
||||
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.AudioFormat}-{torrent.ReleaseGroup}";
|
||||
IndexerFlags flags = 0;
|
||||
|
||||
if (torrent.Freeleech == "1.00")
|
||||
{
|
||||
flags |= IndexerFlags.G_Freeleech;
|
||||
}
|
||||
|
||||
torrentInfos.Add(new TorrentInfo()
|
||||
{
|
||||
@ -80,7 +86,8 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.Time.ToUniversalTime(),
|
||||
ImdbId = int.Parse(torrent.ImdbId.Substring(2))
|
||||
ImdbId = int.Parse(torrent.ImdbId.Substring(2)),
|
||||
IndexerFlags = flags,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,18 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
var id = result.Id;
|
||||
var internalRelease = (result.TypeOrigin == 1 ? true : false);
|
||||
|
||||
IndexerFlags flags = 0;
|
||||
|
||||
if (result.FreeLeech == "yes")
|
||||
{
|
||||
flags |= IndexerFlags.G_Freeleech;
|
||||
}
|
||||
|
||||
if (internalRelease)
|
||||
{
|
||||
flags |= IndexerFlags.HDB_Internal;
|
||||
}
|
||||
|
||||
torrentInfos.Add(new HDBitsInfo()
|
||||
{
|
||||
Guid = string.Format("HDBits-{0}", id),
|
||||
@ -65,7 +77,8 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
Peers = result.Leechers + result.Seeders,
|
||||
PublishDate = result.Added.ToUniversalTime(),
|
||||
Internal = internalRelease,
|
||||
ImdbId = result.ImdbInfo?.Id ?? 0
|
||||
ImdbId = result.ImdbInfo?.Id ?? 0,
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ public class Torrent
|
||||
public string ReleaseName { get; set; }
|
||||
public bool Checked { get; set; }
|
||||
public bool GoldenPopcorn { get; set; }
|
||||
public string FreeleechType { get; set; }
|
||||
}
|
||||
|
||||
public class Movie
|
||||
|
@ -55,11 +55,11 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
{
|
||||
var id = torrent.Id;
|
||||
var title = torrent.ReleaseName;
|
||||
IndexerFlags flags = 0;
|
||||
IndexerFlags flags = 0;
|
||||
|
||||
if (torrent.GoldenPopcorn)
|
||||
{
|
||||
flags |= IndexerFlags.PTP_Golden;//title = $"{title} 🍿";
|
||||
flags |= IndexerFlags.PTP_Golden;//title = $"{title} 🍿";
|
||||
}
|
||||
|
||||
if (torrent.Checked)
|
||||
@ -67,52 +67,57 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
flags |= IndexerFlags.PTP_Approved;//title = $"{title} ✔";
|
||||
}
|
||||
|
||||
// Only add approved torrents
|
||||
if (_settings.RequireApproved && torrent.Checked)
|
||||
if (torrent.FreeleechType == "Freeleech")
|
||||
{
|
||||
torrentInfos.Add(new PassThePopcornInfo()
|
||||
{
|
||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||
Title = title,
|
||||
Size = long.Parse(torrent.Size),
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||
Golden = torrent.GoldenPopcorn,
|
||||
Scene = torrent.Scene,
|
||||
Approved = torrent.Checked,
|
||||
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||
IndexerFlags = flags
|
||||
});
|
||||
flags |= IndexerFlags.G_Freeleech;
|
||||
}
|
||||
|
||||
// Add all torrents
|
||||
else if (!_settings.RequireApproved)
|
||||
{
|
||||
torrentInfos.Add(new PassThePopcornInfo()
|
||||
// Only add approved torrents
|
||||
if (_settings.RequireApproved && torrent.Checked)
|
||||
{
|
||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||
Title = title,
|
||||
Size = long.Parse(torrent.Size),
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||
Golden = torrent.GoldenPopcorn,
|
||||
Scene = torrent.Scene,
|
||||
Approved = torrent.Checked,
|
||||
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
// Don't add any torrents
|
||||
else if (_settings.RequireApproved && !torrent.Checked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
torrentInfos.Add(new PassThePopcornInfo()
|
||||
{
|
||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||
Title = title,
|
||||
Size = long.Parse(torrent.Size),
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||
Golden = torrent.GoldenPopcorn,
|
||||
Scene = torrent.Scene,
|
||||
Approved = torrent.Checked,
|
||||
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
|
||||
// Add all torrents
|
||||
else if (!_settings.RequireApproved)
|
||||
{
|
||||
torrentInfos.Add(new PassThePopcornInfo()
|
||||
{
|
||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||
Title = title,
|
||||
Size = long.Parse(torrent.Size),
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||
Golden = torrent.GoldenPopcorn,
|
||||
Scene = torrent.Scene,
|
||||
Approved = torrent.Checked,
|
||||
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
// Don't add any torrents
|
||||
else if (_settings.RequireApproved && !torrent.Checked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@ protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInf
|
||||
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
|
||||
}
|
||||
}
|
||||
|
||||
torrentInfo.IndexerFlags = GetFlags(item);
|
||||
|
||||
return torrentInfo;
|
||||
}
|
||||
|
||||
@ -151,6 +154,32 @@ protected override string GetMagnetUrl(XElement item)
|
||||
return base.GetPeers(item);
|
||||
}
|
||||
|
||||
protected IndexerFlags GetFlags(XElement item)
|
||||
{
|
||||
IndexerFlags flags = 0;
|
||||
|
||||
var downloadFactor = TryGetFloatTorznabAttribute(item, "downloadvolumefactor", 1);
|
||||
|
||||
var uploadFactor = TryGetFloatTorznabAttribute(item, "uploadvolumefactor", 1);
|
||||
|
||||
if (uploadFactor == 2)
|
||||
{
|
||||
flags |= IndexerFlags.G_DoubleUpload;
|
||||
}
|
||||
|
||||
if (downloadFactor == 0.5)
|
||||
{
|
||||
flags |= IndexerFlags.G_Halfleech;
|
||||
}
|
||||
|
||||
if (downloadFactor == 0.0)
|
||||
{
|
||||
flags |= IndexerFlags.G_Freeleech;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
protected string TryGetTorznabAttribute(XElement item, string key, string defaultValue = "")
|
||||
{
|
||||
var attr = item.Elements(ns + "attr").FirstOrDefault(e => e.Attribute("name").Value.Equals(key, StringComparison.CurrentCultureIgnoreCase));
|
||||
@ -160,6 +189,20 @@ protected string TryGetTorznabAttribute(XElement item, string key, string defaul
|
||||
return attr.Attribute("value").Value;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
protected float TryGetFloatTorznabAttribute(XElement item, string key, float defaultValue = 0)
|
||||
{
|
||||
var attr = TryGetTorznabAttribute(item, key, defaultValue.ToString());
|
||||
|
||||
float result = 0;
|
||||
|
||||
if (float.TryParse(attr, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,11 @@ public virtual string ToString(string format)
|
||||
[Flags]
|
||||
public enum IndexerFlags
|
||||
{
|
||||
PTP_Golden = 1, //PTP
|
||||
PTP_Approved = 2, //PTP
|
||||
G_Freeleech = 1, //General
|
||||
G_Halfleech = 2, //General, only 1/2 of download counted
|
||||
G_DoubleUpload = 4, //General
|
||||
PTP_Golden = 8, //PTP
|
||||
PTP_Approved = 16, //PTP
|
||||
HDB_Internal = 32 //HDBits
|
||||
}
|
||||
}
|
58
src/UI/Cells/IndexerFlagsCell.js
Normal file
58
src/UI/Cells/IndexerFlagsCell.js
Normal file
@ -0,0 +1,58 @@
|
||||
var Backgrid = require('backgrid');
|
||||
var Marionette = require('marionette');
|
||||
require('bootstrap');
|
||||
|
||||
module.exports = Backgrid.Cell.extend({
|
||||
className : 'edition-cell',
|
||||
//template : 'Cells/EditionCellTemplate',
|
||||
|
||||
render : function() {
|
||||
|
||||
var flags = this.model.get("indexerFlags");
|
||||
if (!flags) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var html = "";
|
||||
|
||||
if (flags) {
|
||||
_.each(flags, function(flag){
|
||||
var addon = "";
|
||||
var title = "";
|
||||
|
||||
switch (flag) {
|
||||
case "G_Freeleech":
|
||||
addon = "⬇";
|
||||
title = "Freeleech";
|
||||
break;
|
||||
case "G_Halfleech":
|
||||
addon = "⇩";
|
||||
title = "50% Freeleech";
|
||||
break;
|
||||
case "G_DoubleUpload":
|
||||
addon = "⬆";
|
||||
title = "Double upload";
|
||||
break;
|
||||
case "PTP_Golden":
|
||||
addon = "🍿";
|
||||
title = "Golden";
|
||||
break;
|
||||
case "PTP_Approved":
|
||||
addon = "✔";
|
||||
title = "Approved by PTP"
|
||||
case "HDB_Internal":
|
||||
addon = "⭐️";
|
||||
title = "HDBits Internal";
|
||||
break;
|
||||
}
|
||||
if (addon != "") {
|
||||
html += "<span title='{0}'>{1}</span> ".format(title, addon);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.$el.html(html);
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
@ -10,22 +10,7 @@ module.exports = NzbDroneCell.extend({
|
||||
var infoUrl = this.model.get('infoUrl');
|
||||
|
||||
var flags = this.model.get("indexerFlags");
|
||||
if (flags) {
|
||||
_.each(flags, function(flag){
|
||||
var addon = "";
|
||||
|
||||
switch (flag) {
|
||||
case "PTP_Golden":
|
||||
addon = "🍿";
|
||||
break;
|
||||
case "PTP_Approved":
|
||||
addon = "✔";
|
||||
break;
|
||||
}
|
||||
|
||||
title += addon;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (infoUrl) {
|
||||
this.$el.html('<a href="{0}">{1}</a>'.format(infoUrl, title));
|
||||
|
@ -9,6 +9,7 @@ var AgeCell = require('../../Release/AgeCell');
|
||||
var ProtocolCell = require('../../Release/ProtocolCell');
|
||||
var PeersCell = require('../../Release/PeersCell');
|
||||
var EditionCell = require('../../Cells/EditionCell');
|
||||
var IndexerFlagsCell = require('../../Cells/IndexerFlagsCell');
|
||||
|
||||
module.exports = Marionette.Layout.extend({
|
||||
template : 'Movies/Search/ManualLayoutTemplate',
|
||||
@ -39,6 +40,11 @@ module.exports = Marionette.Layout.extend({
|
||||
cell : EditionCell,
|
||||
title : "Edition",
|
||||
},
|
||||
{
|
||||
name : 'flags',
|
||||
label : 'Flags',
|
||||
cell : IndexerFlagsCell,
|
||||
},
|
||||
{
|
||||
name : 'indexer',
|
||||
label : 'Indexer',
|
||||
|
@ -33,6 +33,33 @@ var Collection = PagableCollection.extend({
|
||||
"edition" : {
|
||||
sortKey : "edition"
|
||||
},
|
||||
"flags" : {
|
||||
sortValue : function(model) {
|
||||
var flags = model.get("indexerFlags");
|
||||
var weight = 0;
|
||||
if (flags) {
|
||||
_.each(flags, function(flag){
|
||||
var addon = "";
|
||||
var title = "";
|
||||
|
||||
switch (flag) {
|
||||
case "G_Halfleech":
|
||||
weight += 1;
|
||||
break;
|
||||
case "G_Freeleech":
|
||||
case "G_DoubleUpload":
|
||||
case "PTP_Approved":
|
||||
case "PTP_Golden":
|
||||
case "HDB_Internal":
|
||||
weight += 2;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return weight;
|
||||
}
|
||||
},
|
||||
'download' : {
|
||||
sortKey : 'releaseWeight'
|
||||
},
|
||||
|
@ -8,7 +8,7 @@ var QualityCell = require('../Cells/QualityCell');
|
||||
var ApprovalStatusCell = require('../Cells/ApprovalStatusCell');
|
||||
var LoadingView = require('../Shared/LoadingView');
|
||||
var EditionCell = require('../Cells/EditionCell');
|
||||
var ReleaseTitleCell = require("./ReleaseTitleCell");
|
||||
var ReleaseTitleCell = require("../Cells/ReleaseTitleCell");
|
||||
|
||||
module.exports = Marionette.Layout.extend({
|
||||
template : 'Release/ReleaseLayoutTemplate',
|
||||
|
@ -1,33 +0,0 @@
|
||||
var _ = require('underscore');
|
||||
var Backgrid = require('backgrid');
|
||||
|
||||
var FormatHelpers = require('../Shared/FormatHelpers');
|
||||
|
||||
module.exports = Backgrid.Cell.extend({
|
||||
className : 'title-cell',
|
||||
|
||||
render : function() {
|
||||
debugger;
|
||||
var title = this.model.get('title');
|
||||
var flags = this.model.get("indexerFlags");
|
||||
if (flags) {
|
||||
_.each(flags, function(flag){
|
||||
var addon = "";
|
||||
debugger;
|
||||
switch (flag) {
|
||||
case "PTP_Golden":
|
||||
addon = "🍿";
|
||||
break;
|
||||
case "PTP_Approved":
|
||||
addon = "✔";
|
||||
break;
|
||||
}
|
||||
|
||||
title += addon;
|
||||
});
|
||||
}
|
||||
this.$el.html(title);
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
@ -25,6 +25,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Prefer Special Indexer Flags</label>
|
||||
<div class="col-sm-1 col-sm-push-2 help-inline">
|
||||
<i class="icon-sonarr-form-info" title="If set to yes, the more indexer flags (such as Golden, Approved, Internal, Freeleech, Double upload, etc.) a release has the more priorized it will be. Quality and Preferred words would still come first."/>
|
||||
</div>
|
||||
<div class="col-sm-2 col-sm-pull-1">
|
||||
<div class="input-group">
|
||||
<label class="checkbox toggle well">
|
||||
<input type="checkbox" name="preferIndexerFlags" class="x-completed-download-handling"/>
|
||||
<p>
|
||||
<span>Yes</span>
|
||||
<span>No</span>
|
||||
</p>
|
||||
|
||||
<div class="btn btn-primary slide-button"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group advanced-setting">
|
||||
<label class="col-sm-3 control-label">RSS Sync Interval</label>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user