update GitHubClient, ditch json.net, fix compiler complaints

This commit is contained in:
13xforever
2020-11-11 11:51:38 +05:00
parent 1acda9420c
commit 80384916df
8 changed files with 79 additions and 79 deletions

View File

@@ -2,8 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Json;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using CompatApiClient;
@@ -11,15 +12,13 @@ using CompatApiClient.Compression;
using CompatApiClient.Utils;
using GithubClient.POCOs;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using JsonContractResolver = CompatApiClient.JsonContractResolver;
namespace GithubClient
{
public class Client
{
private readonly HttpClient client;
private readonly MediaTypeFormatterCollection formatters;
private readonly JsonSerializerOptions jsonOptions;
private static readonly TimeSpan PrStatusCacheTime = TimeSpan.FromMinutes(3);
private static readonly TimeSpan IssueStatusCacheTime = TimeSpan.FromMinutes(30);
@@ -33,17 +32,17 @@ namespace GithubClient
public Client()
{
client = HttpClientFactory.Create(new CompressionMessageHandler());
var settings = new JsonSerializerSettings
jsonOptions = new JsonSerializerOptions
{
ContractResolver = new JsonContractResolver(NamingStyles.Underscore),
NullValueHandling = NullValueHandling.Ignore
PropertyNamingPolicy = SpecialJsonNamingPolicy.SnakeCase,
IgnoreNullValues = true,
IncludeFields = true,
};
formatters = new MediaTypeFormatterCollection(new[] { new JsonMediaTypeFormatter { SerializerSettings = settings } });
}
public async Task<PrInfo> GetPrInfoAsync(int pr, CancellationToken cancellationToken)
public async Task<PrInfo?> GetPrInfoAsync(int pr, CancellationToken cancellationToken)
{
if (StatusesCache.TryGetValue(pr, out PrInfo result))
if (StatusesCache.TryGetValue(pr, out PrInfo? result))
{
ApiConfig.Log.Debug($"Returned {nameof(PrInfo)} for {pr} from cache");
return result;
@@ -58,7 +57,7 @@ namespace GithubClient
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
UpdateRateLimitStats(response.Headers);
result = await response.Content.ReadAsAsync<PrInfo>(formatters, cancellationToken).ConfigureAwait(false);
result = await response.Content.ReadFromJsonAsync<PrInfo>(jsonOptions, cancellationToken).ConfigureAwait(false);
}
catch (Exception e)
{
@@ -80,9 +79,9 @@ namespace GithubClient
return result;
}
public async Task<IssueInfo> GetIssueInfoAsync(int issue, CancellationToken cancellationToken)
public async Task<IssueInfo?> GetIssueInfoAsync(int issue, CancellationToken cancellationToken)
{
if (IssuesCache.TryGetValue(issue, out IssueInfo result))
if (IssuesCache.TryGetValue(issue, out IssueInfo? result))
{
ApiConfig.Log.Debug($"Returned {nameof(IssueInfo)} for {issue} from cache");
return result;
@@ -97,7 +96,7 @@ namespace GithubClient
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
UpdateRateLimitStats(response.Headers);
result = await response.Content.ReadAsAsync<IssueInfo>(formatters, cancellationToken).ConfigureAwait(false);
result = await response.Content.ReadFromJsonAsync<IssueInfo>(jsonOptions, cancellationToken).ConfigureAwait(false);
}
catch (Exception e)
{
@@ -119,13 +118,13 @@ namespace GithubClient
return result;
}
public Task<List<PrInfo>> GetOpenPrsAsync(CancellationToken cancellationToken) => GetPrsWithStatusAsync("open", cancellationToken);
public Task<List<PrInfo>> GetClosedPrsAsync(CancellationToken cancellationToken) => GetPrsWithStatusAsync("closed&sort=updated&direction=desc", cancellationToken);
public Task<List<PrInfo>?> GetOpenPrsAsync(CancellationToken cancellationToken) => GetPrsWithStatusAsync("open", cancellationToken);
public Task<List<PrInfo>?> GetClosedPrsAsync(CancellationToken cancellationToken) => GetPrsWithStatusAsync("closed&sort=updated&direction=desc", cancellationToken);
private async Task<List<PrInfo>> GetPrsWithStatusAsync(string status, CancellationToken cancellationToken)
private async Task<List<PrInfo>?> GetPrsWithStatusAsync(string status, CancellationToken cancellationToken)
{
var requestUri = "https://api.github.com/repos/RPCS3/rpcs3/pulls?state=" + status;
if (StatusesCache.TryGetValue(requestUri, out List<PrInfo> result))
if (StatusesCache.TryGetValue(requestUri, out List<PrInfo>? result))
{
ApiConfig.Log.Debug("Returned list of opened PRs from cache");
return result;
@@ -140,7 +139,7 @@ namespace GithubClient
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
UpdateRateLimitStats(response.Headers);
result = await response.Content.ReadAsAsync<List<PrInfo>>(formatters, cancellationToken).ConfigureAwait(false);
result = await response.Content.ReadFromJsonAsync<List<PrInfo>>(jsonOptions, cancellationToken).ConfigureAwait(false);
}
catch (Exception e)
{
@@ -161,9 +160,9 @@ namespace GithubClient
return result;
}
public async Task<List<StatusInfo>> GetStatusesAsync(string statusesUrl, CancellationToken cancellationToken)
public async Task<List<StatusInfo>?> GetStatusesAsync(string statusesUrl, CancellationToken cancellationToken)
{
if (StatusesCache.TryGetValue(statusesUrl, out List<StatusInfo> result))
if (StatusesCache.TryGetValue(statusesUrl, out List<StatusInfo>? result))
{
ApiConfig.Log.Debug($"Returned cached item for {statusesUrl}");
return result;
@@ -178,7 +177,7 @@ namespace GithubClient
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
UpdateRateLimitStats(response.Headers);
result = await response.Content.ReadAsAsync<List<StatusInfo>>(formatters, cancellationToken).ConfigureAwait(false);
result = await response.Content.ReadFromJsonAsync<List<StatusInfo>>(jsonOptions, cancellationToken).ConfigureAwait(false);
}
catch (Exception e)
{
@@ -201,17 +200,17 @@ namespace GithubClient
private static void UpdateRateLimitStats(HttpResponseHeaders headers)
{
if (headers.TryGetValues("X-RateLimit-Limit", out var rateLimitValues)
&& rateLimitValues?.FirstOrDefault() is string limitValue
&& rateLimitValues.FirstOrDefault() is string limitValue
&& int.TryParse(limitValue, out var limit)
&& limit > 0)
RateLimit = limit;
if (headers.TryGetValues("X-RateLimit-Remaining", out var rateLimitRemainingValues)
&& rateLimitRemainingValues?.FirstOrDefault() is string remainingValue
&& rateLimitRemainingValues.FirstOrDefault() is string remainingValue
&& int.TryParse(remainingValue, out var remaining)
&& remaining > 0)
RateLimitRemaining = remaining;
if (headers.TryGetValues("X-RateLimit-Reset", out var rateLimitResetValues)
&& rateLimitResetValues?.FirstOrDefault() is string resetValue
&& rateLimitResetValues.FirstOrDefault() is string resetValue
&& long.TryParse(resetValue, out var resetSeconds)
&& resetSeconds > 0)
RateLimitResetTime = DateTimeOffset.FromUnixTimeSeconds(resetSeconds).UtcDateTime;

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View File

@@ -4,61 +4,61 @@ using System.Diagnostics;
namespace GithubClient.POCOs
{
[DebuggerDisplay("{Body}", Name = "#{Number}")]
public class PrInfo
public sealed class PrInfo
{
public string HtmlUrl;
public string? HtmlUrl;
public int Number;
public string State;
public string Title;
public GithubUser User;
public string Body;
public string? State;
public string? Title;
public GithubUser? User;
public string? Body;
public DateTime CreatedAt;
public DateTime? UpdatedAt;
public DateTime? ClosedAt;
public DateTime? MergedAt;
public string MergeCommitSha;
public string StatusesUrl;
public RefInfo Head;
public RefInfo Base;
public string? MergeCommitSha;
public string? StatusesUrl;
public RefInfo? Head;
public RefInfo? Base;
public int Additions;
public int Deletions;
public int ChangedFiles;
public string Message;
public string? Message;
}
public class IssueInfo
public sealed class IssueInfo
{
public string HtmlUrl;
public string? HtmlUrl;
public int Number;
public string State;
public string Title;
public GithubUser User;
public string? State;
public string? Title;
public GithubUser? User;
public DateTime CreatedAt;
public DateTime? UpdatedAt;
public DateTime? ClosedAt;
public DateTime? MergedAt;
public string Body;
public PullRequestReference PullRequest;
public string? Body;
public PullRequestReference? PullRequest;
}
public class GithubUser
public sealed class GithubUser
{
public string Login;
public string? Login;
}
public class PullRequestReference
public sealed class PullRequestReference
{
public string Url;
public string HtmlUrl;
public string DiffUrl;
public string PatchUrl;
public string? Url;
public string? HtmlUrl;
public string? DiffUrl;
public string? PatchUrl;
}
public class RefInfo
public sealed class RefInfo
{
public string Label;
public string Ref;
public GithubUser User;
public string Sha;
public string? Label;
public string? Ref;
public GithubUser? User;
public string? Sha;
}
}

View File

@@ -2,12 +2,12 @@
namespace GithubClient.POCOs
{
public class StatusInfo
public sealed class StatusInfo
{
public string State; // success
public string Description;
public string TargetUrl;
public string Context; // continuous-integration/appveyor/pr
public string? State; // success
public string? Description;
public string? TargetUrl;
public string? Context; // continuous-integration/appveyor/pr
public DateTime? CreatedAt;
public DateTime? UpdatedAt;
}

View File

@@ -3,7 +3,7 @@ using System.Text.Json.Serialization;
namespace IrdLibraryClient.POCOs
{
public class SearchResult
public sealed class SearchResult
{
public List<SearchResultItem>? Data;
public int Draw;
@@ -15,7 +15,7 @@ namespace IrdLibraryClient.POCOs
public int RecordsTotal;
}
public class SearchResultItem
public sealed class SearchResultItem
{
public string? Id; // product code
public string? AppVersion;

View File

@@ -61,7 +61,7 @@ namespace PsnClient
xmlFormatters = new MediaTypeFormatterCollection(new[] {new XmlMediaTypeFormatter {UseXmlSerializer = true}});
}
public string[] GetLocales()
public static string[] GetLocales()
{
// Sony removed the ability to get the full store list, now relying on geolocation service instead
return KnownStoreLocales;
@@ -126,7 +126,7 @@ namespace PsnClient
try
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
var html = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var html = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
var matches = ContainerIdLink.Matches(html);
var result = new List<string>();
foreach (Match m in matches)
@@ -151,8 +151,8 @@ namespace PsnClient
{
try
{
var loc = locale.AsLocaleData();
var baseUrl = $"https://store.playstation.com/valkyrie-api/{loc.language}/{loc.country}/999/storefront/{containerId}";
var (language, country) = locale.AsLocaleData();
var baseUrl = $"https://store.playstation.com/valkyrie-api/{language}/{country}/999/storefront/{containerId}";
using var message = new HttpRequestMessage(HttpMethod.Get, baseUrl);
using var response = await client.SendAsync(message, cancellationToken).ConfigureAwait(false);
try
@@ -180,8 +180,8 @@ namespace PsnClient
{
try
{
var loc = locale.AsLocaleData();
var url = new Uri($"https://store.playstation.com/valkyrie-api/{loc.language}/{loc.country}/999/container/{containerId}");
var (language, country) = locale.AsLocaleData();
var url = new Uri($"https://store.playstation.com/valkyrie-api/{language}/{country}/999/container/{containerId}");
filters ??= new Dictionary<string, string>();
filters["start"] = start.ToString();
filters["size"] = take.ToString();
@@ -214,8 +214,8 @@ namespace PsnClient
{
try
{
var loc = locale.AsLocaleData();
using var message = new HttpRequestMessage(HttpMethod.Get, $"https://store.playstation.com/valkyrie-api/{loc.language}/{loc.country}/999/resolve/{contentId}?depth={depth}");
var (language, country) = locale.AsLocaleData();
using var message = new HttpRequestMessage(HttpMethod.Get, $"https://store.playstation.com/valkyrie-api/{language}/{country}/999/resolve/{contentId}?depth={depth}");
using var response = await client.SendAsync(message, cancellationToken).ConfigureAwait(false);
try
{
@@ -253,7 +253,7 @@ namespace PsnClient
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
patchInfo = await response.Content.ReadAsAsync<TitlePatch>(xmlFormatters, cancellationToken).ConfigureAwait(false);
ResponseCache.Set(productId, patchInfo, ResponseCacheDuration);
return patchInfo ?? new TitlePatch { Tag = new TitlePatchTag { Packages = new TitlePatchPackage[0], }, };
return patchInfo ?? new TitlePatch { Tag = new TitlePatchTag { Packages = Array.Empty<TitlePatchPackage>(), }, };
}
catch (Exception e)
{
@@ -300,10 +300,10 @@ namespace PsnClient
{
try
{
var loc = locale.AsLocaleData();
var (language, country) = locale.AsLocaleData();
var searchId = Uri.EscapeUriString(search);
var queryId = Uri.EscapeDataString(searchId);
var uri = new Uri($"https://store.playstation.com/valkyrie-api/{loc.language}/{loc.country}/999/faceted-search/{searchId}?query={queryId}&game_content_type=games&size=30&bucket=games&platform=ps3&start=0");
var uri = new Uri($"https://store.playstation.com/valkyrie-api/{language}/{country}/999/faceted-search/{searchId}?query={queryId}&game_content_type=games&size=30&bucket=games&platform=ps3&start=0");
using var message = new HttpRequestMessage(HttpMethod.Get, uri);
using var response = await client.SendAsync(message, cancellationToken).ConfigureAwait(false);
try
@@ -357,7 +357,7 @@ namespace PsnClient
private async Task<string> GetSessionCookies(string locale, CancellationToken cancellationToken)
{
var loc = locale.AsLocaleData();
var (language, country) = locale.AsLocaleData();
var uri = new Uri("https://store.playstation.com/kamaji/api/valkyrie_storefront/00_09_000/user/session");
var tries = 0;
do
@@ -374,8 +374,8 @@ namespace PsnClient
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["country_code"] = loc.country,
["language_code"] = loc.language,
["country_code"] = country,
["language_code"] = language,
})
};
using (authMessage)
@@ -418,7 +418,7 @@ namespace PsnClient
return null;
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var data = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(data))
return null;

View File

@@ -21,7 +21,7 @@ namespace PsnClient.Utils
return null;
if (hexString.Length == 0)
return new byte[0];
return Array.Empty<byte>();
if (hexString.Length % 2 != 0)
throw new ArgumentException("Invalid hex string format: odd number of octets", nameof(hexString));

View File

@@ -99,7 +99,7 @@ namespace CompatBot.ThumbScrapper
if (ScrapeStateProvider.IsFresh(StoreRefreshTimestamp))
return;
var result = GetLocalesInPreferredOrder(Client.GetLocales());
var result = GetLocalesInPreferredOrder(PsnClient.Client.GetLocales());
await LockObj.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{