foxcord/Foxcord/Rest/DiscordRestClient.cs
2024-09-03 00:07:12 +02:00

66 lines
No EOL
2.3 KiB
C#

using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Foxcord.Models;
using Foxcord.Rest.Rate;
using Foxcord.Rest.Types;
using Foxcord.Serialization;
using Polly;
using Serilog;
namespace Foxcord.Rest;
public class DiscordRestClient : BaseRestClient
{
public DiscordRestClient(ILogger logger, DiscordRestClientOptions options) : base(logger, new RestClientOptions
{
JsonSerializerOptions = JsonSerializerOptions,
ApiBaseUrl = options.ApiBaseUrl ?? DefaultApiBaseUrl,
UserAgent = options.UserAgent ?? DefaultUserAgent,
TokenFactory = () => $"Bot {options.Token}",
ErrorHandler = HandleError,
})
{
Pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddDiscordStrategy(new RateLimiter(logger.ForContext<DiscordRestClient>()))
.Build();
}
public const string DefaultUserAgent = "DiscordBot (https://code.vulpine.solutions/sam/Foxcord, v1)";
public const string DefaultApiBaseUrl = "https://discord.com/api/v10";
public async Task<GetGatewayBotResponse> GatewayBotAsync(CancellationToken ct = default) =>
await RequestAsync<GetGatewayBotResponse>(HttpMethod.Get, "/gateway/bot", ct);
public async Task<Message> CreateMessageAsync(Snowflake channelId, CreateMessageParams message,
CancellationToken ct = default) =>
await RequestAsync<CreateMessageParams, Message>(HttpMethod.Post, $"/channels/{channelId}/messages", message,
ct);
#region BaseRestClient parameters
private static readonly JsonSerializerOptions JsonSerializerOptions = JsonSerializerExtensions.CreateSerializer();
private static async Task HandleError(HttpResponseMessage resp, CancellationToken ct)
{
if (resp.IsSuccessStatusCode) return;
if (resp.StatusCode == HttpStatusCode.TooManyRequests)
{
throw new RateLimitError(resp.Headers);
}
var error = await resp.Content.ReadFromJsonAsync<DiscordRestError>(JsonSerializerOptions, ct);
if (error == null) throw new ArgumentNullException(nameof(resp), "Response was deserialized as null");
throw error;
}
#endregion
}
public class DiscordRestClientOptions
{
public required string Token { get; init; }
public string? UserAgent { get; init; }
public string? ApiBaseUrl { get; init; }
}