mirror of
https://github.com/veganhacktivists/arabot.git
synced 2025-05-19 11:04:14 +02:00
Merge pull request #77 from veganhacktivists/main
update restrict branch
This commit is contained in:
commit
cf0078ad25
60
package-lock.json
generated
60
package-lock.json
generated
@ -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": {
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
17
prisma/migrations/20230211001033_vcmute/migration.sql
Normal file
17
prisma/migrations/20230211001033_vcmute/migration.sql
Normal file
@ -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;
|
@ -47,6 +47,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 {
|
||||
@ -127,3 +129,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?
|
||||
}
|
||||
|
119
src/commands/mod/softMute.ts
Normal file
119
src/commands/mod/softMute.ts
Normal file
@ -0,0 +1,119 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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('✅');
|
||||
}
|
||||
}
|
163
src/commands/mod/vcMute.ts
Normal file
163
src/commands/mod/vcMute.ts
Normal file
@ -0,0 +1,163 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
if (member.voice.channel !== null) {
|
||||
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
|
||||
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}`,
|
||||
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);
|
||||
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('✅');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if mod is in database
|
||||
if (!await userExists(mod.id)) {
|
||||
await addExistingUser(mod);
|
||||
}
|
||||
|
||||
// Add VC Mute
|
||||
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}`);
|
||||
|
||||
await message.react('✅');
|
||||
}
|
||||
}
|
77
src/listeners/vcMute.ts
Normal file
77
src/listeners/vcMute.ts
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
src/utils/database/vcMute.ts
Normal file
69
src/utils/database/vcMute.ts
Normal file
@ -0,0 +1,69 @@
|
||||
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 mute = await container.database.vCMute.findFirst({
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
orderBy: {
|
||||
id: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
if (mute === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Query to deactivate the specific sus note
|
||||
await container.database.vCMute.update({
|
||||
where: {
|
||||
id: mute.id,
|
||||
},
|
||||
data: {
|
||||
endTime: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function checkActive(userId: Snowflake) {
|
||||
const mute = await container.database.vCMute.findFirst({
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
endTime: true,
|
||||
},
|
||||
orderBy: {
|
||||
id: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
if (mute === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mute.endTime === null;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user