mirror of
https://github.com/veganhacktivists/arabot.git
synced 2025-05-18 18:04:13 +02:00
Compare commits
5 Commits
9b3908cdc4
...
2207d996a1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2207d996a1 | ||
![]() |
8f60c3eac9 | ||
![]() |
c976905104 | ||
![]() |
cd4526bfb1 | ||
![]() |
e44c0c2037 |
@ -21,7 +21,11 @@ import {
|
|||||||
InteractionHandler,
|
InteractionHandler,
|
||||||
InteractionHandlerTypes,
|
InteractionHandlerTypes,
|
||||||
} from '@sapphire/framework';
|
} from '@sapphire/framework';
|
||||||
import type { ButtonInteraction, GuildMember } from 'discord.js';
|
import {
|
||||||
|
ButtonInteraction,
|
||||||
|
GuildMember,
|
||||||
|
MessageFlagsBitField,
|
||||||
|
} from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
|
||||||
export class NonVeganAccessButtonHandler extends InteractionHandler {
|
export class NonVeganAccessButtonHandler extends InteractionHandler {
|
||||||
@ -51,7 +55,7 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
|
|||||||
if (member === null) {
|
if (member === null) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: errorMessage,
|
content: errorMessage,
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -62,7 +66,7 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
|
|||||||
if (!member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
if (!member.roles.cache.has(IDs.roles.vegan.vegan)) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: 'You need to be vegan to use this button!',
|
content: 'You need to be vegan to use this button!',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -73,7 +77,7 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
|
|||||||
content:
|
content:
|
||||||
'Your access from the non vegan section has been removed. ' +
|
'Your access from the non vegan section has been removed. ' +
|
||||||
'If you want to gain access again, click this button again.',
|
'If you want to gain access again, click this button again.',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -83,13 +87,13 @@ export class NonVeganAccessButtonHandler extends InteractionHandler {
|
|||||||
content:
|
content:
|
||||||
'Your access to the non vegan section has been given back. ' +
|
'Your access to the non vegan section has been given back. ' +
|
||||||
'If you want to remove access again, click this button again.',
|
'If you want to remove access again, click this button again.',
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.container.logger.error(`Non Vegan Access Interaction: ${error}`);
|
this.container.logger.error(`Non Vegan Access Interaction: ${error}`);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: errorMessage,
|
content: errorMessage,
|
||||||
ephemeral: true,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@ import {
|
|||||||
ButtonInteraction,
|
ButtonInteraction,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
MessageFlagsBitField,
|
MessageFlagsBitField,
|
||||||
TextChannel,
|
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
import { checkActive } from '#utils/database/moderation/restriction';
|
import { checkActive } from '#utils/database/moderation/restriction';
|
||||||
|
import { addUser } from '#utils/database/dbExistingUser';
|
||||||
|
|
||||||
export class WelcomeButtonHandler extends InteractionHandler {
|
export class WelcomeButtonHandler extends InteractionHandler {
|
||||||
public constructor(
|
public constructor(
|
||||||
@ -48,25 +48,54 @@ export class WelcomeButtonHandler extends InteractionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async run(interaction: ButtonInteraction) {
|
public async run(interaction: ButtonInteraction) {
|
||||||
let { member } = interaction;
|
const { member } = interaction;
|
||||||
const general = this.container.client.channels.cache.get(
|
let general = this.container.client.channels.cache.get(
|
||||||
IDs.channels.nonVegan.general,
|
IDs.channels.nonVegan.general,
|
||||||
) as TextChannel | undefined;
|
);
|
||||||
if (general === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member === null) {
|
// Messages that are used multiple times
|
||||||
|
const roleErrorMessage =
|
||||||
|
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.';
|
||||||
|
const welcomeMessage =
|
||||||
|
`${member} Welcome to ARA! :D Please check <#${IDs.channels.information.roles}> ` +
|
||||||
|
`and remember to follow the <#${IDs.channels.information.conduct}> and to respect ongoing discussions and debates.` +
|
||||||
|
`\n\nIf you are vegan, you can join the 'Verification' voice channel, or use \`/apply\` with the Appy bot in <#${IDs.channels.nonVegan.vcText}>, ` +
|
||||||
|
'to be verified and gain access to more channels.';
|
||||||
|
|
||||||
|
// Checks if general is not in the cache
|
||||||
|
if (general === undefined) {
|
||||||
|
// Sends an API request to get the channel
|
||||||
|
const generalFetch = await this.container.client.channels
|
||||||
|
.fetch(IDs.channels.nonVegan.general)
|
||||||
|
.catch(() => undefined);
|
||||||
|
|
||||||
|
// If general does not exist
|
||||||
|
if (generalFetch === null || generalFetch === undefined) {
|
||||||
|
this.container.logger.error(
|
||||||
|
'WelcomeButtonHandler: Could not find and fetch the general channel!',
|
||||||
|
);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content:
|
||||||
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.',
|
'Sorry there was a problem trying to give you access to the server. Please try again later.',
|
||||||
flags: MessageFlagsBitField.Flags.Ephemeral,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Replace fetched version of general with the cached version
|
||||||
member = member as GuildMember;
|
general = generalFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the member could not be found
|
||||||
|
if (!(member instanceof GuildMember)) {
|
||||||
|
await interaction.reply({
|
||||||
|
content: roleErrorMessage,
|
||||||
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the user is currently restricted
|
// Checks if the user is currently restricted
|
||||||
if (await checkActive(member.id)) {
|
if (await checkActive(member.id)) {
|
||||||
@ -79,29 +108,41 @@ export class WelcomeButtonHandler extends InteractionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Give non-vegan role
|
// Give non-vegan role
|
||||||
if (!member.voice.channel) {
|
if (member.voice.channel) {
|
||||||
await member.roles.add(IDs.roles.nonvegan.nonvegan);
|
|
||||||
|
|
||||||
await general.send(
|
|
||||||
`${member} Welcome to ARA! :D Please check <#${IDs.channels.information.roles}> ` +
|
|
||||||
`and remember to follow the <#${IDs.channels.information.conduct}> and to respect ongoing discussions and debates.` +
|
|
||||||
`\n\nIf you are vegan, you can join the 'Verification' voice channel, or use \`/apply\` with the Appy bot in <#${IDs.channels.nonVegan.vcText}>, ` +
|
|
||||||
'to be verified and gain access to more channels.',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content:
|
||||||
"You're currently in a verification, you'll have to leave the verification or get verified before being able to access the server again.",
|
"You're currently in a verification, you'll have to leave the verification or get verified before being able to access the server again.",
|
||||||
flags: MessageFlagsBitField.Flags.Ephemeral,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the user to the database
|
||||||
|
await addUser(member.id);
|
||||||
|
|
||||||
|
// Give the role to the member
|
||||||
|
const role = await member.roles
|
||||||
|
.add(IDs.roles.nonvegan.nonvegan)
|
||||||
|
.catch(() => undefined);
|
||||||
|
|
||||||
|
// If the role could not be given
|
||||||
|
if (role === undefined) {
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content:
|
content: roleErrorMessage,
|
||||||
'There was an error giving you the role, please try again later or contact ModMail to be let into this server.',
|
|
||||||
flags: MessageFlagsBitField.Flags.Ephemeral,
|
flags: MessageFlagsBitField.Flags.Ephemeral,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (general.isSendable()) {
|
||||||
|
await general.send(welcomeMessage);
|
||||||
|
} else {
|
||||||
|
this.container.logger.error(
|
||||||
|
'WelcomeButtonHandler: The bot does not have permission to send in general!',
|
||||||
|
);
|
||||||
|
await member.send(welcomeMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,13 @@ export class FixRolesOnReady extends Listener {
|
|||||||
// THIS SHOULD BE DISABLED BY DEFAULT
|
// THIS SHOULD BE DISABLED BY DEFAULT
|
||||||
// THIS IS ONLY USED FOR RESTORING ROLES TO THE SERVER!
|
// THIS IS ONLY USED FOR RESTORING ROLES TO THE SERVER!
|
||||||
// ENABLING THIS UNINTENTIONALLY WILL CAUSE SLOWDOWNS TO THE BOT DUE TO RATE LIMITING!
|
// ENABLING THIS UNINTENTIONALLY WILL CAUSE SLOWDOWNS TO THE BOT DUE TO RATE LIMITING!
|
||||||
enabled: true,
|
enabled: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(client: Client) {
|
public async run(client: Client) {
|
||||||
this.container.logger.info(
|
this.container.logger.info(
|
||||||
'FixRolesOnReady: Preparation before starting to fix the roles for nonvegans...',
|
'FixRolesOnReady: Preparation before starting to fix the roles for each user...',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetching the Guild
|
// Fetching the Guild
|
||||||
@ -60,9 +60,7 @@ export class FixRolesOnReady extends Listener {
|
|||||||
|
|
||||||
// Fetching the channel for the logs
|
// Fetching the channel for the logs
|
||||||
// Leave the snowflake parameter empty for no logs
|
// Leave the snowflake parameter empty for no logs
|
||||||
const logChannel = await client.channels
|
const logChannel = await client.channels.fetch('').catch(() => null);
|
||||||
.fetch('1329152627312824320')
|
|
||||||
.catch(() => null);
|
|
||||||
const sendLogs = logChannel !== null;
|
const sendLogs = logChannel !== null;
|
||||||
|
|
||||||
if (!sendLogs) {
|
if (!sendLogs) {
|
||||||
@ -109,10 +107,13 @@ export class FixRolesOnReady extends Listener {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (const [userId, member] of members) {
|
for (const [userId, member] of members) {
|
||||||
|
// Update the counter for the total number of users processed
|
||||||
|
count += 1;
|
||||||
|
|
||||||
// Send a message with an update for every 50 completions
|
// Send a message with an update for every 50 completions
|
||||||
// Checks if `channelLog` has been set to null
|
// Checks if `channelLog` has been set to null
|
||||||
// The RHS of the modulo should be around 100
|
// The RHS of the modulo should be around 100
|
||||||
if (sendLogs && count % 50 === 0) {
|
if (sendLogs && count % 250 === 0) {
|
||||||
const currentTime = new Date().getTime();
|
const currentTime = new Date().getTime();
|
||||||
const runningTime = currentTime - startTime;
|
const runningTime = currentTime - startTime;
|
||||||
|
|
||||||
@ -127,14 +128,6 @@ export class FixRolesOnReady extends Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the user already has vegan or non-vegan role
|
// Checks if the user already has vegan or non-vegan role
|
||||||
if (
|
|
||||||
member.roles.cache.has(IDs.roles.vegan.vegan) ||
|
|
||||||
member.roles.cache.has(IDs.roles.nonvegan.nonvegan)
|
|
||||||
) {
|
|
||||||
await this.delay(1000);
|
|
||||||
count++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if the user is restricted, and skips over them if they are
|
// Checks if the user is restricted, and skips over them if they are
|
||||||
const restricted = await checkActive(userId);
|
const restricted = await checkActive(userId);
|
||||||
@ -143,9 +136,10 @@ export class FixRolesOnReady extends Listener {
|
|||||||
restricted ||
|
restricted ||
|
||||||
member.roles.cache.has(IDs.roles.restrictions.restricted1) ||
|
member.roles.cache.has(IDs.roles.restrictions.restricted1) ||
|
||||||
member.roles.cache.has(IDs.roles.restrictions.restricted2) ||
|
member.roles.cache.has(IDs.roles.restrictions.restricted2) ||
|
||||||
|
member.roles.cache.has(IDs.roles.restrictions.restricted3) ||
|
||||||
|
member.roles.cache.has(IDs.roles.restrictions.restricted4) ||
|
||||||
member.roles.cache.has(IDs.roles.restrictions.restrictedVegan)
|
member.roles.cache.has(IDs.roles.restrictions.restrictedVegan)
|
||||||
) {
|
) {
|
||||||
count++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,9 +154,6 @@ export class FixRolesOnReady extends Listener {
|
|||||||
|
|
||||||
if (xp !== null && xp.xp > 0) {
|
if (xp !== null && xp.xp > 0) {
|
||||||
roles.push(IDs.roles.nonvegan.nonvegan);
|
roles.push(IDs.roles.nonvegan.nonvegan);
|
||||||
} else {
|
|
||||||
count++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,13 +163,12 @@ export class FixRolesOnReady extends Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log the completion
|
// Log the completion
|
||||||
count += 1;
|
|
||||||
this.container.logger.info(
|
this.container.logger.info(
|
||||||
`FixRolesOnReady: Given roles to ${count}/${totalMembers}.`,
|
`FixRolesOnReady: Given roles to ${count}/${totalMembers}.`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add a delay so that there's around 4 users processed a second
|
// Add a delay so that there's around 4 users processed a second
|
||||||
await this.delay(5000);
|
await this.delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the logs that the fix has finished.
|
// Send the logs that the fix has finished.
|
||||||
|
@ -17,20 +17,18 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {
|
import { GuildMember, GuildMemberRoleManager, Snowflake } from 'discord.js';
|
||||||
GuildMember,
|
|
||||||
GuildMemberRoleManager,
|
|
||||||
Snowflake,
|
|
||||||
} from 'discord.js';
|
|
||||||
import { container } from '@sapphire/framework';
|
import { container } from '@sapphire/framework';
|
||||||
import IDs from '#utils/ids';
|
import IDs from '#utils/ids';
|
||||||
|
import { Prisma } from '@prisma/client';
|
||||||
|
import { DefaultArgs, GetResult } from '@prisma/client/runtime/binary';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the user exists on the User table in the database
|
* Checks if the user exists on the User table in the database
|
||||||
* @param {string} userId Snowflake for the user being checked
|
* @param {string} userId Snowflake for the user being checked
|
||||||
* @return {boolean} If the user was found
|
* @return {Promise<boolean>} If the user was found
|
||||||
*/
|
*/
|
||||||
export async function userExists(userId: Snowflake) {
|
export async function userExists(userId: Snowflake): Promise<boolean> {
|
||||||
// Counts if the user is on the database by their snowflake
|
// Counts if the user is on the database by their snowflake
|
||||||
const userQuery = await container.database.user.findFirst({
|
const userQuery = await container.database.user.findFirst({
|
||||||
where: {
|
where: {
|
||||||
@ -66,6 +64,26 @@ function getRoles(roles: GuildMemberRoleManager) {
|
|||||||
return rolesDict;
|
return rolesDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new user to the server
|
||||||
|
* @param {Snowflake} userId the `User` snowflake to be added to the database
|
||||||
|
*/
|
||||||
|
export async function addUser(userId: Snowflake) {
|
||||||
|
// Uses upsert just in case the user has joined the server previously but has not gotten the roles previously
|
||||||
|
await container.database.user.upsert({
|
||||||
|
where: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
notVegan: true,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: userId,
|
||||||
|
notVegan: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add user to the database, if they have not been added beforehand
|
* Add user to the database, if they have not been added beforehand
|
||||||
* @param {GuildMember} member GuildMember for the user to be added to the database
|
* @param {GuildMember} member GuildMember for the user to be added to the database
|
||||||
@ -155,9 +173,9 @@ export async function updateUser(member: GuildMember) {
|
|||||||
/**
|
/**
|
||||||
* Gets the roles that the user that is on the User table.
|
* Gets the roles that the user that is on the User table.
|
||||||
* @param {string} userId Snowflake of the user to fetch roles from
|
* @param {string} userId Snowflake of the user to fetch roles from
|
||||||
* @return {Snowflake[]} Array of Role Snowflakes
|
* @return {Promise<Snowflake[]>} Array of Role Snowflakes
|
||||||
*/
|
*/
|
||||||
export async function fetchRoles(userId: Snowflake) {
|
export async function fetchRoles(userId: Snowflake): Promise<Snowflake[]> {
|
||||||
// Get the user's roles
|
// Get the user's roles
|
||||||
const roleQuery = await container.database.user.findUnique({
|
const roleQuery = await container.database.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
@ -230,12 +248,26 @@ export async function logLeaving(member: GuildMember) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The type returned by `getLeaveRoles`.
|
||||||
|
// Includes a list of all the role Snowflakes when the user last left the server
|
||||||
|
type GetLeaveRoles = Prisma.Prisma__LeaveLogClient<
|
||||||
|
GetResult<
|
||||||
|
Prisma.$LeaveLogPayload<DefaultArgs>,
|
||||||
|
{
|
||||||
|
select: { roles: boolean };
|
||||||
|
},
|
||||||
|
'findFirst'
|
||||||
|
> | null,
|
||||||
|
null,
|
||||||
|
DefaultArgs
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the roles that the user had prior to when they left the server.
|
* Get the roles that the user had prior to when they left the server.
|
||||||
* @param {string} userId Snowflake of the user who joined the server
|
* @param {string} userId Snowflake of the user who joined the server
|
||||||
* @return {string[]} Array of Role Snowflakes
|
* @return {GetLeaveRoles} Array of Role Snowflakes
|
||||||
*/
|
*/
|
||||||
export async function getLeaveRoles(userId: Snowflake) {
|
export function getLeaveRoles(userId: Snowflake): GetLeaveRoles {
|
||||||
const roles = container.database.leaveLog.findFirst({
|
const roles = container.database.leaveLog.findFirst({
|
||||||
where: {
|
where: {
|
||||||
userId,
|
userId,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user