using System.Net; using Myriad.Rest.Types; using Myriad.Rest.Types.Requests; using Myriad.Types; using Serilog; namespace Myriad.Rest; public class DiscordApiClient { public const string UserAgent = "DiscordBot (https://github.com/xSke/PluralKit/tree/main/Myriad/, v1)"; private const string DefaultApiBaseUrl = "https://discord.com/api/v9"; private readonly BaseRestClient _client; public EventHandler<(string, int, long)> OnResponseEvent; public DiscordApiClient(string token, ILogger logger, string? baseUrl = null) { _client = new BaseRestClient(UserAgent, token, logger, baseUrl ?? DefaultApiBaseUrl); _client.OnResponseEvent += (_, ev) => OnResponseEvent?.Invoke(null, ev); } public Task GetGateway() => _client.Get("/gateway", ("GetGateway", default))!; public Task GetGatewayBot() => _client.Get("/gateway/bot", ("GetGatewayBot", default))!; public Task GetChannel(ulong channelId) => _client.Get($"/channels/{channelId}", ("GetChannel", channelId)); public Task GetMessage(ulong channelId, ulong messageId) => _client.Get($"/channels/{channelId}/messages/{messageId}", ("GetMessage", channelId)); public Task GetGuild(ulong id) => _client.Get($"/guilds/{id}", ("GetGuild", id)); public Task GetGuildChannels(ulong id) => _client.Get($"/guilds/{id}/channels", ("GetGuildChannels", id))!; public Task GetUser(ulong id) => _client.Get($"/users/{id}", ("GetUser", default)); public Task GetGuildMember(ulong guildId, ulong userId) => _client.Get($"/guilds/{guildId}/members/{userId}", ("GetGuildMember", guildId)); public Task CreateMessage(ulong channelId, MessageRequest request, MultipartFile[]? files = null) => _client.PostMultipart($"/channels/{channelId}/messages", ("CreateMessage", channelId), request, files)!; public Task EditMessage(ulong channelId, ulong messageId, MessageEditRequest request) => _client.Patch($"/channels/{channelId}/messages/{messageId}", ("EditMessage", channelId), request)!; public Task DeleteMessage(ulong channelId, ulong messageId) => _client.Delete($"/channels/{channelId}/messages/{messageId}", ("DeleteMessage", channelId)); public Task DeleteMessage(Message message) => _client.Delete($"/channels/{message.ChannelId}/messages/{message.Id}", ("DeleteMessage", message.ChannelId)); public Task CreateReaction(ulong channelId, ulong messageId, Emoji emoji) => _client.Put($"/channels/{channelId}/messages/{messageId}/reactions/{EncodeEmoji(emoji)}/@me", ("CreateReaction", channelId), null); public Task DeleteOwnReaction(ulong channelId, ulong messageId, Emoji emoji) => _client.Delete($"/channels/{channelId}/messages/{messageId}/reactions/{EncodeEmoji(emoji)}/@me", ("DeleteOwnReaction", channelId)); public Task DeleteUserReaction(ulong channelId, ulong messageId, Emoji emoji, ulong userId) => _client.Delete($"/channels/{channelId}/messages/{messageId}/reactions/{EncodeEmoji(emoji)}/{userId}", ("DeleteUserReaction", channelId)); public Task DeleteAllReactions(ulong channelId, ulong messageId) => _client.Delete($"/channels/{channelId}/messages/{messageId}/reactions", ("DeleteAllReactions", channelId)); public Task DeleteAllReactionsForEmoji(ulong channelId, ulong messageId, Emoji emoji) => _client.Delete($"/channels/{channelId}/messages/{messageId}/reactions/{EncodeEmoji(emoji)}", ("DeleteAllReactionsForEmoji", channelId)); public Task CreateGlobalApplicationCommand(ulong applicationId, ApplicationCommandRequest request) => _client.Post($"/applications/{applicationId}/commands", ("CreateGlobalApplicationCommand", applicationId), request)!; public Task GetGuildApplicationCommands(ulong applicationId, ulong guildId) => _client.Get($"/applications/{applicationId}/guilds/{guildId}/commands", ("GetGuildApplicationCommands", applicationId))!; public Task CreateGuildApplicationCommand(ulong applicationId, ulong guildId, ApplicationCommandRequest request) => _client.Post($"/applications/{applicationId}/guilds/{guildId}/commands", ("CreateGuildApplicationCommand", applicationId), request)!; public Task EditGuildApplicationCommand(ulong applicationId, ulong guildId, ApplicationCommandRequest request) => _client.Patch($"/applications/{applicationId}/guilds/{guildId}/commands", ("EditGuildApplicationCommand", applicationId), request)!; public Task DeleteGuildApplicationCommand(ulong applicationId, ulong commandId) => _client.Delete($"/applications/{applicationId}/commands/{commandId}", ("DeleteGuildApplicationCommand", applicationId)); public Task CreateInteractionResponse(ulong interactionId, string token, InteractionResponse response) => _client.Post($"/interactions/{interactionId}/{token}/callback", ("CreateInteractionResponse", interactionId), response); public Task ModifyGuildMember(ulong guildId, ulong userId, ModifyGuildMemberRequest request) => _client.Patch($"/guilds/{guildId}/members/{userId}", ("ModifyGuildMember", guildId), request); public Task CreateWebhook(ulong channelId, CreateWebhookRequest request) => _client.Post($"/channels/{channelId}/webhooks", ("CreateWebhook", channelId), request)!; public Task GetWebhook(ulong webhookId) => _client.Get($"/webhooks/{webhookId}/webhooks", ("GetWebhook", webhookId))!; public Task GetChannelWebhooks(ulong channelId) => _client.Get($"/channels/{channelId}/webhooks", ("GetChannelWebhooks", channelId))!; public Task ExecuteWebhook(ulong webhookId, string webhookToken, ExecuteWebhookRequest request, MultipartFile[]? files = null, ulong? threadId = null) { var url = $"/webhooks/{webhookId}/{webhookToken}?wait=true"; if (threadId != null) url += $"&thread_id={threadId}"; return _client.PostMultipart(url, ("ExecuteWebhook", webhookId), request, files)!; } public Task EditWebhookMessage(ulong webhookId, string webhookToken, ulong messageId, WebhookMessageEditRequest request, ulong? threadId = null) { var url = $"/webhooks/{webhookId}/{webhookToken}/messages/{messageId}"; if (threadId != null) url += $"?thread_id={threadId}"; return _client.Patch(url, ("EditWebhookMessage", webhookId), request)!; } public Task CreateDm(ulong recipientId) => _client.Post("/users/@me/channels", ("CreateDM", default), new CreateDmRequest(recipientId))!; private static string EncodeEmoji(Emoji emoji) => WebUtility.UrlEncode(emoji.Id != null ? $"{emoji.Name}:{emoji.Id}" : emoji.Name) ?? throw new ArgumentException("Could not encode emoji"); }