diff --git a/src/discord/Core.ts b/src/discord/Core.ts index 3e42eb2..7a57e6f 100644 --- a/src/discord/Core.ts +++ b/src/discord/Core.ts @@ -1,4 +1,4 @@ -import { Guild } from 'discord.js'; +import { ActivityType, Guild } from 'discord.js'; import DiscordModule from '../utils/DiscordModule'; import DiscordProvider from '../providers/Discord'; @@ -48,7 +48,7 @@ export default class Core extends DiscordModule { private setActivity() { DiscordProvider.client.user!.setActivity('for your heart πŸ’–', { - type: 'COMPETING' + type: ActivityType.Competing }); } } diff --git a/src/discord/Developer/Debug.ts b/src/discord/Developer/Debug.ts index dd8a0ad..328e856 100644 --- a/src/discord/Developer/Debug.ts +++ b/src/discord/Developer/Debug.ts @@ -1,11 +1,11 @@ import { User as PrismaUser, Guild as PrismaGuild } from '@prisma/client'; import { Message, - Interaction, + ActionRowBuilder, CommandInteraction, - MessageActionRow, - MessageButton, - ButtonInteraction + ButtonInteraction, + ButtonBuilder, + ButtonStyle } from 'discord.js'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; @@ -162,14 +162,14 @@ export default class Debug extends DiscordModule { }); }, invalidInteraction: async (data: HybridInteractionMessage) => { - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('πŸ˜₯') .setLabel( ' Make invalid interaction (Wait 7 seconds, check error in console or logs)' ) .setCustomId('dev_make_invalid_interaction') - .setStyle('PRIMARY') + .setStyle(ButtonStyle.Primary) ); await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_TEST(data)], @@ -187,7 +187,7 @@ export default class Debug extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index f721fae..00f3e43 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Message, MessageEmbed, Interaction, CommandInteraction, TextChannel } from 'discord.js'; +import { Message, EmbedBuilder, Interaction, CommandInteraction, TextChannel, BaseInteraction } from 'discord.js'; import { Promise } from 'bluebird'; import fs from 'fs'; import path from 'path'; @@ -22,7 +22,7 @@ import Prisma from '../../providers/Prisma'; import Users from '../../services/Users'; const EMBEDS = { - ANNOUNCEMENT_INFO: (data: Message | Interaction) => { + ANNOUNCEMENT_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Service Announcement', description: `This module contains management tool for announcement feed\n The announcement message is located in \`\`configs/ServiceAnnouncement.json\`\``, @@ -32,14 +32,14 @@ const EMBEDS = { value: '``reload`` ``previewNews`` ``sendNews`` ``previewMaintenance`` ``sendMaintenance`` ``previewMessage`` ``sendMessage`` ``previewAlert`` ``sendAlert``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NOT_DEVELOPER: (data: Message | Interaction) => { + NOT_DEVELOPER: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Developer only', description: `This command is restricted to the developers only`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, MAKE_PAYLOAD: (payload: any) => { @@ -60,40 +60,40 @@ const EMBEDS = { if (payload.description) payload.description = payload.description.replaceAll('{bot_username}', user?.username); - return new MessageEmbed(payload); + return new EmbedBuilder(payload); }, - RELOADED: (data: Message | Interaction) => { + RELOADED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Service Announcement Configuration Reloaded', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - RELOAD_ERROR: (data: Message | Interaction, error: string) => { + RELOAD_ERROR: (data: Message | BaseInteraction, error: string) => { return makeErrorEmbed({ title: 'Unable to reload Service Announcement Configuration', description: `\`\`\`${error}\`\`\``, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - SENDING_SERVICE_ANNOUNCEMENT: (data: Message | Interaction) => { + SENDING_SERVICE_ANNOUNCEMENT: (data: Message | BaseInteraction) => { return makeProcessingEmbed({ title: 'Service Announcement', description: `Broadcasting Service Announcement`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - SERVICE_ANNOUNCEMENT_SENT: (data: Message | Interaction) => { + SERVICE_ANNOUNCEMENT_SENT: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Service Announcement', description: `Broadcasted Service Announcement`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS: (data: Message | Interaction) => { + SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS: (data: Message | BaseInteraction) => { return makeWarningEmbed({ title: 'Service Announcement', description: `Broadcasted Service Announcement with errors, check console for more info`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); } }; @@ -298,7 +298,7 @@ export default class ServiceAnnouncement extends DiscordModule { EMBEDS.SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS(data.getRaw()) ] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { @@ -313,7 +313,7 @@ export default class ServiceAnnouncement extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data.getRaw())] }, @@ -331,7 +331,7 @@ export default class ServiceAnnouncement extends DiscordModule { embeds: [EMBEDS.ANNOUNCEMENT_INFO(data.getRaw())] }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/InteractionManager.ts b/src/discord/InteractionManager.ts index a94ce68..ac051b5 100644 --- a/src/discord/InteractionManager.ts +++ b/src/discord/InteractionManager.ts @@ -1,4 +1,4 @@ -import { Message, Interaction, CommandInteraction } from 'discord.js'; +import { Message, Interaction, CommandInteraction, BaseInteraction } from 'discord.js'; import Users from '../services/Users'; @@ -18,7 +18,7 @@ import { } from '../utils/DiscordInteraction'; const EMBEDS = { - INTERACTION_INFO: (data: Message | Interaction) => { + INTERACTION_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Interaction', description: `This module contains management tool for interaction based contents`, @@ -28,47 +28,47 @@ const EMBEDS = { value: '``reloadAll`` ``unloadAll`` ``reloadglobal``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - PROCESSING: (data: Message | Interaction) => { + PROCESSING: (data: Message | BaseInteraction) => { return makeProcessingEmbed({ icon: data instanceof Message ? undefined : 'βŒ›', title: `Performing actions`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NOT_DEVELOPER: (data: Message | Interaction) => { + NOT_DEVELOPER: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Developer only', description: `This command is restricted to the developers only`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - UNLOADALL_SUCCESS: (data: Message | Interaction) => { + UNLOADALL_SUCCESS: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Unloaded all Interaction', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - UNLOADALL_ERROR: (data: Message | Interaction, err: any) => { + UNLOADALL_ERROR: (data: Message | BaseInteraction, err: any) => { return makeErrorEmbed({ title: 'An error occurred while trying to unload interaction', description: '```' + err + '```', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - RELOADALL_SUCCESS: (data: Message | Interaction) => { + RELOADALL_SUCCESS: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Reloaded all Interaction', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - RELOADALL_ERROR: (data: Message | Interaction, err: any) => { + RELOADALL_ERROR: (data: Message | BaseInteraction, err: any) => { return makeErrorEmbed({ title: 'An error occurred while trying to reload interaction', description: '```' + err + '```', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); } }; @@ -111,7 +111,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.UNLOADALL_SUCCESS(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.UNLOADALL_SUCCESS(data.getRaw())] }, @@ -122,7 +122,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.UNLOADALL_ERROR(data.getRaw(), err)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.UNLOADALL_ERROR(data.getRaw(), err)] }, @@ -146,7 +146,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }, @@ -157,7 +157,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }, @@ -181,7 +181,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }, @@ -192,7 +192,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }, @@ -211,7 +211,7 @@ export default class InteractionManager extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/MembershipScreening.ts b/src/discord/MembershipScreening.ts index 03aaa00..7179b5e 100644 --- a/src/discord/MembershipScreening.ts +++ b/src/discord/MembershipScreening.ts @@ -3,15 +3,20 @@ import { GuildChannel, GuildMember, Message, - Permissions, TextChannel, - MessageActionRow, - MessageButton, - Interaction, + ButtonBuilder, CommandInteraction, Role, ThreadChannel, - ButtonInteraction + ButtonInteraction, + BaseInteraction, + PermissionsBitField, + EmbedBuilder, + ButtonStyle, + ActionRowBuilder, + ActionRowData, + ActionRowComponent, + MessageActionRowComponentBuilder } from 'discord.js'; import DiscordProvider from '../providers/Discord'; @@ -27,44 +32,44 @@ import { import DiscordModule, { HybridInteractionMessage } from '../utils/DiscordModule'; const EMBEDS = { - NO_PERMISSION: (data: Message | Interaction) => { + NO_PERMISSION: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'You need ``ADMINISTRATOR`` permission on this guild!', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_PARAMETER: (data: Message | Interaction) => { + NO_PARAMETER: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Missing parameter', description: `You must define membership screening channel and role to enable this feature`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_ROLE_MENTIONED: (data: Message | Interaction) => { + NO_ROLE_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'No role mentioned', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_ROLE_FOUND: (data: Message | Interaction) => { + NO_ROLE_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot find that role', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_CHANNEL_MENTIONED: (data: Message | Interaction) => { + NO_CHANNEL_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'No channel mentioned', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_CHANNEL_FOUND: (data: Message | Interaction) => { + NO_CHANNEL_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot find that channel', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - MSINFO: (data: Message | Interaction) => { + MSINFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Membership Screening', description: `Membership Screening is a feature to prevent unwanted people to join your guild, similar to whitelist feature. Moderators can approve or deny join request`, @@ -74,58 +79,58 @@ const EMBEDS = { value: '``setRole`` ``setChannel`` ``createMessage``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - ALREADY_ENABLED: (data: Message | Interaction) => { + ALREADY_ENABLED: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Membership Screening is already enabled', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - MESSAGE_CREATED: (data: Message | Interaction) => { + MESSAGE_CREATED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Membership Screening message created', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - ALREADY_DISABLED: (data: Message | Interaction) => { + ALREADY_DISABLED: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Membership Screening is already disabled', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - ENABLED: (data: Message | Interaction) => { + ENABLED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Enabled Membership Screening', description: `All new member join request will be sent in your defined channel`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - DISABLED: (data: Message | Interaction) => { + DISABLED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Disabled Membership Screening', description: `No longer accepting request, all new member can join directly`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - MANAGED_ROLE: (data: Message | Interaction, role: Role) => { + MANAGED_ROLE: (data: Message | BaseInteraction, role: Role) => { return makeErrorEmbed({ title: 'You cannot use this role', description: '``' + role.name + '``' + ' is managed by external service and cannot be used', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CONFIGURED_ROLE: (data: Message | Interaction, role: Role) => { + CONFIGURED_ROLE: (data: Message | BaseInteraction, role: Role) => { return makeSuccessEmbed({ title: 'Configured Membership Screening Role', description: 'New member will be given a ' + '``' + role.name + '``' + ' role after approval', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CONFIGURED_CHANNEL: (data: Message | Interaction, channel: GuildChannel) => { + CONFIGURED_CHANNEL: (data: Message | BaseInteraction, channel: GuildChannel) => { return makeSuccessEmbed({ title: 'Configured Membership Screening Channel', description: @@ -134,18 +139,18 @@ const EMBEDS = { channel.name + '``' + ' can approve or deny request', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - INVALID_CHANNEL: (data: Message | Interaction, channel: GuildChannel) => { + INVALID_CHANNEL: (data: Message | BaseInteraction, channel: GuildChannel) => { return makeErrorEmbed({ title: 'Invalid channel type, only TextChannel is supported', description: '``' + channel.name + '``' + ' is not a text channel', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, INVALID_CHANNEL_THREAD: ( - data: Message | Interaction, + data: Message | BaseInteraction, channel: GuildChannel | ThreadChannel ) => { return makeErrorEmbed({ @@ -155,38 +160,38 @@ const EMBEDS = { channel.name + '``' + ' is a thread channel. Please use a regular text channel', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - BOT_NO_PERMISSION: (data: Message | Interaction, channel: GuildChannel) => { + BOT_NO_PERMISSION: (data: Message | BaseInteraction, channel: GuildChannel) => { return makeErrorEmbed({ title: `I don't have permission`, description: 'I cannot access/send message in ' + '``' + channel.name + '``', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_LONGER_VALID_ROLE: (data: Message | Interaction) => { + NO_LONGER_VALID_ROLE: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'The configured role is no longer valid. Please update the role in configuration', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CANNOT_PERFORM_ASSIGN_ROLE: (data: Message | Interaction) => { + CANNOT_PERFORM_ASSIGN_ROLE: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot grant the role to user, make sure I have permission to do that', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CANNOT_PERFORM_ASSIGN_KICK: (data: Message | Interaction) => { + CANNOT_PERFORM_ASSIGN_KICK: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot kick the user, make sure I have permission to do that', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CANNOT_PERFORM_ASSIGN_BAN: (data: Message | Interaction) => { + CANNOT_PERFORM_ASSIGN_BAN: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot ban the user, make sure I have permission to do that', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, CREATE_MESSAGE: () => { @@ -246,10 +251,12 @@ export default class MembershipScreening extends DiscordModule { ) return; - embed[0].footer = { + const newEmbed = new EmbedBuilder(embed[0].data); + + newEmbed.setFooter({ text: `${interaction.user.username} | v${App.version}`, iconURL: `${interaction.user.displayAvatarURL()}?size=4096` - }; + }); if (['approve', 'deny', 'ban'].includes(payload.a)) { if (!payload.d.requester) return; @@ -268,26 +275,29 @@ export default class MembershipScreening extends DiscordModule { }); if (!requesterMember) { - embed[0].addField('❌ Invalid', `Unable to find the user. User left already?`); - return await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '❌ Invalid', + value: `Unable to find the user. User left already?` + }); + return await message.edit({ components: [], embeds: [newEmbed] }); } if (requesterMember.roles.cache.has(PrismaGuild.MembershipScreening_GivenRole)) { - embed[0].addField( - 'βœ… Approved', - `By: Unknown (User already obtained the role by other means)` - ); - return await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: 'βœ… Approved', + value: `By: Unknown (User already obtained the role by other means)` + }); + return await message.edit({ components: [], embeds: [newEmbed] }); } if (payload.a === 'approve') { try { await requesterMember.roles.add(role); - embed[0].addField( - 'βœ… Approved', - `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - ); - await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: 'βœ… Approved', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + }); + await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ ephemeral: true, @@ -297,11 +307,11 @@ export default class MembershipScreening extends DiscordModule { } else if (payload.a === 'deny') { try { await requesterMember.kick(); - embed[0].addField( - '❌ Denied', - `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - ); - await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '❌ Denied', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + }); + await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ ephemeral: true, @@ -313,11 +323,11 @@ export default class MembershipScreening extends DiscordModule { await requesterMember.ban({ reason: `Membership Screening, action issued by ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` }); - embed[0].addField( - 'πŸ”ͺ Banned', - `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - ); - await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: 'πŸ”ͺ Banned', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + }); + await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ ephemeral: true, @@ -395,9 +405,9 @@ export default class MembershipScreening extends DiscordModule { role = data.getMessage().mentions.roles.first() || guild.roles.cache.find((role) => role.name === _name); - } else if (data.isSlashCommand()) + } else if (data.isApplicationCommand()) role = guild.roles.cache.find( - (role) => role.id === data.getSlashCommand().options.getRole('role')?.id + (role) => role.id === data.getSlashCommand().options.get('role')?.role?.id ); if (!role) @@ -427,8 +437,8 @@ export default class MembershipScreening extends DiscordModule { embeds: [EMBEDS.NO_CHANNEL_MENTIONED(data.getRaw())] }); mentionChannel = data.getMessage().mentions.channels.first(); - } else if (data.isSlashCommand()) - mentionChannel = data.getSlashCommand().options.getChannel('channel'); + } else if (data.isApplicationCommand()) + mentionChannel = data.getSlashCommand().options.get('channel', true).channel; if (!mentionChannel) return await sendHybridInteractionMessageResponse(data, { @@ -443,15 +453,14 @@ export default class MembershipScreening extends DiscordModule { embeds: [EMBEDS.INVALID_CHANNEL_THREAD(data.getRaw(), TargetChannel)] }); - if (!TargetChannel.isText()) + if (!TargetChannel.isTextBased()) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_CHANNEL(data.getRaw(), TargetChannel)] }); if ( - !guild - .me!.permissionsIn(TargetChannel) - .has([Permissions.FLAGS.SEND_MESSAGES, Permissions.FLAGS.VIEW_CHANNEL]) + !guild.members.me?.permissionsIn(TargetChannel) + .has([PermissionsBitField.Flags.SendMessages, PermissionsBitField.Flags.ViewChannel]) ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.BOT_NO_PERMISSION(data.getRaw(), TargetChannel)] @@ -470,7 +479,7 @@ export default class MembershipScreening extends DiscordModule { return await sendMessage(channel, undefined, { embeds: [EMBEDS.CREATE_MESSAGE()] }); - else if (data.isSlashCommand()) { + else if (data.isApplicationCommand()) { await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.MESSAGE_CREATED(data.getRaw())] }); @@ -483,7 +492,7 @@ export default class MembershipScreening extends DiscordModule { let query; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_PERMISSION(data.getRaw())] }); @@ -495,7 +504,7 @@ export default class MembershipScreening extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) query = args.getSubcommand(); + } else if (data.isApplicationCommand()) query = args.getSubcommand(); switch (query) { case 'enable': @@ -549,9 +558,9 @@ export default class MembershipScreening extends DiscordModule { embed.setThumbnail(`${member.user.displayAvatarURL()}?size=4096`); - const row = new MessageActionRow() + const row = new ActionRowBuilder() .addComponents( - new MessageButton() + new ButtonBuilder() .setCustomId( JSON.stringify({ m: 'MembershipScreening', @@ -563,10 +572,10 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('βœ…') .setLabel(' Approve') - .setStyle('SUCCESS') + .setStyle(ButtonStyle.Success) ) .addComponents( - new MessageButton() + new ButtonBuilder() .setCustomId( JSON.stringify({ m: 'MembershipScreening', @@ -578,10 +587,10 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('β›”') .setLabel(' Deny and kick') - .setStyle('DANGER') + .setStyle(ButtonStyle.Danger) ) .addComponents( - new MessageButton() + new ButtonBuilder() .setCustomId( JSON.stringify({ m: 'MembershipScreening', @@ -593,7 +602,7 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('πŸ”ͺ') .setLabel(' Vision Hunt Decree (Ban)') - .setStyle('DANGER') + .setStyle(ButtonStyle.Danger) ); await channel.send({ content: '\u200b', embeds: [embed], components: [row] }); diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index 2f5fb66..75fd345 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -7,10 +7,12 @@ import { GuildMember, DMChannel, StageChannel, - MessageActionRow, - MessageButton, + ActionRowBuilder, + ButtonBuilder, TextChannel, - VoiceBasedChannel + VoiceBasedChannel, + PermissionsBitField, + ButtonStyle } from 'discord.js'; import { I18n } from 'i18n'; @@ -116,7 +118,7 @@ export async function joinVoiceChannelProcedure( instance: DiscordMusicPlayerInstance | null, voiceChannel: VoiceChannel | StageChannel ) { - const isSlashCommand = data.isSlashCommand(); + const isSlashCommand = data.isApplicationCommand(); const isAcceptableInteraction = data.isSelectMenu() || data.isButton(); const isMessage = data.isMessage(); if (!isSlashCommand && !isAcceptableInteraction && !isMessage) return; @@ -133,7 +135,7 @@ export async function joinVoiceChannelProcedure( const memberVoiceChannel = member.voice.channel; //isMessage ? member.voice.channel : DiscordProvider.client.guilds.cache.get(guild.id)!.members.cache.get((data as Interaction).user.id)?.voice.channel; if (!memberVoiceChannel) return; - const bot = guild.me; + const bot = guild.members.me; if (!bot) return; const locale = await Locale.getGuildLocale(guild.id); @@ -179,7 +181,7 @@ export async function joinVoiceChannelProcedure( EMBEDS.VOICECHANNEL_INUSE( data, locale, - member.permissions.has([Permissions.FLAGS.MOVE_MEMBERS]) + member.permissions.has([PermissionsBitField.Flags.MoveMembers]) ) ] }); @@ -223,12 +225,12 @@ export async function joinVoiceChannelProcedure( if (event.instance.queue.track[0] !== previousTrack) isLoopMessageSent = false; else if (event.instance.queue.track[0] === previousTrack && isLoopMessageSent) return; - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('▢️') .setLabel(' Open on YouTube') .setURL(encodeURI(`https://www.youtube.com/watch?v=${event.instance.queue.track[0].id}`)) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); if (event.instance.textChannel) { diff --git a/src/discord/MusicPlayer/Loop.ts b/src/discord/MusicPlayer/Loop.ts index 2dafc78..4edac7d 100644 --- a/src/discord/MusicPlayer/Loop.ts +++ b/src/discord/MusicPlayer/Loop.ts @@ -1,5 +1,5 @@ import { I18n } from "i18n"; -import { Message, CommandInteraction, Interaction, MessageActionRow, ButtonInteraction, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +import { Message, CommandInteraction } from "discord.js"; import DiscordMusicPlayer, { DiscordMusicPlayerLoopMode } from "../../providers/DiscordMusicPlayer"; import Locale from "../../services/Locale"; @@ -81,7 +81,7 @@ export default class Loop extends DiscordModule { if (args.length !== 0) query = args.join(' '); } - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) query = args.getSubcommand(); const voiceChannel = member.voice.channel; diff --git a/src/discord/MusicPlayer/NowPlaying.ts b/src/discord/MusicPlayer/NowPlaying.ts index eec9eed..bae412f 100644 --- a/src/discord/MusicPlayer/NowPlaying.ts +++ b/src/discord/MusicPlayer/NowPlaying.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, MessageActionRow, MessageButton } from "discord.js"; +import { Message, CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; import { I18n } from "i18n"; import DiscordProvider from "../../providers/Discord"; @@ -55,13 +55,13 @@ export default class NowPlaying extends DiscordModule { const instance = DiscordMusicPlayer.getGuildInstance(guild.id); if(!instance || !instance.queue.track[0]) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_MUSIC_PLAYING(data, locale)] }); - const row = new MessageActionRow() + const row = new ActionRowBuilder() .addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('▢️') .setLabel(' Open on YouTube') .setURL(encodeURI(`https://www.youtube.com/watch?v=${instance.queue.track[0].id}`)) - .setStyle('LINK'), + .setStyle(ButtonStyle.Link), ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NOW_PLAYING(data, locale, instance.queue.track[0])], components: [row] }); diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 82dcce6..2649100 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -1,13 +1,13 @@ import { Message, CommandInteraction, - Interaction, VoiceChannel, - MessageActionRow, - MessageButton, + ActionRowBuilder, + ButtonBuilder, SelectMenuInteraction, ButtonInteraction, - StageChannel + StageChannel, + ButtonStyle } from 'discord.js'; import { I18n } from 'i18n'; @@ -286,8 +286,8 @@ export default class Play extends DiscordModule { return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.PLAY_INFO(data, locale)] }); query = args.join(' '); - } else if (data.isSlashCommand()) { - query = data.getSlashCommand().options.getString('query'); + } else if (data.isApplicationCommand()) { + query = data.getSlashCommand().options.get('query', true).value?.toString(); } if (!query) return; @@ -350,8 +350,8 @@ export default class Play extends DiscordModule { instance.addTrackToQueue(result); if (linkData.list) { - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('βœ…') .setCustomId( JSON.stringify({ @@ -361,7 +361,7 @@ export default class Play extends DiscordModule { }) ) .setLabel(' Add the remaining songs in the playlist') - .setStyle('PRIMARY') + .setStyle(ButtonStyle.Primary) ); return await sendHybridInteractionMessageResponse(data, { @@ -387,8 +387,8 @@ export default class Play extends DiscordModule { // The query length is too long to fit in json if (query.length > 100 - 51) return; - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('πŸ”Ž') .setCustomId( JSON.stringify({ @@ -400,7 +400,7 @@ export default class Play extends DiscordModule { }) ) .setLabel(' Not this? Search!') - .setStyle('PRIMARY') + .setStyle(ButtonStyle.Primary) ); return await sendHybridInteractionMessageResponse(data, { diff --git a/src/discord/MusicPlayer/Search.ts b/src/discord/MusicPlayer/Search.ts index 6a2ae7b..5aadebd 100644 --- a/src/discord/MusicPlayer/Search.ts +++ b/src/discord/MusicPlayer/Search.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, Interaction, MessageActionRow, ButtonInteraction, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +import { Message, CommandInteraction, BaseInteraction, ActionRowBuilder, ButtonInteraction, SelectMenuBuilder, SelectMenuComponentOptionData } from "discord.js"; import { I18n } from "i18n"; import { joinVoiceChannelProcedure } from "./Join"; @@ -96,8 +96,8 @@ export default class Search extends DiscordModule { query = args.join(' '); } - else if (data.isSlashCommand()) - query = data.getSlashCommand().options.getString('query'); + else if (data.isApplicationCommand()) + query = data.getSlashCommand().options.get('query', true).value?.toString(); else if (data.isButton()) query = args; @@ -126,9 +126,9 @@ export default class Search extends DiscordModule { let result = await DiscordMusicPlayer.searchYouTubeByQuery(query); if (!result) return; // TODO: Handle when search returned nothing - const menuOptions: MessageSelectOptionData[] = []; + const menuOptions: SelectMenuComponentOptionData[] = []; - const messageSelectMenu = new MessageSelectMenu(); + const messageSelectMenu = new SelectMenuBuilder(); /* Discord have 100 char custom id char limit So we need to shorten our json. @@ -157,7 +157,7 @@ export default class Search extends DiscordModule { messageSelectMenu.addOptions(menuOptions); - const row = new MessageActionRow(); + const row = new ActionRowBuilder(); row.addComponents(messageSelectMenu); return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.SEARCH_RESULT(data, locale, result)], components: [row] }); diff --git a/src/discord/Ping.ts b/src/discord/Ping.ts index c525e28..eff4d65 100644 --- a/src/discord/Ping.ts +++ b/src/discord/Ping.ts @@ -123,7 +123,7 @@ export default class Ping extends DiscordModule { }` ); - if (data.isSlashCommand()) + if (data.isApplicationCommand()) return await data .getMessageComponentInteraction() .editReply({ embeds: [EMBEDS.PING_INFO(data, locale, finalString.join('\n'))] }); diff --git a/src/discord/Say.ts b/src/discord/Say.ts index b9de61b..9203a48 100644 --- a/src/discord/Say.ts +++ b/src/discord/Say.ts @@ -1,4 +1,4 @@ -import { Message, Permissions, Interaction, CommandInteraction } from 'discord.js'; +import { Message, Permissions, Interaction, CommandInteraction, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordModule, { HybridInteractionMessage } from '../utils/DiscordModule'; @@ -78,9 +78,9 @@ export default class Say extends DiscordModule { if ( !message.member.permissions.has([ - Permissions.FLAGS.VIEW_CHANNEL, - Permissions.FLAGS.SEND_MESSAGES, - Permissions.FLAGS.MANAGE_CHANNELS + PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ManageChannels, ]) ) return await sendHybridInteractionMessageResponse(data, { @@ -93,22 +93,22 @@ export default class Say extends DiscordModule { }); query = args.join(' '); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { const interaction = data.getSlashCommand(); if ( !data .getGuild()! .members.cache.get(interaction.user.id) - ?.permissions.has([Permissions.FLAGS.ADMINISTRATOR]) + ?.permissions.has([PermissionsBitField.Flags.Administrator]) ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_PERMISSION(data, locale)] }); - query = interaction.options.getString('message'); + query = interaction.options.get('message', true).value?.toString(); } - if (data.isSlashCommand() && data.getChannel()) { + if (data.isApplicationCommand() && data.getChannel()) { try { await data.getChannel()!.send({ content: query }); await data diff --git a/src/discord/Settings/Prefix.ts b/src/discord/Settings/Prefix.ts index 757208d..3862022 100644 --- a/src/discord/Settings/Prefix.ts +++ b/src/discord/Settings/Prefix.ts @@ -1,4 +1,4 @@ -import { Permissions, Guild } from 'discord.js'; +import { Permissions, Guild, PermissionFlagsBits, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; @@ -54,7 +54,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const prefix = GuildCache.prefix; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] }); @@ -71,7 +71,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l __name.shift(); _name = __name.join(' '); newPrefix = _name; - } else if (data.isSlashCommand()) newPrefix = data.getSlashCommand().options.getString('prefix'); + } else if (data.isApplicationCommand()) newPrefix = data.getSlashCommand().options.get('prefix', true).value?.toString(); if (!newPrefix) return await sendHybridInteractionMessageResponse(data, { @@ -103,7 +103,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder.getMessage().edit({ embeds: [EMBEDS.PREFIX_UPDATED(data, locale, newPrefix)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.PREFIX_UPDATED(data, locale, newPrefix)] }, diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index 21d4a0c..7320e40 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Permissions, Guild, GuildChannel, ThreadChannel, Message } from 'discord.js'; +import { Permissions, Guild, GuildChannel, ThreadChannel, Message, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; @@ -104,7 +104,7 @@ export const setEnableServiceAnnouncement = async ( let member = data.getMember(); if (!member) return; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] }); @@ -124,7 +124,7 @@ export const setEnableServiceAnnouncement = async ( __name.shift(); _name = __name.join(' '); newStatus = _name; - } else if (data.isSlashCommand()) newStatus = data.getSlashCommand().options.getString('status')!; + } else if (data.isApplicationCommand()) newStatus = data.getSlashCommand().options.get('status', true).value?.toString(); if (!newStatus) return await sendHybridInteractionMessageResponse(data, { @@ -165,7 +165,7 @@ export const setEnableServiceAnnouncement = async ( return await (placeholder as Message).edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_STATUS_UPDATED(data, locale, newStatusBool)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { @@ -184,7 +184,7 @@ export const setServiceAnnouncementChannel = async ( let member = data.getMember(); if (!member) return; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] }); @@ -196,7 +196,7 @@ export const setServiceAnnouncementChannel = async ( embeds: [EMBEDS.NO_CHANNEL_MENTIONED(data, locale)] }); channel = data.getMessage().mentions.channels.first(); - } else if (data.isSlashCommand()) channel = data.getSlashCommand().options.getChannel('channel'); + } else if (data.isApplicationCommand()) channel = data.getSlashCommand().options.get('channel', true).channel; if (!channel) return await sendHybridInteractionMessageResponse(data, { @@ -211,16 +211,14 @@ export const setServiceAnnouncementChannel = async ( embeds: [EMBEDS.INVALID_CHANNEL_THREAD(data, locale, TargetChannel)] }); - if (!TargetChannel.isText()) + if (!TargetChannel.isTextBased()) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_CHANNEL(data, locale, TargetChannel)] }); if ( - !data - .getGuild()! - .me?.permissionsIn(TargetChannel) - .has([Permissions.FLAGS.SEND_MESSAGES, Permissions.FLAGS.VIEW_CHANNEL]) + !data.getGuild()?.members.me?.permissionsIn(TargetChannel) + .has([PermissionsBitField.Flags.SendMessages, PermissionsBitField.Flags.ViewChannel]) ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.BOT_NO_PERMISSION(data, locale, TargetChannel)] @@ -239,7 +237,7 @@ export const setServiceAnnouncementChannel = async ( return await (placeholder as Message).edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_CONFIGURED_CHANNEL(data, locale, TargetChannel)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { diff --git a/src/discord/Settings/index.ts b/src/discord/Settings/index.ts index 5f222b9..4d2d61a 100644 --- a/src/discord/Settings/index.ts +++ b/src/discord/Settings/index.ts @@ -91,7 +91,7 @@ export default class Settings extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/UserInfo.ts b/src/discord/UserInfo.ts index 1f39ce5..535ba66 100644 --- a/src/discord/UserInfo.ts +++ b/src/discord/UserInfo.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, Presence, PresenceStatus } from 'discord.js'; +import { Message, CommandInteraction, Presence, PresenceStatus, ActivityType } from 'discord.js'; import { getColorFromURL, Palette } from 'color-thief-node'; import { I18n } from 'i18n'; @@ -73,10 +73,10 @@ const EMBEDS = { if (user.presence?.activities) { for (let activity of user.presence?.activities) { - if (activity.type === 'CUSTOM') - embed.addField( - `✨ ${locale.__('userinfo.custom_status')}`, - `${ + if (activity.type === ActivityType.Custom) + embed.addFields({ + name: `✨ ${locale.__('userinfo.custom_status')}`, + value: `${ !activity.emoji ? '' : `${ @@ -88,49 +88,51 @@ const EMBEDS = { }` } ${activity.state === null ? '' : activity.state} \u200b`, - false - ); + inline: false + }); else { let title = ''; switch (activity.type) { - case 'PLAYING': - title = `'πŸ•Ή ${locale.__('userinfo.playing_x', {NAME: activity.name})}`; + case ActivityType.Playing: + title = `'πŸ•Ή ${locale.__('userinfo.playing_x', { NAME: activity.name })}`; break; - case 'STREAMING': - title = `'πŸ”΄ ${locale.__('userinfo.streaming_x', {NAME: activity.name})}`; + case ActivityType.Streaming: + title = `'πŸ”΄ ${locale.__('userinfo.streaming_x', { NAME: activity.name })}`; break; - case 'LISTENING': - title = `🎡 ${locale.__('userinfo.listening_x', {NAME: activity.name})}`; + case ActivityType.Listening: + title = `🎡 ${locale.__('userinfo.listening_x', { NAME: activity.name })}`; break; - case 'WATCHING': - title = `πŸ“Ί ${locale.__('userinfo.watching_x', {NAME: activity.name})}`; + case ActivityType.Watching: + title = `πŸ“Ί ${locale.__('userinfo.watching_x', { NAME: activity.name })}`; break; - case 'COMPETING': - title = `'🌠 ${locale.__('userinfo.competing_x', {NAME: activity.name})}`; + case ActivityType.Competing: + title = `'🌠 ${locale.__('userinfo.competing_x', { NAME: activity.name })}`; break; } - embed.addField( - `${title}`, - `${activity.details === null ? '' : activity.details} + embed.addFields({ + name: `${title}`, + value: `${activity.details === null ? '' : activity.details} ${activity.state === null ? '' : activity.state} Since \u200b`, - false - ); + inline: false + }); } } } - embed.addField( - `πŸ“° ${locale.__('userinfo.user_guild_info')}`, - `${ + embed.addFields({ + name: `πŸ“° ${locale.__('userinfo.user_guild_info')}`, + value: `${ user.joinedAt === null ? locale.__('userinfo.join_date_unknown') - : locale.__('userinfo.join_date', {TIME: ``}) + : locale.__('userinfo.join_date', { + TIME: `` + }) } ${user.isGuildOwner ? `${locale.__('userinfo.guild_owner')}` : ''} ` - ); + }); embed.setThumbnail(user.displayAvatarURL + '?size=4096'); embed.setAuthor({ @@ -172,7 +174,7 @@ export default class UserInfo extends DiscordModule { if (typeof data.getMessage().mentions.users.first() !== 'undefined') query = data.getMessage().mentions.users.first()?.id; else query = args[0]; - } else if (data.isSlashCommand()) query = data.getSlashCommand().options.getUser('user')?.id; + } else if (data.isApplicationCommand()) query = data.getSlashCommand().options.getUser('user')?.id; // Find the user want to look up let TargetMember = (await guild.members.fetch()).get(query); @@ -181,7 +183,7 @@ export default class UserInfo extends DiscordModule { embeds: [EMBEDS.USER_NOT_FOUND(data, locale)] }); - if (data.isSlashCommand()) await data.getMessageComponentInteraction().deferReply(); + if (data.isApplicationCommand()) await data.getMessageComponentInteraction().deferReply(); let colorthief = null; try { diff --git a/src/discord/osu.ts b/src/discord/osu.ts index 4375a3c..e2c8faf 100644 --- a/src/discord/osu.ts +++ b/src/discord/osu.ts @@ -1,9 +1,10 @@ import { Message, - MessageActionRow, - MessageButton, - Interaction, - CommandInteraction + ActionRowBuilder, + ButtonBuilder, + CommandInteraction, + BaseInteraction, + ButtonStyle } from 'discord.js'; import validator from 'validator'; import countryLookup from 'country-code-lookup'; @@ -20,7 +21,7 @@ import { } from '../utils/DiscordMessage'; const EMBEDS = { - osu_INFO: (data: Message | Interaction) => { + osu_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'osu!', description: `[osu!](https://osu.ppy.sh/home) is a free-to-play rhythm game primarily developed, published, and created by Dean "peppy" Herbert`, @@ -34,43 +35,43 @@ const EMBEDS = { value: '``user``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_USER_FOUND: (data: Message | Interaction) => { + NO_USER_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `That user doesn't exists on osu!`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_USER_MENTIONED: (data: Message | Interaction) => { + NO_USER_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `No osu! username or user id provided`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - INVALID_USER_MENTIONED: (data: Message | Interaction) => { + INVALID_USER_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `Not a valid osu username or id`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - INVALID_BEATMAP_ID_MENTIONED: (data: Message | Interaction) => { + INVALID_BEATMAP_ID_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `Not a valid osu beatmap id`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_BEATMAP_FOUND: (data: Message | Interaction) => { + NO_BEATMAP_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `That beatmap doesn't exists on osu!`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_BEATMAP_MENTIONED: (data: Message | Interaction) => { + NO_BEATMAP_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `No osu! beatmap id provided`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); } }; @@ -102,8 +103,8 @@ export default class osu extends DiscordModule { }); const [removed, ...newArgs] = args; user = newArgs.join(' '); - } else if (data.isSlashCommand()) - user = data.getSlashCommand().options.getString('user'); + } else if (data.isApplicationCommand()) + user = data.getSlashCommand().options.get('user')?.value?.toString(); if (!validator.isNumeric(user) && !this.validate_osu_username(user)) return await sendHybridInteractionMessageResponse(data, { @@ -117,7 +118,7 @@ export default class osu extends DiscordModule { embeds: [EMBEDS.NO_USER_FOUND(data.getRaw())] }); - if (data.isSlashCommand()) { + if (data.isApplicationCommand()) { await data.getSlashCommand().deferReply(); } @@ -258,12 +259,12 @@ export default class osu extends DiscordModule { 'https://osu.ppy.sh/images/layout/avatar-guest.png' ); - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('πŸ”—') .setLabel(' Open Profile') .setURL(`https://osu.ppy.sh/users/${result.id}`) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); return await sendHybridInteractionMessageResponse(data, { @@ -280,8 +281,8 @@ export default class osu extends DiscordModule { }); const [removed, ...newArgs] = args; beatmap = newArgs.join(' '); - } else if (data.isSlashCommand()) - beatmap = data.getSlashCommand().options.getString('beatmap'); + } else if (data.isApplicationCommand()) + beatmap = data.getSlashCommand().options.get('beatmap')?.value?.toString(); if (!validator.isNumeric(beatmap)) return await sendHybridInteractionMessageResponse(data, { @@ -295,7 +296,7 @@ export default class osu extends DiscordModule { embeds: [EMBEDS.NO_BEATMAP_FOUND(data.getRaw())] }); - if (data.isSlashCommand()) await data.getSlashCommand().deferReply(); + if (data.isApplicationCommand()) await data.getSlashCommand().deferReply(); const bm_result = result[0]; @@ -436,32 +437,32 @@ export default class osu extends DiscordModule { `https://assets.ppy.sh/beatmaps/${bm_result.beatmapSetId}/covers/cover.jpg` ); - const row = new MessageActionRow(); + const row = new ActionRowBuilder(); if (bm_result.hasDownload) row.addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('🌎') .setLabel(' Download (Beatconnect)') .setURL(`https://beatconnect.io/b/${bm_result.beatmapSetId}/`) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); row.addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('πŸ”—') .setLabel(' Open listing') .setURL( `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}${url_mode}/${bm_result.id}` ) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); row.addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('πŸ’¬') .setLabel(' Open discussion') .setURL( `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}/discussion` ) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); return await sendHybridInteractionMessageResponse(data, { @@ -480,7 +481,7 @@ export default class osu extends DiscordModule { }); } query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/providers/Discord.ts b/src/providers/Discord.ts index 1169dd6..e2db41f 100644 --- a/src/providers/Discord.ts +++ b/src/providers/Discord.ts @@ -1,4 +1,4 @@ -import { Guild, Client, GuildMember, Intents, Interaction, Message, TextChannel, BaseGuildTextChannel } from 'discord.js'; +import { Guild, Client, GuildMember, IntentsBitField, Interaction, Message, TextChannel, BaseGuildTextChannel, TextBasedChannelMixin, ChannelType, BaseGuildVoiceChannel, InteractionType } from 'discord.js'; import Logger from '../libs/Logger'; import Environment from './Environment'; @@ -38,13 +38,13 @@ class Discord { constructor() { this.client = new Client({ - //partials: ['MESSAGE', 'CHANNEL', 'REACTION'], intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - Intents.FLAGS.GUILD_MEMBERS, - Intents.FLAGS.GUILD_PRESENCES, - Intents.FLAGS.GUILD_VOICE_STATES + IntentsBitField.Flags.MessageContent, + IntentsBitField.Flags.Guilds, + IntentsBitField.Flags.GuildMessages, + IntentsBitField.Flags.GuildMembers, + IntentsBitField.Flags.GuildPresences, + IntentsBitField.Flags.GuildVoiceStates ] }); } @@ -127,7 +127,7 @@ class Discord { if (interaction.guild) { thisModule.GuildInteractionCreate(interaction); - if (interaction.isCommand() && interaction.commandName && thisModule.commandInteractionName) { + if (interaction.type === InteractionType.ApplicationCommand && interaction.commandName && thisModule.commandInteractionName) { thisModule.GuildCommandInteractionCreate(interaction); if (interaction.commandName.toLowerCase() === thisModule.commandInteractionName) thisModule.GuildModuleCommandInteractionCreate(interaction); @@ -160,7 +160,7 @@ class Discord { // Handling guild commands this.client.on('messageCreate', async (message: Message) => { - if (!(message.channel instanceof BaseGuildTextChannel)) return; + if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel)) return; if (message.author.bot) return; if (typeof message.guild?.id === 'undefined') return; diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index 2013f21..112ed0c 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -1,4 +1,12 @@ -import { VoiceChannel, Snowflake, TextChannel, StageChannel, Guild } from 'discord.js'; +import { + VoiceChannel, + Snowflake, + TextChannel, + StageChannel, + Guild, + PermissionsBitField, + BaseGuildVoiceChannel +} from 'discord.js'; import { AudioPlayer, VoiceConnection, @@ -98,10 +106,7 @@ export class DiscordMusicPlayerInstance { this.player.on(AudioPlayerStatus.Idle, async (oldStage, newStage) => { //The player stopped - if ( - newStage.status === AudioPlayerStatus.Idle && - oldStage.status !== AudioPlayerStatus.Idle - ) { + if (newStage.status === AudioPlayerStatus.Idle && oldStage.status !== AudioPlayerStatus.Idle) { // Loop mode is set to current song if (this.loopMode === DiscordMusicPlayerLoopMode.Current) { if (this.queue.track.length !== 0) { @@ -149,7 +154,7 @@ export class DiscordMusicPlayerInstance { public joinVoiceChannel(voiceChannel: VoiceChannel | StageChannel, textChannel?: TextChannel) { const permissions = voiceChannel.permissionsFor(DiscordProvider.client.user!); - if (!permissions || !voiceChannel.joinable || !permissions.has('CONNECT')) + if (!permissions || !voiceChannel.joinable || !permissions.has(PermissionsBitField.Flags.Connect)) throw new Error('No permissions'); if (textChannel) this.textChannel = textChannel; @@ -157,17 +162,18 @@ export class DiscordMusicPlayerInstance { this.voiceConnection = joinVoiceChannel({ channelId: this.voiceChannel.id, guildId: this.voiceChannel.guild.id, - adapterCreator: this.voiceChannel.guild - .voiceAdapterCreator as DiscordGatewayAdapterCreator + adapterCreator: this.voiceChannel.guild.voiceAdapterCreator as DiscordGatewayAdapterCreator }); this.voiceConnection.on( VoiceConnectionStatus.Ready, - (oldState: VoiceConnectionState, newState: VoiceConnectionState) => { - let currentVC = DiscordProvider.client.guilds.cache.get(voiceChannel.guild.id)?.me - ?.voice.channel; - if (currentVC && currentVC.id !== this.voiceChannel.id) { - this.voiceChannel = currentVC; + async (oldState: VoiceConnectionState, newState: VoiceConnectionState) => { + let guild = DiscordProvider.client.guilds.cache.get(voiceChannel.guild.id); + if (guild) { + let currentVC = guild?.members.me?.voice.channel; + if (currentVC && currentVC.id !== this.voiceChannel.id) { + this.voiceChannel = currentVC; + } } } ); @@ -175,12 +181,12 @@ export class DiscordMusicPlayerInstance { this.voiceConnection.on( VoiceConnectionStatus.Disconnected, (oldState: VoiceConnectionState, newState: VoiceConnectionState) => { - setTimeout(() => { - if ( - !DiscordProvider.client.guilds.cache.get(voiceChannel.guildId!)!.me!.voice - .channelId - ) { - this.events.emit('disconnect', new VoiceDisconnectedEvent(this)); + setTimeout(async () => { + let guild = DiscordProvider.client.guilds.cache.get(voiceChannel.guildId); + if(guild) { + if (!guild?.members.me?.voice.channelId) { + this.events.emit('disconnect', new VoiceDisconnectedEvent(this)); + } } }, 2000); } @@ -190,9 +196,10 @@ export class DiscordMusicPlayerInstance { public async leaveVoiceChannel() { if (this.player) this.player.pause(); - if (DiscordProvider.client.guilds.cache.get(this.voiceChannel.guild.id)?.me?.voice) { - this.voiceConnection?.disconnect(); - } + const guild = DiscordProvider.client.guilds.cache.get(this.voiceChannel.guild.id); + if (!guild) return; + + if (guild.members.me?.voice) this.voiceConnection?.disconnect(); } public async pausePlayer() { @@ -286,10 +293,7 @@ export class DiscordMusicPlayerInstance { const stream = 'https://fakestream:42069/fake/stream/fake/audio/fake.mp3'; const resource = createAudioResource(stream); this.player.play(resource); - this.player.emit( - 'error', - new AudioPlayerError(new Error('Music player was manually crashed'), null!) - ); + this.player.emit('error', new AudioPlayerError(new Error('Music player was manually crashed'), null!)); } } @@ -328,10 +332,9 @@ class DiscordMusicPlayer { public async searchYouTubeByYouTubeLink(youtubeLink: YouTubeLink) { // Search the url - const searched: YouTubeVideo[] = await playdl.search( - 'https://www.youtube.com/watch?v=' + youtubeLink.videoId, - { source: { youtube: 'video' } } - ); + const searched: YouTubeVideo[] = await playdl.search('https://www.youtube.com/watch?v=' + youtubeLink.videoId, { + source: { youtube: 'video' } + }); for (let video of searched) { if (video.id === youtubeLink.videoId) return video; } @@ -345,9 +348,7 @@ class DiscordMusicPlayer { } // Last resort, search the title - const videoInfo = await playdl.video_basic_info( - 'https://www.youtube.com/watch?v=' + youtubeLink.videoId - ); + const videoInfo = await playdl.video_basic_info('https://www.youtube.com/watch?v=' + youtubeLink.videoId); if (videoInfo?.video_details?.title) { const searched: YouTubeVideo[] = await playdl.search(videoInfo.video_details.title, { source: { youtube: 'video' } @@ -357,9 +358,7 @@ class DiscordMusicPlayer { } } - let yt_info = await playdl.video_info( - 'https://www.youtube.com/watch?v=' + youtubeLink.videoId - ); + let yt_info = await playdl.video_info('https://www.youtube.com/watch?v=' + youtubeLink.videoId); if (yt_info) { return new YouTubeVideo({ id: yt_info.video_details.id, diff --git a/src/utils/DiscordMessage.ts b/src/utils/DiscordMessage.ts index 4c30fdf..9977d6d 100644 --- a/src/utils/DiscordMessage.ts +++ b/src/utils/DiscordMessage.ts @@ -1,5 +1,5 @@ import { - MessageEmbed, + EmbedBuilder, User, MessagePayload, MessageOptions, @@ -11,7 +11,8 @@ import { Message, ColorResolvable, Interaction, - InteractionReplyOptions + InteractionReplyOptions, + BaseInteraction } from 'discord.js'; import App from '..'; @@ -43,7 +44,7 @@ interface EmbedDataPresets { } export function makeEmbed(data: EmbedData) { - const embed = new MessageEmbed(); + const embed = new EmbedBuilder(); embed.setColor(data.color || '#FFFFFF'); if (!data.icon) embed.setTitle(data.title); @@ -54,14 +55,14 @@ export function makeEmbed(data: EmbedData) { if (data.setTimestamp) embed.setTimestamp(); if (data.user) - embed.footer = { + embed.setFooter({ text: `${data.user.username} | v${App.version}`, iconURL: `${data.user.displayAvatarURL()}?size=4096` - }; + }); else - embed.footer = { + embed.setFooter({ text: `v${App.version}` - }; + }); if (data.fields) embed.addFields(data.fields); @@ -160,8 +161,8 @@ export async function sendHybridInteractionMessageResponse( data: HybridInteractionMessage, payload: MessageOptions | InteractionReplyOptions, replace = false -): Promise { - if (data.isSlashCommand() || data.isButton() || data.isSelectMenu()) { +): Promise { + if (data.isApplicationCommand() || data.isButton() || data.isSelectMenu()) { const messageComponent = data.getMessageComponentInteraction(); if (!messageComponent.replied) { diff --git a/src/utils/DiscordModule.ts b/src/utils/DiscordModule.ts index a2293fe..22aebc4 100644 --- a/src/utils/DiscordModule.ts +++ b/src/utils/DiscordModule.ts @@ -8,7 +8,9 @@ import { TextBasedChannel, MessageComponentInteraction, User, - SelectMenuInteraction + SelectMenuInteraction, + InteractionType, + BaseInteraction } from 'discord.js'; export default class DiscordModule { @@ -56,17 +58,17 @@ export default class DiscordModule { } export class HybridInteractionMessage { - public data: Interaction | Message; - constructor(data: Interaction | Message) { + public data: BaseInteraction | Message; + constructor(data: BaseInteraction | Message) { this.data = data; } public isInteraction(): boolean { - return this.data instanceof Interaction; + return this.data instanceof BaseInteraction; } - public isSlashCommand(): boolean { - return this.data instanceof CommandInteraction && this.data.isCommand(); + public isApplicationCommand(): boolean { + return this.data instanceof CommandInteraction && this.data.type === InteractionType.ApplicationCommand; } public isButton(): boolean { @@ -130,7 +132,7 @@ export class HybridInteractionMessage { return this.data as Message; } - public getRaw(): Interaction | Message { + public getRaw(): BaseInteraction | Message { return this.data; } }