2019-01-08 02:12:48 +05:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Net.Http.Formatting;
|
|
|
|
|
using System.Net.Http.Headers;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using CompatApiClient;
|
|
|
|
|
using CompatApiClient.Compression;
|
|
|
|
|
using CompatApiClient.Utils;
|
|
|
|
|
using GithubClient.POCOs;
|
2019-01-08 05:13:55 +05:00
|
|
|
|
using Microsoft.Extensions.Caching.Memory;
|
2019-01-08 02:12:48 +05:00
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using JsonContractResolver = CompatApiClient.JsonContractResolver;
|
|
|
|
|
|
|
|
|
|
namespace GithubClient
|
|
|
|
|
{
|
|
|
|
|
public class Client
|
|
|
|
|
{
|
|
|
|
|
private readonly HttpClient client;
|
|
|
|
|
private readonly MediaTypeFormatterCollection formatters;
|
|
|
|
|
|
2019-01-08 05:13:55 +05:00
|
|
|
|
private static readonly ProductInfoHeaderValue ProductInfoHeader = new ProductInfoHeaderValue("RPCS3CompatibilityBot", "2.0");
|
|
|
|
|
private static readonly TimeSpan PrStatusCacheTime = TimeSpan.FromMinutes(1);
|
|
|
|
|
private static readonly MemoryCache StatusesCache = new MemoryCache(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(1) });
|
2019-01-08 02:12:48 +05:00
|
|
|
|
|
|
|
|
|
public Client()
|
|
|
|
|
{
|
|
|
|
|
client = HttpClientFactory.Create(new CompressionMessageHandler());
|
|
|
|
|
var settings = new JsonSerializerSettings
|
|
|
|
|
{
|
|
|
|
|
ContractResolver = new JsonContractResolver(NamingStyles.Underscore),
|
|
|
|
|
NullValueHandling = NullValueHandling.Ignore
|
|
|
|
|
};
|
|
|
|
|
formatters = new MediaTypeFormatterCollection(new[] { new JsonMediaTypeFormatter { SerializerSettings = settings } });
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-10 23:54:33 +05:00
|
|
|
|
public async Task<PrInfo> GetPrInfoAsync(int pr, CancellationToken cancellationToken)
|
2019-01-08 02:12:48 +05:00
|
|
|
|
{
|
2019-01-10 23:54:33 +05:00
|
|
|
|
if (StatusesCache.TryGetValue(pr, out PrInfo result))
|
|
|
|
|
{
|
|
|
|
|
ApiConfig.Log.Debug($"Returned {nameof(PrInfo)} for {pr} from cache");
|
2019-01-08 02:12:48 +05:00
|
|
|
|
return result;
|
2019-01-10 23:54:33 +05:00
|
|
|
|
}
|
2019-01-08 02:12:48 +05:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var message = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/RPCS3/rpcs3/pulls/" + pr))
|
|
|
|
|
{
|
2019-01-08 05:13:55 +05:00
|
|
|
|
message.Headers.UserAgent.Add(ProductInfoHeader);
|
2019-01-08 02:12:48 +05:00
|
|
|
|
using (var response = await client.SendAsync(message, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
|
|
|
|
|
result = await response.Content.ReadAsAsync<PrInfo>(formatters, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
ConsoleLogger.PrintError(e, response);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
ApiConfig.Log.Error(e);
|
|
|
|
|
}
|
|
|
|
|
if (result == null)
|
|
|
|
|
{
|
2019-01-10 23:54:33 +05:00
|
|
|
|
ApiConfig.Log.Debug($"Failed to get {nameof(PrInfo)}, returning empty result");
|
|
|
|
|
return new PrInfo { Number = pr };
|
2019-01-08 02:12:48 +05:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-10 23:54:33 +05:00
|
|
|
|
StatusesCache.Set(pr, result, PrStatusCacheTime);
|
|
|
|
|
ApiConfig.Log.Debug($"Cached {nameof(PrInfo)} for {pr} for {PrStatusCacheTime}");
|
|
|
|
|
return result;
|
2019-01-08 02:12:48 +05:00
|
|
|
|
}
|
2019-01-08 05:13:55 +05:00
|
|
|
|
|
2019-01-08 07:04:23 +05:00
|
|
|
|
public async Task<List<PrInfo>> GetOpenPrsAsync(CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
var requestUri = "https://api.github.com/repos/RPCS3/rpcs3/pulls?state=open";
|
2019-01-08 18:56:56 +05:00
|
|
|
|
if (StatusesCache.TryGetValue(requestUri, out List<PrInfo> result))
|
2019-01-10 23:54:33 +05:00
|
|
|
|
{
|
|
|
|
|
ApiConfig.Log.Debug("Returned list of opened PRs from cache");
|
2019-01-08 07:04:23 +05:00
|
|
|
|
return result;
|
2019-01-10 23:54:33 +05:00
|
|
|
|
}
|
2019-01-08 07:04:23 +05:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var message = new HttpRequestMessage(HttpMethod.Get, requestUri))
|
|
|
|
|
{
|
|
|
|
|
message.Headers.UserAgent.Add(ProductInfoHeader);
|
|
|
|
|
using (var response = await client.SendAsync(message, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
|
|
|
|
|
result = await response.Content.ReadAsAsync<List<PrInfo>>(formatters, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
ConsoleLogger.PrintError(e, response);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
ApiConfig.Log.Error(e);
|
|
|
|
|
}
|
|
|
|
|
if (result != null)
|
2019-01-10 23:54:33 +05:00
|
|
|
|
{
|
2019-01-08 07:04:23 +05:00
|
|
|
|
StatusesCache.Set(requestUri, result, PrStatusCacheTime);
|
2019-01-10 23:54:33 +05:00
|
|
|
|
ApiConfig.Log.Debug($"Cached list of open PRs for {PrStatusCacheTime}");
|
|
|
|
|
}
|
2019-01-08 07:04:23 +05:00
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-08 05:13:55 +05:00
|
|
|
|
public async Task<List<StatusInfo>> GetStatusesAsync(string statusesUrl, CancellationToken cancellationToken)
|
|
|
|
|
{
|
2019-01-08 18:56:56 +05:00
|
|
|
|
if (StatusesCache.TryGetValue(statusesUrl, out List<StatusInfo> result))
|
2019-01-10 23:54:33 +05:00
|
|
|
|
{
|
|
|
|
|
ApiConfig.Log.Debug($"Returned cached item for {statusesUrl}");
|
2019-01-08 05:13:55 +05:00
|
|
|
|
return result;
|
2019-01-10 23:54:33 +05:00
|
|
|
|
}
|
2019-01-08 05:13:55 +05:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var message = new HttpRequestMessage(HttpMethod.Get, statusesUrl))
|
|
|
|
|
{
|
|
|
|
|
message.Headers.UserAgent.Add(ProductInfoHeader);
|
|
|
|
|
using (var response = await client.SendAsync(message, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
|
|
|
|
|
result = await response.Content.ReadAsAsync<List<StatusInfo>>(formatters, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
ConsoleLogger.PrintError(e, response);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
ApiConfig.Log.Error(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result != null)
|
2019-01-10 23:54:33 +05:00
|
|
|
|
{
|
2019-01-08 05:13:55 +05:00
|
|
|
|
StatusesCache.Set(statusesUrl, result, PrStatusCacheTime);
|
2019-01-10 23:54:33 +05:00
|
|
|
|
ApiConfig.Log.Debug($"Cached item for {statusesUrl} for {PrStatusCacheTime}");
|
|
|
|
|
}
|
2019-01-08 05:13:55 +05:00
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-01-08 02:12:48 +05:00
|
|
|
|
}
|
|
|
|
|
}
|