diff --git a/README.md b/README.md index 7c4b852..e706ab3 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Download the current source code [here](https://git.baipyr.us/Baipyrus/DiscordJS-Example/archive/main.zip). Or clone the repository manually: + ```bash git clone https://git.baipyr.us/Baipyrus/DiscordJS-Example.git ``` @@ -17,6 +18,7 @@ git clone https://git.baipyr.us/Baipyrus/DiscordJS-Example.git ## Installation Install the required dependencies: + ```bash npm install ``` @@ -24,6 +26,7 @@ npm install ## Running Start the bot with: + ```bash npm run start ``` diff --git a/commands/admin/member_roles/slash.js b/commands/admin/member_roles/slash.js index 181e108..e0adbb7 100644 --- a/commands/admin/member_roles/slash.js +++ b/commands/admin/member_roles/slash.js @@ -1,103 +1,103 @@ -import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; -import { Role, Guild } from '../../../database.js'; - -/** - * @param {Guild} guild - * @param {Role} role - */ -const registerRole = async (guild, role) => { - // Check if guild exists in database, otherwise create it - const guildData = { id: guild.id }; - await Guild.findOrCreate({ - where: guildData, - defaults: guildData - }); - - // Register role in database - await Role.create({ - guild: guild.id, - id: role.id, - assign: true - }); -}; - -export const data = new SlashCommandBuilder() - .setName('member_roles') - .setDMPermission(false) - .setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles) - .setDescription('Assigns roles to new members.') - .addSubcommand((subcommand) => - subcommand - .setName('add') - .setDescription('Registers a role to be assigned to new members.') - .addRoleOption((option) => - option - .setName('role') - .setDescription('The role to assign to new members.') - .setRequired(true) - ) - ) - .addSubcommand((subcommand) => - subcommand - .setName('remove') - .setDescription('Unregisters a role from new member assignment.') - .addRoleOption((option) => - option - .setName('role') - .setDescription('The role to unregister from assignmment.') - .setRequired(true) - ) - ); - -/** @param {ChatInputCommandInteraction} interaction */ -export async function execute(interaction) { - const { options } = interaction; - - // Get command options - const role = options.getRole('role'); - switch (options.getSubcommand()) { - case 'add': - // Search for role in database - const found = await Role.findOne({ - where: { - id: role.id - } - }); - - // Toggle role assignment if found - if (found) { - found.assign = true; - await found.save(); - // Otherwise create new database entry - } else await registerRole(interaction.guild, role); - // Reply successfully to acknowledge command - await interaction.reply({ - content: 'Successfully registered role.', - ephemeral: true - }); - - console.info(`[INFO] Registered role to be assigned with ID '${role.id}'.`); - break; - case 'remove': - // Remove role from database - const count = await Role.destroy({ - where: { - id: role.id, - assign: true - } - }); - - // Set reply based on result of deletion - let response = 'Successfully removed'; - if (count === 0) response = 'Failed to remove'; - - // Reply to acknowledge command - await interaction.reply({ - content: `${response} role from new member assignment!`, - ephemeral: true - }); - - console.info(`[INFO] Removed role to be assigned with ID '${role.id}'.`); - break; - } -} +import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { Role, Guild } from '../../../database.js'; + +/** + * @param {Guild} guild + * @param {Role} role + */ +const registerRole = async (guild, role) => { + // Check if guild exists in database, otherwise create it + const guildData = { id: guild.id }; + await Guild.findOrCreate({ + where: guildData, + defaults: guildData + }); + + // Register role in database + await Role.create({ + guild: guild.id, + id: role.id, + assign: true + }); +}; + +export const data = new SlashCommandBuilder() + .setName('member_roles') + .setDMPermission(false) + .setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles) + .setDescription('Assigns roles to new members.') + .addSubcommand((subcommand) => + subcommand + .setName('add') + .setDescription('Registers a role to be assigned to new members.') + .addRoleOption((option) => + option + .setName('role') + .setDescription('The role to assign to new members.') + .setRequired(true) + ) + ) + .addSubcommand((subcommand) => + subcommand + .setName('remove') + .setDescription('Unregisters a role from new member assignment.') + .addRoleOption((option) => + option + .setName('role') + .setDescription('The role to unregister from assignmment.') + .setRequired(true) + ) + ); + +/** @param {ChatInputCommandInteraction} interaction */ +export async function execute(interaction) { + const { options } = interaction; + + // Get command options + const role = options.getRole('role'); + switch (options.getSubcommand()) { + case 'add': + // Search for role in database + const found = await Role.findOne({ + where: { + id: role.id + } + }); + + // Toggle role assignment if found + if (found) { + found.assign = true; + await found.save(); + // Otherwise create new database entry + } else await registerRole(interaction.guild, role); + // Reply successfully to acknowledge command + await interaction.reply({ + content: 'Successfully registered role.', + ephemeral: true + }); + + console.info(`[INFO] Registered role to be assigned with ID '${role.id}'.`); + break; + case 'remove': + // Remove role from database + const count = await Role.destroy({ + where: { + id: role.id, + assign: true + } + }); + + // Set reply based on result of deletion + let response = 'Successfully removed'; + if (count === 0) response = 'Failed to remove'; + + // Reply to acknowledge command + await interaction.reply({ + content: `${response} role from new member assignment!`, + ephemeral: true + }); + + console.info(`[INFO] Removed role to be assigned with ID '${role.id}'.`); + break; + } +} diff --git a/events/members/guildMemberAdd.js b/events/members/guildMemberAdd.js index 70aba56..55722c0 100644 --- a/events/members/guildMemberAdd.js +++ b/events/members/guildMemberAdd.js @@ -1,27 +1,27 @@ -import { Events, GuildMember } from 'discord.js'; -import { Role } from '../../database.js'; - -export const name = Events.GuildMemberAdd; -/** @param {GuildMember} member */ -export async function execute(member) { - // Find roles to be assigned in guild from database - const roles = await Role.findAll({ - where: { - guild: member.guild.id, - assign: true - } - }); - - // Ignore if no none found - if (roles.length === 0) return; - - try { - // Add roles to member - await member.roles.add(roles.map((role) => role.id)); - } catch (error) { - // Missing permissions - console.error(error); - await member.user.send('Could not assign roles. Please contact server staff.'); - } - console.info(`[INFO] Added ${roles.length} roles to new member with ID '${member.user.id}'.`); -} +import { Events, GuildMember } from 'discord.js'; +import { Role } from '../../database.js'; + +export const name = Events.GuildMemberAdd; +/** @param {GuildMember} member */ +export async function execute(member) { + // Find roles to be assigned in guild from database + const roles = await Role.findAll({ + where: { + guild: member.guild.id, + assign: true + } + }); + + // Ignore if no none found + if (roles.length === 0) return; + + try { + // Add roles to member + await member.roles.add(roles.map((role) => role.id)); + } catch (error) { + // Missing permissions + console.error(error); + await member.user.send('Could not assign roles. Please contact server staff.'); + } + console.info(`[INFO] Added ${roles.length} roles to new member with ID '${member.user.id}'.`); +} diff --git a/models/guilds.js b/models/guilds.js index c537fbf..08e17e9 100644 --- a/models/guilds.js +++ b/models/guilds.js @@ -1,24 +1,24 @@ -import { DataTypes, Sequelize } from 'sequelize'; - -/** - * @typedef {Object} Guild - * @property {string} id A Discord guild ID. - * @property {(model: Object) => void} hasMany Defines an One-To-Many relationship. - * @property {(conditions: Object) => Promise} findOne Finds one instance in the database matching the provided condition(-s). - * @property {(conditions: Object) => Promise>} findAll Finds all instances in the database matching the provided condition(-s). - * @property {(conditions: Object) => Promise} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values. - */ - -/** - * The definition of the `Guild` table in the database. - * @param {Sequelize} sequelize - * @returns {Guild} - */ -export default function (sequelize) { - return sequelize.define('Guilds', { - id: { - type: DataTypes.STRING, - primaryKey: true - } - }); -} +import { DataTypes, Sequelize } from 'sequelize'; + +/** + * @typedef {Object} Guild + * @property {string} id A Discord guild ID. + * @property {(model: Object) => void} hasMany Defines an One-To-Many relationship. + * @property {(conditions: Object) => Promise} findOne Finds one instance in the database matching the provided condition(-s). + * @property {(conditions: Object) => Promise>} findAll Finds all instances in the database matching the provided condition(-s). + * @property {(conditions: Object) => Promise} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values. + */ + +/** + * The definition of the `Guild` table in the database. + * @param {Sequelize} sequelize + * @returns {Guild} + */ +export default function (sequelize) { + return sequelize.define('Guilds', { + id: { + type: DataTypes.STRING, + primaryKey: true + } + }); +} diff --git a/models/roles.js b/models/roles.js index fec00d9..5f26749 100644 --- a/models/roles.js +++ b/models/roles.js @@ -1,38 +1,38 @@ -import { DataTypes, Deferrable, Sequelize } from 'sequelize'; - -/** - * @typedef {Object} Role - * @property {string} id A Discord role ID. - * @property {boolean} assign Whether or not the role should be assigned to new members. - * @property {string} guild A Discord guild ID as a foreign key reference. - * @property {(model: Object) => void} hasMany Defines an One-To-Many relationship. - * @property {(conditions: Object) => Promise} findOne Finds one instance in the database matching the provided condition(-s). - * @property {(conditions: Object) => Promise>} findAll Finds all instances in the database matching the provided condition(-s). - * @property {(conditions: Object) => Promise} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values. - */ - -/** - * The definition of the `Role` table in the database. - * @param {Sequelize} sequelize - * @returns {Role} - */ -export default function (sequelize) { - return sequelize.define('Roles', { - id: { - type: DataTypes.STRING, - primaryKey: true - }, - assign: { - type: DataTypes.BOOLEAN, - defaultValue: false - }, - guild: { - type: DataTypes.STRING, - references: { - deferrable: Deferrable.INITIALLY_IMMEDIATE, - model: 'Guilds', - key: 'id' - } - } - }); -} +import { DataTypes, Deferrable, Sequelize } from 'sequelize'; + +/** + * @typedef {Object} Role + * @property {string} id A Discord role ID. + * @property {boolean} assign Whether or not the role should be assigned to new members. + * @property {string} guild A Discord guild ID as a foreign key reference. + * @property {(model: Object) => void} hasMany Defines an One-To-Many relationship. + * @property {(conditions: Object) => Promise} findOne Finds one instance in the database matching the provided condition(-s). + * @property {(conditions: Object) => Promise>} findAll Finds all instances in the database matching the provided condition(-s). + * @property {(conditions: Object) => Promise} findOrCreate Finds or creates an instance in the database matching the provided condition(-s) or default values. + */ + +/** + * The definition of the `Role` table in the database. + * @param {Sequelize} sequelize + * @returns {Role} + */ +export default function (sequelize) { + return sequelize.define('Roles', { + id: { + type: DataTypes.STRING, + primaryKey: true + }, + assign: { + type: DataTypes.BOOLEAN, + defaultValue: false + }, + guild: { + type: DataTypes.STRING, + references: { + deferrable: Deferrable.INITIALLY_IMMEDIATE, + model: 'Guilds', + key: 'id' + } + } + }); +}