mirror of
https://github.com/veganhacktivists/arabot.git
synced 2025-11-02 22:19:49 +01:00
Merge pull request #78 from veganhacktivists/restrict
feat(arabot): new restrict system
This commit is contained in:
commit
c3dbd42d36
355
src/commands/mod/restriction/restrict.ts
Normal file
355
src/commands/mod/restriction/restrict.ts
Normal file
@ -0,0 +1,355 @@
|
||||
// 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,
|
||||
container,
|
||||
} from '@sapphire/framework';
|
||||
import {
|
||||
ChannelType,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
time,
|
||||
} from 'discord.js';
|
||||
import type {
|
||||
User,
|
||||
Message,
|
||||
TextChannel,
|
||||
Guild,
|
||||
Snowflake,
|
||||
} from 'discord.js';
|
||||
import IDs from '#utils/ids';
|
||||
import { randint } from '#utils/random';
|
||||
import {
|
||||
addEmptyUser,
|
||||
updateUser,
|
||||
userExists,
|
||||
fetchRoles,
|
||||
} from '#utils/database/dbExistingUser';
|
||||
import { restrict, checkActive } from '#utils/database/restriction';
|
||||
|
||||
export async function restrictRun(
|
||||
userId: Snowflake,
|
||||
modId: Snowflake,
|
||||
reason: string,
|
||||
guild: Guild,
|
||||
tolerance = false,
|
||||
) {
|
||||
const info = {
|
||||
message: '',
|
||||
success: false,
|
||||
};
|
||||
|
||||
// Gets mod's GuildMember
|
||||
const mod = guild.members.cache.get(modId);
|
||||
|
||||
// Checks if guildMember is null
|
||||
if (mod === undefined) {
|
||||
info.message = 'Error fetching mod';
|
||||
return info;
|
||||
}
|
||||
|
||||
// Check if mod is in database
|
||||
await updateUser(mod);
|
||||
|
||||
if (await checkActive(userId)) {
|
||||
info.message = `<@${userId}> is already restricted!`;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Gets guildMember
|
||||
let member = guild.members.cache.get(userId);
|
||||
|
||||
if (member === undefined) {
|
||||
member = await guild.members.fetch(userId);
|
||||
}
|
||||
|
||||
const restrictRoles = IDs.roles.restrictions.restricted;
|
||||
|
||||
let section = tolerance ? randint(3, 4) : randint(1, 2);
|
||||
|
||||
if (member !== undefined) {
|
||||
// Checks if the user is not restricted
|
||||
if (member.roles.cache.hasAny(...restrictRoles)) {
|
||||
info.message = `${member} is already restricted!`;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Check if user and mod are on the database
|
||||
await updateUser(member);
|
||||
|
||||
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||
// TODO remove this error before enabling vegan restricts
|
||||
info.message = `${member} is vegan, can't restrict them yet 😭`;
|
||||
return info;
|
||||
section = 5;
|
||||
}
|
||||
|
||||
await member.roles.add(restrictRoles[section - 1]);
|
||||
|
||||
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||
const voiceChannel = await guild.channels.create({
|
||||
name: 'Restricted Voice Channel',
|
||||
type: ChannelType.GuildVoice,
|
||||
parent: IDs.categories.restricted,
|
||||
permissionOverwrites: [
|
||||
{
|
||||
id: guild.roles.everyone,
|
||||
deny: [PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
{
|
||||
id: member.id,
|
||||
allow: [PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
{
|
||||
id: IDs.roles.staff.restricted,
|
||||
allow: [PermissionsBitField.Flags.SendMessages,
|
||||
PermissionsBitField.Flags.ViewChannel,
|
||||
PermissionsBitField.Flags.Connect,
|
||||
PermissionsBitField.Flags.MuteMembers],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let restrictedChannel: TextChannel;
|
||||
let bannedName = false;
|
||||
try {
|
||||
restrictedChannel = await guild.channels.create({
|
||||
name: `⛔┃${member.user.username}-restricted`,
|
||||
type: ChannelType.GuildText,
|
||||
topic: `Restricted channel. ${member.id} ${voiceChannel.id} (Please do not change this)`,
|
||||
parent: IDs.categories.restricted,
|
||||
permissionOverwrites: [
|
||||
{
|
||||
id: guild.roles.everyone,
|
||||
allow: [PermissionsBitField.Flags.ReadMessageHistory],
|
||||
deny: [PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
{
|
||||
id: member.id,
|
||||
allow: [PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
{
|
||||
id: IDs.roles.staff.restricted,
|
||||
allow: [PermissionsBitField.Flags.SendMessages,
|
||||
PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
],
|
||||
});
|
||||
} catch {
|
||||
restrictedChannel = await guild.channels.create({
|
||||
name: `⛔┃${member.user.id}-restricted`,
|
||||
type: ChannelType.GuildText,
|
||||
topic: `Restricted channel. ${member.id} ${voiceChannel.id} (Please do not change this)`,
|
||||
parent: IDs.categories.restricted,
|
||||
permissionOverwrites: [
|
||||
{
|
||||
id: guild.roles.everyone,
|
||||
allow: [PermissionsBitField.Flags.ReadMessageHistory],
|
||||
deny: [PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
{
|
||||
id: member.id,
|
||||
allow: [PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
{
|
||||
id: IDs.roles.staff.restricted,
|
||||
allow: [PermissionsBitField.Flags.SendMessages,
|
||||
PermissionsBitField.Flags.ViewChannel],
|
||||
},
|
||||
],
|
||||
});
|
||||
bannedName = true;
|
||||
}
|
||||
|
||||
if (!bannedName) {
|
||||
await voiceChannel.setName(`${member.user.username}-restricted`);
|
||||
} else {
|
||||
await voiceChannel.setName(`${member.user.id}-restricted`);
|
||||
}
|
||||
|
||||
const joinTime = time(member.joinedAt!);
|
||||
const registerTime = time(member.user.createdAt);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(member.displayHexColor)
|
||||
.setTitle(`Restricted channel for ${member.user.username}`)
|
||||
.setDescription(`${member}`)
|
||||
.setThumbnail(member.user.avatarURL()!)
|
||||
.addFields(
|
||||
{ name: 'Joined:', value: `${joinTime}`, inline: true },
|
||||
{ name: 'Created:', value: `${registerTime}`, inline: true },
|
||||
);
|
||||
|
||||
await restrictedChannel.send({ embeds: [embed] });
|
||||
}
|
||||
|
||||
await member.roles.remove([
|
||||
IDs.roles.vegan.vegan,
|
||||
IDs.roles.vegan.plus,
|
||||
IDs.roles.vegan.activist,
|
||||
IDs.roles.trusted,
|
||||
IDs.roles.nonvegan.nonvegan,
|
||||
IDs.roles.nonvegan.convinced,
|
||||
IDs.roles.nonvegan.vegCurious,
|
||||
]);
|
||||
} else if (!await userExists(userId)) {
|
||||
// TODO remove this error before replacing other bot role replacement
|
||||
info.message = `<@${userId}> is not on this server, can't restrict them yet! 😭`;
|
||||
return info;
|
||||
await addEmptyUser(userId);
|
||||
const dbRoles = await fetchRoles(userId);
|
||||
if (dbRoles.includes(IDs.roles.vegan.vegan)) {
|
||||
section = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Restrict the user on the database
|
||||
await restrict(userId, modId, reason, section);
|
||||
|
||||
info.message = `Restricted ${member}`;
|
||||
info.success = true;
|
||||
|
||||
// Log the ban
|
||||
let logChannel = guild.channels.cache
|
||||
.get(IDs.channels.logs.restricted) as TextChannel | undefined;
|
||||
|
||||
if (logChannel === undefined) {
|
||||
logChannel = await guild.channels
|
||||
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined;
|
||||
if (logChannel === undefined) {
|
||||
container.logger.error('Restrict Error: Could not fetch log channel');
|
||||
info.message = `Restricted ${member} but could not find the log channel. This has been logged to the database.`;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
const message = new EmbedBuilder()
|
||||
.setColor('#FF6700')
|
||||
.setAuthor({ name: `Restricted ${member.user.tag}`, iconURL: `${member.user.avatarURL()}` })
|
||||
.addFields(
|
||||
{ name: 'User', value: `${member}`, inline: true },
|
||||
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||
{ name: 'Reason', value: reason },
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({ text: `ID: ${member.id}` });
|
||||
|
||||
await logChannel.send({ embeds: [message] });
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
export class RestrictCommand extends Command {
|
||||
public constructor(context: Command.Context, options: Command.Options) {
|
||||
super(context, {
|
||||
...options,
|
||||
name: 'restrict',
|
||||
aliases: ['r', 'rest', 'rr'], // TODO add 'rv' when enabling vegan restrictions
|
||||
description: 'Restricts a user',
|
||||
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 restrict')
|
||||
.setRequired(true))
|
||||
.addStringOption((option) => option.setName('reason')
|
||||
.setDescription('Reason for restricting the user')
|
||||
.setRequired(true)),
|
||||
{
|
||||
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', true);
|
||||
const mod = interaction.member;
|
||||
const { guild } = interaction;
|
||||
|
||||
// Checks if all the variables are of the right type
|
||||
if (guild === null || mod === null) {
|
||||
await interaction.reply({
|
||||
content: 'Error fetching user!',
|
||||
ephemeral: true,
|
||||
fetchReply: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await restrictRun(user?.id, mod.user.id, reason, guild);
|
||||
|
||||
await interaction.reply({
|
||||
content: info.message,
|
||||
fetchReply: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Non Application Command method of banning a user
|
||||
public async messageRun(message: Message, args: Args) {
|
||||
// Get arguments
|
||||
let user: User;
|
||||
try {
|
||||
user = await args.pick('user');
|
||||
} 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 (reason === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Restrict reason was not provided!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Moderator not found! Try again or contact a developer!');
|
||||
return;
|
||||
}
|
||||
|
||||
const { guild } = message;
|
||||
|
||||
if (guild === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Guild not found! Try again or contact a developer!');
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await restrictRun(user?.id, mod.user.id, reason, guild);
|
||||
|
||||
await message.reply(info.message);
|
||||
await message.react(info.success ? '✅' : '❌');
|
||||
}
|
||||
}
|
||||
118
src/commands/mod/restriction/restrictTolerance.ts
Normal file
118
src/commands/mod/restriction/restrictTolerance.ts
Normal file
@ -0,0 +1,118 @@
|
||||
// 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 { User, Message } from 'discord.js';
|
||||
import { restrictRun } from './restrict';
|
||||
|
||||
export class RestrictToleranceCommand extends Command {
|
||||
public constructor(context: Command.Context, options: Command.Options) {
|
||||
super(context, {
|
||||
...options,
|
||||
name: 'restricttolerance',
|
||||
aliases: ['rt'],
|
||||
description: 'Restricts a user for bigoted reasons',
|
||||
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 restrict')
|
||||
.setRequired(true))
|
||||
.addStringOption((option) => option.setName('reason')
|
||||
.setDescription('Reason for restricting the user')
|
||||
.setRequired(true)),
|
||||
{
|
||||
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', true);
|
||||
const mod = interaction.member;
|
||||
const { guild } = interaction;
|
||||
|
||||
// Checks if all the variables are of the right type
|
||||
if (guild === null || mod === null) {
|
||||
await interaction.reply({
|
||||
content: 'Error fetching user!',
|
||||
ephemeral: true,
|
||||
fetchReply: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await restrictRun(user?.id, mod.user.id, reason, guild, true);
|
||||
|
||||
await interaction.reply({
|
||||
content: info.message,
|
||||
fetchReply: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Non Application Command method of banning a user
|
||||
public async messageRun(message: Message, args: Args) {
|
||||
// Get arguments
|
||||
let user: User;
|
||||
try {
|
||||
user = await args.pick('user');
|
||||
} 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 (reason === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Restrict reason was not provided!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Moderator not found! Try again or contact a developer!');
|
||||
return;
|
||||
}
|
||||
|
||||
const { guild } = message;
|
||||
|
||||
if (guild === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Guild not found! Try again or contact a developer!');
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await restrictRun(user?.id, mod.user.id, reason, guild, true);
|
||||
|
||||
await message.reply(info.message);
|
||||
await message.react(info.success ? '✅' : '❌');
|
||||
}
|
||||
}
|
||||
236
src/commands/mod/restriction/unrestrict.ts
Normal file
236
src/commands/mod/restriction/unrestrict.ts
Normal file
@ -0,0 +1,236 @@
|
||||
// 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 { CategoryChannel, ChannelType, EmbedBuilder } from 'discord.js';
|
||||
import type {
|
||||
User,
|
||||
Message,
|
||||
TextChannel,
|
||||
Guild,
|
||||
Snowflake,
|
||||
} from 'discord.js';
|
||||
import IDs from '#utils/ids';
|
||||
import { fetchRoles, addExistingUser, userExists } from '#utils/database/dbExistingUser';
|
||||
import { unRestrict, checkActive, unRestrictLegacy } from '#utils/database/restriction';
|
||||
|
||||
export class UnRestrictCommand extends Command {
|
||||
public constructor(context: Command.Context, options: Command.Options) {
|
||||
super(context, {
|
||||
...options,
|
||||
name: 'unrestrict',
|
||||
aliases: ['ur', 'urv'],
|
||||
description: 'Unrestricts a user',
|
||||
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 unrestrict')
|
||||
.setRequired(true)),
|
||||
{
|
||||
behaviorWhenNotIdentical: RegisterBehavior.Overwrite,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Command run
|
||||
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
|
||||
// Get the arguments
|
||||
const user = interaction.options.getUser('user', true);
|
||||
const mod = interaction.member;
|
||||
const { guild } = interaction;
|
||||
|
||||
// Checks if all the variables are of the right type
|
||||
if (guild === null || mod === null) {
|
||||
await interaction.reply({
|
||||
content: 'Error fetching user!',
|
||||
ephemeral: true,
|
||||
fetchReply: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await this.unRestrictRun(user?.id, mod.user.id, guild);
|
||||
|
||||
await interaction.reply({
|
||||
content: info.message,
|
||||
fetchReply: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Non Application Command method of banning a user
|
||||
public async messageRun(message: Message, args: Args) {
|
||||
// Get arguments
|
||||
let user: User;
|
||||
try {
|
||||
user = await args.pick('user');
|
||||
} catch {
|
||||
await message.react('❌');
|
||||
await message.reply('User was not provided!');
|
||||
return;
|
||||
}
|
||||
|
||||
const mod = message.member;
|
||||
|
||||
if (mod === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Moderator not found! Try again or contact a developer!');
|
||||
return;
|
||||
}
|
||||
|
||||
const { guild } = message;
|
||||
|
||||
if (guild === null) {
|
||||
await message.react('❌');
|
||||
await message.reply('Guild not found! Try again or contact a developer!');
|
||||
return;
|
||||
}
|
||||
|
||||
const info = await this.unRestrictRun(user?.id, mod.user.id, guild);
|
||||
|
||||
await message.reply(info.message);
|
||||
await message.react(info.success ? '✅' : '❌');
|
||||
}
|
||||
|
||||
private async unRestrictRun(userId: Snowflake, modId: Snowflake, guild: Guild) {
|
||||
const info = {
|
||||
message: '',
|
||||
success: false,
|
||||
};
|
||||
|
||||
// Gets mod's GuildMember
|
||||
const mod = guild.members.cache.get(modId);
|
||||
|
||||
// Checks if guildMember is null
|
||||
if (mod === undefined) {
|
||||
info.message = 'Error fetching mod';
|
||||
return info;
|
||||
}
|
||||
|
||||
// Check if mod is in database
|
||||
if (!await userExists(mod.id)) {
|
||||
await addExistingUser(mod);
|
||||
}
|
||||
|
||||
// Gets guildMember
|
||||
let member = guild.members.cache.get(userId);
|
||||
|
||||
if (member === undefined) {
|
||||
member = await guild.members.fetch(userId);
|
||||
}
|
||||
|
||||
if (member === undefined) {
|
||||
info.message = 'Can\'t unrestrict the user as they are not on this server';
|
||||
return info;
|
||||
}
|
||||
|
||||
const restrictRoles = IDs.roles.restrictions.restricted;
|
||||
|
||||
// Checks if the user is not restricted
|
||||
if (!member.roles.cache.hasAny(...restrictRoles)) {
|
||||
info.message = `${member} is not restricted!`;
|
||||
return info;
|
||||
}
|
||||
|
||||
if (await checkActive(userId)) {
|
||||
const roles = await fetchRoles(userId);
|
||||
await member.roles.add(roles);
|
||||
// Unrestricts the user on the database
|
||||
await unRestrict(userId, modId);
|
||||
} else {
|
||||
let section = 1;
|
||||
for (let i = 0; i < restrictRoles.length; i += 0) {
|
||||
if (member.roles.cache.has(restrictRoles[i])) {
|
||||
section = i + 1;
|
||||
}
|
||||
}
|
||||
await member.roles.add(IDs.roles.nonvegan.nonvegan);
|
||||
// Unrestricts the user on the database but for restricts done on the old bot
|
||||
await unRestrictLegacy(userId, modId, section);
|
||||
}
|
||||
|
||||
await member.roles.remove(restrictRoles);
|
||||
|
||||
// Remove vegan restrict channels
|
||||
if (member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||
const category = guild.channels.cache
|
||||
.get(IDs.categories.restricted) as CategoryChannel | undefined;
|
||||
|
||||
let topic: string[];
|
||||
|
||||
if (category !== undefined) {
|
||||
const textChannels = category.children.cache
|
||||
.filter((c) => c.type === ChannelType.GuildText);
|
||||
textChannels.forEach((c) => {
|
||||
const textChannel = c as TextChannel;
|
||||
// Checks if the channel topic has the user's snowflake
|
||||
if (textChannel.topic?.includes(userId)) {
|
||||
topic = textChannel.topic.split(' ');
|
||||
const vcId = topic[topic.indexOf(userId) + 1];
|
||||
const voiceChannel = guild.channels.cache.get(vcId);
|
||||
|
||||
if (voiceChannel !== undefined
|
||||
&& voiceChannel.parentId === IDs.categories.restricted) {
|
||||
voiceChannel.delete();
|
||||
}
|
||||
textChannel.delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
info.success = true;
|
||||
|
||||
// Log the ban
|
||||
let logChannel = guild.channels.cache
|
||||
.get(IDs.channels.logs.restricted) as TextChannel | undefined;
|
||||
|
||||
if (logChannel === undefined) {
|
||||
logChannel = await guild.channels
|
||||
.fetch(IDs.channels.logs.restricted) as TextChannel | undefined;
|
||||
if (logChannel === undefined) {
|
||||
this.container.logger.error('Restrict Error: Could not fetch log channel');
|
||||
info.message = `Unrestricted ${member} but could not find the log channel. This has been logged to the database.`;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
const message = new EmbedBuilder()
|
||||
.setColor('#28A745')
|
||||
.setAuthor({ name: `Unrestricted ${member.user.tag}`, iconURL: `${member.user.avatarURL()}` })
|
||||
.addFields(
|
||||
{ name: 'User', value: `${member}`, inline: true },
|
||||
{ name: 'Moderator', value: `${mod}`, inline: true },
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({ text: `ID: ${member.id}` });
|
||||
|
||||
await logChannel.send({ embeds: [message] });
|
||||
|
||||
info.message = `Unrestricted ${member}`;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@ -19,11 +19,12 @@
|
||||
|
||||
import { Listener } from '@sapphire/framework';
|
||||
import type { GuildMember } from 'discord.js';
|
||||
// import { fetchRoles } from '../../utils/database/dbExistingUser';
|
||||
import IDs from '#utils/ids';
|
||||
import { blockTime } from '#utils/database/verification';
|
||||
import { fetchRoles } from '#utils/database/dbExistingUser';
|
||||
// import IDs from '#utils/ids';
|
||||
// import { blockTime } from '#utils/database/verification';
|
||||
// import { checkActive, getSection } from '#utils/database/restriction';
|
||||
|
||||
export class VerificationReady extends Listener {
|
||||
export class RolesJoinServerListener extends Listener {
|
||||
public constructor(context: Listener.Context, options: Listener.Options) {
|
||||
super(context, {
|
||||
...options,
|
||||
@ -31,20 +32,27 @@ export class VerificationReady extends Listener {
|
||||
});
|
||||
}
|
||||
|
||||
public async run(user: GuildMember) {
|
||||
public async run(member: GuildMember) {
|
||||
// Add basic roles
|
||||
// Removed this because it can give restricted people access back,
|
||||
// Currently using another bot for this
|
||||
// const roles = await fetchRoles(user.id);
|
||||
const roles: string[] = [];
|
||||
|
||||
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;
|
||||
roles.push(IDs.roles.restrictions.restricted[section - 1]);
|
||||
}
|
||||
|
||||
// Check if the user has a verification block
|
||||
const timeout = await blockTime(user.id);
|
||||
const timeout = await blockTime(member.id);
|
||||
if (timeout > 0) {
|
||||
roles.push(IDs.roles.verifyBlock);
|
||||
}
|
||||
*/
|
||||
|
||||
// Add roles if they don't have verification block
|
||||
await user.roles.add(roles);
|
||||
await member.roles.add(roles);
|
||||
}
|
||||
}
|
||||
@ -17,12 +17,12 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import type { GuildMember, GuildMemberRoleManager } from 'discord.js';
|
||||
import type { GuildMember, GuildMemberRoleManager, Snowflake } from 'discord.js';
|
||||
import { container } from '@sapphire/framework';
|
||||
import IDs from '#utils/ids';
|
||||
|
||||
// Checks if the user exists on the database
|
||||
export async function userExists(userId: string) {
|
||||
export async function userExists(userId: Snowflake) {
|
||||
// Counts if the user is on the database by their snowflake
|
||||
const userQuery = await container.database.user.count({
|
||||
where: {
|
||||
@ -51,11 +51,11 @@ function getRoles(roles: GuildMemberRoleManager) {
|
||||
}
|
||||
|
||||
// Adds the user to the database if they were already on the server before the bot/database
|
||||
export async function addExistingUser(user: GuildMember) {
|
||||
export async function addExistingUser(member: GuildMember) {
|
||||
// Counts if the user is on the database by their snowflake
|
||||
const userQuery = await container.database.user.count({
|
||||
where: {
|
||||
id: user.id,
|
||||
id: member.id,
|
||||
},
|
||||
});
|
||||
|
||||
@ -65,12 +65,12 @@ export async function addExistingUser(user: GuildMember) {
|
||||
}
|
||||
|
||||
// Parse all the roles into a dictionary
|
||||
const roles = getRoles(user.roles);
|
||||
const roles = getRoles(member.roles);
|
||||
|
||||
// Create the user in the database
|
||||
await container.database.user.create({
|
||||
data: {
|
||||
id: user.id,
|
||||
id: member.id,
|
||||
vegan: roles.vegan,
|
||||
trusted: roles.trusted,
|
||||
activist: roles.activist,
|
||||
@ -84,7 +84,7 @@ export async function addExistingUser(user: GuildMember) {
|
||||
}
|
||||
|
||||
// Add an empty user to database in case they are not on the server
|
||||
export async function addEmptyUser(userId: string) {
|
||||
export async function addEmptyUser(userId: Snowflake) {
|
||||
// Counts if the user is on the database by their snowflake
|
||||
const userQuery = await container.database.user.count({
|
||||
where: {
|
||||
@ -105,22 +105,22 @@ export async function addEmptyUser(userId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateUser(user: GuildMember) {
|
||||
export async function updateUser(member: GuildMember) {
|
||||
// Check if the user is already on the database
|
||||
if (!(await userExists(user.id))) {
|
||||
await addExistingUser(user);
|
||||
if (!(await userExists(member.id))) {
|
||||
await addExistingUser(member);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse all the roles into a dictionary
|
||||
const roles = getRoles(user.roles);
|
||||
const roles = getRoles(member.roles);
|
||||
|
||||
await container.database.user.update({
|
||||
where: {
|
||||
id: user.id,
|
||||
id: member.id,
|
||||
},
|
||||
data: {
|
||||
id: user.id,
|
||||
id: member.id,
|
||||
vegan: roles.vegan,
|
||||
trusted: roles.trusted,
|
||||
activist: roles.activist,
|
||||
@ -133,11 +133,11 @@ export async function updateUser(user: GuildMember) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchRoles(user: string) {
|
||||
export async function fetchRoles(userId: Snowflake) {
|
||||
// Get the user's roles
|
||||
const roleQuery = await container.database.user.findUnique({
|
||||
where: {
|
||||
id: user,
|
||||
id: userId,
|
||||
},
|
||||
select: {
|
||||
vegan: true,
|
||||
|
||||
124
src/utils/database/restriction.ts
Normal file
124
src/utils/database/restriction.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import { container } from '@sapphire/framework';
|
||||
import type { Snowflake } from 'discord.js';
|
||||
|
||||
export async function restrict(
|
||||
userId: Snowflake,
|
||||
modId: Snowflake,
|
||||
reason: string,
|
||||
section: number,
|
||||
) {
|
||||
// Add the user to the database
|
||||
await container.database.restrict.create({
|
||||
data: {
|
||||
user: {
|
||||
connect: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
mod: {
|
||||
connect: {
|
||||
id: modId,
|
||||
},
|
||||
},
|
||||
reason,
|
||||
section,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function unRestrict(userId: Snowflake, modId: Snowflake) {
|
||||
const restriction = await container.database.restrict.findFirst({
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
orderBy: {
|
||||
id: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
if (restriction === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await container.database.restrict.update({
|
||||
where: {
|
||||
id: restriction.id,
|
||||
},
|
||||
data: {
|
||||
endMod: {
|
||||
connect: {
|
||||
id: modId,
|
||||
},
|
||||
},
|
||||
endTime: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function checkActive(userId: Snowflake) {
|
||||
const restriction = await container.database.restrict.findFirst({
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
endTime: true,
|
||||
},
|
||||
orderBy: {
|
||||
id: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
if (restriction === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return restriction.endTime === null;
|
||||
}
|
||||
|
||||
export async function getSection(userId: Snowflake) {
|
||||
const restriction = await container.database.restrict.findFirst({
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
section: true,
|
||||
},
|
||||
orderBy: {
|
||||
id: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
if (restriction === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return restriction.section;
|
||||
}
|
||||
|
||||
// This is only for restrictions created with the old bot
|
||||
export async function unRestrictLegacy(userId: Snowflake, modId: Snowflake, section: number) {
|
||||
await container.database.restrict.create({
|
||||
data: {
|
||||
user: {
|
||||
connect: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
mod: {
|
||||
connect: {
|
||||
id: modId,
|
||||
},
|
||||
},
|
||||
endMod: {
|
||||
connect: {
|
||||
id: modId,
|
||||
},
|
||||
},
|
||||
reason: 'This user was restricted with the old bot. Restrict reason, time and mod unknown, check old bot logs.',
|
||||
section,
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -38,6 +38,13 @@ const devIDs = {
|
||||
restricted2: '999431674997788676',
|
||||
restricted3: '999431674997788675',
|
||||
restricted4: '999431674997788674',
|
||||
restricted: [
|
||||
'999431674997788677', // Restricted 1
|
||||
'999431674997788676', // Restricted 2
|
||||
'999431674997788675', // Restricted 3
|
||||
'999431674997788674', // Restricted 4
|
||||
'999431674997788677', // Restricted Vegan
|
||||
],
|
||||
},
|
||||
staff: {
|
||||
coordinator: '999431675165556822',
|
||||
|
||||
@ -41,6 +41,13 @@ let IDs = {
|
||||
restricted2: '872482843304001566',
|
||||
restricted3: '856582673258774538',
|
||||
restricted4: '872472182888992858',
|
||||
restricted: [
|
||||
'809769217477050369', // Restricted 1
|
||||
'872482843304001566', // Restricted 2
|
||||
'856582673258774538', // Restricted 3
|
||||
'872472182888992858', // Restricted 4
|
||||
'809769217477050369', // Restricted Vegan
|
||||
],
|
||||
},
|
||||
staff: {
|
||||
coordinator: '993636242019323904',
|
||||
|
||||
23
src/utils/random.ts
Normal file
23
src/utils/random.ts
Normal file
@ -0,0 +1,23 @@
|
||||
// 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/>.
|
||||
*/
|
||||
|
||||
// Random integer between min and max
|
||||
export function randint(min: number, max: number) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user