Discord.JS & Sequelize integration - node.js

I've been building a discord bot over the last few weeks just as a side project.
I've built a fair amount as i've been working through the various tutorials in Discordjs.guide.
I've come to the Sequelize section of the tutorial and worked through it, ok all makes perfect sense to me.
Instead of creating a new bot file, i've been trying to incorporate it into everything i've built already. Being a little bit of a novice i've tried to make sense of how to do that with everything that was in the previous sections, but some of the code doesn't match up to the bot that has been built up until this point.
Now i feel like i'm getting there after a lot of reading and some trial an error, but i'm missing something, or i don't quite understand what i'm writing and i've hit a dead end and need some help.
I've worked through this page. - https://discordjs.guide/sequelize/#a-simple-tag-system
I've incorporated the Alpha, Beta & Gamma into my index.js file that was originally created at the start of the guide.
I've then taken the "Delta, Epsilon Etc" and split them into their own command files as shown previously in the tutorial.
I've also got the reload command that is previously in the tutorial.
So, my bot runs fine, i can use my previous commands for things like telling a joke, or showing a avatar.
But when i try to use any of the "addTag", "editTag" nothing happens, when i try to reload these commands, my bot tells me the command doesnt exist, but when i do my help command these commands are displayed in the dynamic command menu.
I've got a feeling i'm missing something makes the module export as async functions?
If anyone could explain what im doing wrong, or just point me in the right direction i would be grateful and if you need me to provide anything else let me know! Thank you.
Index.js
const fs = require('fs');
const Discord = require('discord.js');
const { prefix, token } = require('./config.json');
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
const cooldowns = new Discord.Collection();
const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'user', 'password', {
host: 'localhost',
dialect: 'sqlite',
logging: false,
// SQLite only
storage: 'database.sqlite',
});
const Tags = sequelize.define('tags', {
name: {
type: Sequelize.STRING,
unique: true,
},
description: Sequelize.TEXT,
username: Sequelize.STRING,
usage_count: {
type: Sequelize.INTEGER,
defaultValue: 0,
allowNull: false,
},
});
client.on('ready', async () => {
Tags.sync();
console.log(`Logged in as ${client.user.tag}!`);
client.user.setActivity('for souls.', { type: 'WATCHING' });
})
client.on('message', async message => {
if (!message.content.toLowerCase().startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
const commandArgs = args.join(' ');
const command = client.commands.get(commandName) ||
client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) return;
if (command.guildOnly && message.channel.type != 'text') {
return message.reply ('I can\'t do this here, you filthy human.');
}
if (command.args && !args.length) {
let reply = `Well, you gotta tell me what to do?!`;
if (command.usage) {
reply += `\nDo it properly, imbecile. \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
if (!cooldowns.has(command.name)) {
cooldowns.set(command.name, new Discord.Collection());
}
const now = Date.now();
const timestamps = cooldowns.get(command.name);
const cooldownAmount = (command.cooldown || 3) * 1000;
if (timestamps.has(message.author.id)) {
const expirationTime = timestamps.get(message.author.id) + cooldownAmount;
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
return message.reply(`Slow down, you/'ve got all life....Heh heh heh.`);
}
}
timestamps.set(message.author.id, now);
setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply('I can/t do that, mortal. ')
}
});
client.login(token);
process.on('unhandledRejection', error => {
console.error('Unhandled promise rejection:', error);
});
command-addTag.Js
const { prefix } = require('../config.json');
const Sequelize = require('sequelize');
const Discord = require('discord.js');
module.exports = {
name: 'addTag',
description:'Adds a tag to the user in the database',
args: true,
cooldown: 10,
execute(message, args) {
(async() => {
try {
const tag = await Tags.create({
name: tagName,
description: tagDescription,
username: message.author.username
});
return message.reply(`Tag ${tag.name} added.`)
}
catch (e) {
if (e.name === 'SequelizeUniqueConstaintError') {
return message.reply('That tag already exists.');
}
return message.reply('Something went wrong with adding a tag.');
}
})();
}
};

This is a bit late, but here is what I think you need to add.
client.once('ready', () => {
Tags.sync();
console.log(`Logged in as ${client.user.tag}!`);
});
You can get more at https://discordjs.guide/sequelize/#creating-the-model

Related

Discord JS SlashCommandBuilder

I'm Currently trying to implement SlashCommandBuilder into my Discord Bot.
The bot is currently using prefix '!' and I want to remake it to work with the SlashCommandBuilder, The following code is what i have used and tested, as it pretty much works fine or looks like it's working fine I'm still having an issue caused when someone uses '/hello' It will give him Error 'The application did not respond'.
I did double check the API, Token and such using a Prefix as a check.
The Code does actually add the command to the discord and it looks in the lists of commands.
I'm also splitting the commands inside 'commands' folder.
index.js :
const Discord = require('discord.js');
const fs = require('fs');
const { Client, Collection } = require('discord.js');
const { REST } = require('#discordjs/rest');
const config = require('./config.json');
const { Routes } = require('discord-api-types/v9');
const client = new Client();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
client.commands = new Collection();
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
client.once('ready', () => {
console.log('Bot is ready!');
const rest = new REST({ version: '9' }).setToken(config.token);
rest.put(
Routes.applicationCommands(client.user.id),
{ body: client.commands },
)
.then(() => console.log('Successfully registered commands'))
.catch(error => console.error(error));
});
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
interaction.reply({ content: 'Error executing command', ephemeral: true });
}
});
client.login(config.token)
commands/hello.js
module.exports = {
name: 'hello',
description: 'Replys with Hi',
execute(interaction) {
interaction.reply({ content: 'Hi!' });
},
};
Please if anyone has information on why this was caused, i would love to listen.
Thank you for reading and appreciate any help or hints.

Discord.js command handling. Command handling dont work

I copied the code exactly from the official Discord.JS Guide. But the bot does not respond to the command in any way. How to solve it?
index.js:
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, Events, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
client.commands.set(command.data.name, command);
}
client.once(Events.ClientReady, () => {
console.log('Ready!');
});
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
client.login(token);
config.json:
{
"clientId": "my id",
"guildId": "my id",
"token": "my token"
}
ping.js:
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
async execute(interaction) {
return interaction.reply('Pong!');
},
};
I searched on the Internet, and even found something, but in an attempt to repeat this, the bot did not respond to commands, although it turned on calmly.

How to move members between channels in Discord.js V 14

I need my Bot to move members between Channels. I recently upgraded to Discord.js Version 14 from Version 12.
My discord.js Version: 14.7.1
My node.js Version: 18.12.1
My main.js
const { Client, Events, GatewayIntentBits, Collection, ActivityType } = require("discord.js");
const fs = require("node:fs");
const path = require("node:path");
const { token } = require("./config.json");
const botIntents = [
GatewayIntentBits.Guilds,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildVoiceStates
];
const client = new Client({ intents: botIntents, partials: ["CHANNEL"] });
client.commands = new Collection();
const commandsPath = path.join(__dirname, "commands");
const commandFiles = fs.readdirSync(commandsPath).filter((file) => file.endsWith(".js"));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
if ("data" in command && "execute" in command) {
client.commands.set(command.data.name, command);
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
// Bot ready event
client.once(Events.ClientReady, (c) => {
console.log(`Logged in as ${c.user.tag}`);
c.user.setActivity("/help", { type: ActivityType.Watching });
});
// Message input to command
client.on(Events.InteractionCreate, async (interaction) => {
if (!(interaction.isChatInputCommand())) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!(command)) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
// ephemeral: true / private message, only visible to message sender (user)
await interaction.reply({ content: "There was an error while executing this command!", ephemeral: true });
}
});
client.login(token);
My working Code in Version 12.
module.exports = {
name: "my_name",
description: "my_description",
execute(message, args) {
const member = message.mentions.members.first();
if (!(args[1])) {
const embed = new Discord.MessageEmbed()
.setTitle("my_command")
.setColor(0x992d22)
.setDescription("my_description")
.setFooter(`Requested by ${message.author.tag}.`, message.author.displayAvatarURL);
message.channel.send(embed);
}
if (!member) return message.reply("enter a member name.")
if (!member.voice.channel) return message.reply("the member is not in a voice channel.");
if (!message.member.voice.channel) return message.reply("you need to join a voice channel first.");
message.channel.send("my_message");
member.voice.setChannel("my_channel_id");
}
}
I tried to get it to work in Version 14 like so.
module.exports = {
data: new SlashCommandBuilder()
.setName("my_name")
.setDescription("my_description")
.addUserOption((option) =>
option
.setName("member")
.setDescription("my_description")
.setRequired(true)
)
.setDMPermission(false),
async execute(interaction) {
const master = interaction.user.username;
const target = interaction.options.getUser("member");
const cageId = "my_channel_id";
if (!(interaction.member.voice.channel)) {
return await interaction.reply({ content: "You need to join a Voice-Channel first.", ephemeral: true });
}
if (!(target.voice.channelId)) {
return await interaction.reply({ content: "The Member is currently not in a Voice-Channel.", ephemeral: true });
}
await target.voice.setChannel(cageId);
const embed = new EmbedBuilder()
.setColor(0x992d22)
.setTitle("my_title")
.setDescription("my_description")
.setFooter({ text: `Requested by ${master}` })
.setTimestamp();
return await interaction.reply({ embeds: [embed] });
},
}
Problem
TypeError: Cannot read properties of undefined (reading 'setChannel')
TypeError: Cannot read properties of undefined (reading 'channelId')
I tried to Google it for quite some time, but i was not able to find a fitting solution.
Just a couple of little tweaks and you should have what you're looking for.
First, make sure that when you're starting your bot you are requesting the needed Intent GatewayIntentBits.GuildVoiceStates. Gateway Intents Documentation
Make certain that the option collected is the GuildMember:
const target = interaction.options.getUser("member");
to
const target = interaction.options.getMember("member");
Then when you are referencing the guild member, you need to specify that you're talking about the VoiceState:
if (!(target.channelId)) {
becomes
if (!(target.voice.channelId)) {
and
await target.setChannel(cageId);
becomes
await target.voice.setChannel(cageId);

Bot not responding to commands (discord.js v12)

I've tried doing a test command using client.on which worked but everything else in my command handler does not work. Nothing is returned, is there something I am doing wrong?
Issue: My ping command does not do anything whatsoever.
Index.js file
require('dotenv').config();
const Discord = require('discord.js');
const { Client, Collection, Intents } = require('discord.js');
const config = require('./config.json');
const fs = require("fs");
const client = new Client({ disableMentions: 'everyone', partials: ['MESSAGE', 'CHANNEL', 'REACTION'], ws: { intents: Intents.ALL } });
const PREFIX = config.PREFIX;
client.commands = new Discord.Collection();
const commandFiles = fs
.readdirSync("./commands/")
.filter((file) => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
client.commands = new Collection();
Ping file
let config = require('../config.json');
const Discord = require('discord.js');
const { MessageEmbed } = require('discord.js');
module.exports = {
name: 'ping',
category: 'Info',
description: 'Returns the bot\'s latency and API ping.',
aliases: ['latency'],
usage: 'ping',
userperms: [],
botperms: [],
run: async (client, message, args) => {
message.channel.send('🏓 Pinging....').then((msg) => {
const pEmbed = new MessageEmbed()
.setTitle('🏓 Pong!')
.setColor('BLUE')
.setDescription(
`Latency: ${Math.floor(
msg.createdTimestamp - message.createdTimestamp,
)}ms\nAPI Latency: ${client.ws.ping}ms`,
);
msg.edit(pEmbed);
});
},
};
You need to add event which will trigger every time a message is created and the bot can see it.
An example on version 12 would be (using message :
client.on('message', message => {
if (message.content.startsWith("!ping")) {
message.channel.send('Pong!');
}
});
In v13, message is deprecated so use messageCreate :
client.on('messageCreate', message => {
if (message.content.startsWith("!ping")) {
message.channel.send('Pong!');
}
});

Discord.JS Events Handler Commands

Ok so I finally figured out how to code my fs events handler to use the events folder. now I just need to know the basic method for coding the evtns in their own files.
Here is what I have for now [starting with the ready.js file]. Is this correct and if not how do I code the event files properly?
module.exports = {
name: 'avatar',
description: 'Get the avatar URL of the tagged user(s), or your own avatar.',
execute(message) {
client.on("ready", () => {
client.user.setActivity(`on ${client.guilds.size} servers`);
console.log(`Ready to serve on ${client.guilds.size} servers, for ${client.users.size} users.`);
}
}};
This is my index.js file for reference:
const fs = require('fs');
const Discord = require('discord.js');
const client = new Discord.Client();
const { prefix, token } = require('./config.json');
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
fs.readdir('./events/', (err, files) => {
if (err) return console.error(err);
files.forEach(file => {
const eventFunction = require(`./events/${file}`);
if (eventFunction.disabled) return; //
const event = eventFunction.event || file.split('.')[0];
const emitter = (typeof eventFunction.emitter === 'string' ? client[eventFunction.emitter] : eventFunction.emitter) || client; /
const once = eventFunction.once;
try {
emitter[once ? 'once' : 'on'](event, (...args) => eventFunction.run(...args));
} catch (error) {
console.error(error.stack);
}
});
});
client.login(token);
The upper code block is not ready.js its avatar.js i think.

Resources