Create all interaction models

This commit is contained in:
Daan Boerlage 2021-09-20 01:28:26 +02:00
parent 209887e237
commit 60547140ea
Signed by: daan
GPG key ID: FCE070E1E4956606
59 changed files with 1589 additions and 222 deletions

View file

@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object"/>
public record Command
{
/// <summary>
/// unique id of the command
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; }
/// <summary>
/// the type of command, defaults 1 if not set
/// </summary>
[JsonPropertyName("type")]
public CommandType Type { get; set; }
/// <summary>
/// unique id of the parent application
/// </summary>
[JsonPropertyName("application_id")]
public string ApplicationId { get; set; }
/// <summary>
/// guild id of the command, if not global
/// </summary>
[JsonPropertyName("guild_id")]
public string GuildId { get; set; }
/// <summary>
/// 1-32 character name
/// </summary>
/// <remarks>
/// CHAT_INPUT command names and command option names must match the following regex ^[\w-]{1,32}$ with the unicode flag set. If there is a lowercase variant of any letters used, you must use those.
/// Characters with no lowercase variants and/or uncased letters are still allowed. USER and MESSAGE commands may be mixed case and can include spaces.
/// </remarks>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// 1-100 character description for CHAT_INPUT commands, empty string for USER and MESSAGE commands
/// </summary>
/// <remarks>
/// Exclusive: CHAT_INPUT
/// </remarks>
[JsonPropertyName("description")]
public string Description { get; set; }
/// <summary>
/// the parameters for the command, max 25
/// </summary>
/// <remarks>
/// Exclusive: CHAT_INPUT
/// </remarks>
[JsonPropertyName("options")]
public List<Option> Options { get; set; }
/// <summary>
/// whether the command is enabled by default when the app is added to a guild
/// </summary>
[JsonPropertyName("default_permission")]
public bool DefaultPermission { get; set; } = true;
/// <summary>
/// autoincrementing version identifier updated during substantial record changes
/// </summary>
[JsonPropertyName("version")]
public string Version { get; set; }
}
}

View file

@ -0,0 +1,21 @@
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types"/>
public enum CommandType
{
/// <summary>
/// Slash commands; a text-based command that shows up when a user types /
/// </summary>
ChatInput = 1,
/// <summary>
/// A UI-based command that shows up when you right click or tap on a user
/// </summary>
User = 2,
/// <summary>
/// A UI-based command that shows up when you right click or tap on a message
/// </summary>
Message = 3,
}
}

View file

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <remarks>
/// Required options must be listed before optional options
/// </remarks>
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure"/>
public record Option
{
/// <summary>
/// the type of option
/// </summary>
[JsonPropertyName("type")]
public OptionType Type { get; set; }
/// <summary>
/// 1-32 character name
/// </summary>
/// <remarks>
/// Must match ^[\w-]{1,32}$
/// </remarks>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// 1-100 character description
/// </summary>
[JsonPropertyName("description")]
public string Description { get; set; }
/// <summary>
/// if the parameter is required or optional--default false
/// </summary>
[JsonPropertyName("required")]
public bool Required { get; set; }
/// <summary>
/// choices for STRING, INTEGER, and NUMBER types for the user to pick from, max 25
/// </summary>
[JsonPropertyName("choices")]
public List<OptionChoice> Choices { get; set; }
/// <summary>
/// if the option is a subcommand or subcommand group type, this nested options will be the parameters
/// </summary>
[JsonPropertyName("options")]
public List<Option> Options { get; set; }
}
}

View file

@ -0,0 +1,17 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <remarks>
/// If you specify choices for an option, they are the only valid values for a user to pick
/// </remarks>
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-choice-structure"/>
public record OptionChoice
{
/// <summary>
/// 1-100 character choice name
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; }
}
}

View file

@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-choice-structure"/>
public record OptionChoiceDouble : OptionChoice
{
/// <summary>
/// value of the choice, up to 100 characters if string
/// </summary>
[JsonPropertyName("value")]
public double Value { get; set; }
}
}

View file

@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-choice-structure"/>
public record OptionChoiceInteger : OptionChoice
{
/// <summary>
/// value of the choice, up to 100 characters if string
/// </summary>
[JsonPropertyName("value")]
public int Value { get; set; }
}
}

View file

@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-choice-structure"/>
public record OptionChoiceString : OptionChoice
{
/// <summary>
/// value of the choice, up to 100 characters if string
/// </summary>
[JsonPropertyName("value")]
public string Value { get; set; }
}
}

View file

@ -0,0 +1,38 @@
namespace Geekbot.Core.Interactions.ApplicationCommand
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-type"/>
public enum OptionType
{
SubCommand = 1,
SubCommandGroup = 2,
String = 3,
/// <summary>
/// Any integer between -2^53 and 2^53
/// </summary>
Integer = 4,
Boolean = 5,
User = 6,
/// <summary>
/// Includes all channel types + categories
/// </summary>
Channel = 7,
Role = 8,
/// <summary>
/// Includes users and roles
/// </summary>
Mentionable = 9,
/// <summary>
/// Any double between -2^53 and 2^53
/// </summary>
Number = 10,
}
}

View file

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object" />
public record Embed
{
/// <summary>
/// title of embed
/// </summary>
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// type of embed (always "rich" for webhook embeds)
/// </summary>
[JsonPropertyName("type")]
public EmbedTypes Type { get; set; }
/// <summary>
/// description of embed
/// </summary>
[JsonPropertyName("description")]
public string Description { get; set; }
/// <summary>
/// url of embed
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// timestamp of embed content
/// </summary>
[JsonPropertyName("timestamp")]
public DateTime? Timestamp { get; set; }
/// <summary>
/// color code of the embed
/// </summary>
[JsonPropertyName("color")]
public int Color { get; set; }
/// <summary>
/// footer information
/// </summary>
[JsonPropertyName("footer")]
public EmbedFooter Footer { get; set; }
/// <summary>
/// image information
/// </summary>
[JsonPropertyName("image")]
public EmbedImage Image { get; set; }
/// <summary>
/// thumbnail information
/// </summary>
[JsonPropertyName("thumbnail")]
public EmbedThumbnail Thumbnail { get; set; }
/// <summary>
/// video information
/// </summary>
[JsonPropertyName("video")]
public EmbedVideo Video { get; set; }
/// <summary>
/// provider information
/// </summary>
[JsonPropertyName("provider")]
public EmbedProvider Provider { get; set; }
/// <summary>
/// author information
/// </summary>
[JsonPropertyName("author")]
public EmbedAuthor Author { get; set; }
/// <summary>
/// fields information
/// </summary>
[JsonPropertyName("fields")]
public List<EmbedField> Fields { get; set; }
}
}

View file

@ -0,0 +1,32 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
public record EmbedAuthor
{
/// <summary>
/// name of author
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// url of author
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// url of author icon (only supports http(s) and attachments)
/// </summary>
[JsonPropertyName("icon_url")]
public string IconUrl { get; set; }
/// <summary>
/// a proxied url of author icon
/// </summary>
[JsonPropertyName("proxy_icon_url")]
public string ProxyIconUrl { get; set; }
}
}

View file

@ -0,0 +1,26 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure" />
public record EmbedField
{
/// <summary>
/// name of the field
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// value of the field
/// </summary>
[JsonPropertyName("value")]
public string Value { get; set; }
/// <summary>
/// whether or not this field should display inline
/// </summary>
[JsonPropertyName("inline")]
public bool Inline { get; set; }
}
}

View file

@ -0,0 +1,27 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure" />
public record EmbedFooter
{
/// <summary>
/// footer text
/// </summary>
[JsonPropertyName("text")]
public string Text { get; set; }
/// <summary>
/// url of footer icon (only supports http(s) and attachments)
/// </summary>
[JsonPropertyName("icon_url")]
public string IconUrl { get; set; }
/// <summary>
/// a proxied url of footer icon
/// </summary>
[JsonPropertyName("proxy_icon_url")]
public string ProxyIconUrl { get; set; }
}
}

View file

@ -0,0 +1,32 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure" />
public record EmbedImage
{
/// <summary>
/// source url of image (only supports http(s) and attachments)
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// a proxied url of the image
/// </summary>
[JsonPropertyName("proxy_url")]
public string ProxyUrl { get; set; }
/// <summary>
/// height of image
/// </summary>
[JsonPropertyName("height")]
public int Height { get; set; }
/// <summary>
/// width of image
/// </summary>
[JsonPropertyName("width")]
public int Width { get; set; }
}
}

View file

@ -0,0 +1,20 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-provider-structure" />
public record EmbedProvider
{
/// <summary>
/// name of provider
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// url of provider
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; }
}
}

View file

@ -0,0 +1,33 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-thumbnail-structure" />
public record EmbedThumbnail
{
/// <summary>
/// source url of thumbnail (only supports http(s) and attachments)
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// a proxied url of the thumbnail
/// </summary>
[JsonPropertyName("proxy_url")]
public string ProxyUrl { get; set; }
/// <summary>
/// height of thumbnail
/// </summary>
[JsonPropertyName("height")]
public int Height { get; set; }
/// <summary>
/// width of thumbnail
/// </summary>
[JsonPropertyName("width")]
public int Width { get; set; }
}
}

View file

@ -0,0 +1,49 @@
using System.Runtime.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <summary>
/// Embed types are "loosely defined" and, for the most part, are not used by our clients for rendering.
/// Embed attributes power what is rendered.
/// Embed types should be considered deprecated and might be removed in a future API version.
/// </summary>
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-types" />
public enum EmbedTypes
{
/// <summary>
/// generic embed rendered from embed attributes
/// </summary>
[EnumMember(Value = "rich")]
Rich,
/// <summary>
/// image embed
/// </summary>
[EnumMember(Value = "image")]
Image,
/// <summary>
/// video embed
/// </summary>
[EnumMember(Value = "video")]
Video,
/// <summary>
/// animated gif image embed rendered as a video embed
/// </summary>
[EnumMember(Value = "gifv")]
Gifv,
/// <summary>
/// article embed
/// </summary>
[EnumMember(Value = "article")]
Article,
/// <summary>
/// link embed
/// </summary>
[EnumMember(Value = "link")]
Link,
}
}

View file

@ -0,0 +1,32 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Embed
{
/// <see href="https://discord.com/developers/docs/resources/channel#embed-object-embed-video-structure" />
public record EmbedVideo
{
/// <summary>
/// source url of video
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// a proxied url of the video
/// </summary>
[JsonPropertyName("proxy_url")]
public string ProxyUrl { get; set; }
/// <summary>
/// height of video
/// </summary>
[JsonPropertyName("height")]
public int Height { get; set; }
/// <summary>
/// width of video
/// </summary>
[JsonPropertyName("width")]
public int Width { get; set; }
}
}

View file

@ -0,0 +1,31 @@
namespace Geekbot.Core.Interactions.MessageComponents
{
/// <see href="https://discord.com/developers/docs/interactions/message-components#button-object-button-styles" />
public enum ButtonStyle
{
/// <summary>
/// blurple
/// </summary>
Primary = 1,
/// <summary>
/// grey
/// </summary>
Secondary = 2,
/// <summary>
/// green
/// </summary>
Success = 3,
/// <summary>
/// red
/// </summary>
Danger = 4,
/// <summary>
/// grey, navigates to a URL
/// </summary>
Link = 5
}
}

View file

@ -0,0 +1,111 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.MessageComponents
{
/// <see href="https://discord.com/developers/docs/interactions/message-components#component-object-component-structure"/>
public record Component
{
/// <summary>
/// component type
/// </summary>
[JsonPropertyName("type")]
public ComponentType Type { get; set; }
/// <summary>
/// a developer-defined identifier for the component, max 100 characters
/// </summary>
/// <remarks>
/// For: Buttons, Select Menus
/// </remarks>
[JsonPropertyName("custom_id")]
public string CustomId { get; set; }
/// <summary>
/// whether the component is disabled, default false
/// </summary>
/// <remarks>
/// For: Buttons, Select Menus
/// </remarks>
[JsonPropertyName("disabled")]
public bool Disabled { get; set; }
/// <summary>
/// one of button styles
/// </summary>
/// <remarks>
/// For: Buttons
/// </remarks>
[JsonPropertyName("style")]
public ButtonStyle Style { get; set; }
/// <summary>
/// text that appears on the button, max 80 characters
/// </summary>
/// <remarks>
/// For: Buttons
/// </remarks>
[JsonPropertyName("label")]
public string Label { get; set; }
/// <summary>
/// name, id, and animated
/// </summary>
/// <remarks>
/// For: Buttons
/// </remarks>
[JsonPropertyName("emoji")]
public ComponentEmoji Emoji { get; set; }
/// <summary>
/// a url for link-style buttons
/// </summary>
/// <remarks>
/// For: Buttons
/// </remarks>
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// the choices in the select, max 25
/// </summary>
/// <remarks>
/// For: Select Menus
/// </remarks>
[JsonPropertyName("options")]
public List<SelectOption> Options { get; set; }
/// <summary>
/// custom placeholder text if nothing is selected, max 100 characters
/// </summary>
/// <remarks>
/// For: Select Menus
/// </remarks>
[JsonPropertyName("placeholder")]
public string Placeholder { get; set; }
/// <summary>
/// the minimum number of items that must be chosen; default 1, min 0, max 25
/// </summary>
/// <remarks>
/// For: Select Menus
/// </remarks>
[JsonPropertyName("min_values")]
public int MinValues { get; set; }
/// <summary>
/// the maximum number of items that can be chosen; default 1, max 25
/// </summary>
/// <remarks>
/// For: Select Menus
/// </remarks>
[JsonPropertyName("max_values")]
public int MaxValues { get; set; }
/// <summary>
/// a list of child components
/// </summary>
[JsonPropertyName("components")]
public List<Component> Components { get; set; }
}
}

View file

@ -0,0 +1,33 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.MessageComponents
{
/// <remarks>
/// Partial emoji with just id, name, and animated
/// </remarks>
/// <see href="https://discord.com/developers/docs/resources/emoji#emoji-object" />
public record ComponentEmoji
{
/// <summary>
/// emoji name
/// </summary>
/// <remarks>
/// can be null only in reaction emoji objects
/// </remarks>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// emoji id
/// </summary>
/// <see href="https://discord.com/developers/docs/reference#image-formatting" />
[JsonPropertyName("id")]
public string Id { get; set; }
/// <summary>
/// whether this emoji can be used, may be false due to loss of Server Boosts
/// </summary>
[JsonPropertyName("animated")]
public bool Animated { get; set; }
}
}

View file

@ -0,0 +1,21 @@
namespace Geekbot.Core.Interactions.MessageComponents
{
/// <see href="https://discord.com/developers/docs/interactions/message-components#component-object-component-types" />
public enum ComponentType
{
/// <summary>
/// A container for other components
/// </summary>
ActionRow = 1,
/// <summary>
/// A button object
/// </summary>
Button = 2,
/// <summary>
/// A select menu for picking from choices
/// </summary>
SelectMenu = 3
}
}

View file

@ -0,0 +1,38 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.MessageComponents
{
/// <see href="https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure" />
public record SelectOption
{
/// <summary>
/// the user-facing name of the option, max 100 characters
/// </summary>
[JsonPropertyName("label")]
public string Label { get; set; }
/// <summary>
/// the dev-define value of the option, max 100 characters
/// </summary>
[JsonPropertyName("value")]
public string Value { get; set; }
/// <summary>
/// an additional description of the option, max 100 characters
/// </summary>
[JsonPropertyName("description")]
public string Description { get; set; }
/// <summary>
/// id, name, and animated
/// </summary>
[JsonPropertyName("emoji")]
public ComponentEmoji Emoji { get; set; }
/// <summary>
/// will render this option as selected by default
/// </summary>
[JsonPropertyName("default")]
public bool Default { get; set; }
}
}

View file

@ -0,0 +1,77 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Geekbot.Core.Interactions.Resolved;
namespace Geekbot.Core.Interactions.Request
{
/// <see href="https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-structure" />
public record Interaction
{
/// <summary>
/// id of the interaction
/// </summary>
[JsonPropertyName("id")]
public string Id { get; init; }
/// <summary>
/// id of the application this interaction is for
/// </summary>
[JsonPropertyName("application_id")]
public string ApplicationId { get; init; }
/// <summary>
/// the type of interaction
/// </summary>
[JsonPropertyName("type")]
public InteractionType Type { get; init; }
/// <summary>
/// the command data payload
/// </summary>
[JsonPropertyName("data")]
public InteractionData Data { get; init; }
/// <summary>
/// the guild it was sent from
/// </summary>
[JsonPropertyName("guild_id")]
public string GuildId { get; init; }
/// <summary>
/// the channel it was sent from
/// </summary>
[JsonPropertyName("channel_id")]
public string ChannelId { get; init; }
/// <summary>
/// guild member data for the invoking user, including permissions
/// </summary>
[JsonPropertyName("member")]
public Member Member { get; init; }
/// <summary>
/// user object for the invoking user, if invoked in a DM
/// </summary>
[JsonPropertyName("user")]
public User User { get; init; }
/// <summary>
/// a continuation token for responding to the interaction
/// </summary>
[JsonPropertyName("token")]
public string Token { get; init; }
/// <summary>
/// read-only property, always 1
/// </summary>
[JsonPropertyName("version")]
public int Version { get; init; }
/// <summary>
/// object for components, the message they were attached to
/// </summary>
[JsonPropertyName("message")]
public Message Message { get; init; }
}
}

View file

@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Geekbot.Core.Interactions.ApplicationCommand;
using Geekbot.Core.Interactions.MessageComponents;
namespace Geekbot.Core.Interactions.Request
{
/// <see href="https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-data-structure" />
public class InteractionData
{
/// <summary>
/// the ID of the invoked command
/// </summary>
/// <remarks>
/// For: Application Command
/// </remarks>
[JsonPropertyName("id")]
public string Id { get; init; }
/// <summary>
/// the name of the invoked command
/// </summary>
/// <remarks>
/// For: Application Command
/// </remarks>
[JsonPropertyName("name")]
public string Name { get; init; }
/// <summary>
/// the type of the invoked command
/// </summary>
/// <remarks>
/// For: Application Command
/// </remarks>
[JsonPropertyName("type")]
public CommandType Type { get; init; }
/// <summary>
/// converted users + roles + channels
/// </summary>
/// <remarks>
/// For: Application Command
/// </remarks>
[JsonPropertyName("resolved")]
public InteractionResolvedData Resolved { get; init; }
/// <summary>
/// of application command interaction data option the params + values from the user
/// </summary>
/// <remarks>
/// For: Application Command
/// </remarks>
[JsonPropertyName("options")]
public List<InteractionOption> Options { get; init; }
/// <summary>
/// the custom_id of the component
/// </summary>
/// <remarks>
/// For: Component
/// </remarks>
[JsonPropertyName("custom_id")]
public string CustomId { get; init; }
/// <summary>
/// the type of the component
/// </summary>
/// <remarks>
/// For: Component
/// </remarks>
[JsonPropertyName("component_type")]
public ComponentType ComponentType { get; init; }
/// <summary>
/// of select option values the values the user selected
/// </summary>
/// <remarks>
/// Component (Select)
/// </remarks>
[JsonPropertyName("values")]
public string Values { get; init; }
/// <summary>
/// id the of user or message targetted by a user or message command
/// </summary>
/// <remarks>
/// For: Application Command
/// Present in: User Command, Message Command
/// </remarks>
[JsonPropertyName("target_id")]
public string TargetId { get; init; }
public string GetTargetNickname()
{
return GetUserNickename(TargetId);
}
public string GetUserNickename(string userId)
{
var username = Resolved.Members[userId].Nick;
if (string.IsNullOrEmpty(username))
{
username = Resolved.Users[userId].Username;
}
return username;
}
}
}

View file

@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Geekbot.Core.Interactions.ApplicationCommand;
namespace Geekbot.Core.Interactions.Request
{
/// <see href="https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-interaction-data-option-structure" />
public record InteractionOption
{
/// <summary>
/// the name of the parameter
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; }
/// <summary>
/// value of application command option type
/// </summary>
[JsonPropertyName("type")]
public OptionType Type { get; set; }
/// <summary>
/// the value of the pair
/// </summary>
[JsonPropertyName("value")]
public object Value { get; set; }
/// <summary>
/// present if this option is a group or subcommand
/// </summary>
[JsonPropertyName("options")]
public List<InteractionOption> Options { get; set; }
}
}

View file

@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Geekbot.Core.Interactions.Resolved;
namespace Geekbot.Core.Interactions.Request
{
public class InteractionResolvedData
{
[JsonPropertyName("users")]
public Dictionary<string, User> Users { get; set; }
[JsonPropertyName("members")]
public Dictionary<string, Member> Members { get; set; }
[JsonPropertyName("roles")]
public Dictionary<string, Role> Roles { get; set; }
[JsonPropertyName("channels")]
public Dictionary<string, Channel> Channels { get; set; }
[JsonPropertyName("messages")]
public Dictionary<string, Message> Messages { get; set; }
}
}

View file

@ -0,0 +1,10 @@
namespace Geekbot.Core.Interactions.Request
{
/// <see href="https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-type" />
public enum InteractionType
{
Ping = 1,
ApplicationCommand = 2,
MessageComponent = 3,
}
}

View file

@ -0,0 +1,34 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record Attachment
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("filename")]
public string Filename { get; set; }
[JsonPropertyName("content_type")]
public string ContentType { get; set; }
[JsonPropertyName("size")]
public int Size { get; set; }
[JsonPropertyName("url")]
public string Url { get; set; }
[JsonPropertyName("proxy_url")]
public string ProxyUrl { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("ephemeral")]
public bool Ephemeral { get; set; }
}
}

View file

@ -0,0 +1,25 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record Channel
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("type")]
public ChannelType Type { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("parent_id")]
public string ParentId { get; set; }
[JsonPropertyName("thread_metadata")]
public ThreadMetadata ThreadMetadata { get; set; }
[JsonPropertyName("permissions")]
public string Permissions { get; set; }
}
}

View file

@ -1,4 +1,4 @@
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved namespace Geekbot.Core.Interactions.Resolved
{ {
public enum ChannelType public enum ChannelType
{ {

View file

@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record Emoji
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("roles")]
public List<string> Roles { get; set; }
[JsonPropertyName("user")]
public User User { get; set; }
[JsonPropertyName("require_colons")]
public bool RequireColons { get; set; }
[JsonPropertyName("managed")]
public bool Managed { get; set; }
[JsonPropertyName("animated")]
public bool Animated { get; set; }
[JsonPropertyName("available")]
public bool Available { get; set; }
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record Member
{
[JsonPropertyName("nick")]
public string Nick { get; set; }
[JsonPropertyName("roles")]
public List<string> Roles { get; set; }
[JsonPropertyName("joined_at")]
public DateTime JoinedAt { get; set; }
[JsonPropertyName("premium_since")]
public DateTime? PremiumSince { get; set; }
[JsonPropertyName("pending")]
public bool Pending { get; set; }
[JsonPropertyName("permissions")]
public string Permissions { get; set; }
}
}

View file

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record Message
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("channel_id")]
public string ChannelId { get; set; }
[JsonPropertyName("guild_id")]
public string GuildId { get; set; }
[JsonPropertyName("author")]
public User Author { get; set; }
[JsonPropertyName("member")]
public Member Member { get; set; }
[JsonPropertyName("content")]
public string Content { get; set; }
[JsonPropertyName("timestamp")]
public DateTime Timestamp { get; set; }
[JsonPropertyName("edited_timestamp")]
public DateTime? EditedTimestamp { get; set; }
[JsonPropertyName("tts")]
public bool Tts { get; set; }
[JsonPropertyName("mention_everyone")]
public bool MentionEveryone { get; set; }
[JsonPropertyName("mentions")]
public List<User> Mentions { get; set; }
[JsonPropertyName("mention_roles")]
public List<Role> MentionRoles { get; set; }
[JsonPropertyName("mention_channels")]
public List<Channel> MentionChannels { get; set; }
[JsonPropertyName("attachments")]
public List<Attachment> Attachments { get; set; }
[JsonPropertyName("embeds")]
public List<Embed.Embed> Embeds { get; set; }
[JsonPropertyName("reactions")]
public List<Reaction> Reactions { get; set; }
// [JsonPropertyName("nonce")]
// public string Nonce { get; set; }
[JsonPropertyName("pinned")]
public bool Pinned { get; set; }
[JsonPropertyName("webhook_id")]
public string WebhookId { get; set; }
[JsonPropertyName("type")]
public MessageType Type { get; set; }
// [JsonPropertyName("activity")]
// public string Activity { get; set; }
// [JsonPropertyName("application")]
// public string Application { get; set; }
[JsonPropertyName("application_id")]
public string ApplicationId { get; set; }
// [JsonPropertyName("message_reference")]
// public string MessageReference { get; set; }
[JsonPropertyName("flags")]
public int Flags { get; set; }
[JsonPropertyName("referenced_message")]
public Message ReferencedMessage { get; set; }
[JsonPropertyName("interaction")]
public MessageInteraction Interaction { get; set; }
[JsonPropertyName("thread")]
public Channel Thread { get; set; }
// [JsonPropertyName("components")]
// public string Components { get; set; }
// [JsonPropertyName("sticker_items")]
// public string StickerItems { get; set; }
// [JsonPropertyName("stickers")]
// public string Stickers { get; set; }
}
}

View file

@ -0,0 +1,20 @@
using System.Text.Json.Serialization;
using Geekbot.Core.Interactions.Request;
namespace Geekbot.Core.Interactions.Resolved
{
public record MessageInteraction
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("type")]
public InteractionType Type { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("user")]
public User User { get; set; }
}
}

View file

@ -0,0 +1,29 @@
namespace Geekbot.Core.Interactions.Resolved
{
public enum MessageType
{
Default = 0,
RecipientAdd = 1,
RecipientRemove = 2,
Call = 3,
ChannelNameChange = 4,
ChannelIconChange = 5,
ChannelPinnedMessage = 6,
GuildMemberJoin = 7,
UserPremiumGuildSubscription = 8,
UserPremiumGuildSubscriptionTier1 = 9,
UserPremiumGuildSubscriptionTier2 = 10,
UserPremiumGuildSubscriptionTier3 = 11,
ChannelFollowAdd = 12,
GuildDiscoveryDisqualified = 14,
GuildDiscoveryRequalified = 15,
GuildDiscoveryGracePeriodInitialWarning = 16,
GuildDiscoveryGracePeriodFinalWarning = 17,
ThreadCreated = 18,
Reply = 19,
ChatInputCommand = 20,
ThreadStarterMessage = 21,
GuildInviteReminder = 22,
ContextMenuCommand = 23,
}
}

View file

@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public struct Reaction
{
[JsonPropertyName("count")]
public int Count { get; set; }
[JsonPropertyName("me")]
public bool Me { get; set; }
[JsonPropertyName("emoji")]
public Emoji emoji { get; set; }
}
}

View file

@ -0,0 +1,34 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record Role
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("color")]
public int Color { get; set; }
[JsonPropertyName("hoist")]
public bool Hoist { get; set; }
[JsonPropertyName("position")]
public int Position { get; set; }
[JsonPropertyName("permissions")]
public string Permissions { get; set; }
[JsonPropertyName("managed")]
public bool Managed { get; set; }
[JsonPropertyName("mentionable")]
public bool Mentionable { get; set; }
[JsonPropertyName("tags")]
public RoleTag Tags { get; set; }
}
}

View file

@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record RoleTag
{
[JsonPropertyName("bot_id")]
public string BotId { get; set; }
[JsonPropertyName("integration_id")]
public string IntegrationId { get; set; }
[JsonPropertyName("premium_subscriber")]
public bool PremiumSubscriber { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record ThreadMetadata
{
[JsonPropertyName("archived")]
public bool Archived { get; set; }
[JsonPropertyName("auto_archive_duration")]
public int AutoArchiveDuration { get; set; }
[JsonPropertyName("archive_timestamp")]
public DateTime ArchiveTimestamp { get; set; }
[JsonPropertyName("locked")]
public bool Locked { get; set; }
[JsonPropertyName("invitable")]
public bool Invitable { get; set; }
}
}

View file

@ -0,0 +1,52 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Resolved
{
public record User
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("username")]
public string Username { get; set; }
[JsonPropertyName("discriminator")]
public string Discriminator { get; set; }
[JsonPropertyName("avatar")]
public string Avatar { get; set; }
[JsonPropertyName("bot")]
public bool Bot { get; set; }
[JsonPropertyName("system")]
public bool System { get; set; }
[JsonPropertyName("mfa_enabled")]
public bool MfaEnabled { get; set; }
[JsonPropertyName("banner")]
public string Banner { get; set; }
[JsonPropertyName("accent_color")]
public int AccentColor { get; set; }
[JsonPropertyName("locale")]
public string Locale { get; set; }
[JsonPropertyName("verified")]
public bool Verified { get; set; }
[JsonPropertyName("email")]
public string Email { get; set; }
[JsonPropertyName("flags")]
public int Flags { get; set; }
[JsonPropertyName("premium_type")]
public int PremiumType { get; set; }
[JsonPropertyName("public_flags")]
public int PublicFlags { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System.Text.Json.Serialization;
namespace Geekbot.Core.Interactions.Response
{
/// <summary>
/// Interactions--both receiving and responding--are webhooks under the hood. So responding to an Interaction is just like sending a webhook request!
/// </summary>
/// <see href="https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-response-structure"/>
public record InteractionResponse
{
/// <summary>
/// the type of response
/// </summary>
[JsonPropertyName("type")]
public InteractionResponseType Type { get; set; }
/// <summary>
/// an optional response message
/// </summary>
[JsonPropertyName("data")]
public InteractionResponseData Data { get; set; }
}
}

View file

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Discord;
using Geekbot.Core.Interactions.MessageComponents;
using Embed = Geekbot.Core.Interactions.Embed.Embed;
namespace Geekbot.Core.Interactions.Response
{
/// <remarks>
/// Not all message fields are currently supported.
/// </remarks>
/// <see href="https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-callback-data-structure"/>
public record InteractionResponseData
{
/// <summary>
/// is the response TTS
/// </summary>
[JsonPropertyName("tts")]
public bool Tts { get; set; } = false;
/// <summary>
/// message content
/// </summary>
[JsonPropertyName("content")]
public string Content { get; set; }
/// <summary>
/// supports up to 10 embeds
/// </summary>
[JsonPropertyName("embeds")]
public List<Embed.Embed> Embeds { get; set; }
/// <summary>
/// allowed mentions object
/// </summary>
[JsonPropertyName("allowed_mentions")]
public AllowedMentions AllowedMentions { get; set; }
/// <summary>
/// interaction callback data flags
/// </summary>
[JsonPropertyName("flags")]
public int Flags { get; set; }
/// <summary>
/// message components
/// </summary>
[JsonPropertyName("components")]
public List<Component> Components { get; set; }
}
}

View file

@ -0,0 +1,34 @@
namespace Geekbot.Core.Interactions.Response
{
/// <see href="https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type"/>
public enum InteractionResponseType
{
/// <summary>
/// ACK a Ping
/// </summary>
Pong = 1,
/// <summary>
/// respond to an interaction with a message
/// </summary>
ChannelMessageWithSource = 4,
/// <summary>
/// ACK an interaction and edit a response later, the user sees a loading state
/// </summary>
DeferredChannelMessageWithSource = 5,
/// <summary>
/// for components, ACK an interaction and edit the original message later; the user does not see a loading state
/// </summary>
DeferredUpdateMessage = 6,
/// <summary>
/// for components, edit the message the component was attached to
/// </summary>
/// <remarks>
/// Only valid for component-based interactions
/// </remarks>
UpdateMessage = 7,
}
}

View file

@ -1,16 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model
{
public enum ApplicationCommandOption
{
SubCommand = 1,
SubCommandGroup = 2,
String = 3,
Integer = 4,
Boolean = 5,
User = 6,
Channel = 7,
Role = 8,
Mentionable = 9,
Number = 10,
}
}

View file

@ -1,22 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace Geekbot.Web.Controllers.Interactions.Model
{
public record Interaction
{
public string Id { get; set; }
public string ApplicationId { get; init; }
[Required]
public InteractionType Type { get; set; }
public InteractionData Data { get; init; }
public string GuildId { get; init; }
public string Name { get; init; }
public string Description { get; init; }
public List<InteractionOption> Options { get; init; }
public bool DefaultPermission { get; init; }
[Required]
public int Version { get; set; }
}
}

View file

@ -1,14 +0,0 @@
using System.Collections.Generic;
namespace Geekbot.Web.Controllers.Interactions.Model
{
public record InteractionData
{
public string Id { get; set; }
public string Name { get; set; }
public int Type { get; set;}
public InteractionResolvedData Resolved { get; set; }
public List<InteractionOption> Options { get; set; }
public string TargetId { get; set; }
}
}

View file

@ -1,12 +0,0 @@
using System.Collections.Generic;
namespace Geekbot.Web.Controllers.Interactions.Model
{
public record InteractionOption
{
public string Name { get; set; }
public ApplicationCommandOption Type { get; set; }
public string Value { get; set; }
public List<InteractionOption> Options { get; set; }
}
}

View file

@ -1,15 +0,0 @@
using System.Collections.Generic;
using Discord;
using Geekbot.Web.Controllers.Interactions.Model.Resolved;
namespace Geekbot.Web.Controllers.Interactions.Model
{
public class InteractionResolvedData
{
public Dictionary<string, User> Users { get; set; }
public Dictionary<string, Member> Members { get; set; }
public Dictionary<string, Roles> Roles { get; set; }
public Dictionary<string, Channel> Channels { get; set; }
// public Dictionary<string, IMessage> Messages { get; set; }
}
}

View file

@ -1,13 +0,0 @@
using System.Text.Json.Serialization;
namespace Geekbot.Web.Controllers.Interactions.Model
{
public record InteractionResponse
{
[JsonPropertyName("type")]
public InteractionResponseType Type { get; set; }
[JsonPropertyName("data")]
public InteractionData Data { get; set; }
}
}

View file

@ -1,16 +0,0 @@
using System.Collections.Generic;
using Discord;
using Geekbot.Web.Controllers.Interactions.Model.MessageComponents;
namespace Geekbot.Web.Controllers.Interactions.Model
{
public record InteractionResponseData
{
public bool Tts { get; set; } = false;
public string Content { get; set; }
public List<string> Embeds { get; set; }
public AllowedMentions AllowedMentions { get; set; }
public int Flags { get; set; }
public List<Component> Components { get; set; }
}
}

View file

@ -1,11 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model
{
public enum InteractionResponseType
{
Pong = 1,
ChannelMessageWithSource = 4,
DeferredChannelMessageWithSource = 5,
DeferredUpdateMessage = 6,
UpdateMessage = 7,
}
}

View file

@ -1,9 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model
{
public enum InteractionType
{
Ping = 1,
ApplicationCommand = 2,
MessageComponent = 3,
}
}

View file

@ -1,7 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model.MessageComponents
{
public record Component
{
}
}

View file

@ -1,12 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved
{
public record Channel
{
public string Id { get; set; }
public ChannelType Type { get; set; }
public string Name { get; set; }
public string ParentId { get; set; }
public ThreadMetadata ThreadMetadata { get; set; }
public string Permissions { get; set; }
}
}

View file

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved
{
public record Member
{
// public User User { get; set; }
public string Nick { get; set; }
public List<string> Roles { get; set; }
public DateTime JoinedAt { get; set; }
public DateTime PremiumSince { get; set; }
public bool Pending { get; set; }
public string Permissions { get; set; }
}
}

View file

@ -1,9 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved
{
public record RoleTag
{
public string BotId { get; set; }
public string IntegrationId { get; set; }
public bool PremiumSubscriber { get; set; }
}
}

View file

@ -1,15 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved
{
public record Roles
{
public string Id { get; set; }
public string Name { get; set; }
public int Color { get; set; }
public bool Hoist { get; set; }
public int Position { get; set; }
public string Permissions { get; set; }
public bool Managed { get; set; }
public bool Mentionable { get; set; }
public RoleTag Tags { get; set; }
}
}

View file

@ -1,13 +0,0 @@
using System;
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved
{
public record ThreadMetadata
{
public bool Archived { get; set; }
public int AutoArchiveDuration { get; set; }
public DateTime ArchiveTimestamp { get; set; }
public bool Locked { get; set; }
public bool Invitable { get; set; }
}
}

View file

@ -1,21 +0,0 @@
namespace Geekbot.Web.Controllers.Interactions.Model.Resolved
{
public record User
{
public string Id { get; set; }
public string Username { get; set; }
public string Discriminator { get; set; }
public string Avatar { get; set; }
public bool Bot { get; set; }
public bool System { get; set; }
public bool MfaEnabled { get; set; }
public string Banner { get; set; }
public int AccentColor { get; set; }
public string Locale { get; set; }
public bool Verified { get; set; }
public string Email { get; set; }
public int Flags { get; set; }
public int PremiumType { get; set; }
public int PublicFlags { get; set; }
}
}