parent
3a287bf7e7
commit
2c1d3339d0
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public class HttpException : Exception
|
||||
{
|
||||
public HttpRequest Request { get; private set; }
|
||||
public HttpResponse Response { get; private set; }
|
||||
|
||||
public HttpException(HttpRequest request, HttpResponse response)
|
||||
: base(string.Format("HTTP request failed: [{0}] [{1}] at [{2}]", (int)response.StatusCode, request.Method, request.Url.ToString()))
|
||||
{
|
||||
Request = request;
|
||||
Response = response;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Response != null)
|
||||
{
|
||||
return base.ToString() + Environment.NewLine + Response.Content;
|
||||
}
|
||||
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public class HttpHeader : Dictionary<string, object>
|
||||
{
|
||||
public HttpHeader(NameValueCollection headers)
|
||||
{
|
||||
foreach (var key in headers.AllKeys)
|
||||
{
|
||||
this[key] = headers[key];
|
||||
}
|
||||
}
|
||||
|
||||
public HttpHeader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public long? ContentLength
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ContainsKey("Content-Length"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Convert.ToInt64(this["Content-Length"]);
|
||||
}
|
||||
set
|
||||
{
|
||||
this["Content-Length"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ContentType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ContainsKey("Content-Type"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this["Content-Type"].ToString();
|
||||
}
|
||||
set
|
||||
{
|
||||
this["Content-Type"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Accept
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ContainsKey("Accept"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this["Accept"].ToString();
|
||||
}
|
||||
set
|
||||
{
|
||||
this["Accept"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public enum HttpMethod
|
||||
{
|
||||
GET,
|
||||
PUT,
|
||||
POST,
|
||||
HEAD,
|
||||
DELETE,
|
||||
PATCH,
|
||||
OPTIONS
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public class HttpRequest
|
||||
{
|
||||
|
||||
private readonly Dictionary<string, string> _segments;
|
||||
|
||||
public HttpRequest(string url)
|
||||
{
|
||||
UriBuilder = new UriBuilder(url);
|
||||
Headers = new HttpHeader();
|
||||
_segments = new Dictionary<string, string>();
|
||||
|
||||
Headers.Accept = "application/json";
|
||||
}
|
||||
|
||||
public UriBuilder UriBuilder { get; private set; }
|
||||
|
||||
public Uri Url
|
||||
{
|
||||
get
|
||||
{
|
||||
var uri = UriBuilder.Uri.ToString();
|
||||
|
||||
foreach (var segment in _segments)
|
||||
{
|
||||
uri = uri.Replace(segment.Key, segment.Value);
|
||||
}
|
||||
|
||||
return new Uri(uri);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpMethod Method { get; set; }
|
||||
public HttpHeader Headers { get; set; }
|
||||
public string Body { get; set; }
|
||||
public NetworkCredential NetworkCredential { get; set; }
|
||||
public bool SuppressHttpError { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Body == null)
|
||||
{
|
||||
return string.Format("Req: [{0}] {1}", Method, Url);
|
||||
}
|
||||
|
||||
return string.Format("Req: [{0}] {1} {2} {3}", Method, Url, Environment.NewLine, Body);
|
||||
}
|
||||
|
||||
public void AddSegment(string segment, string value)
|
||||
{
|
||||
var key = "{" + segment + "}";
|
||||
|
||||
if (!UriBuilder.Uri.ToString().Contains(key))
|
||||
{
|
||||
throw new InvalidOperationException("Segment " + key +" is not defined in Uri");
|
||||
}
|
||||
|
||||
_segments.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public class HttpRequestBuilder
|
||||
{
|
||||
public Uri BaseUri { get; private set; }
|
||||
public bool SupressHttpError { get; set; }
|
||||
public NetworkCredential NetworkCredential { get; set; }
|
||||
|
||||
public Action<HttpRequest> PostProcess { get; set; }
|
||||
|
||||
public HttpRequestBuilder(string baseUri)
|
||||
{
|
||||
BaseUri = new Uri(baseUri);
|
||||
}
|
||||
|
||||
public virtual HttpRequest Build(string path)
|
||||
{
|
||||
if (BaseUri.ToString().EndsWith("/"))
|
||||
{
|
||||
path = path.TrimStart('/');
|
||||
}
|
||||
|
||||
var request = new HttpRequest(BaseUri + path)
|
||||
{
|
||||
SuppressHttpError = SupressHttpError,
|
||||
NetworkCredential = NetworkCredential
|
||||
};
|
||||
|
||||
if (PostProcess != null)
|
||||
{
|
||||
PostProcess(request);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using NzbDrone.Common.Serializer;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public class HttpResponse
|
||||
{
|
||||
public HttpResponse(HttpRequest request, HttpHeader headers, string content, HttpStatusCode statusCode)
|
||||
{
|
||||
Request = request;
|
||||
Headers = headers;
|
||||
Content = content;
|
||||
StatusCode = statusCode;
|
||||
}
|
||||
|
||||
public HttpRequest Request { get; private set; }
|
||||
public HttpHeader Headers { get; private set; }
|
||||
public HttpStatusCode StatusCode { get; private set; }
|
||||
public string Content { get; private set; }
|
||||
|
||||
public bool HasHttpError
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)StatusCode >= 400;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var result = string.Format("Res: [{0}] {1} : {2}.{3}", Request.Method, Request.Url, (int)StatusCode, StatusCode);
|
||||
|
||||
if (HasHttpError)
|
||||
{
|
||||
result += Environment.NewLine + Content;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Stream GetStream()
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var writer = new StreamWriter(stream);
|
||||
writer.Write(Content);
|
||||
writer.Flush();
|
||||
stream.Position = 0;
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class HttpResponse<T> : HttpResponse where T : new()
|
||||
{
|
||||
public HttpResponse(HttpResponse response)
|
||||
: base(response.Request, response.Headers, response.Content, response.StatusCode)
|
||||
{
|
||||
Resource = Json.Deserialize<T>(response.Content);
|
||||
}
|
||||
|
||||
public T Resource { get; private set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace NzbDrone.Common.Http
|
||||
{
|
||||
public static class UriExtensions
|
||||
{
|
||||
public static void SetQueryParam(this UriBuilder uriBuilder, string key, object value)
|
||||
{
|
||||
var query = uriBuilder.Query;
|
||||
|
||||
if (query.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
query += "&";
|
||||
}
|
||||
|
||||
uriBuilder.Query = query.Trim('?') + (key + "=" + value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,53 +1,33 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using FluentAssertions;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.Categories;
|
||||
|
||||
namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
[IntegrationTest]
|
||||
public class SceneMappingProxyFixture : CoreTest<SceneMappingProxy>
|
||||
{
|
||||
private const string SCENE_MAPPING_URL = "http://services.nzbdrone.com/v1/SceneMapping";
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
UseRealHttp();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void fetch_should_return_list_of_mappings()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(SCENE_MAPPING_URL))
|
||||
.Returns(ReadAllText("Files", "SceneMappings.json"));
|
||||
|
||||
var mappings = Subject.Fetch();
|
||||
|
||||
mappings.Should().NotBeEmpty();
|
||||
|
||||
mappings.Should().NotContain(c => String.IsNullOrWhiteSpace(c.SearchTerm));
|
||||
mappings.Should().NotContain(c => String.IsNullOrWhiteSpace(c.Title));
|
||||
mappings.Should().NotContain(c => c.TvdbId == 0);
|
||||
mappings.Should().NotContain(c => c.SearchTerm.IsNullOrWhiteSpace());
|
||||
mappings.Should().NotContain(c => c.Title.IsNullOrWhiteSpace());
|
||||
mappings.Should().Contain(c => c.SeasonNumber > 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_on_server_error()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(SCENE_MAPPING_URL))
|
||||
.Throws(new WebException());
|
||||
Assert.Throws<WebException>(() => Subject.Fetch());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_on_bad_json()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(SCENE_MAPPING_URL))
|
||||
.Returns("bad json");
|
||||
Assert.Throws<JsonReaderException>(() => Subject.Fetch());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
[
|
||||
{
|
||||
"title": "Adventure Time",
|
||||
"searchTitle": "Adventure Time",
|
||||
"season": -1,
|
||||
"tvdbId": 152831
|
||||
},
|
||||
{
|
||||
"title": "Americas Funniest Home Videos",
|
||||
"searchTitle": "Americas Funniest Home Videos",
|
||||
"season": -1,
|
||||
"tvdbId": 76235
|
||||
},
|
||||
{
|
||||
"title": "Antiques Roadshow UK",
|
||||
"searchTitle": "Antiques Roadshow UK",
|
||||
"season": -1,
|
||||
"tvdbId": 83774
|
||||
},
|
||||
{
|
||||
"title": "Aqua Something You Know Whatever",
|
||||
"searchTitle": "Aqua Something You Know Whatever",
|
||||
"season": 9,
|
||||
"tvdbId": 77120
|
||||
},
|
||||
{
|
||||
"title": "Aqua Teen Hunger Force",
|
||||
"searchTitle": "Aqua Teen Hunger Force",
|
||||
"season": -1,
|
||||
"tvdbId": 77120
|
||||
}
|
||||
]
|
@ -0,0 +1,7 @@
|
||||
namespace NzbDrone.Core.DataAugmentation.DailySeries
|
||||
{
|
||||
public class DailySeries
|
||||
{
|
||||
public int TvdbId { get; set; }
|
||||
}
|
||||
}
|
@ -1,44 +1,30 @@
|
||||
using NzbDrone.Core.Tv;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Cache;
|
||||
|
||||
namespace NzbDrone.Core.DataAugmentation.DailySeries
|
||||
{
|
||||
public interface IDailySeriesService
|
||||
{
|
||||
void UpdateDailySeries();
|
||||
bool IsDailySeries(int tvdbid);
|
||||
}
|
||||
|
||||
public class DailySeriesService : IDailySeriesService
|
||||
{
|
||||
//TODO: add timer command
|
||||
|
||||
private readonly IDailySeriesDataProxy _proxy;
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly ICached<List<int>> _cache;
|
||||
|
||||
public DailySeriesService(IDailySeriesDataProxy proxy, ISeriesService seriesService)
|
||||
public DailySeriesService(IDailySeriesDataProxy proxy, ICacheManager cacheManager)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_seriesService = seriesService;
|
||||
}
|
||||
|
||||
public void UpdateDailySeries()
|
||||
{
|
||||
var dailySeries = _proxy.GetDailySeriesIds();
|
||||
|
||||
foreach (var tvdbId in dailySeries)
|
||||
{
|
||||
var series = _seriesService.FindByTvdbId(tvdbId);
|
||||
|
||||
if (series != null)
|
||||
{
|
||||
_seriesService.SetSeriesType(series.Id, SeriesTypes.Daily);
|
||||
}
|
||||
}
|
||||
_cache = cacheManager.GetCache<List<int>>(GetType());
|
||||
}
|
||||
|
||||
public bool IsDailySeries(int tvdbid)
|
||||
{
|
||||
return _proxy.IsDailySeries(tvdbid);
|
||||
var dailySeries = _cache.Get("all", () => _proxy.GetDailySeriesIds().ToList(), TimeSpan.FromHours(1));
|
||||
return dailySeries.Any(i => i == tvdbid);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue