mirror of
https://github.com/Sonarr/Sonarr
synced 2025-03-03 18:26:42 +00:00
Fixed issue with nzbs.org search where title contained brackets
This commit is contained in:
parent
861026f743
commit
f2b091dcd2
3 changed files with 57 additions and 40 deletions
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.ServiceModel.Syndication;
|
using System.ServiceModel.Syndication;
|
||||||
|
@ -159,8 +160,9 @@ namespace NzbDrone.Core.Test
|
||||||
ExceptionVerification.IgnoreWarns();
|
ExceptionVerification.IgnoreWarns();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCase("simpsons", 21, 23)]
|
||||||
public void nzbsorg_search_returns_valid_results()
|
[TestCase("Hawaii Five-0 (2010)", 1, 5)]
|
||||||
|
public void nzbsorg_search_returns_valid_results(string title, int season, int episode)
|
||||||
{
|
{
|
||||||
var mocker = new AutoMoqer();
|
var mocker = new AutoMoqer();
|
||||||
|
|
||||||
|
@ -174,16 +176,16 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
mocker.Resolve<HttpProvider>();
|
mocker.Resolve<HttpProvider>();
|
||||||
|
|
||||||
var result = mocker.Resolve<NzbsOrg>().FetchEpisode("Simpsons", 21, 23);
|
var result = mocker.Resolve<NzbsOrg>().FetchEpisode(title, season, episode);
|
||||||
|
|
||||||
result.Should().NotBeEmpty();
|
result.Should().NotBeEmpty();
|
||||||
result.Should().OnlyContain(r => r.CleanTitle == "simpsons");
|
result.Should().OnlyContain(r => r.CleanTitle == Parser.NormalizeTitle(title));
|
||||||
result.Should().OnlyContain(r => r.SeasonNumber == 21);
|
result.Should().OnlyContain(r => r.SeasonNumber == season);
|
||||||
result.Should().OnlyContain(r => r.EpisodeNumbers.Contains(23));
|
result.Should().OnlyContain(r => r.EpisodeNumbers.Contains(episode));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("simpsons", 21, 23)]
|
[TestCase("simpsons", 21, 23)]
|
||||||
[TestCase("Hawaii Five-0 2010", 1, 5)]
|
[TestCase("Hawaii Five-0 (2010)", 1, 5)]
|
||||||
public void newzbin_search_returns_valid_results(string title, int season, int episode)
|
public void newzbin_search_returns_valid_results(string title, int season, int episode)
|
||||||
{
|
{
|
||||||
var mocker = new AutoMoqer();
|
var mocker = new AutoMoqer();
|
||||||
|
@ -275,5 +277,20 @@ namespace NzbDrone.Core.Test
|
||||||
result.Should().OnlyContain(r => r.SeasonNumber == 1);
|
result.Should().OnlyContain(r => r.SeasonNumber == 1);
|
||||||
result.Should().OnlyContain(r => r.EpisodeNumbers.Contains(19));
|
result.Should().OnlyContain(r => r.EpisodeNumbers.Contains(19));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestCase("hawaii five-0 (2010)", "hawaii+five+0+2010")]
|
||||||
|
[TestCase("this& that", "this+that")]
|
||||||
|
[TestCase("this& that", "this+that")]
|
||||||
|
public void get_query_title(string raw, string clean)
|
||||||
|
{
|
||||||
|
var result = IndexerBase.GetQueryTitle(raw);
|
||||||
|
|
||||||
|
result.Should().Be(clean);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.ServiceModel.Syndication;
|
using System.ServiceModel.Syndication;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -16,6 +17,8 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
private readonly HttpProvider _httpProvider;
|
private readonly HttpProvider _httpProvider;
|
||||||
protected readonly ConfigProvider _configProvider;
|
protected readonly ConfigProvider _configProvider;
|
||||||
|
|
||||||
|
private static readonly Regex TitleSearchRegex = new Regex(@"[\W]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IndexerBase(HttpProvider httpProvider, ConfigProvider configProvider)
|
protected IndexerBase(HttpProvider httpProvider, ConfigProvider configProvider)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +61,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
/// <param name="episodeNumber">The episode number.</param>
|
/// <param name="episodeNumber">The episode number.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected abstract IList<String> GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);
|
protected abstract IList<String> GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);
|
||||||
|
public abstract IList<String> GetSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This method can be overwritten to provide indexer specific info parsing
|
/// This method can be overwritten to provide indexer specific info parsing
|
||||||
|
@ -102,7 +106,7 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
|
|
||||||
var result = new List<EpisodeParseResult>();
|
var result = new List<EpisodeParseResult>();
|
||||||
|
|
||||||
var searchUrls = GetSearchUrls(HttpUtility.UrlDecode(seriesTitle), seasonNumber, episodeNumber);
|
var searchUrls = GetSearchUrls(GetQueryTitle(seriesTitle), seasonNumber, episodeNumber);
|
||||||
|
|
||||||
foreach (var url in searchUrls)
|
foreach (var url in searchUrls)
|
||||||
{
|
{
|
||||||
|
@ -165,9 +169,13 @@ namespace NzbDrone.Core.Providers.Indexer
|
||||||
return CustomParser(item, episodeParseResult);
|
return CustomParser(item, episodeParseResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static string GetQueryTitle(string title)
|
public static string GetQueryTitle(string title)
|
||||||
{
|
{
|
||||||
return title.Trim().Replace(' ', '+');
|
var cleanTitle = TitleSearchRegex.Replace(title, "+").Trim('+', ' ');
|
||||||
|
|
||||||
|
//remove any repeating +s
|
||||||
|
cleanTitle = Regex.Replace(cleanTitle, @"\+{1,100}", "+");
|
||||||
|
return cleanTitle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,33 +1,26 @@
|
||||||
@using NzbDrone.Web.Helpers;
|
@using NzbDrone.Web.Helpers;
|
||||||
@model NzbDrone.Web.Models.QualityModel
|
@model NzbDrone.Web.Models.QualityModel
|
||||||
|
|
||||||
@section HeaderContent{
|
@section HeaderContent{
|
||||||
<link rel="stylesheet" type="text/css" href="../../Content/Settings.css" />
|
<link rel="stylesheet" type="text/css" href="/Content/Settings.css" />
|
||||||
<link href="../../Content/QualitySettings.css" rel="stylesheet" type="text/css" />
|
<link href="/Content/QualitySettings.css" rel="stylesheet" type="text/css" />
|
||||||
|
|
||||||
<script src="../../Scripts/jquery-1.6.1.js" type="text/javascript"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
</script>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@section TitleContent{
|
@section TitleContent{
|
||||||
Settings
|
Settings
|
||||||
}
|
}
|
||||||
|
|
||||||
@section ActionMenu{
|
@section ActionMenu{
|
||||||
@{Html.RenderPartial("SubMenu");}
|
@{Html.RenderPartial("SubMenu");}
|
||||||
}
|
}
|
||||||
|
|
||||||
@section MainContent{
|
@section MainContent{
|
||||||
<div id="stylized">
|
<div id="stylized">
|
||||||
@using (Html.BeginForm("SaveQuality", "Settings", FormMethod.Post, new { id = "form", name = "form" }))
|
@using (Html.BeginForm("SaveQuality", "Settings", FormMethod.Post, new { id = "form", name = "form" }))
|
||||||
{
|
{
|
||||||
<div id="top" class="settingsForm clearfix">
|
<div id="top" class="settingsForm clearfix">
|
||||||
<h1>Quality</h1>
|
<h1>
|
||||||
<p></p>
|
Quality</h1>
|
||||||
|
<p>
|
||||||
|
</p>
|
||||||
<label class="labelClass">@Html.LabelFor(m => m.DefaultQualityProfileId)
|
<label class="labelClass">@Html.LabelFor(m => m.DefaultQualityProfileId)
|
||||||
<span class="small">@Html.DescriptionFor(m => m.DefaultQualityProfileId)</span>
|
<span class="small">@Html.DescriptionFor(m => m.DefaultQualityProfileId)</span>
|
||||||
</label>
|
</label>
|
||||||
@Html.DropDownListFor(m => m.DefaultQualityProfileId, Model.QualityProfileSelectList, new { @class = "inputClass" })
|
@Html.DropDownListFor(m => m.DefaultQualityProfileId, Model.QualityProfileSelectList, new { @class = "inputClass" })
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,9 +29,9 @@
|
||||||
<div id="profileContainer">
|
<div id="profileContainer">
|
||||||
<div id="profileHeader">
|
<div id="profileHeader">
|
||||||
<a id="addItem" href="@Url.Action("AddProfile", "Settings")">
|
<a id="addItem" href="@Url.Action("AddProfile", "Settings")">
|
||||||
<img src="../../Content/Images/Plus.png" alt="Add New Profile" width="20px" height="20px" /> Add New Profile</a>
|
<img src="../../Content/Images/Plus.png" alt="Add New Profile" width="20px" height="20px" />
|
||||||
|
Add New Profile</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="profiles" class="clearfix">
|
<div id="profiles" class="clearfix">
|
||||||
@foreach (var item in Model.Profiles)
|
@foreach (var item in Model.Profiles)
|
||||||
{
|
{
|
||||||
|
@ -46,21 +39,20 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="submit" id="save_button">
|
||||||
<button type="submit" id="save_button" >Save</button><img src="../../Content/Images/ajax-loader.gif" alt="Loader" id="saveAjax"/>
|
Save</button><img src="../../Content/Images/ajax-loader.gif" alt="Loader" id="saveAjax" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
<div id="result" class="hiddenResult">
|
||||||
<div id="result" class="hiddenResult"></div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@section Scripts{
|
@section Scripts{
|
||||||
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
|
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
|
||||||
<script src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
|
<script src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js"
|
||||||
|
type="text/javascript"></script>
|
||||||
<script src="../../Scripts/settingsForm.js" type="text/javascript"></script>
|
<script src="../../Scripts/settingsForm.js" type="text/javascript"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$("#addItem").live('click', function () {
|
$("#addItem").live('click', function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -117,7 +109,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProfileId(obj) {
|
function getProfileId(obj) {
|
||||||
var parentProfileSection = $(obj).parents('.profileSection');
|
var parentProfileSection = $(obj).parents('.profileSection');
|
||||||
return parentProfileSection.children('.qualityProfileId').val();
|
return parentProfileSection.children('.qualityProfileId').val();
|
||||||
|
|
Loading…
Reference in a new issue