Add project files.

This commit is contained in:
Dima yawaflua Andreev
2024-06-22 23:21:48 +03:00
parent bc437be3dc
commit 7d6932fdc6
26 changed files with 626 additions and 0 deletions

33
.github/workflows/dotnet.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: .NET
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal
- name: Publish
uses: brandedoutcast/publish-nuget@v2.5.5
with:
PROJECT_FILE_PATH: SPWorldsApi.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}

39
HttpClient/HttpRequest.cs Normal file
View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace SPWorldsApi.HttpClient
{
public class HttpRequest(string BASE_URL, AuthenticationHeaderValue AuthHeader)
{
internal async Task<string> SendRequest(string endpoint, HttpMethod method = null, object body = null)
{
method ??= body == null ? HttpMethod.Get : HttpMethod.Post;
HttpResponseMessage message;
var client = new System.Net.Http.HttpClient();
using (var requestMessage = new HttpRequestMessage(method, BASE_URL + endpoint))
{
requestMessage.Content = new StringContent(
JsonSerializer.Serialize(body),
Encoding.UTF8, "application/json"
);
requestMessage.Headers.Authorization = AuthHeader;
message = await client.SendAsync(requestMessage);
}
client.Dispose();
return await message.Content.ReadAsStringAsync();
}
}
}

View File

@@ -0,0 +1,72 @@
using SPWorldsApi.Types.Interfaces;
using SPWorldsApi.Utils;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace SPWorldsApi.Payments
{
internal interface IPaymentWrapper
{
HttpClient.HttpRequest client { get; set; }
internal async Task<string> SendRequest(string endpoint, HttpMethod method = null, object body = null)
{
return await client.SendRequest(endpoint, method, body);
}
/// <summary>
/// Get card from spworlds
/// </summary>
/// <returns></returns>
public async Task<ICard> GetCard()
=> (await SendRequest("card")).Deserialize<ICard>();
/// <summary>
/// Create transaction
/// </summary>
/// <param name="receiver">receiver card</param>
/// <param name="amount">amount of AR</param>
/// <param name="comment">comment to transaction</param>
/// <returns>balance of card</returns>
public async Task<int> CreateTransaction(string receiver, int amount, string comment)
{
var transitionInfo = new Dictionary<string, object>
{
{ "receiver", receiver },
{ "amount", amount },
{ "comment", comment }
};
var response = JsonNode.Parse(await SendRequest(endpoint: "transactions", body: transitionInfo));
return (int)response["balance"];
}
public async Task<string> InitPayment(IPaymentItems[] items, string redirectUrl, string webhookUrl, string data)
{
var paymentInfo = new Dictionary<string, object>
{
{ "items", JsonSerializer.Serialize(items).ToLower()},
{ "redirectUrl", redirectUrl },
{ "webhookUrl", webhookUrl },
{ "data", data }
};
var payment = JsonObject.Parse(await SendRequest(endpoint: $"payment", body: paymentInfo));
var url = payment["url"];
return (string)url;
}
/// <summary>
/// Create payment url
/// </summary>
/// <param name="paymentData"></param>
/// <returns></returns>
public async Task<string> InitPayment(IPaymentData paymentData)
{
var payment = JsonObject.Parse(await SendRequest(endpoint: $"payment", body: JsonSerializer.Serialize(paymentData)));
return (string)payment["url"];
}
}
}

47
Program.cs Normal file
View File

@@ -0,0 +1,47 @@
using SPWorldsApi.HttpClient;
using SPWorldsApi.Payments;
using SPWorldsApi.Users;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
namespace SPWorldsApi
{
public sealed class SPWorlds : IPaymentWrapper, IUserWrapper
{
internal string token { get; }
public HttpRequest client { get; set; }
string BASE_URL { get; set; } = "https://spworlds.ru/api/public";
AuthenticationHeaderValue AuthHeader { get; set; }
public SPWorlds(string id, string token)
{
var BearerToken = $"{id}:{token}";
this.token = token;
string Base64BearerToken = Convert.ToBase64String(Encoding.UTF8.GetBytes(BearerToken));
AuthHeader = new("Bearer", Base64BearerToken);
client = new(BASE_URL, AuthHeader);
}
/// <summary>
/// Validating wenhook from site
/// </summary>
/// <param name="requestBody">Body of request</param>
/// <param name="base64Hash">X-Body-Hash</param>
/// <returns></returns>
public bool ValidateWebhook(string requestBody, string base64Hash)
{
byte[] requestData = Encoding.UTF8.GetBytes(requestBody);
using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(token)))
{
byte[] hashBytes = hmac.ComputeHash(requestData);
string computedHash = Convert.ToBase64String(hashBytes);
return base64Hash.Equals(computedHash);
}
}
}
}

98
README.md Normal file
View File

@@ -0,0 +1,98 @@
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> spworlds API
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> - [Mih4n](https://github.com/Mih4n/spworlds-csharp-library), <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
# CS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> dotnet <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> API <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> API [<EFBFBD><EFBFBD><EFBFBD>](https://github.com/sp-worlds/api-docs).
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CLI
(`dotnet`), NuGet <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
```bash
dotnet add package spworlds
```
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
```cs
...
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
var spw = new SPWorldsApi("[<5B><><EFBFBD> <20><><EFBFBD><EFBFBD>]", "[<5B><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>]");
```
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 16 <20><>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> `https://example.com/success`, <20> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> `https://api.example.com/webhook` <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> `SomeString`. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> ID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
```cs
const url = await sp.InitPayment(
[
new PaymentItems() { Name = "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", Count = 1, Price = 16, Comment = "<22><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"}
],
"https://example.com/success",
"https://api.example.com/webhook",
"SomeString"
);
```
<EFBFBD><EFBFBD><EFBFBD>
```cs
[HttpPost("/create_payment_url/")]
public async Task<IActionResult> GetCreatePaymentFunction([FromBody] PaymentData paymentData)
{
const url = await sp.InitPayment(paymentData);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
```
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 16 <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 11111 <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "<22> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"
```cs
await sp.CreateTransaction("11111", 16, "<22> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!");
```
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
```cs
int balance = await sp.GetCardBalance();
```
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Discord <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
```cs
IUser user = await sp.GetUser("111111111111111111");
if (user.Name == "yawaflua")
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
```
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SkinPart <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 64, 128 <20> <20>.<2E>., <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> User, <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD>:
```cs
IUser user = await sp.GetUser("111111111111111111");
const faceUrl = user.GetSkinPart(SkinPart.face);
```
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD>:
```cs
bool IsWebHook = await sp.ValidateWebHook(WebHookText, X_Body_Hash);
```
## Contributing
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> pull <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.

24
SPWorldsApi.csproj Normal file
View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>spworldsapi</PackageId>
<Description>Библиотека, созданная для облегчения работы с API сайта spworlds.ru . Что-то добавить или обновить можно в github проекта.</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Version>1.0.0</Version>
<Authors>yawaflua</Authors>
<Company>yawaflua</Company>
<RepositoryUrl>https://github.com/yawaflua/spworlds</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

25
SPWorldsApi.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPWorldsApi", "SPWorldsApi.csproj", "{AD0307C9-8042-44D2-B773-4DEB62D27F3D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AD0307C9-8042-44D2-B773-4DEB62D27F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD0307C9-8042-44D2-B773-4DEB62D27F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD0307C9-8042-44D2-B773-4DEB62D27F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD0307C9-8042-44D2-B773-4DEB62D27F3D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B52E51DB-0209-420D-9359-424764DC76C7}
EndGlobalSection
EndGlobal

13
Types/Enums/SkinPart.cs Normal file
View File

@@ -0,0 +1,13 @@
namespace SPWorldsApi.Types.Enums
{
public enum SkinPart
{
face,
front,
front_full,
head,
bust,
full,
skin
}
}

View File

@@ -0,0 +1,8 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface ICard
{
public int Balance { get; set; }
public string Webhook { get; set; }
}
}

12
Types/Interfaces/ICity.cs Normal file
View File

@@ -0,0 +1,12 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface ICity
{
public string id { get; set; }
public string name { get; set; }
public string description { get; set; }
public int x { get; set; }
public int z { get; set; }
public bool isMayor { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface IPaymentData
{
public IPaymentItems[] Items { get; set; }
public string RedirectUrl { get; set; }
public string WebHookUrl { get; set; }
public string Data { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface IPaymentItems
{
public string Name { get; set; }
public int Count { get; set; }
public int Price { get; set; }
public string? Comment { get; set; }
}
}

29
Types/Interfaces/IUser.cs Normal file
View File

@@ -0,0 +1,29 @@
using SPWorldsApi.Types.Enums;
using SPWorldsApi.Types.Models;
using System.Text.Json.Nodes;
namespace SPWorldsApi.Types.Interfaces
{
public interface IUser
{
public string Name { get; }
public string Uuid { get; }
public static async Task<IUser> CreateUserAsync(string name)
{
string? uuid;
using (System.Net.Http.HttpClient client = new())
{
uuid = (string?)JsonNode.Parse(await client.GetStringAsync($"https://api.mojang.com/users/profiles/minecraft/{name}"))["id"];
}
User user = new(name, uuid);
return user;
}
public string GetSkinPart(SkinPart skinPart, string size = "64")
{
return (string)$"https://avatar.spworlds.ru/{skinPart}/{size}/{Name}";
}
}
}

View File

@@ -0,0 +1,14 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface IUserAccount
{
public string id { get; set; }
public string username { get; set; }
public string minecraftUUID { get; set; }
public string status { get; set; }
public List<string> roles { get; set; }
public ICity city { get; set; }
public List<IUserCard> cards { get; set; }
public DateTime createdAt { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface IUserCard
{
public string id { get; set; }
public string name { get; set; }
public string number { get; set; }
public int color { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace SPWorldsApi.Types.Interfaces
{
public interface IWebhookResponse
{
public int Id { get; set; }
public string Webhook { get; set; }
}
}

10
Types/Models/Card.cs Normal file
View File

@@ -0,0 +1,10 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class Card : ICard
{
public int Balance { get; set; }
public string Webhook { get; set; }
}
}

14
Types/Models/City.cs Normal file
View File

@@ -0,0 +1,14 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class City : ICity
{
public string id { get; set; }
public string name { get; set; }
public string description { get; set; }
public int x { get; set; }
public int z { get; set; }
public bool isMayor { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class PaymentData : IPaymentData
{
public IPaymentItems[] Items { get; set; }
public string RedirectUrl { get; set; }
public string WebHookUrl { get; set; }
public string Data { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
public class PaymentItems : IPaymentItems
{
public string Name { get; set; }
public int Count { get; set; }
public int Price { get; set; }
public string? Comment { get; set; } = null;
}
}

16
Types/Models/User.cs Normal file
View File

@@ -0,0 +1,16 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class User : IUser
{
public string Name { get; }
public string Uuid { get; }
public User(string name, string uuid)
{
Name = name;
Uuid = uuid;
}
}
}

View File

@@ -0,0 +1,16 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class UserAccount : IUserAccount
{
public string id { get; set; }
public string username { get; set; }
public string minecraftUUID { get; set; }
public string status { get; set; }
public List<string> roles { get; set; }
public ICity city { get; set; }
public List<IUserCard> cards { get; set; }
public DateTime createdAt { get; set; }
}
}

12
Types/Models/UserCard.cs Normal file
View File

@@ -0,0 +1,12 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class UserCard : IUserCard
{
public string id { get; set; }
public string name { get; set; }
public string number { get; set; }
public int color { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using SPWorldsApi.Types.Interfaces;
namespace SPWorldsApi.Types.Models
{
internal class WebhookResponse : IWebhookResponse
{
public int Id { get; set; }
public string Webhook { get; set; }
}
}

49
Users/IUserWrapper.cs Normal file
View File

@@ -0,0 +1,49 @@
using SPWorldsApi.Types.Interfaces;
using SPWorldsApi.Types.Models;
using SPWorldsApi.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace SPWorldsApi.Users
{
internal interface IUserWrapper
{
HttpClient.HttpRequest client { get; set; }
internal async Task<string> SendRequest(string endpoint, HttpMethod method = null, object body = null)
{
return await client.SendRequest(endpoint, method, body);
}
/// <summary>
/// Get user cards by nickname
/// </summary>
/// <param name="username">Username of player</param>
/// <returns>Array of cards</returns>
public async Task<IUserCard[]> GetUserCardsAsync(string username)
=> (await SendRequest($"accounts/{username}/cards")).Deserialize<IUserCard[]>();
/// <summary>
/// Get user info from site
/// </summary>
/// <param name="discordId">Discord id of user</param>
/// <returns></returns>
public async Task<IUser> GetUser(string discordId)
=> (await SendRequest($"users/{discordId}")).Deserialize<IUser>();
public async Task<IUserAccount> GetMeAsync()
=> (await SendRequest("accounts/me")).Deserialize<IUserAccount>();
/// <summary>
/// Setting up a webhook to card
/// </summary>
/// <param name="webhookUrl">Url of webhook</param>
/// <returns></returns>
public async Task<IWebhookResponse> SetWebhook(string webhookUrl)
=> (await SendRequest("card/webhook", HttpMethod.Put, @$"{{ ""url"": ""{webhookUrl}"" }}")).Deserialize<IWebhookResponse>();
}
}

23
Utils/Deserialization.cs Normal file
View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace SPWorldsApi.Utils
{
internal static class Deserialization
{
public static TClass Deserialize<TClass>(this string body) where TClass : class
{
TClass? objectToReturn = JsonSerializer.Deserialize<TClass>(body);
if (objectToReturn == null)
throw new Exception($"Error with deserializing object");
else
return objectToReturn;
}
}
}