-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
355 additions
and
287 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
name: Build and Release | ||
|
||
env: | ||
DOTNET_VERSION: '8.x' | ||
NUGET_SOURCE_URL: 'https://api.nuget.org/v3/index.json' | ||
BUILD_DIRECTORY: '${{ github.workspace }}/build' | ||
|
||
on: | ||
push: | ||
tags: | ||
- 'v*.*.*' | ||
|
||
jobs: | ||
build-and-release: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout Repository | ||
uses: actions/checkout@v2 | ||
|
||
- name: Get Version | ||
id: get_version | ||
run: | | ||
echo "tag=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT | ||
echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT | ||
- name: Get Project Metadata | ||
id: get_project_meta | ||
run: | | ||
name=$(echo '${{ github.repository }}' | cut -d '/' -f 2) | ||
echo "name=${name}" >> $GITHUB_OUTPUT | ||
echo "path=${name}/${name}.csproj" >> $GITHUB_OUTPUT | ||
- name: Setup .NET | ||
uses: actions/[email protected] | ||
with: | ||
dotnet-version: ${{ env.DOTNET_VERSION }} | ||
|
||
- name: Restore Packages | ||
run: dotnet restore ${{ steps.get_project_meta.outputs.path }} | ||
|
||
- name: Build Project | ||
run: dotnet build ${{ steps.get_project_meta.outputs.path }} /p:ContinuousIntegrationBuild=true --no-restore --configuration Release | ||
|
||
- name: Pack Project | ||
run: dotnet pack ${{ steps.get_project_meta.outputs.path }} --no-restore --no-build --configuration Release --include-symbols -p:PackageVersion=${{ steps.get_version.outputs.version }} --output ${{ env.BUILD_DIRECTORY }} | ||
|
||
- name: Push Package | ||
env: | ||
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_AUTH_TOKEN }} | ||
run: dotnet nuget push ${{ env.BUILD_DIRECTORY }}/*.nupkg -k $NUGET_AUTH_TOKEN -s ${{ env.NUGET_SOURCE_URL }} | ||
|
||
- name: Create Release | ||
uses: softprops/action-gh-release@v1 | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
name: ${{ steps.get_version.outputs.tag }} | ||
body: ${{ github.event.head_commit.message }} | ||
files: '${{ env.BUILD_DIRECTORY }}/*' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,64 @@ | ||
using Netcraft.Entities; | ||
using System; | ||
using System.IO; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
using System.Text; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
|
||
namespace Netcraft | ||
{ | ||
public static class API | ||
internal static class API | ||
{ | ||
public const int MaxRetries = 3; | ||
public const int RetryDelay = 1000 * 1; | ||
public const int PreviewMaxLength = 500; | ||
|
||
public static async Task<HttpResponseMessage> Request | ||
( | ||
this HttpClient cl, | ||
HttpMethod method, | ||
string url, | ||
string path, | ||
object obj, | ||
HttpStatusCode target = HttpStatusCode.OK, | ||
JsonSerializerOptions options = null) | ||
=> await Request(cl, method, url, new StringContent(JsonSerializer.Serialize(obj, options ?? Constants.EnumOptions), Encoding.UTF8, "application/json"), target); | ||
=> await Request(cl, method, path, await obj.Serialize(options ?? Constants.EnumOptions), target); | ||
|
||
public static async Task<HttpResponseMessage> Request | ||
( | ||
this HttpClient cl, | ||
HttpMethod method, | ||
string url, | ||
string path, | ||
HttpContent content = null, | ||
HttpStatusCode target = HttpStatusCode.OK) | ||
{ | ||
HttpRequestMessage req = new(method, url) | ||
using HttpRequestMessage req = new(method, path) | ||
{ | ||
Content = content | ||
}; | ||
|
||
HttpResponseMessage res = await cl.SendAsync(req); | ||
content?.Dispose(); | ||
|
||
if ((int)res.StatusCode > 500) throw new NetcraftException("Received a failure status code."); | ||
|
||
if (!target.HasFlag(res.StatusCode)) | ||
{ | ||
string text = await res.Content.ReadAsStringAsync(); | ||
|
||
MediaTypeHeaderValue contentType = res.Content.Headers.ContentType; | ||
if (contentType is null) throw new NetcraftException("The 'Content-Type' header is missing in the response.", method.ToString(), url); | ||
if (target.HasFlag(res.StatusCode)) return res; | ||
|
||
bool isJson = contentType.MediaType.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase); | ||
if (!isJson) | ||
throw new NetcraftException( | ||
$"received status code {res.StatusCode} and Content-Type {contentType.MediaType}" + | ||
$"\nPreview: {text[..Math.Min(text.Length, PreviewMaxLength)]}", | ||
method.ToString(), | ||
url); | ||
NetcraftError error = await res.Deseralize<NetcraftError>() ?? | ||
throw new NetcraftException($"Failed to request {method} {path}, received status code {res.StatusCode}\nPreview: {await res.GetPreview()}", res); | ||
|
||
NetcraftError error = await res.Deseralize<NetcraftError>(); | ||
if (error is null) throw new NetcraftException("Parsed error object is null.", method.ToString(), url); | ||
StringBuilder sb = new(); | ||
|
||
StringBuilder sb = new(); | ||
sb.AppendLine("Operation resulted in the following API error:"); | ||
sb.AppendLine($"\nStatus: {error.Status}"); | ||
if (!string.IsNullOrEmpty(error.Description)) sb.AppendLine($"\nDescription: {error.Description}"); | ||
sb.AppendLine($"Failed to request {method} {path}, received the following API error:"); | ||
sb.AppendLine($"Status: {error.Status}"); | ||
if (!string.IsNullOrEmpty(error.Description)) sb.AppendLine($"Description: {error.Description}"); | ||
|
||
if (error.Details is not null && error.Details.Length > 0) | ||
if (error.Details is not null && error.Details.Length > 0) | ||
{ | ||
for (int i = 0; i < error.Details.Length; i++) | ||
{ | ||
for (int i = 0; i < error.Details.Length; i++) | ||
{ | ||
ErrorDetail detail = error.Details[i]; | ||
ErrorDetail detail = error.Details[i]; | ||
|
||
sb.AppendLine($"[#{i + 1}] {detail.Message} caused by input '{detail.Input}' at '{detail.Path}'"); | ||
} | ||
sb.AppendLine(string.Concat( | ||
$"[#{i + 1}] {detail.Message}", | ||
(string.IsNullOrEmpty(detail.Input) || string.IsNullOrEmpty(detail.Path)) ? "" : $" caused by input \"{detail.Input}\" at \"{detail.Path}\"")); | ||
} | ||
|
||
throw new NetcraftException(sb.ToString()); | ||
} | ||
|
||
return res; | ||
} | ||
|
||
public static async Task<T> Deseralize<T>(this HttpResponseMessage res, JsonSerializerOptions options = null) | ||
{ | ||
Stream stream = await res.Content.ReadAsStreamAsync(); | ||
if (stream.Length == 0) throw new NetcraftException("Response content is empty, can't parse as JSON."); | ||
|
||
try | ||
{ | ||
return await JsonSerializer.DeserializeAsync<T>(stream, options ?? Constants.EnumOptions); | ||
} | ||
catch (Exception ex) | ||
{ | ||
using StreamReader sr = new(stream); | ||
string text = await sr.ReadToEndAsync(); | ||
|
||
throw new NetcraftException($"Exception while parsing JSON: {ex.GetType().Name} => {ex.Message}\nPreview: {text[..Math.Min(text.Length, PreviewMaxLength)]}"); | ||
} | ||
throw new NetcraftException(sb.ToString(), res); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,4 +25,4 @@ public class LeaderboardEntry | |
[JsonPropertyName("rank")] | ||
public int Rank { get; set; } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.