From 8d1276ab2cc158f43269b0abce28df1f778d4c00 Mon Sep 17 00:00:00 2001 From: smyalygames Date: Thu, 9 Feb 2023 17:56:53 +0000 Subject: [PATCH 1/9] feat(arabot): add soft mute basics --- src/commands/mod/softMute.ts | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/commands/mod/softMute.ts diff --git a/src/commands/mod/softMute.ts b/src/commands/mod/softMute.ts new file mode 100644 index 0000000..1543966 --- /dev/null +++ b/src/commands/mod/softMute.ts @@ -0,0 +1,105 @@ +// 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 { Args, Command, RegisterBehavior } from '@sapphire/framework'; +import type { GuildMember, Message } from 'discord.js'; +import IDs from '#utils/ids'; + +export class SoftMuteCommand extends Command { + public constructor(context: Command.Context, options: Command.Options) { + super(context, { + ...options, + name: 'softmute', + aliases: ['sm'], + description: 'Prevent a user from reacting to a message by giving ' + + 'the soft mute role', + preconditions: ['ModOnly'], + }); + } + + // Registers that this is a slash command + public override registerApplicationCommands(registry: Command.Registry) { + registry.registerChatInputCommand( + (builder) => builder + .setName(this.name) + .setDescription(this.description) + .addUserOption((option) => option.setName('user') + .setDescription('User to soft mute') + .setRequired(true)), + { + behaviorWhenNotIdentical: RegisterBehavior.Overwrite, + }, + ); + } + + // Command run + public async chatInputRun(interaction: Command.ChatInputCommandInteraction) { + // TODO add database updates + // Get the arguments + const user = interaction.options.getUser('user', true); + const { guild } = interaction; + + // Checks if all the variables are of the right type + if (guild === null) { + await interaction.reply({ + content: 'Error fetching the guild!', + ephemeral: true, + fetchReply: true, + }); + return; + } + + // Gets guildMember whilst removing the ability of each other variables being null + const guildMember = guild.members.cache.get(user.id); + + // Checks if guildMember is null + if (guildMember === undefined) { + await interaction.reply({ + content: 'Error fetching user!', + ephemeral: true, + fetchReply: true, + }); + return; + } + + await guildMember.roles.add(IDs.roles.restrictions.softMute); + + await interaction.reply({ + content: `Soft muted ${user}`, + fetchReply: true, + ephemeral: true, + }); + } + + public async messageRun(message: Message, args: Args) { + // Get arguments + let user: GuildMember; + try { + user = await args.pick('member'); + } catch { + await message.react('❌'); + await message.reply('User was not provided!'); + return; + } + + await user.roles.add(IDs.roles.restrictions.softMute); + + await message.react('✅'); + } +} From fa0d9c2a6030b9e9089a4ecfc54b8cdd3dd3aa15 Mon Sep 17 00:00:00 2001 From: smyalygames Date: Fri, 10 Feb 2023 01:17:52 +0000 Subject: [PATCH 2/9] feat(arabot): add soft mute command --- src/commands/mod/softMute.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/commands/mod/softMute.ts b/src/commands/mod/softMute.ts index 1543966..5d8caa5 100644 --- a/src/commands/mod/softMute.ts +++ b/src/commands/mod/softMute.ts @@ -78,12 +78,20 @@ export class SoftMuteCommand extends Command { return; } + if (guildMember.roles.cache.has(IDs.roles.restrictions.softMute)) { + await guildMember.roles.remove(IDs.roles.restrictions.softMute); + await interaction.reply({ + content: `Removed soft muted for ${user}`, + fetchReply: true, + }); + return; + } + await guildMember.roles.add(IDs.roles.restrictions.softMute); await interaction.reply({ content: `Soft muted ${user}`, fetchReply: true, - ephemeral: true, }); } @@ -98,7 +106,13 @@ export class SoftMuteCommand extends Command { return; } - await user.roles.add(IDs.roles.restrictions.softMute); + if (user.roles.cache.has(IDs.roles.restrictions.softMute)) { + await user.roles.remove(IDs.roles.restrictions.softMute); + await message.reply(`Removed soft mute for ${user}`); + } else { + await user.roles.add(IDs.roles.restrictions.softMute); + await message.reply(`Soft muted ${user}`); + } await message.react('✅'); } From 4b6dde3af2f60caa535fa2709aca2242d65dbd99 Mon Sep 17 00:00:00 2001 From: smyalygames Date: Fri, 10 Feb 2023 23:55:11 +0000 Subject: [PATCH 3/9] build(db): update prisma --- package-lock.json | 60 +++++++++++++++++++++++------------------------ package.json | 4 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c44373..b632a10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "license": "GPL-3.0-or-later", "dependencies": { - "@prisma/client": "^4.0.0", + "@prisma/client": "^4.10.1", "@sapphire/discord.js-utilities": "^6.0.0", "@sapphire/framework": "^4.0.1", "@sapphire/plugin-logger": "^3.0.1", @@ -34,7 +34,7 @@ "eslint-config-airbnb-typescript": "^17.0.0", "eslint-import-resolver-typescript": "^3.5.3", "eslint-plugin-import": "^2.27.5", - "prisma": "^4.4.0" + "prisma": "^4.10.1" } }, "node_modules/@cspotcode/source-map-support": { @@ -306,12 +306,12 @@ } }, "node_modules/@prisma/client": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.9.0.tgz", - "integrity": "sha512-bz6QARw54sWcbyR1lLnF2QHvRW5R/Jxnbbmwh3u+969vUKXtBkXgSgjDA85nji31ZBlf7+FrHDy5x+5ydGyQDg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.10.1.tgz", + "integrity": "sha512-VonXLJZybdt8e5XZH5vnIGCRNnIh6OMX1FS3H/yzMGLT3STj5TJ/OkMcednrvELgk8PK89Vo3aSh51MWNO0axA==", "hasInstallScript": true, "dependencies": { - "@prisma/engines-version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5" + "@prisma/engines-version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19" }, "engines": { "node": ">=14.17" @@ -326,16 +326,16 @@ } }, "node_modules/@prisma/engines": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.9.0.tgz", - "integrity": "sha512-t1pt0Gsp+HcgPJrHFc+d/ZSAaKKWar2G/iakrE07yeKPNavDP3iVKPpfXP22OTCHZUWf7OelwKJxQgKAm5hkgw==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.10.1.tgz", + "integrity": "sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA==", "devOptional": true, "hasInstallScript": true }, "node_modules/@prisma/engines-version": { - "version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5.tgz", - "integrity": "sha512-M16aibbxi/FhW7z1sJCX8u+0DriyQYY5AyeTH7plQm9MLnURoiyn3CZBqAyIoQ+Z1pS77usCIibYJWSgleBMBA==" + "version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19.tgz", + "integrity": "sha512-tsjTho7laDhf9EJ9EnDxAPEf7yrigSMDhniXeU4YoWc7azHAs4GPxRi2P9LTFonmHkJLMOLjR77J1oIP8Ife1w==" }, "node_modules/@sapphire/async-queue": { "version": "1.5.0", @@ -3039,13 +3039,13 @@ } }, "node_modules/prisma": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.9.0.tgz", - "integrity": "sha512-bS96oZ5oDFXYgoF2l7PJ3Mp1wWWfLOo8B/jAfbA2Pn0Wm5Z/owBHzaMQKS3i1CzVBDWWPVnOohmbJmjvkcHS5w==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.10.1.tgz", + "integrity": "sha512-0jDxgg+DruB1kHVNlcspXQB9au62IFfVg9drkhzXudszHNUAQn0lVuu+T8np0uC2z1nKD5S3qPeCyR8u5YFLnA==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "4.9.0" + "@prisma/engines": "4.10.1" }, "bin": { "prisma": "build/index.js", @@ -4029,23 +4029,23 @@ } }, "@prisma/client": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.9.0.tgz", - "integrity": "sha512-bz6QARw54sWcbyR1lLnF2QHvRW5R/Jxnbbmwh3u+969vUKXtBkXgSgjDA85nji31ZBlf7+FrHDy5x+5ydGyQDg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.10.1.tgz", + "integrity": "sha512-VonXLJZybdt8e5XZH5vnIGCRNnIh6OMX1FS3H/yzMGLT3STj5TJ/OkMcednrvELgk8PK89Vo3aSh51MWNO0axA==", "requires": { - "@prisma/engines-version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5" + "@prisma/engines-version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19" } }, "@prisma/engines": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.9.0.tgz", - "integrity": "sha512-t1pt0Gsp+HcgPJrHFc+d/ZSAaKKWar2G/iakrE07yeKPNavDP3iVKPpfXP22OTCHZUWf7OelwKJxQgKAm5hkgw==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.10.1.tgz", + "integrity": "sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA==", "devOptional": true }, "@prisma/engines-version": { - "version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5.tgz", - "integrity": "sha512-M16aibbxi/FhW7z1sJCX8u+0DriyQYY5AyeTH7plQm9MLnURoiyn3CZBqAyIoQ+Z1pS77usCIibYJWSgleBMBA==" + "version": "4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.10.1-2.aead147aa326ccb985dcfed5b065b4fdabd44b19.tgz", + "integrity": "sha512-tsjTho7laDhf9EJ9EnDxAPEf7yrigSMDhniXeU4YoWc7azHAs4GPxRi2P9LTFonmHkJLMOLjR77J1oIP8Ife1w==" }, "@sapphire/async-queue": { "version": "1.5.0", @@ -5991,12 +5991,12 @@ "dev": true }, "prisma": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.9.0.tgz", - "integrity": "sha512-bS96oZ5oDFXYgoF2l7PJ3Mp1wWWfLOo8B/jAfbA2Pn0Wm5Z/owBHzaMQKS3i1CzVBDWWPVnOohmbJmjvkcHS5w==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.10.1.tgz", + "integrity": "sha512-0jDxgg+DruB1kHVNlcspXQB9au62IFfVg9drkhzXudszHNUAQn0lVuu+T8np0uC2z1nKD5S3qPeCyR8u5YFLnA==", "devOptional": true, "requires": { - "@prisma/engines": "4.9.0" + "@prisma/engines": "4.10.1" } }, "punycode": { diff --git a/package.json b/package.json index 6521980..65ab526 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/veganhacktivists/arabot#readme", "dependencies": { - "@prisma/client": "^4.0.0", + "@prisma/client": "^4.10.1", "@sapphire/discord.js-utilities": "^6.0.0", "@sapphire/framework": "^4.0.1", "@sapphire/plugin-logger": "^3.0.1", @@ -54,6 +54,6 @@ "eslint-config-airbnb-typescript": "^17.0.0", "eslint-import-resolver-typescript": "^3.5.3", "eslint-plugin-import": "^2.27.5", - "prisma": "^4.4.0" + "prisma": "^4.10.1" } } From b14de4793417881e771259301f2bd710c869fb3c Mon Sep 17 00:00:00 2001 From: smyalygames Date: Sat, 11 Feb 2023 00:35:35 +0000 Subject: [PATCH 4/9] feat(db): add vcmute database --- .../20230211001033_vcmute/migration.sql | 17 +++++++++++++++++ prisma/schema.prisma | 13 +++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 prisma/migrations/20230211001033_vcmute/migration.sql diff --git a/prisma/migrations/20230211001033_vcmute/migration.sql b/prisma/migrations/20230211001033_vcmute/migration.sql new file mode 100644 index 0000000..fe45f2f --- /dev/null +++ b/prisma/migrations/20230211001033_vcmute/migration.sql @@ -0,0 +1,17 @@ +-- CreateTable +CREATE TABLE "VCMute" ( + "id" SERIAL NOT NULL, + "userId" TEXT NOT NULL, + "modId" TEXT NOT NULL, + "time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "endTime" TIMESTAMP(3), + "reason" TEXT, + + CONSTRAINT "VCMute_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "VCMute" ADD CONSTRAINT "VCMute_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "VCMute" ADD CONSTRAINT "VCMute_modId_fkey" FOREIGN KEY ("modId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 129ad31..1c3dfa3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -46,6 +46,8 @@ model User { BanEndMod Ban[] @relation("endBanMod") TempBanUser TempBan[] @relation("tbanUser") TempBanMod TempBan[] @relation("tbanMod") + VCMuteUser VCMute[] @relation("vcMuteUser") + VCMuteMod VCMute[] @relation("vcMuteMod") } model Verify { @@ -124,3 +126,14 @@ model TempBan { active Boolean @default(true) reason String } + +model VCMute { + id Int @id @default(autoincrement()) + user User @relation("vcMuteUser", fields: [userId], references: [id]) + userId String + mod User @relation("vcMuteMod", fields: [modId], references: [id]) + modId String + time DateTime @default(now()) + endTime DateTime? + reason String? +} From 0e31061d9984cff7104f866aa171f8fc485c680d Mon Sep 17 00:00:00 2001 From: smyalygames Date: Sat, 11 Feb 2023 00:35:51 +0000 Subject: [PATCH 5/9] feat(arabot): add vcmute database utils --- src/utils/database/vcMute.ts | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/utils/database/vcMute.ts diff --git a/src/utils/database/vcMute.ts b/src/utils/database/vcMute.ts new file mode 100644 index 0000000..3cb4bf7 --- /dev/null +++ b/src/utils/database/vcMute.ts @@ -0,0 +1,66 @@ +import { container } from '@sapphire/framework'; +import type { Snowflake } from 'discord.js'; + +export async function addMute(userId: Snowflake, modId: Snowflake, reason: string | null) { + // Add the user to the database + await container.database.vCMute.create({ + data: { + user: { + connect: { + id: userId, + }, + }, + mod: { + connect: { + id: modId, + }, + }, + reason, + }, + }); +} + +export async function removeMute(userId: Snowflake) { + const ban = await container.database.vCMute.findFirst({ + where: { + userId, + }, + select: { + id: true, + }, + orderBy: { + id: 'desc', + }, + }); + + if (ban === null) { + return; + } + + // Query to deactivate the specific sus note + await container.database.vCMute.update({ + where: { + id: ban.id, + }, + data: { + endTime: new Date(), + }, + }); +} + +export async function checkActive(userId: Snowflake) { + const ban = await container.database.vCMute.findFirst({ + where: { + userId, + }, + select: { + endTime: true, + }, + orderBy: { + id: 'desc', + }, + }); + + return !(ban === null + || ban.endTime === null); +} From ecf75b63e7daa5ffdfbb6f58df5cf0203fe15b8f Mon Sep 17 00:00:00 2001 From: smyalygames Date: Sat, 11 Feb 2023 00:36:02 +0000 Subject: [PATCH 6/9] feat(arabot): add vcmute command --- src/commands/mod/vcMute.ts | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/commands/mod/vcMute.ts diff --git a/src/commands/mod/vcMute.ts b/src/commands/mod/vcMute.ts new file mode 100644 index 0000000..cb806db --- /dev/null +++ b/src/commands/mod/vcMute.ts @@ -0,0 +1,155 @@ +// 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 { Args, Command, RegisterBehavior } from '@sapphire/framework'; +import type { GuildMember, Message } from 'discord.js'; +import { addMute, removeMute, checkActive } from '#utils/database/vcMute'; +import { addExistingUser, userExists } from '#utils/database/dbExistingUser'; + +export class VCMuteCommand extends Command { + public constructor(context: Command.Context, options: Command.Options) { + super(context, { + ...options, + name: 'vcmute', + aliases: ['vmute'], + description: 'Persists a server mute if a user is trying to bypass mute', + preconditions: [['CoordinatorOnly', 'ModOnly']], + }); + } + + // Registers that this is a slash command + public override registerApplicationCommands(registry: Command.Registry) { + registry.registerChatInputCommand( + (builder) => builder + .setName(this.name) + .setDescription(this.description) + .addUserOption((option) => option.setName('user') + .setDescription('User to persistently mute') + .setRequired(true)) + .addStringOption((option) => option.setName('reason') + .setDescription('Reason for persistently muting the user')), + { + behaviorWhenNotIdentical: RegisterBehavior.Overwrite, + }, + ); + } + + // Command run + public async chatInputRun(interaction: Command.ChatInputCommandInteraction) { + // Get the arguments + const user = interaction.options.getUser('user', true); + const reason = interaction.options.getString('reason'); + const modUser = interaction.member; + const { guild } = interaction; + + // Checks if all the variables are of the right type + if (modUser === null || guild === null) { + await interaction.reply({ + content: 'Error fetching user!', + ephemeral: true, + fetchReply: true, + }); + return; + } + + // Gets guildMember whilst removing the ability of each other variables being null + const member = guild.members.cache.get(user.id); + const mod = guild.members.cache.get(modUser.user.id); + + // Checks if guildMember is null + if (member === undefined || mod === undefined) { + await interaction.reply({ + content: 'Error fetching user!', + ephemeral: true, + fetchReply: true, + }); + return; + } + + // Check if removing VC Mute + if (await checkActive(member.id)) { + await removeMute(member.id); + await member.voice.setMute(false, reason === null ? undefined : reason); + + await interaction.reply({ + content: `Removed server mute from ${user}`, + fetchReply: true, + ephemeral: true, + }); + return; + } + + // Check if mod is in database + if (!await userExists(mod.id)) { + await addExistingUser(mod); + } + + // Add VC Mute + await member.voice.setMute(true, reason === null ? undefined : reason); + await addMute(member.id, mod.id, reason); + await interaction.reply({ + content: `Server muted ${user}`, + fetchReply: true, + ephemeral: true, + }); + } + + public async messageRun(message: Message, args: Args) { + // Get arguments + let member: GuildMember; + try { + member = await args.pick('member'); + } catch { + await message.react('❌'); + await message.reply('User was not provided!'); + return; + } + + const reason = args.finished ? null : await args.rest('string'); + const mod = message.member; + + if (mod === null) { + await message.react('❌'); + await message.reply('Moderator not found! Try again or contact a developer!'); + return; + } + + // Check if removing VC Mute + if (await checkActive(member.id)) { + await removeMute(member.id); + await member.voice.setMute(false, reason === null ? undefined : reason); + + await message.reply(`Removed server mute from ${member}`); + await message.react('✅'); + return; + } + + // Check if mod is in database + if (!await userExists(mod.id)) { + await addExistingUser(mod); + } + + // Add VC Mute + await member.voice.setMute(true, reason === null ? undefined : reason); + await addMute(member.id, mod.id, reason); + await message.reply(`Server muted ${member}`); + + await message.react('✅'); + } +} From c735509f57786a46aac6be2bbfe58319af08771a Mon Sep 17 00:00:00 2001 From: smyalygames Date: Sat, 11 Feb 2023 01:53:24 +0000 Subject: [PATCH 7/9] fix(arabot): fix logic for checkActive --- src/utils/database/vcMute.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/utils/database/vcMute.ts b/src/utils/database/vcMute.ts index 3cb4bf7..e57e63b 100644 --- a/src/utils/database/vcMute.ts +++ b/src/utils/database/vcMute.ts @@ -21,7 +21,7 @@ export async function addMute(userId: Snowflake, modId: Snowflake, reason: strin } export async function removeMute(userId: Snowflake) { - const ban = await container.database.vCMute.findFirst({ + const mute = await container.database.vCMute.findFirst({ where: { userId, }, @@ -33,14 +33,14 @@ export async function removeMute(userId: Snowflake) { }, }); - if (ban === null) { + if (mute === null) { return; } // Query to deactivate the specific sus note await container.database.vCMute.update({ where: { - id: ban.id, + id: mute.id, }, data: { endTime: new Date(), @@ -49,7 +49,7 @@ export async function removeMute(userId: Snowflake) { } export async function checkActive(userId: Snowflake) { - const ban = await container.database.vCMute.findFirst({ + const mute = await container.database.vCMute.findFirst({ where: { userId, }, @@ -61,6 +61,9 @@ export async function checkActive(userId: Snowflake) { }, }); - return !(ban === null - || ban.endTime === null); + if (mute === null) { + return false; + } + + return mute.endTime === null; } From d7aea2c6c1cae814c2f3045e91bcaa55361e8389 Mon Sep 17 00:00:00 2001 From: smyalygames Date: Sat, 11 Feb 2023 01:54:10 +0000 Subject: [PATCH 8/9] fix(arabot): add checkers if user is in vc when server muting --- src/commands/mod/vcMute.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/commands/mod/vcMute.ts b/src/commands/mod/vcMute.ts index cb806db..bfeae20 100644 --- a/src/commands/mod/vcMute.ts +++ b/src/commands/mod/vcMute.ts @@ -85,7 +85,9 @@ export class VCMuteCommand extends Command { // Check if removing VC Mute if (await checkActive(member.id)) { await removeMute(member.id); - await member.voice.setMute(false, reason === null ? undefined : reason); + if (member.voice.channel !== null) { + await member.voice.setMute(false, reason === null ? undefined : reason); + } await interaction.reply({ content: `Removed server mute from ${user}`, @@ -101,7 +103,9 @@ export class VCMuteCommand extends Command { } // Add VC Mute - await member.voice.setMute(true, reason === null ? undefined : reason); + if (member.voice.channel !== null) { + await member.voice.setMute(true, reason === null ? undefined : reason); + } await addMute(member.id, mod.id, reason); await interaction.reply({ content: `Server muted ${user}`, @@ -133,7 +137,9 @@ export class VCMuteCommand extends Command { // Check if removing VC Mute if (await checkActive(member.id)) { await removeMute(member.id); - await member.voice.setMute(false, reason === null ? undefined : reason); + if (member.voice.channel !== null) { + await member.voice.setMute(false, reason === null ? undefined : reason); + } await message.reply(`Removed server mute from ${member}`); await message.react('✅'); @@ -146,7 +152,9 @@ export class VCMuteCommand extends Command { } // Add VC Mute - await member.voice.setMute(true, reason === null ? undefined : reason); + if (member.voice.channel !== null) { + await member.voice.setMute(true, reason === null ? undefined : reason); + } await addMute(member.id, mod.id, reason); await message.reply(`Server muted ${member}`); From dedd72c731a822ddf15fd934d27d9c5ff152c838 Mon Sep 17 00:00:00 2001 From: smyalygames Date: Sat, 11 Feb 2023 01:54:47 +0000 Subject: [PATCH 9/9] feat(arabot): add listener to mute user on join or remove vcmute on unmute --- src/listeners/vcMute.ts | 77 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/listeners/vcMute.ts diff --git a/src/listeners/vcMute.ts b/src/listeners/vcMute.ts new file mode 100644 index 0000000..f6ce33d --- /dev/null +++ b/src/listeners/vcMute.ts @@ -0,0 +1,77 @@ +// 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 type { VoiceState } from 'discord.js'; +import { checkActive, removeMute } from '#utils/database/vcMute'; + +export class VCMuteListener extends Listener { + public constructor(context: Listener.Context, options: Listener.Options) { + super(context, { + ...options, + event: 'voiceStateUpdate', + }); + } + + public async run(oldState: VoiceState, newState: VoiceState) { + // Check the user joining the channel if they need to be muted + if (oldState.channel === null && newState.channel !== null) { + const { member } = newState; + + if (member === null) { + this.container.logger.error('VCMute Listener - GuildMember not found when joining'); + return; + } + + // Check if user is already muted + if (member.voice.serverMute) { + return; + } + + // Check if user is muted on the database + if (!await checkActive(member.id)) { + return; + } + + // Server mute the user + await member.voice.setMute(true); + return; + } + + // Check if the user has been unmuted by a mod + if (oldState.channel !== null && newState.channel !== null) { + const { member } = newState; + + if (member === null) { + this.container.logger.error('VCMute Listener - GuildMember not found when unmuting'); + return; + } + + // Check if user is muted on the database + if (!await checkActive(member.id)) { + return; + } + + // Checks if the user has been unmuted + if (oldState.serverMute && !newState.serverMute) { + await removeMute(member.id); + } + } + } +}