Skip to content

Commit

Permalink
Add project files.
Browse files Browse the repository at this point in the history
  • Loading branch information
itssimple committed Nov 5, 2021
1 parent 0d5a224 commit 2612d11
Show file tree
Hide file tree
Showing 49 changed files with 915 additions and 0 deletions.
133 changes: 133 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Rules in this file were initially inferred by Visual Studio IntelliCode from the D:\Git\Journal-Limpet codebase based on best match to current usage at 2021-02-20
# You can modify the rules from these initially generated values to suit your own policies
# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
[*.cs]


#Core editorconfig formatting - indentation

#use soft tabs (spaces) for indentation
indent_style = space
indent_size = 4

#Formatting - indentation options

#indent switch case contents.
csharp_indent_case_contents = true
#indent switch labels
csharp_indent_switch_labels = true

#Formatting - new line options

#place catch statements on a new line
csharp_new_line_before_catch = true
#place else statements on a new line
csharp_new_line_before_else = true
#require members of anonymous types to be on separate lines
csharp_new_line_before_members_in_anonymous_types = true
#require members of object initializers to be on the same line
csharp_new_line_before_members_in_object_initializers = false
#require braces to be on a new line for accessors, types, control_blocks, lambdas, methods, anonymous_types, properties, and object_collection_array_initializers (also known as "Allman" style)
csharp_new_line_before_open_brace = accessors, types, control_blocks, lambdas, methods, anonymous_types, properties, object_collection_array_initializers

#Formatting - organize using options

#do not place System.* using directives before other using directives
dotnet_sort_system_directives_first = false

#Formatting - spacing options

#require NO space between a cast and the value
csharp_space_after_cast = false
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_after_colon_in_inheritance_clause = true
#require a space after a keyword in a control flow statement such as a for loop
csharp_space_after_keywords_in_control_flow_statements = true
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_before_colon_in_inheritance_clause = true
#remove space within empty argument list parentheses
csharp_space_between_method_call_empty_parameter_list_parentheses = false
#remove space between method call name and opening parenthesis
csharp_space_between_method_call_name_and_opening_parenthesis = false
#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
csharp_space_between_method_call_parameter_list_parentheses = false
#remove space within empty parameter list parentheses for a method declaration
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
csharp_space_between_method_declaration_parameter_list_parentheses = false

#Formatting - wrapping options

#leave code block on single line
csharp_preserve_single_line_blocks = true
#leave statements and member declarations on the same line
csharp_preserve_single_line_statements = true

#Style - Code block preferences

#prefer curly braces even for one line of code
csharp_prefer_braces = true:suggestion

#Style - expression bodied member options

#prefer block bodies for accessors
csharp_style_expression_bodied_accessors = false:suggestion
#prefer block bodies for constructors
csharp_style_expression_bodied_constructors = false:suggestion
#prefer block bodies for methods
csharp_style_expression_bodied_methods = false:suggestion
#prefer block bodies for properties
csharp_style_expression_bodied_properties = false:suggestion

#Style - expression level options

#prefer out variables to be declared before the method call
csharp_style_inlined_variable_declaration = false:suggestion
#prefer tuple names to ItemX properties
dotnet_style_explicit_tuple_names = true:suggestion
#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_member_access = true:suggestion

#Style - Expression-level preferences

#prefer default over default(T)
csharp_prefer_simple_default_expression = true:suggestion
#prefer objects to be initialized using object initializers when possible
dotnet_style_object_initializer = true:suggestion
#prefer inferred anonymous type member names
dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion
#prefer inferred tuple element names
dotnet_style_prefer_inferred_tuple_names = true:suggestion

#Style - implicit and explicit types

#prefer var over explicit type in all cases, unless overridden by another code style rule
csharp_style_var_elsewhere = true:suggestion
#prefer var is used to declare variables with built-in system types such as int
csharp_style_var_for_built_in_types = true:suggestion
#prefer var when the type is already mentioned on the right-hand side of a declaration expression
csharp_style_var_when_type_is_apparent = true:suggestion

#Style - language keyword and framework type options

#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion

#Style - modifier options

#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion

#Style - Modifier preferences

#when this rule is set to a list of modifiers, prefer the specified ordering.
csharp_preferred_modifier_order = public,private,internal,async,static,readonly,override:suggestion

#Style - qualification options

#prefer fields not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_field = false:suggestion
#prefer methods not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_method = false:suggestion
#prefer properties not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_property = false:suggestion
97 changes: 97 additions & 0 deletions ApiClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using CurseForge.APIClient.Exceptions;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace CurseForge.APIClient
{
public partial class ApiClient : IDisposable
{
private static HttpClient _httpClient;
private const string curseForgeApiBaseUrl = "https://api.curseforge.com";

private readonly string _apiKey;
private readonly long _partnerId;
private readonly string _contactEmail;

private void InitHttpClientIfMissing()
{
if (string.IsNullOrWhiteSpace(_apiKey))
{
throw new MissingApiKeyException("You need to provide an API key to be able to call the API");
}

if (string.IsNullOrWhiteSpace(_contactEmail))
{
throw new MissingContactEmailException("You need to provide an email to be contacted on, if needed.");
}

if (_httpClient == null)
{
_httpClient = new HttpClient
{
BaseAddress = new Uri(curseForgeApiBaseUrl),
};

_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", $"CurseForge Api Client (PartnerId: {_partnerId}) (+{_contactEmail})");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("x-api-key", _apiKey);
}
}

public ApiClient(string apiKey, long partnerId, string contactEmail)
{
_apiKey = apiKey;
_partnerId = partnerId;
_contactEmail = contactEmail;

InitHttpClientIfMissing();
}

internal string GetQuerystring(params (string Key, object Value)[] queryParameters)
{
return queryParameters.Count(k => k.Value != null) > 0 ? "?" +
string.Join("&",
queryParameters
.Where(k => k.Value != null)
.Select(k => $"{System.Net.WebUtility.UrlEncode(k.Key)}={System.Net.WebUtility.UrlEncode(k.Value.ToString())}")) : "";
}

internal async Task<T> GET<T>(string endpoint, params (string Key, object Value)[] queryParameters)
{
return await HandleResponseMessage<T>(
await _httpClient.GetAsync(
endpoint + GetQuerystring(queryParameters)
)
);
}

internal async Task<T> POST<T>(string endpoint, object body)
{
return await HandleResponseMessage<T>(
await _httpClient.PostAsync(
endpoint,
new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json")
)
);
}

internal async Task<T> HandleResponseMessage<T>(HttpResponseMessage result)
{
if (!result.IsSuccessStatusCode)
{
Console.WriteLine(JsonConvert.SerializeObject(result));
throw new Exception(await result.Content.ReadAsStringAsync());
}

return JsonConvert.DeserializeObject<T>(await result.Content.ReadAsStringAsync());
}

public void Dispose()
{
throw new NotImplementedException();
}
}
}
13 changes: 13 additions & 0 deletions Categories.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using CurseForge.APIClient.Models;
using System.Threading.Tasks;

namespace CurseForge.APIClient
{
public partial class ApiClient
{
public async Task<GenericListResponse<Category>> GetCategoriesAsync(int? gameId = null, int? classId = null)
{
return await GET<GenericListResponse<Category>>("/v1/categories", ("gameId", gameId), ("classId", classId));
}
}
}
27 changes: 27 additions & 0 deletions CurseForge.APIClient.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp3.1;net5.0</TargetFrameworks>
<Authors>itssimple / NoLifeKing85</Authors>
<Company />
<Description>A .NET client for connecting to the CurseForge API</Description>
<Copyright>2021 © NoLifeKing85</Copyright>
</PropertyGroup>

<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
<DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

</Project>
30 changes: 30 additions & 0 deletions CurseForge.APIClient.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31402.337
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CurseForge.APIClient", "CurseForge.APIClient.csproj", "{C4B82C61-4F05-49C3-B812-F4FE6EAA7169}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C0B555B8-9E7F-4763-A52E-4723E6390F27}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C4B82C61-4F05-49C3-B812-F4FE6EAA7169}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4B82C61-4F05-49C3-B812-F4FE6EAA7169}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4B82C61-4F05-49C3-B812-F4FE6EAA7169}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4B82C61-4F05-49C3-B812-F4FE6EAA7169}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {67AF453F-ADA7-4BF1-898E-85E4D5914608}
EndGlobalSection
EndGlobal
9 changes: 9 additions & 0 deletions Exceptions/MissingApiKeyException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace CurseForge.APIClient.Exceptions
{
internal class MissingApiKeyException : Exception
{
public MissingApiKeyException(string message) : base(message) { }
}
}
9 changes: 9 additions & 0 deletions Exceptions/MissingContactEmailException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace CurseForge.APIClient.Exceptions
{
internal class MissingContactEmailException : Exception
{
public MissingContactEmailException(string message) : base(message) { }
}
}
36 changes: 36 additions & 0 deletions Files.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using CurseForge.APIClient.Models;
using CurseForge.APIClient.Models.Files;
using System.Threading.Tasks;

namespace CurseForge.APIClient
{
public partial class ApiClient
{
public async Task<GenericResponse<File>> GetModFileAsync(int modId, int fileId)
{
return await GET<GenericResponse<File>>($"/v1/mods/{modId}/files/{fileId}");
}

public async Task<GenericListResponse<File>> GetModFilesAsync(int modId, string gameVersionFlavor = null, int? index = null, int? pageSize = null)
{
return await GET<GenericListResponse<File>>($"/v1/mods/{modId}/files",
("gameVersionFlavor", gameVersionFlavor), ("index", index), ("pageSize", pageSize)
);
}

public async Task<GenericListResponse<File>> GetFilesAsync(GetModFilesRequestBody body)
{
return await POST<GenericListResponse<File>>("/v1/mods/files", body);
}

public async Task<GenericResponse<string>> GetModFileChangelogAsync(int modId, int fileId)
{
return await GET<GenericResponse<string>>($"/v1/mods/{modId}/files/{fileId}/changelog");
}

public async Task<GenericResponse<string>> GetModFileDownloadUrlAsync(int modId, int fileId)
{
return await GET<GenericResponse<string>>($"/v1/mods/{modId}/files/{fileId}/download-url");
}
}
}
19 changes: 19 additions & 0 deletions Fingerprints.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using CurseForge.APIClient.Models;
using CurseForge.APIClient.Models.Fingerprints;
using System.Threading.Tasks;

namespace CurseForge.APIClient
{
public partial class ApiClient
{
public async Task<GenericResponse<FingerprintMatchesResult>> GetFingerprintMatchesAsync(GetFingerprintMatchesRequestBody body)
{
return await POST<GenericResponse<FingerprintMatchesResult>>("/v1/fingerprints", body);
}

public async Task<GenericResponse<FingerprintFuzzyMatchResult>> GetFingerprintsFuzzyMatchesAsync(GetFuzzyMatchesRequestBody body)
{
return await POST<GenericResponse<FingerprintFuzzyMatchResult>>("/v1/fingerprints/fuzzy", body);
}
}
}
Loading

0 comments on commit 2612d11

Please sign in to comment.