discord.zig/src/structures/component.zig
2024-12-13 05:18:49 -05:00

229 lines
11 KiB
Zig

const Partial = @import("partial.zig").Partial;
const Snowflake = @import("snowflake.zig").Snowflake;
const Emoji = @import("emoji.zig").Emoji;
const ButtonStyles = @import("shared.zig").ButtonStyles;
const ChannelTypes = @import("shared.zig").ChannelTypes;
const MessageComponentTypes = @import("shared.zig").MessageComponentTypes;
const zjson = @import("../json.zig");
const std = @import("std");
/// https://discord.com/developers/docs/interactions/message-components#buttons
pub const Button = struct {
/// 2 for a button
type: MessageComponentTypes,
/// A button style
style: ButtonStyles,
/// Text that appears on the button; max 80 characters
label: ?[]const u8,
/// name, id, and animated
emoji: Partial(Emoji),
/// Developer-defined identifier for the button; max 100 characters
custom_id: ?[]const u8,
/// Identifier for a purchasable SKU, only available when using premium-style buttons
sku_id: ?Snowflake,
/// URL for link-style buttons
url: ?[]const u8,
/// Whether the button is disabled (defaults to false)
disabled: ?bool,
};
pub const SelectOption = struct {
/// User-facing name of the option; max 100 characters
label: []const u8,
/// Dev-defined value of the option; max 100 characters
value: []const u8,
/// Additional description of the option; max 100 characters
description: ?[]const u8,
/// id, name, and animated
emoji: ?Partial(Emoji),
/// Will show this option as selected by default
default: ?bool,
};
pub const DefaultValue = struct {
/// ID of a user, role, or channel
id: Snowflake,
/// Type of value that id represents. Either "user", "role", or "channel"
type: union(enum) { user, role, channel },
};
/// https://discord.com/developers/docs/interactions/message-components#select-menus
pub const SelectMenuString = struct {
/// Type of select menu component (text: 3, user: 5, role: 6, mentionable: 7, channels: 8)
type: MessageComponentTypes,
/// ID for the select menu; max 100 characters
custom_id: []const u8,
/// Specified choices in a select menu (only required and available for string selects (type 3); max 25
/// * options is required for string select menus (component type 3), and unavailable for all other select menu components.
options: ?[]SelectOption,
/// Placeholder text if nothing is selected; max 150 characters
placeholder: ?[]const u8,
/// Minimum number of items that must be chosen (defaults to 1); min 0, max 25
min_values: ?usize,
/// Maximum number of items that can be chosen (defaults to 1); max 25
max_values: ?usize,
/// Whether select menu is disabled (defaults to false)
disabled: ?bool,
};
/// https://discord.com/developers/docs/interactions/message-components#select-menus
pub const SelectMenuUsers = struct {
/// Type of select menu component (text: 3, user: 5, role: 6, mentionable: 7, channels: 8)
type: MessageComponentTypes,
/// ID for the select menu; max 100 characters
custom_id: []const u8,
/// Placeholder text if nothing is selected; max 150 characters
placeholder: ?[]const u8,
/// List of default values for auto-populated select menu components; number of default values must be in the range defined by min_values and max_values
/// *** default_values is only available for auto-populated select menu components, which include user (5), role (6), mentionable (7), and channel (8) components.
default_values: ?[]DefaultValue,
/// Minimum number of items that must be chosen (defaults to 1); min 0, max 25
min_values: ?usize,
/// Maximum number of items that can be chosen (defaults to 1); max 25
max_values: ?usize,
/// Whether select menu is disabled (defaults to false)
disabled: ?bool,
};
/// https://discord.com/developers/docs/interactions/message-components#select-menus
pub const SelectMenuRoles = struct {
/// Type of select menu component (text: 3, user: 5, role: 6, mentionable: 7, channels: 8)
type: MessageComponentTypes,
/// ID for the select menu; max 100 characters
custom_id: []const u8,
/// Placeholder text if nothing is selected; max 150 characters
placeholder: ?[]const u8,
/// List of default values for auto-populated select menu components; number of default values must be in the range defined by min_values and max_values
/// *** default_values is only available for auto-populated select menu components, which include user (5), role (6), mentionable (7), and channel (8) components.
default_values: ?[]DefaultValue,
/// Minimum number of items that must be chosen (defaults to 1); min 0, max 25
min_values: ?usize,
/// Maximum number of items that can be chosen (defaults to 1); max 25
max_values: ?usize,
/// Whether select menu is disabled (defaults to false)
disabled: ?bool,
};
/// https://discord.com/developers/docs/interactions/message-components#select-menus
pub const SelectMenuUsersAndRoles = struct {
/// Type of select menu component (text: 3, user: 5, role: 6, mentionable: 7, channels: 8)
type: MessageComponentTypes,
/// ID for the select menu; max 100 characters
custom_id: []const u8,
/// Placeholder text if nothing is selected; max 150 characters
placeholder: ?[]const u8,
/// List of default values for auto-populated select menu components; number of default values must be in the range defined by min_values and max_values
/// *** default_values is only available for auto-populated select menu components, which include user (5), role (6), mentionable (7), and channel (8) components.
default_values: ?[]DefaultValue,
/// Minimum number of items that must be chosen (defaults to 1); min 0, max 25
min_values: ?usize,
/// Maximum number of items that can be chosen (defaults to 1); max 25
max_values: ?usize,
/// Whether select menu is disabled (defaults to false)
disabled: ?bool,
};
/// https://discord.com/developers/docs/interactions/message-components#select-menus
pub const SelectMenuChannels = struct {
/// Type of select menu component (text: 3, user: 5, role: 6, mentionable: 7, channels: 8)
type: MessageComponentTypes,
/// ID for the select menu; max 100 characters
custom_id: []const u8,
/// List of channel types to include in the channel select component (type 8)
/// ** channel_types can only be used for channel select menu components.
channel_types: ?[]ChannelTypes,
/// Placeholder text if nothing is selected; max 150 characters
placeholder: ?[]const u8,
/// List of default values for auto-populated select menu components; number of default values must be in the range defined by min_values and max_values
/// *** default_values is only available for auto-populated select menu components, which include user (5), role (6), mentionable (7), and channel (8) components.
default_values: ?[]DefaultValue,
/// Minimum number of items that must be chosen (defaults to 1); min 0, max 25
min_values: ?usize,
/// Maximum number of items that can be chosen (defaults to 1); max 25
max_values: ?usize,
/// Whether select menu is disabled (defaults to false)
disabled: ?bool,
};
pub const SelectMenu = union(MessageComponentTypes) {
SelectMenu: SelectMenuString,
SelectMenuUsers: SelectMenuUsers,
SelectMenuRoles: SelectMenuRoles,
SelectMenuUsersAndRoles: SelectMenuUsersAndRoles,
SelectMenuChannels: SelectMenuChannels,
pub fn json(allocator: std.mem.Allocator, value: zjson.JsonType) !@This() {
if (!value.is(.object))
@panic("coulnd't match against non-object type");
switch (value.object.get("type") orelse @panic("couldn't find property `type`")) {
.number => |num| return switch (@as(MessageComponentTypes, @enumFromInt(num.integer))) {
.SelectMenu => .{ .SelectMenu = try zjson.parseInto(SelectMenuString, allocator, value) },
.SelectMenuUsers => .{ .SelectMenuUsers = try zjson.parseInto(SelectMenuUsers, allocator, value) },
.SelectMenuRoles => .{ .SelectMenuRoles = try zjson.parseInto(SelectMenuRoles, allocator, value) },
.SelectMenuUsersAndRoles => .{ .SelectMenuUsersAndRoles = try zjson.parseInto(SelectMenuUsersAndRoles, allocator, value) },
.SelectMenuChannels => .{ .SelectMenuChannels = try zjson.parseInto(SelectMenuChannels, allocator, value) },
},
else => @panic("got type but couldn't match against non enum member `type`"),
}
unreachable;
}
};
pub const InputTextStyles = enum(u4) {
Short = 1,
Paragraph,
};
pub const InputText = struct {
/// 4 for a text input
type: MessageComponentTypes,
/// Developer-defined identifier for the input; max 100 characters
custom_id: []const u8,
/// The Text Input Style
style: InputTextStyles,
/// Label for this component; max 45 characters
label: []const u8,
/// Minimum input length for a text input; min 0, max 4000
min_length: ?usize,
/// Maximum input length for a text input; min 1, max 4000
max_length: ?usize,
/// Whether this component is required to be filled (defaults to true)
required: ?bool,
/// Pre-filled value for this component; max 4000 characters
value: ?[]const u8,
/// Custom placeholder text if the input is empty; max 100 characters
placeholder: ?[]const u8,
};
pub const MessageComponent = union(MessageComponentTypes) {
ActionRow: []MessageComponent,
Button: Button,
SelectMenu: SelectMenuString,
InputText: InputText,
SelectMenuUsers: SelectMenuUsers,
SelectMenuRoles: SelectMenuRoles,
SelectMenuUsersAndRoles: SelectMenuUsersAndRoles,
SelectMenuChannels: SelectMenuChannels,
pub fn json(allocator: std.mem.Allocator, value: zjson.JsonType) !@This() {
if (!value.is(.object))
@panic("coulnd't match against non-object type");
switch (value.object.get("type") orelse @panic("couldn't find property `type`")) {
.number => |num| return switch (@as(MessageComponentTypes, @enumFromInt(num.integer))) {
.ActionRow => .{ .ActionRow = try zjson.parseInto([]MessageComponent, allocator, value) },
.Button => .{ .Button = try zjson.parseInto(Button, allocator, value) },
.SelectMenu => .{ .SelectMenu = try zjson.parseInto(SelectMenuString, allocator, value) },
.InputText => .{ .InputText = try zjson.parseInto(InputText, allocator, value) },
.SelectMenuUsers => .{ .SelectMenuUsers = try zjson.parseInto(SelectMenuUsers, allocator, value) },
.SelectMenuRoles => .{ .SelectMenuRoles = try zjson.parseInto(SelectMenuRoles, allocator, value) },
.SelectMenuUsersAndRoles => .{ .SelectMenuUsersAndRoles = try zjson.parseInto(SelectMenuUsersAndRoles, allocator, value) },
.SelectMenuChannels => .{ .SelectMenuChannels = try zjson.parseInto(SelectMenuChannels, allocator, value) },
},
else => @panic("got type but couldn't match against non enum member `type`"),
}
}
};