mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-15 05:41:51 +00:00
feat: add start_new_row option for role button options
This commit is contained in:
parent
5042d9997f
commit
4a9ece8e3b
6 changed files with 57 additions and 35 deletions
|
@ -8,6 +8,8 @@ import { RoleManagerPlugin } from "../RoleManager/RoleManagerPlugin";
|
||||||
import { StrictValidationError } from "../../validatorUtils";
|
import { StrictValidationError } from "../../validatorUtils";
|
||||||
import { onButtonInteraction } from "./events/buttonInteraction";
|
import { onButtonInteraction } from "./events/buttonInteraction";
|
||||||
import { pluginInfo } from "./info";
|
import { pluginInfo } from "./info";
|
||||||
|
import { createButtonComponents } from "./functions/createButtonComponents";
|
||||||
|
import { TooManyComponentsError } from "./functions/TooManyComponentsError";
|
||||||
|
|
||||||
export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
|
export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
|
||||||
name: "role_buttons",
|
name: "role_buttons",
|
||||||
|
@ -26,10 +28,6 @@ export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
|
||||||
|
|
||||||
if (buttonsConfig) {
|
if (buttonsConfig) {
|
||||||
buttonsConfig.name = name;
|
buttonsConfig.name = name;
|
||||||
// 5 action rows * 5 buttons
|
|
||||||
if (buttonsConfig.options?.length > 25) {
|
|
||||||
throw new StrictValidationError(["A single message can have at most 25 role buttons"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buttonsConfig.message) {
|
if (buttonsConfig.message) {
|
||||||
if ("message_id" in buttonsConfig.message) {
|
if ("message_id" in buttonsConfig.message) {
|
||||||
|
@ -39,6 +37,17 @@ export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
|
||||||
seenMessages.add(buttonsConfig.message.message_id);
|
seenMessages.add(buttonsConfig.message.message_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buttonsConfig.options) {
|
||||||
|
try {
|
||||||
|
createButtonComponents(buttonsConfig);
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof TooManyComponentsError) {
|
||||||
|
throw new StrictValidationError(["Too many options; can only have max 5 buttons per row on max 5 rows."]);
|
||||||
|
}
|
||||||
|
throw new StrictValidationError(["Error validating options"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export class TooManyComponentsError extends Error {}
|
|
@ -4,8 +4,8 @@ import { isSnowflake, snowflakeRegex } from "../../../utils";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { Message, MessageButton, MessageEditOptions, MessageOptions, Snowflake } from "discord.js";
|
import { Message, MessageButton, MessageEditOptions, MessageOptions, Snowflake } from "discord.js";
|
||||||
import { RoleButtonsItem } from "../../../data/entities/RoleButtonsItem";
|
import { RoleButtonsItem } from "../../../data/entities/RoleButtonsItem";
|
||||||
import { splitButtonsIntoRows } from "./splitButtonsIntoRows";
|
|
||||||
import { buildCustomId } from "../../../utils/buildCustomId";
|
import { buildCustomId } from "../../../utils/buildCustomId";
|
||||||
|
import { createButtonComponents } from "./createButtonComponents";
|
||||||
|
|
||||||
const channelMessageRegex = new RegExp(`^(${snowflakeRegex.source})-(${snowflakeRegex.source})$`);
|
const channelMessageRegex = new RegExp(`^(${snowflakeRegex.source})-(${snowflakeRegex.source})$`);
|
||||||
|
|
||||||
|
@ -104,24 +104,8 @@ export async function applyRoleButtons(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply role buttons
|
// Apply role buttons
|
||||||
const buttons = configItem.options.map((opt, index) => {
|
const components = createButtonComponents(configItem);
|
||||||
const button = new MessageButton()
|
await message.edit({ components });
|
||||||
.setLabel(opt.label ?? "")
|
|
||||||
.setStyle(opt.style ?? "PRIMARY")
|
|
||||||
.setCustomId(buildCustomId("roleButtons", { name: configItem.name, index }));
|
|
||||||
|
|
||||||
if (opt.emoji) {
|
|
||||||
const emo = pluginData.client.emojis.resolve(opt.emoji as Snowflake) ?? opt.emoji;
|
|
||||||
button.setEmoji(emo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return button;
|
|
||||||
});
|
|
||||||
const rows = splitButtonsIntoRows(buttons);
|
|
||||||
|
|
||||||
await message.edit({
|
|
||||||
components: rows,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channel_id: message.channelId,
|
channel_id: message.channelId,
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { MessageActionRow, MessageButton, Snowflake } from "discord.js";
|
||||||
|
import { chunkArray } from "../../../utils";
|
||||||
|
import { RoleButtonsPluginType, TRoleButtonOption, TRoleButtonsConfigItem } from "../types";
|
||||||
|
import { buildCustomId } from "../../../utils/buildCustomId";
|
||||||
|
import { GuildPluginData } from "knub";
|
||||||
|
import { TooManyComponentsError } from "./TooManyComponentsError";
|
||||||
|
|
||||||
|
export function createButtonComponents(configItem: TRoleButtonsConfigItem): MessageActionRow[] {
|
||||||
|
const rows: MessageActionRow[] = [];
|
||||||
|
|
||||||
|
let currentRow = new MessageActionRow();
|
||||||
|
for (const [index, option] of configItem.options.entries()) {
|
||||||
|
if (currentRow.components.length === 5 || (currentRow.components.length > 0 && option.start_new_row)) {
|
||||||
|
rows.push(currentRow);
|
||||||
|
currentRow = new MessageActionRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
const button = new MessageButton()
|
||||||
|
.setLabel(option.label ?? "")
|
||||||
|
.setStyle(option.style ?? "PRIMARY")
|
||||||
|
.setCustomId(buildCustomId("roleButtons", { name: configItem.name, index }));
|
||||||
|
|
||||||
|
if (option.emoji) {
|
||||||
|
button.setEmoji(option.emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentRow.components.push(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRow.components.length > 0) {
|
||||||
|
rows.push(currentRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.length > 5) {
|
||||||
|
throw new TooManyComponentsError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
import { MessageActionRow, MessageButton } from "discord.js";
|
|
||||||
import { chunkArray } from "../../../utils";
|
|
||||||
|
|
||||||
export function splitButtonsIntoRows(buttons: MessageButton[]): MessageActionRow[] {
|
|
||||||
// Max 5 buttons per row
|
|
||||||
const buttonChunks = chunkArray(buttons, 5);
|
|
||||||
return buttonChunks.map((chunk) => {
|
|
||||||
const row = new MessageActionRow();
|
|
||||||
row.setComponents(chunk);
|
|
||||||
return row;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -16,6 +16,7 @@ const RoleButtonOption = t.type({
|
||||||
label: tNullable(t.string),
|
label: tNullable(t.string),
|
||||||
emoji: tNullable(t.string),
|
emoji: tNullable(t.string),
|
||||||
style: tNullable(t.keyof(ButtonStyles)), // https://discord.js.org/#/docs/discord.js/v13/typedef/MessageButtonStyle
|
style: tNullable(t.keyof(ButtonStyles)), // https://discord.js.org/#/docs/discord.js/v13/typedef/MessageButtonStyle
|
||||||
|
start_new_row: tNullable(t.boolean),
|
||||||
});
|
});
|
||||||
export type TRoleButtonOption = t.TypeOf<typeof RoleButtonOption>;
|
export type TRoleButtonOption = t.TypeOf<typeof RoleButtonOption>;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue