Create button event to gain the server access role #398

Merged
Vylpes merged 2 commits from feature/232-server-access-button into develop 2024-01-26 20:59:05 +00:00
10 changed files with 179 additions and 33 deletions
Showing only changes of commit 8598419e1f - Show all commits

View file

@ -0,0 +1,42 @@
import { ButtonInteraction, CacheType } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import SettingsHelper from "../helpers/SettingsHelper";
export default class Verify extends ButtonEvent {
public override async execute(interaction: ButtonInteraction<CacheType>) {
if (!interaction.guildId || !interaction.guild) return;
const roleName = await SettingsHelper.GetSetting("verification.role", interaction.guildId);
if (!roleName) return;
const role = interaction.guild.roles.cache.find(x => x.name == roleName);
if (!role) {
await interaction.reply({
content: `Unable to find the role, ${roleName}`,
ephemeral: true,
});
return;
}
const member = interaction.guild.members.cache.find(x => x.id == interaction.user.id);
if (!member || !member.manageable) {
await interaction.reply({
content: "Unable to give role to user",
ephemeral: true,
});
return;
}
await member.roles.add(role);
await interaction.reply({
content: "Given role",
ephemeral: true,
});
}
}

View file

@ -9,10 +9,13 @@ import { Command } from "../type/command";
import { Events } from "./events"; import { Events } from "./events";
import { Util } from "./util"; import { Util } from "./util";
import AppDataSource from "../database/dataSources/appDataSource"; import AppDataSource from "../database/dataSources/appDataSource";
import ButtonEventItem from "../contracts/ButtonEventItem";
import { ButtonEvent } from "../type/buttonEvent";
export class CoreClient extends Client { export class CoreClient extends Client {
private static _commandItems: ICommandItem[]; private static _commandItems: ICommandItem[];
private static _eventItems: IEventItem[]; private static _eventItems: IEventItem[];
private static _buttonEvents: ButtonEventItem[];
private _events: Events; private _events: Events;
private _util: Util; private _util: Util;
@ -25,12 +28,17 @@ export class CoreClient extends Client {
return this._eventItems; return this._eventItems;
} }
public static get buttonEvents(): ButtonEventItem[] {
return this._buttonEvents;
}
constructor(intents: number[], partials: Partials[]) { constructor(intents: number[], partials: Partials[]) {
super({ intents: intents, partials: partials }); super({ intents: intents, partials: partials });
dotenv.config(); dotenv.config();
CoreClient._commandItems = []; CoreClient._commandItems = [];
CoreClient._eventItems = []; CoreClient._eventItems = [];
CoreClient._buttonEvents = [];
this._events = new Events(); this._events = new Events();
this._util = new Util(); this._util = new Util();
@ -73,4 +81,13 @@ export class CoreClient extends Client {
CoreClient._eventItems.push(item); CoreClient._eventItems.push(item);
} }
public static RegisterButtonEvent(buttonId: string, event: ButtonEvent) {
const item: ButtonEventItem = {
ButtonId: buttonId,
Event: event,
};
CoreClient._buttonEvents.push(item);
}
} }

View file

@ -1,40 +1,18 @@
import { Interaction } from "discord.js"; import { Interaction } from "discord.js";
import ICommandItem from "../contracts/ICommandItem"; import ChatInputCommand from "./interactionCreate/chatInputCommand";
import SettingsHelper from "../helpers/SettingsHelper"; import Button from "./interactionCreate/button";
import { CoreClient } from "./client";
export class Events { export class Events {
public async onInteractionCreate(interaction: Interaction) { public async onInteractionCreate(interaction: Interaction) {
if (!interaction.isChatInputCommand()) return;
if (!interaction.guildId) return; if (!interaction.guildId) return;
const disabledCommandsString = await SettingsHelper.GetSetting("commands.disabled", interaction.guildId); if (interaction.isChatInputCommand()) {
const disabledCommands = disabledCommandsString?.split(","); ChatInputCommand.onChatInput(interaction);
const disabledCommandsMessage = await SettingsHelper.GetSetting("commands.disabled.message", interaction.guildId);
if (disabledCommands?.find(x => x == interaction.commandName)) {
await interaction.reply(disabledCommandsMessage || "This command is disabled.");
return;
} }
const item = CoreClient.commandItems.find(x => x.Name == interaction.commandName && !x.ServerId); if (interaction.isButton()) {
const itemForServer = CoreClient.commandItems.find(x => x.Name == interaction.commandName && x.ServerId == interaction.guildId); Button.onButtonClicked(interaction);
let itemToUse: ICommandItem;
if (!itemForServer) {
if (!item) {
await interaction.reply('Command not found');
return;
} }
itemToUse = item;
} else {
itemToUse = itemForServer;
}
itemToUse.Command.execute(interaction);
} }
// Emit when bot is logged in and ready to use // Emit when bot is logged in and ready to use

View file

@ -0,0 +1,17 @@
import { ButtonInteraction } from "discord.js";
import { CoreClient } from "../client";
export default class Button {
public static async onButtonClicked(interaction: ButtonInteraction) {
if (!interaction.isButton) return;
const item = CoreClient.buttonEvents.find(x => x.ButtonId == interaction.customId.split(" ")[0]);
if (!item) {
await interaction.reply("Event not found.");
return;
}
item.Event.execute(interaction);
}
}

View file

@ -0,0 +1,27 @@
import { Interaction } from "discord.js";
import { CoreClient } from "../client";
import ICommandItem from "../../contracts/ICommandItem";
export default class ChatInputCommand {
public static async onChatInput(interaction: Interaction) {
if (!interaction.isChatInputCommand()) return;
const item = CoreClient.commandItems.find(x => x.Name == interaction.commandName && !x.ServerId);
const itemForServer = CoreClient.commandItems.find(x => x.Name == interaction.commandName && x.ServerId == interaction.guildId);
let itemToUse: ICommandItem;
if (!itemForServer) {
if (!item) {
await interaction.reply("Command not found.");
return;
}
itemToUse = item;
} else {
itemToUse = itemForServer;
}
itemToUse.Command.execute(interaction);
}
}

View file

@ -1,7 +1,8 @@
import { CommandInteraction, EmbedBuilder, PermissionsBitField, SlashCommandBuilder } from "discord.js"; import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder, PermissionsBitField, SlashCommandBuilder } from "discord.js";
import { existsSync, readFileSync } from "fs"; import { existsSync, readFileSync } from "fs";
import EmbedColours from "../constants/EmbedColours"; import EmbedColours from "../constants/EmbedColours";
import { Command } from "../type/command"; import { Command } from "../type/command";
import SettingsHelper from "../helpers/SettingsHelper";
interface IRules { interface IRules {
title?: string; title?: string;
@ -14,13 +15,36 @@ export default class Rules extends Command {
constructor() { constructor() {
super(); super();
super.CommandBuilder = new SlashCommandBuilder() this.CommandBuilder = new SlashCommandBuilder()
.setName("rules") .setName('rules')
.setDescription("Send the rules embeds for this server") .setDescription("Rules-related commands")
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator); .setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator)
.addSubcommand(x =>
x
.setName('embeds')
.setDescription('Send the rules embeds for this server'))
.addSubcommand(x =>
x
.setName('access')
.setDescription('Send the server verification embed button'));
} }
public override async execute(interaction: CommandInteraction) { public override async execute(interaction: CommandInteraction) {
if (!interaction.isChatInputCommand()) return;
switch (interaction.options.getSubcommand()) {
case "embeds":
await this.SendEmbeds(interaction);
break;
case "access":
await this.SendAccessButton(interaction);
break;
default:
await interaction.reply("Subcommand doesn't exist.");
}
}
private async SendEmbeds(interaction: CommandInteraction) {
if (!interaction.guildId) return; if (!interaction.guildId) return;
if (!existsSync(`${process.cwd()}/data/rules/${interaction.guildId}.json`)) { if (!existsSync(`${process.cwd()}/data/rules/${interaction.guildId}.json`)) {
@ -71,4 +95,27 @@ export default class Rules extends Command {
await interaction.reply({ embeds: [ successEmbed ], ephemeral: true }); await interaction.reply({ embeds: [ successEmbed ], ephemeral: true });
} }
private async SendAccessButton(interaction: CommandInteraction) {
if (!interaction.guildId) return;
const buttonLabel = await SettingsHelper.GetSetting("rules.access.label", interaction.guildId);
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId('verify')
.setStyle(ButtonStyle.Primary)
.setLabel(buttonLabel || "Verify")
]);
await interaction.channel?.send({
components: [ row ]
});
await interaction.reply({
content: "Success",
ephemeral: true,
});
}
} }

View file

@ -31,6 +31,7 @@ export default class DefaultValues {
// Rules (Command) // Rules (Command)
this.values.push({ Key: "rules.file", Value: "data/rules/rules" }); this.values.push({ Key: "rules.file", Value: "data/rules/rules" });
this.values.push({ Key: "rules.access.label", Value: "Verify" });
// Channels // Channels
this.values.push({ Key: "channels.logs.message", Value: "message-logs" }); this.values.push({ Key: "channels.logs.message", Value: "message-logs" });

View file

@ -0,0 +1,8 @@
import { ButtonEvent } from "../type/buttonEvent";
interface ButtonEventItem {
ButtonId: string,
Event: ButtonEvent,
}
export default ButtonEventItem;

View file

@ -84,4 +84,8 @@ export default class Registry {
CoreClient.RegisterEvent(EventType.MessageUpdate, MessageUpdate); CoreClient.RegisterEvent(EventType.MessageUpdate, MessageUpdate);
CoreClient.RegisterEvent(EventType.MessageCreate, MessageCreate); CoreClient.RegisterEvent(EventType.MessageCreate, MessageCreate);
} }
public static RegisterButtonEvents() {
}
} }

5
src/type/buttonEvent.ts Normal file
View file

@ -0,0 +1,5 @@
import { ButtonInteraction } from "discord.js";
export abstract class ButtonEvent {
abstract execute(interaction: ButtonInteraction): Promise<void>;
}