diff --git a/src/commands/roles/nvAccess.ts b/src/commands/roles/nvAccess.ts new file mode 100644 index 0000000..5fddacf --- /dev/null +++ b/src/commands/roles/nvAccess.ts @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + Animal Rights Advocates Discord Bot + Copyright (C) 2023 Anthony Berg + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +import { Command } from '@sapphire/framework'; +import type { Message } from 'discord.js'; +import IDs from '#utils/ids'; +import { DurationFormatter } from '@sapphire/time-utilities'; + +export class ActivistCommand extends Command { + public constructor(context: Command.Context, options: Command.Options) { + super(context, { + ...options, + name: 'nvaccess', + description: 'Gives the nvaccess role', + preconditions: ['DevCoordinatorOnly'], + }); + } + + public async messageRun(message: Message) { + const { guild } = message; + + if (guild === null) { + await message.reply('Guild is null'); + await message.react('❌'); + return; + } + await guild.members.fetch(); + + const vegan = await guild.roles.cache.get(IDs.roles.vegan.vegan); + + if (vegan === undefined) { + return; + } + + const vegans = vegan.members.map((member) => member); + const count = vegans.length; + const timeout = 1500; + + await message.reply(`Starting the process now, ETA to completion: ${new DurationFormatter().format(timeout * count)}`); + + for (let i = 0; i < count; i += 1) { + const member = vegans[i]; + setTimeout(async () => { + await member.roles.add(IDs.roles.vegan.nvAccess); + this.container.logger.debug(`NVAccess: Processed ${i + 1}/${count}`); + }, timeout * i); + } + } +} diff --git a/src/interaction-handlers/nonVeganAccess.ts b/src/interaction-handlers/nonVeganAccess.ts new file mode 100644 index 0000000..c2e6d4b --- /dev/null +++ b/src/interaction-handlers/nonVeganAccess.ts @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + Animal Rights Advocates Discord Bot + Copyright (C) 2023 Anthony Berg + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import { InteractionHandler, InteractionHandlerTypes, PieceContext } from '@sapphire/framework'; +import type { ButtonInteraction, GuildMember } from 'discord.js'; +import IDs from '#utils/ids'; + +export class NonVeganAccessButtonHandler extends InteractionHandler { + public constructor(ctx: PieceContext, options: InteractionHandler.Options) { + super(ctx, { + ...options, + interactionHandlerType: InteractionHandlerTypes.Button, + }); + } + + public override parse(interaction: ButtonInteraction) { + if (interaction.customId !== 'nvAccess') return this.none(); + + return this.some(); + } + + public async run(interaction: ButtonInteraction) { + let { member } = interaction; + + const errorMessage = 'There was an error giving you the role, please try again later or contact ModMail/the developer ' + + 'to sort out this problem.'; + + if (member === null) { + await interaction.reply({ + content: errorMessage, + ephemeral: true, + }); + return; + } + + try { + member = member as GuildMember; + + if (!member.roles.cache.has(IDs.roles.vegan.vegan)) { + await interaction.reply({ + content: 'You need to be vegan to use this button!', + ephemeral: true, + }); + return; + } + + if (member.roles.cache.has(IDs.roles.vegan.nvAccess)) { + await member.roles.remove(IDs.roles.vegan.nvAccess); + await interaction.reply({ + content: 'Your access from the non vegan section has been removed. ' + + 'If you want to gain access again, click this button again.', + ephemeral: true, + }); + return; + } + + await member.roles.add(IDs.roles.vegan.nvAccess); + await interaction.reply({ + content: 'Your access to the non vegan section has been given back. ' + + 'If you want to remove access again, click this button again.', + ephemeral: true, + }); + } catch (error) { + this.container.logger.error(`Non Vegan Access Interaction: ${error}`); + await interaction.reply({ + content: errorMessage, + ephemeral: true, + }); + } + } +} diff --git a/src/listeners/nonVeganAccess.ts b/src/listeners/nonVeganAccess.ts new file mode 100644 index 0000000..afee1da --- /dev/null +++ b/src/listeners/nonVeganAccess.ts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + Animal Rights Advocates Discord Bot + Copyright (C) 2023 Anthony Berg + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import { Listener } from '@sapphire/framework'; +import { ButtonStyle, ActionRowBuilder, ButtonBuilder } from 'discord.js'; + +import type { + Client, + TextChannel, +} from 'discord.js'; +import IDs from '#utils/ids'; + +export class NonVeganAccessReady extends Listener { + public constructor(context: Listener.Context, options: Listener.Options) { + super(context, { + ...options, + once: true, + event: 'ready', + enabled: false, + }); + } + + public async run(client: Client) { + let roles = client.channels.cache + .get(IDs.channels.information.roles) as TextChannel | undefined; + if (roles === undefined) { + roles = await client.channels + .fetch(IDs.channels.information.roles) as TextChannel | undefined; + if (roles === undefined) { + this.container.logger.error('nonVeganAccess: Roles not found'); + return; + } + } + + const botId = this.container.client.id; + const messages = await roles.messages.fetch(); + const message = messages.first(); + + const content = '**Change access to non-vegan section of the server:**\n\n' + + 'If you\'re vegan and want your access removed/added back to the non vegan sections, ' + + 'press the button bellow to remove/gain access to the non vegan sections.'; + + const button = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId('nvAccess') + .setLabel('Non Vegan Access') + .setStyle(ButtonStyle.Primary), + ); + + if (message?.author.id !== botId) { + await roles.send({ + content, + components: [button], + }); + } else if (message?.author.id === botId && message?.components.length < 1) { + await message.delete(); + await roles.send({ + content, + components: [button], + }); + } + } +} diff --git a/src/utils/devIDs.ts b/src/utils/devIDs.ts index f8e2fb4..b89f977 100644 --- a/src/utils/devIDs.ts +++ b/src/utils/devIDs.ts @@ -28,6 +28,7 @@ const devIDs = { vegan: { vegan: '999431675098447937', activist: '999431675098447934', + nvAccess: '1076859125415301141', plus: '999431675010359460', }, restrictions: { diff --git a/src/utils/ids.ts b/src/utils/ids.ts index e09e7d2..c69c51b 100644 --- a/src/utils/ids.ts +++ b/src/utils/ids.ts @@ -31,6 +31,7 @@ let IDs = { vegan: { vegan: '788114978020392982', activist: '730915638746546257', + nvAccess: '1076857105648209971', plus: '798682625619132428', }, restrictions: {