1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-18 21:35:51 -04:00

Compare commits

..

37 Commits

Author SHA1 Message Date
Donald Webster 8ca66fb61a Change smtp.google.com to smtp.gmail.com (#1410) 2017-04-18 19:28:15 +02:00
Leonardo Galli 064844ac0c Fix PTP_Approved turning into HDBits Internal. 2017-04-18 16:41:40 +02:00
Leonardo Galli 5540594ecf Fix ptp tests. 2017-04-17 22:30:51 +02:00
Leonardo Galli 433ae019de AHD, PTP and HDB support the new indexer flags too now! Indexer flags can be preferred over other releases. 2017-04-17 17:12:09 +02:00
Leonardo Galli 10091b9454 Movies with Umlauts are now correctly matched and have correct CleanTitles.
An update library is recommended. Fixes #1338
2017-04-17 13:08:47 +02:00
Leonardo Galli 475851775f Minor Text fixes. 2017-04-17 12:11:35 +02:00
Leonardo Galli 0fff862fd2 Updated debug movie title to include Year. 2017-04-17 12:09:24 +02:00
Leonardo Galli 23754c49dc Fix error when MinimumAvailability was Announced and Delay was negative. 2017-04-17 12:08:03 +02:00
Leonardo Galli fbf790e9fd Disable PreDB sync for now. 2017-04-17 12:04:54 +02:00
Leonardo Galli 6d00bd0f7a Stats are now sent to our server instead of Sonarr's :) 2017-04-17 12:01:56 +02:00
hotio 5bf95e0d9e Update Series reference to Movies, should fix #1399 (#1402) 2017-04-16 23:20:42 +02:00
Leonardo Galli 8bb4b02be7 Fix for sql error. Did not think everything through exactly.
Fixes #1390.
2017-04-16 00:48:39 +02:00
Leonardo Galli b26a036eed Fix when MovieTitle is the empty string (should not occur, but what evs)
Fixes #1389
2017-04-16 00:26:16 +02:00
Leonardo Galli ef57882291 Fixes Movie Size not showing correctly.
Fixes #1379
2017-04-15 15:47:40 +02:00
Leonardo Galli 32a2407ad1 Fixed an issue where movies which were labelled with an alternative title could not be found.
Fixes #557 Fixes #1387 Probably fixes #1372, probably fixes #555
2017-04-15 14:50:34 +02:00
Leonardo Galli 33b48eec95 Indexer flags implementation. (#1377) Will be further finalized over the next few weeks with Freelech, preferring of certain flags, etc 2017-04-14 22:27:48 +02:00
Leonardo Galli 3790dc9109 Added test for fix in last commit. 2017-04-13 14:18:48 +02:00
Leonardo Galli 343d849536 Add default runtime when runtime info of tmdb says 0.
Fixes #1371
2017-04-13 14:04:38 +02:00
Leonardo Galli c36b259fa9 Fixes an issue where the semicolon and space afterwards was replaced.
This caused issues with cleaning the title afterwards. Fixes #1185
2017-04-13 10:27:00 +02:00
Leonardo Galli 6463913f22 Final tweak for package.sh 2017-04-12 22:31:49 +02:00
Leonardo Galli e39deb4bdc Update branch. 2017-04-12 21:57:59 +02:00
Leonardo Galli 9ca2c21547 This should finally fix all packaging stuff. 2017-04-12 21:46:33 +02:00
Leonardo Galli f376360611 Update packages.sh some more. 2017-04-12 21:23:02 +02:00
Leonardo Galli 3e966d4d58 Update package.sh script 2017-04-12 21:20:33 +02:00
Leonardo Galli e036267c33 Test fixes. 2017-04-12 18:23:04 +02:00
Leonardo Galli 7d4378ca7a More test debugging. 2017-04-12 18:12:47 +02:00
Leonardo Galli ee1ebfd893 Remote Test debugging yey! 2017-04-12 17:58:52 +02:00
Leonardo Galli 403fd0f0c0 Remove unecessary test. 2017-04-12 17:17:22 +02:00
Leonardo Galli fc5ac8219f Using NUnit.Runners so that teamcity build works. 2017-04-12 17:03:53 +02:00
Leonardo Galli 600a433faa Merge remote-tracking branch 'origin/develop' into develop 2017-04-12 16:45:23 +02:00
Leonardo Galli 5609facd9d Fixed package script for Teamcity. 2017-04-12 16:45:13 +02:00
Leonardo Galli 36ea6c6b99 Turn installer back on. 2017-04-12 12:23:07 +02:00
Leonardo Galli 56ac87c760 Disabled installer being picked up, causes error with update api. 2017-04-11 21:19:31 +02:00
Leonardo Galli 47753c47a5 Now artifacts get pushed even if tests fail 2017-04-11 19:40:13 +02:00
Leonardo Galli 712c0eb84a Log if ParsedMovieInfo is NULL. 2017-04-11 19:31:33 +02:00
Leonardo Galli 8765155223 Merge remote-tracking branch 'origin/develop' into develop 2017-04-11 12:16:14 +02:00
Leonardo Galli 63d7596e98 Catching predb.me errors hopefully. 2017-04-11 12:15:52 +02:00
49 changed files with 740 additions and 164 deletions
+5
View File
@@ -37,6 +37,11 @@ cache:
pull_requests: pull_requests:
do_not_increment_build_number: true do_not_increment_build_number: true
on_failure:
- ps: Get-ChildItem .\_artifacts\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
- ps: Get-ChildItem .\_artifacts\*.exe | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
- ps: Get-ChildItem .\_artifacts\*.tar.gz | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
only_commits: only_commits:
files: files:
- src/ - src/
+2 -2
View File
@@ -208,9 +208,9 @@ PackageTests()
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \; find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
if [ $runtime = "dotnet" ] ; then if [ $runtime = "dotnet" ] ; then
$nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder $nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
else else
mono $nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder mono $nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
fi fi
cp $outputFolder/*.dll $testPackageFolder cp $outputFolder/*.dll $testPackageFolder
+34 -25
View File
@@ -23,6 +23,9 @@ if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
DAY="`date +%d`" DAY="`date +%d`"
else else
VERSION=$1 VERSION=$1
BRANCH=$2
BRANCH=${BRANCH#refs\/heads\/}
BRANCH=${BRANCH//\//-}
fi fi
outputFolder='./_output' outputFolder='./_output'
outputFolderMono='./_output_mono' outputFolderMono='./_output_mono'
@@ -34,35 +37,41 @@ rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log
cp -r $outputFolder/ Radarr_Windows_$VERSION
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
if [ $runtime = "dotnet" ] ; then if [ $runtime = "dotnet" ] ; then
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/* ./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
./7za.exe a -ttar -so Radarr_Mono_$VERSION.tar ./Radarr_Mono_$VERSION/* | ./7za.exe a -si Radarr_Mono_$VERSION.tar.gz ./7za.exe a -ttar -so Radarr_Mono_$VERSION.tar ./Radarr_Mono_$VERSION/* | ./7za.exe a -si Radarr_Mono_$VERSION.tar.gz
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz ./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz ./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
else else
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null cp -r $outputFolder/ Radarr
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz zip -r Radarr.$BRANCH.$VERSION.windows.zip Radarr
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null rm -rf Radarr
cp -r $outputFolderMono/ Radarr
tar -zcvf Radarr.$BRANCH.$VERSION.linux.tar.gz Radarr
rm -rf Radarr
cp -r $outputFolderOsx/ Radarr
tar -zcvf Radarr.$BRANCH.$VERSION.osx.tar.gz Radarr
rm -rf Radarr
#TODO update for tar.gz
cd _output_osx_app/
zip -r ../Radarr.$BRANCH.$VERSION.osx-app.zip *
fi fi
ftp -n ftp.leonardogalli.ch << END_SCRIPT # ftp -n ftp.leonardogalli.ch << END_SCRIPT
passive # passive
quote USER $FTP_USER # quote USER $FTP_USER
quote PASS $FTP_PASS # quote PASS $FTP_PASS
mkdir builds # mkdir builds
cd builds # cd builds
mkdir $YEAR # mkdir $YEAR
cd $YEAR # cd $YEAR
mkdir $MONTH # mkdir $MONTH
cd $MONTH # cd $MONTH
mkdir $DAY # mkdir $DAY
cd $DAY # cd $DAY
binary # binary
put Radarr_Windows_$VERSION.zip # put Radarr_Windows_$VERSION.zip
put Radarr_Mono_$VERSION.zip # put Radarr_Mono_$VERSION.zip
put Radarr_OSX_$VERSION.zip # put Radarr_OSX_$VERSION.zip
quit # quit
END_SCRIPT # END_SCRIPT
@@ -8,9 +8,10 @@ namespace NzbDrone.Api.Config
public int MinimumAge { get; set; } public int MinimumAge { get; set; }
public int Retention { get; set; } public int Retention { get; set; }
public int RssSyncInterval { get; set; } public int RssSyncInterval { get; set; }
public int AvailabilityDelay { get; set; } public bool PreferIndexerFlags { get; set; }
public bool AllowHardcodedSubs { get; set; } public int AvailabilityDelay { get; set; }
public string WhitelistedHardcodedSubs { get; set; } public bool AllowHardcodedSubs { get; set; }
public string WhitelistedHardcodedSubs { get; set; }
} }
public static class IndexerConfigResourceMapper public static class IndexerConfigResourceMapper
@@ -22,9 +23,10 @@ namespace NzbDrone.Api.Config
MinimumAge = model.MinimumAge, MinimumAge = model.MinimumAge,
Retention = model.Retention, Retention = model.Retention,
RssSyncInterval = model.RssSyncInterval, RssSyncInterval = model.RssSyncInterval,
AvailabilityDelay = model.AvailabilityDelay, PreferIndexerFlags = model.PreferIndexerFlags,
AllowHardcodedSubs = model.AllowHardcodedSubs, AvailabilityDelay = model.AvailabilityDelay,
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs, AllowHardcodedSubs = model.AllowHardcodedSubs,
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs,
}; };
} }
+2 -1
View File
@@ -46,6 +46,7 @@ namespace NzbDrone.Api.Indexers
public bool DownloadAllowed { get; set; } public bool DownloadAllowed { get; set; }
public int ReleaseWeight { get; set; } public int ReleaseWeight { get; set; }
public IEnumerable<string> IndexerFlags { get; set; }
public string MagnetUrl { get; set; } public string MagnetUrl { get; set; }
public string InfoHash { get; set; } public string InfoHash { get; set; }
@@ -132,7 +133,7 @@ namespace NzbDrone.Api.Indexers
Seeders = torrentInfo.Seeders, Seeders = torrentInfo.Seeders,
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null, Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
Protocol = releaseInfo.DownloadProtocol, Protocol = releaseInfo.DownloadProtocol,
IndexerFlags = torrentInfo.IndexerFlags.ToString().Split(new string[] { ", " }, StringSplitOptions.None),
Edition = parsedMovieInfo.Edition, Edition = parsedMovieInfo.Edition,
IsDaily = false, IsDaily = false,
+1 -1
View File
@@ -213,7 +213,7 @@ namespace NzbDrone.Api.Movie
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics) private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
{ {
resource.SizeOnDisk = moviesStatistics.SizeOnDisk; //resource.SizeOnDisk = 0;//TODO: incorporate movie statistics moviesStatistics.SizeOnDisk;
} }
private void PopulateAlternateTitles(List<MovieResource> resources) private void PopulateAlternateTitles(List<MovieResource> resources)
+2 -2
View File
@@ -120,7 +120,7 @@ namespace NzbDrone.Api.Movie
//TotalEpisodeCount //TotalEpisodeCount
//EpisodeCount //EpisodeCount
//EpisodeFileCount //EpisodeFileCount
//SizeOnDisk SizeOnDisk = size,
Status = model.Status, Status = model.Status,
Overview = model.Overview, Overview = model.Overview,
//NextAiring //NextAiring
@@ -138,7 +138,7 @@ namespace NzbDrone.Api.Movie
IsAvailable = model.IsAvailable(), IsAvailable = model.IsAvailable(),
FolderName = model.FolderName(), FolderName = model.FolderName(),
SizeOnDisk = size, //SizeOnDisk = size,
Runtime = model.Runtime, Runtime = model.Runtime,
LastInfoSync = model.LastInfoSync, LastInfoSync = model.LastInfoSync,
@@ -29,7 +29,7 @@ namespace NzbDrone.Common.Test.DiskTests
public void should_be_able_to_check_space_on_ramdrive() public void should_be_able_to_check_space_on_ramdrive()
{ {
MonoOnly(); MonoOnly();
Subject.GetAvailableSpace("/run/").Should().NotBe(0); Subject.GetAvailableSpace("/").Should().NotBe(0);
} }
[Test] [Test]
@@ -20,7 +20,6 @@ namespace NzbDrone.Common.Test
} }
[TestCase("")] [TestCase("")]
[TestCase("http://")]
public void DownloadString_should_throw_on_error(string url) public void DownloadString_should_throw_on_error(string url)
{ {
Assert.Throws<ArgumentException>(() => Subject.DownloadString(url)); Assert.Throws<ArgumentException>(() => Subject.DownloadString(url));
@@ -20,6 +20,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private RemoteEpisode parseResultMulti; private RemoteEpisode parseResultMulti;
private RemoteEpisode parseResultSingle; private RemoteEpisode parseResultSingle;
private Series series; private Series series;
private Movie movie;
private RemoteMovie remoteMovie;
private QualityDefinition qualityType; private QualityDefinition qualityType;
[SetUp] [SetUp]
@@ -28,6 +30,16 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
series = Builder<Series>.CreateNew() series = Builder<Series>.CreateNew()
.Build(); .Build();
movie = Builder<Movie>.CreateNew().Build();
remoteMovie = new RemoteMovie
{
Movie = movie,
Release = new ReleaseInfo(),
ParsedMovieInfo = new ParsedMovieInfo { Quality = new QualityModel(Quality.SDTV, new Revision(version: 2)) },
};
parseResultMultiSet = new RemoteEpisode parseResultMultiSet = new RemoteEpisode
{ {
Series = series, Series = series,
@@ -216,5 +228,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue(); Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
} }
[Test]
public void should_use_110_minutes_if_runtime_is_0()
{
movie.Runtime = 0;
remoteMovie.Movie = movie;
remoteMovie.Release.Size = 1095.Megabytes();
Subject.IsSatisfiedBy(remoteMovie, null).Accepted.Should().Be(true);
remoteMovie.Release.Size = 1105.Megabytes();
Subject.IsSatisfiedBy(remoteMovie, null).Accepted.Should().Be(false);
}
} }
} }
File diff suppressed because one or more lines are too long
@@ -0,0 +1,69 @@
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()); stupid timezones
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);
}
}
}
@@ -389,6 +389,10 @@
<Content Include="Files\ArabicRomanNumeralDictionary.JSON"> <Content Include="Files\ArabicRomanNumeralDictionary.JSON">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Compile Include="IndexerTests\PTPTests\PTPFixture.cs" />
<None Include="Files\Indexers\PTP\imdbsearch.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj"> <ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
@@ -574,6 +578,8 @@
<Folder Include="DataAugmentation\SceneNumbering\" /> <Folder Include="DataAugmentation\SceneNumbering\" />
<Folder Include="Providers\" /> <Folder Include="Providers\" />
<Folder Include="ProviderTests\UpdateProviderTests\" /> <Folder Include="ProviderTests\UpdateProviderTests\" />
<Folder Include="IndexerTests\PTPTests\" />
<Folder Include="Files\Indexers\PTP\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
@@ -1,4 +1,4 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
@@ -74,6 +74,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("To.Live.and.Die.in.L.A.1985.1080p.BluRay", "To Live and Die in L.A.")] [TestCase("To.Live.and.Die.in.L.A.1985.1080p.BluRay", "To Live and Die in L.A.")]
[TestCase("A.I.Artificial.Intelligence.(2001)", "A.I. Artificial Intelligence")] [TestCase("A.I.Artificial.Intelligence.(2001)", "A.I. Artificial Intelligence")]
[TestCase("A.Movie.Name.(1998)", "A Movie Name")] [TestCase("A.Movie.Name.(1998)", "A Movie Name")]
[TestCase("Thor: The Dark World 2013", "Thor The Dark World")]
public void should_parse_movie_title(string postTitle, string title) public void should_parse_movie_title(string postTitle, string title)
{ {
Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title); Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title);
@@ -23,6 +23,8 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
private ParsedMovieInfo _wrongYearInfo; private ParsedMovieInfo _wrongYearInfo;
private ParsedMovieInfo _romanTitleInfo; private ParsedMovieInfo _romanTitleInfo;
private ParsedMovieInfo _alternativeTitleInfo; private ParsedMovieInfo _alternativeTitleInfo;
private ParsedMovieInfo _umlautInfo;
private ParsedMovieInfo _umlautAltInfo;
private MovieSearchCriteria _movieSearchCriteria; private MovieSearchCriteria _movieSearchCriteria;
private List<Episode> _episodes; private List<Episode> _episodes;
private ParsedEpisodeInfo _parsedEpisodeInfo; private ParsedEpisodeInfo _parsedEpisodeInfo;
@@ -37,10 +39,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
.Build(); .Build();
_movie = Builder<Movie>.CreateNew() _movie = Builder<Movie>.CreateNew()
.With(m => m.Title = "Mission Impossible 3") .With(m => m.Title = "Fack Ju Göthe 2")
.With(m => m.CleanTitle = "missionimpossible3") .With(m => m.CleanTitle = "fackjugoethe2")
.With(m => m.Year = 2006) .With(m => m.Year = 2015)
.With(m => m.AlternativeTitles = new List<string> { "Mission Impossible 3: Same same" }) .With(m => m.AlternativeTitles = new List<string> { "Fack Ju Göthe 2: Same same" })
.Build(); .Build();
_episodes = Builder<Episode>.CreateListOfSize(1) _episodes = Builder<Episode>.CreateListOfSize(1)
@@ -77,10 +79,22 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
_romanTitleInfo = new ParsedMovieInfo _romanTitleInfo = new ParsedMovieInfo
{ {
MovieTitle = "Mission Impossible III", MovieTitle = "Fack Ju Göthe II",
Year = _movie.Year, Year = _movie.Year,
}; };
_umlautInfo = new ParsedMovieInfo
{
MovieTitle = "Fack Ju Goethe 2",
Year = _movie.Year
};
_umlautAltInfo = new ParsedMovieInfo
{
MovieTitle = "Fack Ju Goethe 2: Same same",
Year = _movie.Year
};
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria _singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
{ {
Series = _series, Series = _series,
@@ -148,5 +162,12 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_romanTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie); Subject.Map(_romanTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
} }
[Test]
public void should_match_umlauts()
{
Subject.Map(_umlautInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
Subject.Map(_umlautAltInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
}
} }
} }
@@ -105,11 +105,11 @@ namespace NzbDrone.Core.Configuration
set { SetValue("RssSyncInterval", value); } set { SetValue("RssSyncInterval", value); }
} }
public int AvailabilityDelay public int AvailabilityDelay
{ {
get { return GetValueInt("AvailabilityDelay",0); } get { return GetValueInt("AvailabilityDelay",0); }
set { SetValue("AvailabilityDelay", value); } set { SetValue("AvailabilityDelay", value); }
} }
public int NetImportSyncInterval public int NetImportSyncInterval
{ {
@@ -190,19 +190,26 @@ namespace NzbDrone.Core.Configuration
set { SetValue("EnableCompletedDownloadHandling", value); } set { SetValue("EnableCompletedDownloadHandling", value); }
} }
public bool AllowHardcodedSubs public bool PreferIndexerFlags
{ {
get { return GetValueBoolean("AllowHardcodedSubs", false); } get { return GetValueBoolean("PreferIndexerFlags", false); }
set { SetValue("AllowHardcodedSubs", value); } set {SetValue("PreferIndexerFlags", value);}
} }
public string WhitelistedHardcodedSubs public bool AllowHardcodedSubs
{ {
get { return GetValue("WhitelistedHardcodedSubs", ""); } 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 public bool RemoveCompletedDownloads
{ {
@@ -46,20 +46,22 @@ namespace NzbDrone.Core.Configuration
int RssSyncInterval { get; set; } int RssSyncInterval { get; set; }
int MinimumAge { get; set; } int MinimumAge { get; set; }
int AvailabilityDelay { get; set; } bool PreferIndexerFlags { get; set; }
bool AllowHardcodedSubs { get; set; } int AvailabilityDelay { get; set; }
string WhitelistedHardcodedSubs { get; set; }
bool AllowHardcodedSubs { get; set; }
string WhitelistedHardcodedSubs { get; set; }
int NetImportSyncInterval { get; set; } int NetImportSyncInterval { get; set; }
string ListSyncLevel { get; set; } string ListSyncLevel { get; set; }
string ImportExclusions { get; set; } string ImportExclusions { get; set; }
string TraktAuthToken { get; set; } string TraktAuthToken { get; set; }
string TraktRefreshToken { get; set; } string TraktRefreshToken { get; set; }
int TraktTokenExpiry { get; set; } int TraktTokenExpiry { get; set; }
string NewTraktAuthToken { get; set; } string NewTraktAuthToken { get; set; }
string NewTraktRefreshToken {get; set; } string NewTraktRefreshToken {get; set; }
int NewTraktTokenExpiry { get; set; } int NewTraktTokenExpiry { get; set; }
//UI //UI
int FirstDayOfWeek { get; set; } int FirstDayOfWeek { get; set; }
@@ -4,18 +4,21 @@ using System.Linq;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles.Delay; using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.DecisionEngine namespace NzbDrone.Core.DecisionEngine
{ {
public class DownloadDecisionComparer : IComparer<DownloadDecision> public class DownloadDecisionComparer : IComparer<DownloadDecision>
{ {
private readonly IDelayProfileService _delayProfileService; private readonly IDelayProfileService _delayProfileService;
private readonly IConfigService _configService;
public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y); public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y);
public delegate int CompareDelegate<TSubject, TValue>(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; _delayProfileService = delayProfileService;
_configService = configService;
} }
public int Compare(DownloadDecision x, DownloadDecision y) public int Compare(DownloadDecision x, DownloadDecision y)
@@ -24,6 +27,7 @@ namespace NzbDrone.Core.DecisionEngine
{ {
CompareQuality, CompareQuality,
ComparePreferredWords, ComparePreferredWords,
CompareIndexerFlags,
CompareProtocol, CompareProtocol,
ComparePeersIfTorrent, ComparePeersIfTorrent,
CompareAgeIfUsenet, CompareAgeIfUsenet,
@@ -84,7 +88,22 @@ namespace NzbDrone.Core.DecisionEngine
return num; 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) private int CompareProtocol(DownloadDecision x, DownloadDecision y)
{ {
@@ -185,5 +204,34 @@ namespace NzbDrone.Core.DecisionEngine
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes())); 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.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Profiles.Delay; using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.DecisionEngine namespace NzbDrone.Core.DecisionEngine
{ {
@@ -13,10 +14,12 @@ namespace NzbDrone.Core.DecisionEngine
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
{ {
private readonly IDelayProfileService _delayProfileService; private readonly IDelayProfileService _delayProfileService;
private readonly IConfigService _configService;
public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService) public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService, IConfigService configService)
{ {
_delayProfileService = delayProfileService; _delayProfileService = delayProfileService;
_configService = configService;
} }
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions) public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
@@ -24,7 +27,7 @@ namespace NzbDrone.Core.DecisionEngine
return decisions.Where(c => c.RemoteEpisode.Series != null) return decisions.Where(c => c.RemoteEpisode.Series != null)
.GroupBy(c => c.RemoteEpisode.Series.Id, (seriesId, downloadDecisions) => .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) .SelectMany(c => c)
.Union(decisions.Where(c => c.RemoteEpisode.Series == null)) .Union(decisions.Where(c => c.RemoteEpisode.Series == null))
@@ -36,7 +39,7 @@ namespace NzbDrone.Core.DecisionEngine
return decisions.Where(c => c.RemoteMovie.Movie != null) return decisions.Where(c => c.RemoteMovie.Movie != null)
.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) => .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) .SelectMany(c => c)
.Union(decisions.Where(c => c.RemoteMovie.Movie == null)) .Union(decisions.Where(c => c.RemoteMovie.Movie == null))
@@ -1,4 +1,4 @@
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.IndexerSearch.Definitions;
@@ -121,6 +121,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
} }
var qualityDefinition = _qualityDefinitionService.Get(quality); var qualityDefinition = _qualityDefinitionService.Get(quality);
if (subject.Movie.Runtime == 0)
{
_logger.Info("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie);
subject.Movie.Runtime = 110;
}
if (qualityDefinition.MinSize.HasValue) if (qualityDefinition.MinSize.HasValue)
{ {
var minSize = qualityDefinition.MinSize.Value.Megabytes(); var minSize = qualityDefinition.MinSize.Value.Megabytes();
@@ -129,7 +129,14 @@ namespace NzbDrone.Core.Download
{ {
var statusMessages = importResults var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported) .Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors)) .Select(v =>
{
if (v.ImportDecision.LocalMovie == null)
{
return new TrackedDownloadStatusMessage("", v.Errors);
}
return new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors);
})
.ToArray(); .ToArray();
trackedDownload.Warn(statusMessages); trackedDownload.Warn(statusMessages);
@@ -226,7 +226,12 @@ namespace NzbDrone.Core.Download.Pending
Title = decision.RemoteMovie.Release.Title, Title = decision.RemoteMovie.Release.Title,
Added = DateTime.UtcNow Added = DateTime.UtcNow
}; };
_repository.Insert(release); if (release.ParsedMovieInfo == null)
{
_logger.Warn("Pending release {0} does not have ParsedMovieInfo, will cause issues.", release.Title);
}
_repository.Insert(release);
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent()); _eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
} }
@@ -69,6 +69,12 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
{ {
var id = torrent.Id; var id = torrent.Id;
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.AudioFormat}-{torrent.ReleaseGroup}"; 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() torrentInfos.Add(new TorrentInfo()
{ {
@@ -80,7 +86,8 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
Seeders = int.Parse(torrent.Seeders), Seeders = int.Parse(torrent.Seeders),
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders), Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
PublishDate = torrent.Time.ToUniversalTime(), PublishDate = torrent.Time.ToUniversalTime(),
ImdbId = int.Parse(torrent.ImdbId.Substring(2)) ImdbId = int.Parse(torrent.ImdbId.Substring(2)),
IndexerFlags = flags,
}); });
} }
} }
@@ -53,6 +53,18 @@ namespace NzbDrone.Core.Indexers.HDBits
var id = result.Id; var id = result.Id;
var internalRelease = (result.TypeOrigin == 1 ? true : false); 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() torrentInfos.Add(new HDBitsInfo()
{ {
Guid = string.Format("HDBits-{0}", id), Guid = string.Format("HDBits-{0}", id),
@@ -65,7 +77,8 @@ namespace NzbDrone.Core.Indexers.HDBits
Peers = result.Leechers + result.Seeders, Peers = result.Leechers + result.Seeders,
PublishDate = result.Added.ToUniversalTime(), PublishDate = result.Added.ToUniversalTime(),
Internal = internalRelease, Internal = internalRelease,
ImdbId = result.ImdbInfo?.Id ?? 0 ImdbId = result.ImdbInfo?.Id ?? 0,
IndexerFlags = flags
}); });
} }
@@ -28,6 +28,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
public string ReleaseName { get; set; } public string ReleaseName { get; set; }
public bool Checked { get; set; } public bool Checked { get; set; }
public bool GoldenPopcorn { get; set; } public bool GoldenPopcorn { get; set; }
public string FreeleechType { get; set; }
} }
public class Movie public class Movie
@@ -55,60 +55,69 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{ {
var id = torrent.Id; var id = torrent.Id;
var title = torrent.ReleaseName; var title = torrent.ReleaseName;
IndexerFlags flags = 0;
if (torrent.GoldenPopcorn) if (torrent.GoldenPopcorn)
{ {
title = $"{title} 🍿"; flags |= IndexerFlags.PTP_Golden;//title = $"{title} 🍿";
} }
if (torrent.Checked) if (torrent.Checked)
{ {
title = $"{title} ✔"; flags |= IndexerFlags.PTP_Approved;//title = $"{title} ✔";
}
if (torrent.FreeleechType == "Freeleech")
{
flags |= IndexerFlags.G_Freeleech;
} }
// Only add approved torrents // Only add approved torrents
if (_settings.RequireApproved && torrent.Checked) if (_settings.RequireApproved && torrent.Checked)
{
torrentInfos.Add(new PassThePopcornInfo()
{ {
Guid = string.Format("PassThePopcorn-{0}", id), torrentInfos.Add(new PassThePopcornInfo()
Title = title, {
Size = long.Parse(torrent.Size), Guid = string.Format("PassThePopcorn-{0}", id),
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey), Title = title,
InfoUrl = GetInfoUrl(result.GroupId, id), Size = long.Parse(torrent.Size),
Seeders = int.Parse(torrent.Seeders), DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders), InfoUrl = GetInfoUrl(result.GroupId, id),
PublishDate = torrent.UploadTime.ToUniversalTime(), Seeders = int.Parse(torrent.Seeders),
Golden = torrent.GoldenPopcorn, Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
Scene = torrent.Scene, PublishDate = torrent.UploadTime.ToUniversalTime(),
Approved = torrent.Checked, Golden = torrent.GoldenPopcorn,
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0) Scene = torrent.Scene,
}); Approved = torrent.Checked,
} ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
// Add all torrents IndexerFlags = flags
else if (!_settings.RequireApproved) });
{ }
torrentInfos.Add(new PassThePopcornInfo()
// Add all torrents
else if (!_settings.RequireApproved)
{ {
Guid = string.Format("PassThePopcorn-{0}", id), torrentInfos.Add(new PassThePopcornInfo()
Title = title, {
Size = long.Parse(torrent.Size), Guid = string.Format("PassThePopcorn-{0}", id),
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey), Title = title,
InfoUrl = GetInfoUrl(result.GroupId, id), Size = long.Parse(torrent.Size),
Seeders = int.Parse(torrent.Seeders), DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders), InfoUrl = GetInfoUrl(result.GroupId, id),
PublishDate = torrent.UploadTime.ToUniversalTime(), Seeders = int.Parse(torrent.Seeders),
Golden = torrent.GoldenPopcorn, Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
Scene = torrent.Scene, PublishDate = torrent.UploadTime.ToUniversalTime(),
Approved = torrent.Checked, Golden = torrent.GoldenPopcorn,
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0) Scene = torrent.Scene,
}); Approved = torrent.Checked,
} ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
// Don't add any torrents IndexerFlags = flags
else if (_settings.RequireApproved && !torrent.Checked) });
{ }
continue; // Don't add any torrents
} else if (_settings.RequireApproved && !torrent.Checked)
{
continue;
}
} }
} }
@@ -46,6 +46,9 @@ namespace NzbDrone.Core.Indexers.Torznab
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2)); torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
} }
} }
torrentInfo.IndexerFlags = GetFlags(item);
return torrentInfo; return torrentInfo;
} }
@@ -151,6 +154,32 @@ namespace NzbDrone.Core.Indexers.Torznab
return base.GetPeers(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 = "") 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)); var attr = item.Elements(ns + "attr").FirstOrDefault(e => e.Attribute("name").Value.Equals(key, StringComparison.CurrentCultureIgnoreCase));
@@ -160,6 +189,20 @@ namespace NzbDrone.Core.Indexers.Torznab
return attr.Attribute("value").Value; 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; return defaultValue;
} }
} }
@@ -62,6 +62,7 @@ namespace NzbDrone.Core.MetadataSource.PreDB
private List<PreDBResult> GetResults(string category = "", string search = "") private List<PreDBResult> GetResults(string category = "", string search = "")
{ {
return new List<PreDBResult>();
var builder = new HttpRequestBuilder("http://predb.me").AddQueryParam("rss", "1"); var builder = new HttpRequestBuilder("http://predb.me").AddQueryParam("rss", "1");
if (category.IsNotNullOrWhiteSpace()) if (category.IsNotNullOrWhiteSpace())
{ {
@@ -171,10 +172,12 @@ namespace NzbDrone.Core.MetadataSource.PreDB
public bool HasReleases(Movie movie) public bool HasReleases(Movie movie)
{ {
var results = GetResults("movies", movie.Title); try
{
var results = GetResults("movies", movie.Title);
foreach (PreDBResult result in results) foreach (PreDBResult result in results)
{ {
var parsed = Parser.Parser.ParseMovieTitle(result.Title); var parsed = Parser.Parser.ParseMovieTitle(result.Title);
if (parsed == null) if (parsed == null)
{ {
@@ -182,13 +185,20 @@ namespace NzbDrone.Core.MetadataSource.PreDB
} }
var match = _parsingService.Map(parsed, "", new MovieSearchCriteria { Movie = movie }); var match = _parsingService.Map(parsed, "", new MovieSearchCriteria { Movie = movie });
if (match != null && match.Movie != null && match.Movie.Id == movie.Id) if (match != null && match.Movie != null && match.Movie.Id == movie.Id)
{ {
return true; return true;
} }
} }
return false; return false;
}
catch (Exception ex)
{
_logger.Warn(ex, "Error while looking on predb.me.");
return false;
}
} }
} }
} }
@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Notifications.Email
public EmailSettings() public EmailSettings()
{ {
Server = "smtp.google.com"; Server = "smtp.gmail.com";
Port = 587; Port = 587;
Ssl = true; Ssl = true;
} }
+1
View File
@@ -1275,6 +1275,7 @@
<Compile Include="Datastore\Migration\131_make_parsed_episode_info_nullable.cs" /> <Compile Include="Datastore\Migration\131_make_parsed_episode_info_nullable.cs" />
<Compile Include="Housekeeping\Housekeepers\FixWronglyMatchedMovieFiles.cs" /> <Compile Include="Housekeeping\Housekeepers\FixWronglyMatchedMovieFiles.cs" />
<Compile Include="Datastore\Migration\135_add_haspredbentry_to_movies.cs" /> <Compile Include="Datastore\Migration\135_add_haspredbentry_to_movies.cs" />
<Compile Include="Tv\QueryExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client"> <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
+14 -1
View File
@@ -1,4 +1,4 @@
using System; using System;
using System.Text; using System.Text;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
@@ -26,6 +26,8 @@ namespace NzbDrone.Core.Parser.Model
public string Codec { get; set; } public string Codec { get; set; }
public string Resolution { get; set; } public string Resolution { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public int Age public int Age
{ {
get get
@@ -91,4 +93,15 @@ namespace NzbDrone.Core.Parser.Model
} }
} }
} }
[Flags]
public enum IndexerFlags
{
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
}
} }
+14 -3
View File
@@ -273,7 +273,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex ReportImdbId = new Regex(@"(?<imdbid>tt\d{7})", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex ReportImdbId = new Regex(@"(?<imdbid>tt\d{7})", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex SimpleTitleRegex = new Regex(@"(?:480[ip]|576[ip]|720[ip]|1080[ip]|2160[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|(8|10)b(it)?)\s*", private static readonly Regex SimpleTitleRegex = new Regex(@"\s*(?:480[ip]|576[ip]|720[ip]|1080[ip]|2160[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|(8|10)b(it)?)",
RegexOptions.IgnoreCase | RegexOptions.Compiled); RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex WebsitePrefixRegex = new Regex(@"^\[\s*[a-z]+(\.[a-z]+)+\s*\][- ]*", private static readonly Regex WebsitePrefixRegex = new Regex(@"^\[\s*[a-z]+(\.[a-z]+)+\s*\][- ]*",
@@ -310,6 +310,12 @@ namespace NzbDrone.Core.Parser
private static readonly Regex RequestInfoRegex = new Regex(@"\[.+?\]", RegexOptions.Compiled); private static readonly Regex RequestInfoRegex = new Regex(@"\[.+?\]", RegexOptions.Compiled);
private static readonly string[] Numbers = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; private static readonly string[] Numbers = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
private static Dictionary<String, String> _umlautMappings = new Dictionary<string, string>
{
{"ö", "oe"},
{"ä", "ae"},
{"ü", "ue"},
};
public static ParsedEpisodeInfo ParsePath(string path) public static ParsedEpisodeInfo ParsePath(string path)
{ {
@@ -405,8 +411,13 @@ namespace NzbDrone.Core.Parser
if (result != null) if (result != null)
{ {
var languageTitle = simpleTitle;
if (result.MovieTitle.IsNotNullOrWhiteSpace() )
{
languageTitle = simpleTitle.Replace(result.MovieTitle, "A Movie");
}
result.Language = LanguageParser.ParseLanguage(simpleTitle.Replace(result.MovieTitle, "A Movie")); result.Language = LanguageParser.ParseLanguage(languageTitle);
Logger.Debug("Language parsed: {0}", result.Language); Logger.Debug("Language parsed: {0}", result.Language);
result.Quality = QualityParser.ParseQuality(title); result.Quality = QualityParser.ParseQuality(title);
@@ -655,7 +666,7 @@ namespace NzbDrone.Core.Parser
if (long.TryParse(title, out number)) if (long.TryParse(title, out number))
return title; return title;
return NormalizeRegex.Replace(title, string.Empty).ToLower().RemoveAccent(); return ReplaceGermanUmlauts(NormalizeRegex.Replace(title, string.Empty).ToLower()).RemoveAccent();
} }
public static string NormalizeEpisodeTitle(string title) public static string NormalizeEpisodeTitle(string title)
+8 -3
View File
@@ -36,6 +36,7 @@ namespace NzbDrone.Core.Parser
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly Logger _logger; private readonly Logger _logger;
private static HashSet<ArabicRomanNumeral> _arabicRomanNumeralMappings; private static HashSet<ArabicRomanNumeral> _arabicRomanNumeralMappings;
public ParsingService(IEpisodeService episodeService, public ParsingService(IEpisodeService episodeService,
ISeriesService seriesService, ISeriesService seriesService,
@@ -178,7 +179,7 @@ namespace NzbDrone.Core.Parser
return _movieService.FindByTitle(title); return _movieService.FindByTitle(title);
} }
var movies = _movieService.FindByTitle(parsedMovieInfo.MovieTitle); var movies = _movieService.FindByTitle(parsedMovieInfo.MovieTitle, parsedMovieInfo.Year);
if (movies == null) if (movies == null)
{ {
@@ -412,7 +413,7 @@ namespace NzbDrone.Core.Parser
return false; return false;
} }
private static bool TryGetMovieBySearchCriteria(ParsedMovieInfo parsedMovieInfo, SearchCriteriaBase searchCriteria, out Movie possibleMovie) private bool TryGetMovieBySearchCriteria(ParsedMovieInfo parsedMovieInfo, SearchCriteriaBase searchCriteria, out Movie possibleMovie)
{ {
possibleMovie = null; possibleMovie = null;
List<string> possibleTitles = new List<string>(); List<string> possibleTitles = new List<string>();
@@ -424,6 +425,8 @@ namespace NzbDrone.Core.Parser
possibleTitles.Add(altTitle.CleanSeriesTitle()); possibleTitles.Add(altTitle.CleanSeriesTitle());
} }
string cleanTitle = parsedMovieInfo.MovieTitle.CleanSeriesTitle();
foreach (string title in possibleTitles) foreach (string title in possibleTitles)
{ {
if (title == parsedMovieInfo.MovieTitle.CleanSeriesTitle()) if (title == parsedMovieInfo.MovieTitle.CleanSeriesTitle())
@@ -436,12 +439,14 @@ namespace NzbDrone.Core.Parser
string arabicNumeral = numeralMapping.ArabicNumeralAsString; string arabicNumeral = numeralMapping.ArabicNumeralAsString;
string romanNumeral = numeralMapping.RomanNumeralLowerCase; string romanNumeral = numeralMapping.RomanNumeralLowerCase;
_logger.Debug(cleanTitle);
if (title.Replace(arabicNumeral, romanNumeral) == parsedMovieInfo.MovieTitle.CleanSeriesTitle()) if (title.Replace(arabicNumeral, romanNumeral) == parsedMovieInfo.MovieTitle.CleanSeriesTitle())
{ {
possibleMovie = searchCriteria.Movie; possibleMovie = searchCriteria.Movie;
} }
if (title.Replace(romanNumeral, arabicNumeral) == parsedMovieInfo.MovieTitle.CleanSeriesTitle()) if (title == parsedMovieInfo.MovieTitle.CleanSeriesTitle().Replace(arabicNumeral, romanNumeral))
{ {
possibleMovie = searchCriteria.Movie; possibleMovie = searchCriteria.Movie;
} }
+8 -2
View File
@@ -98,12 +98,18 @@ namespace NzbDrone.Core.Tv
return true; return true;
} }
return DateTime.Now >= MinimumAvailabilityDate.AddDays((double)delay); if (MinimumAvailabilityDate == DateTime.MinValue || MinimumAvailabilityDate == DateTime.MaxValue)
{
return DateTime.Now >= MinimumAvailabilityDate;
}
return DateTime.Now >= MinimumAvailabilityDate.AddDays((double)delay);
} }
public override string ToString() public override string ToString()
{ {
return string.Format("[{0}][{1}]", ImdbId, Title.NullSafe()); return string.Format("[{0}][{1} ({2})]", ImdbId, Title.NullSafe(), Year.NullSafe());
} }
} }
+12 -10
View File
@@ -238,29 +238,31 @@ namespace NzbDrone.Core.Tv
cleanTitleWithArabicNumbers = cleanTitleWithArabicNumbers.Replace(romanNumber, arabicNumber); cleanTitleWithArabicNumbers = cleanTitleWithArabicNumbers.Replace(romanNumber, arabicNumber);
} }
IEnumerable<Movie> results = Query.Where(s => s.CleanTitle == cleanTitle); Movie result = Query.Where(s => s.CleanTitle == cleanTitle).FirstWithYear(year);
if (results == null) if (result == null)
{ {
results = Query.Where(movie => movie.CleanTitle == cleanTitleWithArabicNumbers) ?? result = Query.Where(movie => movie.CleanTitle == cleanTitleWithArabicNumbers).FirstWithYear(year) ??
Query.Where(movie => movie.CleanTitle == cleanTitleWithRomanNumbers); Query.Where(movie => movie.CleanTitle == cleanTitleWithRomanNumbers).FirstWithYear(year);
if (results == null) if (result == null)
{ {
IEnumerable<Movie> movies = All(); IEnumerable<Movie> movies = All();
Func<string, string> titleCleaner = title => CoreParser.CleanSeriesTitle(title.ToLower()); Func<string, string> titleCleaner = title => CoreParser.CleanSeriesTitle(title.ToLower());
Func<IEnumerable<string>, string, bool> altTitleComparer = Func<IEnumerable<string>, string, bool> altTitleComparer =
(alternativeTitles, atitle) => (alternativeTitles, atitle) =>
alternativeTitles.Any(altTitle => altTitle == titleCleaner(atitle)); alternativeTitles.Any(altTitle => titleCleaner(altTitle) == atitle);
results = movies.Where(m => altTitleComparer(m.AlternativeTitles, cleanTitle) || result = movies.Where(m => altTitleComparer(m.AlternativeTitles, cleanTitle) ||
altTitleComparer(m.AlternativeTitles, cleanTitleWithRomanNumbers) || altTitleComparer(m.AlternativeTitles, cleanTitleWithRomanNumbers) ||
altTitleComparer(m.AlternativeTitles, cleanTitleWithArabicNumbers)); altTitleComparer(m.AlternativeTitles, cleanTitleWithArabicNumbers)).FirstWithYear(year);
} }
} }
return year.HasValue return result;
/*return year.HasValue
? results?.FirstOrDefault(movie => movie.Year == year.Value) ? results?.FirstOrDefault(movie => movie.Year == year.Value)
: results?.FirstOrDefault(); : results?.FirstOrDefault();*/
} }
public Movie FindByTmdbId(int tmdbid) public Movie FindByTmdbId(int tmdbid)
+1
View File
@@ -53,6 +53,7 @@ namespace NzbDrone.Core.Tv
private readonly IBuildFileNames _fileNameBuilder; private readonly IBuildFileNames _fileNameBuilder;
private readonly Logger _logger; private readonly Logger _logger;
public MovieService(IMovieRepository movieRepository, public MovieService(IMovieRepository movieRepository,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
ISceneMappingService sceneMappingService, ISceneMappingService sceneMappingService,
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Linq;
using System.Collections.Generic;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Datastore.Extensions;
using Marr.Data.QGen;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Parser.RomanNumerals;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using CoreParser = NzbDrone.Core.Parser.Parser;
namespace NzbDrone.Core
{
public static class QueryExtensions
{
public static Movie FirstWithYear(this SortBuilder<Movie> query, int? year)
{
return year.HasValue ? query.FirstOrDefault(movie => movie.Year == year) : query.FirstOrDefault();
}
}
public static class EnumerableExtensions
{
public static Movie FirstWithYear(this IEnumerable<Movie> query, int? year)
{
return year.HasValue ? query.FirstOrDefault(movie => movie.Year == year) : query.FirstOrDefault();
}
}
}
+93 -3
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using Mono.Unix; using Mono.Unix;
using Mono.Unix.Native; using Mono.Unix.Native;
using NLog; using NLog;
@@ -17,21 +18,50 @@ namespace NzbDrone.Mono.Disk
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DiskProvider)); private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DiskProvider));
private readonly IProcMountProvider _procMountProvider; private readonly IProcMountProvider _procMountProvider;
private readonly NzbDrone.Mono.Disk.ISymbolicLinkResolver _symLinkResolver; private readonly ISymbLinkResolver _symLinkResolver;
private readonly Logger _logger;
// Mono supports sending -1 for a uint to indicate that the owner or group should not be set // Mono supports sending -1 for a uint to indicate that the owner or group should not be set
// `unchecked((uint)-1)` and `uint.MaxValue` are the same thing. // `unchecked((uint)-1)` and `uint.MaxValue` are the same thing.
private const uint UNCHANGED_ID = uint.MaxValue; private const uint UNCHANGED_ID = uint.MaxValue;
public DiskProvider(IProcMountProvider procMountProvider, NzbDrone.Mono.Disk.ISymbolicLinkResolver symLinkResolver) public DiskProvider(IProcMountProvider procMountProvider, ISymbLinkResolver symLinkResolver, Logger logger)
{ {
_procMountProvider = procMountProvider; _procMountProvider = procMountProvider;
_symLinkResolver = symLinkResolver; _symLinkResolver = symLinkResolver;
_logger = logger;
} }
public override IMount GetMount(string path) public override IMount GetMount(string path)
{ {
path = _symLinkResolver.GetCompleteRealPath(path); if (path == null) return null;
try
{
string[] dirs;
int lastIndex;
GetPathComponents(path, out dirs, out lastIndex);
var realPath = new StringBuilder();
if (dirs.Length > 0)
{
var dir = UnixPath.IsPathRooted(path) ? "/" : "";
dir += dirs[0];
realPath.Append(GetRealPath(dir));
}
for (var i = 1; i < lastIndex; ++i)
{
realPath.Append("/").Append(dirs[i]);
var realSubPath = GetRealPath(realPath.ToString());
realPath.Remove(0, realPath.Length);
realPath.Append(realSubPath);
}
path = realPath.ToString();
}
catch (Exception ex)
{
_logger.Debug(ex, string.Format("Failed to check for symlinks in the path {0}", path));
}
return base.GetMount(path); return base.GetMount(path);
} }
@@ -219,5 +249,65 @@ namespace NzbDrone.Mono.Disk
} }
private static void GetPathComponents(string path, out string[] components, out int lastIndex)
{
var dirs = path.Split(UnixPath.DirectorySeparatorChar);
var target = 0;
for (var i = 0; i < dirs.Length; ++i)
{
if (dirs[i] == "." || dirs[i] == string.Empty)
{
continue;
}
if (dirs[i] == "..")
{
if (target != 0)
{
target--;
}
else
{
target++;
}
}
else
{
dirs[target++] = dirs[i];
}
}
components = dirs;
lastIndex = target;
}
public string GetRealPath(string path)
{
do
{
var link = UnixPath.TryReadLink(path);
if (link == null)
{
var errno = Stdlib.GetLastError();
if (errno != Errno.EINVAL)
{
_logger.Trace("Checking path {0} for symlink returned error {1}, assuming it's not a symlink.", path, errno);
}
return path;
}
if (UnixPath.IsPathRooted(link))
{
path = link;
}
else
{
path = UnixPath.GetDirectoryName(path) + UnixPath.DirectorySeparatorChar + link;
path = UnixPath.GetCanonicalPath(path);
}
} while (true);
}
} }
} }
@@ -6,23 +6,23 @@ using NLog;
namespace NzbDrone.Mono.Disk namespace NzbDrone.Mono.Disk
{ {
public interface ISymbolicLinkResolver public interface ISymbLinkResolver
{ {
string GetCompleteRealPath(string path); string GetCompletePath(string path);
} }
// Mono's own implementation doesn't handle exceptions very well. // Mono's own implementation doesn't handle exceptions very well.
// All of this code was copied from mono with minor changes. // All of this code was copied from mono with minor changes.
public class SymbolicLinkResolver : ISymbolicLinkResolver public class SymbLinkResolver : ISymbLinkResolver
{ {
private readonly Logger _logger; private readonly Logger _logger;
public SymbolicLinkResolver(Logger logger) public SymbLinkResolver(Logger logger)
{ {
_logger = logger; _logger = logger;
} }
public string GetCompleteRealPath(string path) public string GetCompletePath(string path)
{ {
if (path == null) return null; if (path == null) return null;
+59
View File
@@ -0,0 +1,59 @@
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"
break;
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;
}
});
+3
View File
@@ -9,6 +9,9 @@ module.exports = NzbDroneCell.extend({
var title = this.model.get('title'); var title = this.model.get('title');
var infoUrl = this.model.get('infoUrl'); var infoUrl = this.model.get('infoUrl');
var flags = this.model.get("indexerFlags");
if (infoUrl) { if (infoUrl) {
this.$el.html('<a href="{0}">{1}</a>'.format(infoUrl, title)); this.$el.html('<a href="{0}">{1}</a>'.format(infoUrl, title));
} else { } else {
+6
View File
@@ -9,6 +9,7 @@ var AgeCell = require('../../Release/AgeCell');
var ProtocolCell = require('../../Release/ProtocolCell'); var ProtocolCell = require('../../Release/ProtocolCell');
var PeersCell = require('../../Release/PeersCell'); var PeersCell = require('../../Release/PeersCell');
var EditionCell = require('../../Cells/EditionCell'); var EditionCell = require('../../Cells/EditionCell');
var IndexerFlagsCell = require('../../Cells/IndexerFlagsCell');
module.exports = Marionette.Layout.extend({ module.exports = Marionette.Layout.extend({
template : 'Movies/Search/ManualLayoutTemplate', template : 'Movies/Search/ManualLayoutTemplate',
@@ -39,6 +40,11 @@ module.exports = Marionette.Layout.extend({
cell : EditionCell, cell : EditionCell,
title : "Edition", title : "Edition",
}, },
{
name : 'flags',
label : 'Flags',
cell : IndexerFlagsCell,
},
{ {
name : 'indexer', name : 'indexer',
label : 'Indexer', label : 'Indexer',
+27
View File
@@ -33,6 +33,33 @@ var Collection = PagableCollection.extend({
"edition" : { "edition" : {
sortKey : "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' : { 'download' : {
sortKey : 'releaseWeight' sortKey : 'releaseWeight'
}, },
+2 -1
View File
@@ -8,6 +8,7 @@ var QualityCell = require('../Cells/QualityCell');
var ApprovalStatusCell = require('../Cells/ApprovalStatusCell'); var ApprovalStatusCell = require('../Cells/ApprovalStatusCell');
var LoadingView = require('../Shared/LoadingView'); var LoadingView = require('../Shared/LoadingView');
var EditionCell = require('../Cells/EditionCell'); var EditionCell = require('../Cells/EditionCell');
var ReleaseTitleCell = require("../Cells/ReleaseTitleCell");
module.exports = Marionette.Layout.extend({ module.exports = Marionette.Layout.extend({
template : 'Release/ReleaseLayoutTemplate', template : 'Release/ReleaseLayoutTemplate',
@@ -34,7 +35,7 @@ module.exports = Marionette.Layout.extend({
name : 'title', name : 'title',
label : 'Title', label : 'Title',
sortable : true, sortable : true,
cell : Backgrid.StringCell cell : ReleaseTitleCell
}, },
/*{ /*{
name : 'episodeNumbers', name : 'episodeNumbers',
@@ -25,6 +25,27 @@
</div> </div>
</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"> <div class="form-group advanced-setting">
<label class="col-sm-3 control-label">RSS Sync Interval</label> <label class="col-sm-3 control-label">RSS Sync Interval</label>
@@ -39,7 +60,7 @@
</div> </div>
<div class="form-group advanced-setting"> <div class="form-group advanced-setting">
<label class="col-sm-3 control-label">Whitelisted Subtitle Tags Tags</label> <label class="col-sm-3 control-label">Whitelisted Subtitle Tags</label>
<div class="col-sm-1 col-sm-push-2 help-inline"> <div class="col-sm-1 col-sm-push-2 help-inline">
<i class="icon-sonarr-form-info" title="All subtitle tags set here will not be considered hardcoded (e.g. dksub). This field is caseinsensitive. Tags must be put in singular (dksub instead of dksubs)."/> <i class="icon-sonarr-form-info" title="All subtitle tags set here will not be considered hardcoded (e.g. dksub). This field is caseinsensitive. Tags must be put in singular (dksub instead of dksubs)."/>
</div> </div>
@@ -106,7 +106,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">Filter Series Tags</label> <label class="col-sm-3 control-label">Filter Movies Tags</label>
<div class="col-sm-5"> <div class="col-sm-5">
<input type="text" class="form-control x-tags"> <input type="text" class="form-control x-tags">
+2 -2
View File
@@ -25,7 +25,7 @@ module.exports = Marionette.AppRouter.extend({
if (window.NzbDrone.Analytics && window.Piwik) { if (window.NzbDrone.Analytics && window.Piwik) {
try { try {
var piwik = window.Piwik.getTracker(window.location.protocol + '//piwik.nzbdrone.com/piwik.php', 1); var piwik = window.Piwik.getTracker(window.location.protocol + '//radarr.video/piwik/piwik.php', 1);
piwik.setReferrerUrl(''); piwik.setReferrerUrl('');
piwik.setCustomUrl('http://local' + window.location.pathname); piwik.setCustomUrl('http://local' + window.location.pathname);
piwik.setCustomVariable(1, 'version', window.NzbDrone.Version, 'page'); piwik.setCustomVariable(1, 'version', window.NzbDrone.Version, 'page');
@@ -60,7 +60,7 @@ module.exports = Marionette.AppRouter.extend({
window.localStorage.clear(); window.localStorage.clear();
Config.setValue("pageSize", pageSize); Config.setValue("pageSize", pageSize);
// Remove above when out of pre-release :) // Remove above when out of pre-release :)
this.pendingUpdate = true; this.pendingUpdate = true;
}, },
+1 -2
View File
@@ -1,5 +1,4 @@
'use strict'; 'use strict';
if(window.NzbDrone.Analytics) { if(window.NzbDrone.Analytics) {
var d = document; var d = document;
var g = d.createElement('script'); var g = d.createElement('script');
@@ -7,6 +6,6 @@ if(window.NzbDrone.Analytics) {
g.type = 'text/javascript'; g.type = 'text/javascript';
g.async = true; g.async = true;
g.defer = true; g.defer = true;
g.src = '//piwik.sonarr.tv/piwik.js'; g.src = 'https://radarr.video/piwik/piwik.js';
s.parentNode.insertBefore(g, s); s.parentNode.insertBefore(g, s);
} }
+3
View File
@@ -30,6 +30,9 @@
<!-- Windows Phone --> <!-- Windows Phone -->
<meta name="msapplication-navbutton-color" content="#272727"/> <meta name="msapplication-navbutton-color" content="#272727"/>
<!-- Piwik -->
<!-- End Piwik Code -->
<!-- Generated by http://realfavicongenerator.net/ --> <!-- Generated by http://realfavicongenerator.net/ -->
<link rel="apple-touch-icon" sizes="180x180" href="/Content/Images/favicon/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/Content/Images/favicon/apple-touch-icon.png">