diff --git a/src/commands/mod/restriction/restrict.ts b/src/commands/mod/restriction/restrict.ts index cfc3915..3810e8d 100644 --- a/src/commands/mod/restriction/restrict.ts +++ b/src/commands/mod/restriction/restrict.ts @@ -214,6 +214,7 @@ export async function restrictRun( IDs.roles.vegan.vegan, IDs.roles.vegan.plus, IDs.roles.vegan.activist, + IDs.roles.vegan.nvAccess, IDs.roles.trusted, IDs.roles.nonvegan.nonvegan, IDs.roles.nonvegan.convinced, diff --git a/src/commands/roles/vegan.ts b/src/commands/roles/vegan.ts index 3d26932..a68a3c8 100644 --- a/src/commands/roles/vegan.ts +++ b/src/commands/roles/vegan.ts @@ -103,6 +103,7 @@ export class VeganCommand extends Command { await guildMember.roles.remove([ vegan, IDs.roles.vegan.activist, + IDs.roles.vegan.nvAccess, ]); await interaction.reply({ content: `Removed the ${vegan.name} role from ${user}`, @@ -113,7 +114,10 @@ export class VeganCommand extends Command { } // Add Vegan role to the user - await guildMember.roles.add(vegan); + await guildMember.roles.add([ + vegan, + IDs.roles.vegan.nvAccess, + ]); await guildMember.roles.remove([ IDs.roles.nonvegan.nonvegan, IDs.roles.nonvegan.convinced, 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..f005e1f --- /dev/null +++ b/src/listeners/nonVeganAccess.ts @@ -0,0 +1,79 @@ +// 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', + }); + } + + 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/listeners/rolesJoinServer.ts b/src/listeners/rolesJoinServer.ts index a4e7216..bb77209 100644 --- a/src/listeners/rolesJoinServer.ts +++ b/src/listeners/rolesJoinServer.ts @@ -19,7 +19,7 @@ import { Listener } from '@sapphire/framework'; import type { GuildMember } from 'discord.js'; -// import { fetchRoles } from '#utils/database/dbExistingUser'; +import { fetchRoles } from '#utils/database/dbExistingUser'; import IDs from '#utils/ids'; import { blockTime } from '#utils/database/verification'; import { checkActive, getSection } from '#utils/database/restriction'; @@ -35,13 +35,14 @@ export class RolesJoinServerListener extends Listener { public async run(member: GuildMember) { // Add basic roles - const roles = []; - // const roles = await fetchRoles(member.id); + const roles = await fetchRoles(member.id); // Check if the user is restricted if (await checkActive(member.id)) { const section = await getSection(member.id); - roles.length = 0; + for (let i = 0; i < roles.length; i += 1) { + roles.pop(); + } roles.push(IDs.roles.restrictions.restricted[section - 1]); } diff --git a/src/listeners/verification/joinVC.ts b/src/listeners/verification/joinVC.ts index f5489d3..1af6c45 100644 --- a/src/listeners/verification/joinVC.ts +++ b/src/listeners/verification/joinVC.ts @@ -38,6 +38,7 @@ import { ActionRowBuilder, EmbedBuilder, } from 'discord.js'; +import { createVerificationText, createVerificationVoice } from '#utils/verification'; import { maxVCs, questionInfo, serverFind } from '#utils/verificationConfig'; import { joinVerification, startVerification, finishVerification } from '#utils/database/verification'; import { findNotes } from '#utils/database/sus'; @@ -139,73 +140,19 @@ export class VerificationJoinVCListener extends Listener { .filter((c) => c.type === ChannelType.GuildVoice); // Create a text channel for verifiers only - // Checks if there are more than 10 voice channels if (!verifier) { - // TODO refactor this mess to circumvent - // "Contains words not allowed for servers in Server Discovery." let verificationText: TextChannel; let bannedName = false; try { - verificationText = await guild.channels.create({ - name: `✅┃${member.displayName}-verification`, - type: ChannelType.GuildText, - topic: `Channel for verifiers only. ${member.id} ${channel.id} (Please do not change this)`, - parent: category.id, - userLimit: 1, - permissionOverwrites: [ - { - id: guild.roles.everyone, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.verifyBlock, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.staff.verifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.staff.trialVerifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - ], - }); + verificationText = await createVerificationText(member, channel, category); } catch { - verificationText = await guild.channels.create({ - name: `✅┃${member.displayName}-verification`, - type: ChannelType.GuildText, - topic: `Channel for verifiers only. ${member.id} ${channel.id} (Please do not change this)`, - parent: category.id, - userLimit: 1, - permissionOverwrites: [ - { - id: guild.roles.everyone, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.verifyBlock, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.staff.verifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.staff.trialVerifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel], - }, - ], - }); bannedName = true; + verificationText = await createVerificationText( + member, + channel, + category, + bannedName, + ); } if (!bannedName) { @@ -230,102 +177,9 @@ export class VerificationJoinVCListener extends Listener { // Checks if there are more than 10 voice channels if (listVoiceChannels.size > maxVCs - 1) { - await guild.channels.create({ - name: 'Verification', - type: ChannelType.GuildVoice, - parent: category.id, - userLimit: 1, - permissionOverwrites: [ - { - id: guild.roles.everyone, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Stream], - }, - { - id: IDs.roles.verifyBlock, - deny: [PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.nonvegan.nonvegan, - allow: [PermissionsBitField.Flags.ViewChannel], - deny: [PermissionsBitField.Flags.Connect], - }, - { - id: IDs.roles.vegan.vegan, - allow: [PermissionsBitField.Flags.ViewChannel], - deny: [PermissionsBitField.Flags.Connect], - }, - { - id: IDs.roles.vegan.activist, - deny: [PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect], - }, - { - id: IDs.roles.staff.verifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - { - id: IDs.roles.staff.trialVerifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - ], - }); + await createVerificationVoice(category, true); } else { - await guild.channels.create({ - name: 'Verification', - type: ChannelType.GuildVoice, - parent: category.id, - userLimit: 1, - permissionOverwrites: [ - { - id: guild.roles.everyone, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.verifyBlock, - deny: [PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.nonvegan.nonvegan, - allow: [PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.vegan.vegan, - allow: [PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.vegan.activist, - deny: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.Connect], - }, - { - id: IDs.roles.staff.verifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - { - id: IDs.roles.staff.trialVerifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - ], - }); + await createVerificationVoice(category); } // Change permissions to join the current channel @@ -680,6 +534,7 @@ export class VerificationJoinVCListener extends Listener { } if (roles.vegan) { rolesText += `<@&${IDs.roles.vegan.vegan}>`; + rolesText += `<@&${IDs.roles.vegan.nvAccess}`; } else { rolesText += `<@&${IDs.roles.nonvegan.nonvegan}>`; } @@ -711,6 +566,7 @@ export class VerificationJoinVCListener extends Listener { } if (roles.vegan) { rolesAdd.push(IDs.roles.vegan.vegan); + rolesAdd.push(IDs.roles.vegan.nvAccess); } else { rolesAdd.push(IDs.roles.nonvegan.nonvegan); } diff --git a/src/listeners/verification/leaveVC.ts b/src/listeners/verification/leaveVC.ts index e110d71..ea33c8f 100644 --- a/src/listeners/verification/leaveVC.ts +++ b/src/listeners/verification/leaveVC.ts @@ -21,7 +21,8 @@ import { Listener } from '@sapphire/framework'; import type { VoiceState, CategoryChannel, VoiceChannel, TextChannel, } from 'discord.js'; -import { time, ChannelType, PermissionsBitField } from 'discord.js'; +import { time, ChannelType } from 'discord.js'; +import { createVerificationVoice } from '#utils/verification'; import { maxVCs, leaveBan } from '#utils/verificationConfig'; import { getUser, checkFinish, countIncomplete } from '#utils/database/verification'; import { fetchRoles } from '#utils/database/dbExistingUser'; @@ -126,52 +127,7 @@ export class VerificationLeaveVCListener extends Listener { // If there are no VCs left in verification after having the channel deleted if (listVoiceChannels.size - 1 === 0) { // Create a verification channel - await guild.channels.create({ - name: 'Verification', - type: ChannelType.GuildVoice, - parent: category.id, - userLimit: 1, - permissionOverwrites: [ - { - id: guild.roles.everyone, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.verifyBlock, - deny: [PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.nonvegan.nonvegan, - allow: [PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.vegan.vegan, - allow: [PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.vegan.activist, - deny: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.Connect], - }, - { - id: IDs.roles.staff.verifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - { - id: IDs.roles.staff.trialVerifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - ], - }); + await createVerificationVoice(category); } // If there are less than 10, stop diff --git a/src/listeners/verification/start.ts b/src/listeners/verification/start.ts index 9500a01..afe081f 100644 --- a/src/listeners/verification/start.ts +++ b/src/listeners/verification/start.ts @@ -24,7 +24,8 @@ import type { TextChannel, VoiceChannel, } from 'discord.js'; -import { ChannelType, PermissionsBitField } from 'discord.js'; +import { ChannelType } from 'discord.js'; +import { createVerificationVoice } from '#utils/verification'; import IDs from '#utils/ids'; export class VerificationReady extends Listener { @@ -84,52 +85,7 @@ export class VerificationReady extends Listener { } }); if (!verification) { - await category.guild.channels.create({ - name: 'Verification', - type: ChannelType.GuildVoice, - parent: category.id, - userLimit: 1, - permissionOverwrites: [ - { - id: category.guild.roles.everyone, - deny: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.verifyBlock, - deny: [PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.SendMessages], - }, - { - id: IDs.roles.nonvegan.nonvegan, - allow: [PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.vegan.vegan, - allow: [PermissionsBitField.Flags.ViewChannel], - }, - { - id: IDs.roles.vegan.activist, - deny: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.Connect], - }, - { - id: IDs.roles.staff.verifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - { - id: IDs.roles.staff.trialVerifier, - allow: [PermissionsBitField.Flags.SendMessages, - PermissionsBitField.Flags.ViewChannel, - PermissionsBitField.Flags.Connect, - PermissionsBitField.Flags.MuteMembers], - }, - ], - }); + await createVerificationVoice(category); } } } 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: { diff --git a/src/utils/verification.ts b/src/utils/verification.ts new file mode 100644 index 0000000..e752249 --- /dev/null +++ b/src/utils/verification.ts @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + Animal Rights Advocates Discord Bot + Copyright (C) 2022 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 { + CategoryChannel, + ChannelType, + GuildMember, + PermissionsBitField, + VoiceBasedChannel, +} from 'discord.js'; +import IDs from '#utils/ids'; + +export async function createVerificationText( + member: GuildMember, + voiceChannel: VoiceBasedChannel, + category: CategoryChannel, + bannedName = false, +) { + const { guild } = category; + + const channel = await guild.channels.create({ + name: `✅┃${!bannedName ? member.displayName : member.id}-verification`, + type: ChannelType.GuildText, + topic: `Channel for verifiers only. ${member.id} ${voiceChannel.id} (Please do not change this)`, + parent: category.id, + userLimit: 1, + permissionOverwrites: [ + { + id: guild.roles.everyone, + deny: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel], + }, + { + id: IDs.roles.verifyBlock, + deny: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel], + }, + { + id: IDs.roles.staff.verifier, + allow: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel], + }, + { + id: IDs.roles.staff.trialVerifier, + allow: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel], + }, + ], + }); + return channel; +} + +export async function createVerificationVoice( + category: CategoryChannel, + full = false, +) { + const { guild } = category; + + const channel = await guild.channels.create({ + name: 'Verification', + type: ChannelType.GuildVoice, + parent: category.id, + userLimit: 1, + permissionOverwrites: [ + { + id: guild.roles.everyone, + deny: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.Stream], + }, + { + id: IDs.roles.verifyBlock, + deny: [PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.Connect, + PermissionsBitField.Flags.SendMessages], + }, + { + id: IDs.roles.nonvegan.nonvegan, + allow: [PermissionsBitField.Flags.ViewChannel], + }, + { + id: IDs.roles.vegan.vegan, + allow: [PermissionsBitField.Flags.ViewChannel], + }, + { + id: IDs.roles.vegan.activist, + deny: [PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.Connect], + }, + { + id: IDs.roles.staff.verifier, + allow: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.Connect, + PermissionsBitField.Flags.MuteMembers], + }, + { + id: IDs.roles.staff.trialVerifier, + allow: [PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.Connect, + PermissionsBitField.Flags.MuteMembers], + }, + ], + }); + + if (full) { + await channel.permissionOverwrites.edit(IDs.roles.nonvegan.nonvegan, { Connect: false }); + await channel.permissionOverwrites.edit(IDs.roles.vegan.vegan, { Connect: false }); + } +}