DiscordAPIError: Unknown Interaction - javascript

I have been using an online guide to set up a currency bot but when I use the command to add items to the shop the terminal throws out this error and while the bot says the item has been added when I check the shop it has nothing in it. this is the exact error that i get I'm new to coding and a have little to no idea what it means any help or point towards a guide that might explain it would be greatly appreciated
DiscordAPIError: Unknown interaction
at RequestHandler.execute (c:\Users\danie\Desktop\CurrencyBot\node_modules\discord.js\src\rest\RequestHandler.js:349:13)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (c:\Users\danie\Desktop\CurrencyBot\node_modules\discord.js\src\rest\RequestHandler.js:50:14)
at async CommandInteraction.reply (c:\Users\danie\Desktop\CurrencyBot\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:99:5)
====================
Here is the code for the command
const Discord = require('discord.js')
const CurrencySystem = require("currency-system");
const cs = new CurrencySystem;
exports.run = async (client, message, args) => {
await message.deferReply();
if (message.options.getInteger('price') < 1) return message.editReply("You can't add an item for less than 1$!");
let result = await cs.addItem({
guild: message.guild,
inventory: {
name: message.options.getString('name'),
price: message.options.getInteger('price'),
description: message.options.getString('description') || 'No Description'
}
});
if (result.error) {
if (result.type == 'No-Inventory-Name') return message.editReply('There was a error, Please enter item name to add.!')
if (result.type == 'Invalid-Inventory-Price') return message.editReply('There was a error, invalid price!')
if (result.type == 'No-Inventory-Price') return message.editReply('There was a error, You didnt specify price!')
if (result.type == 'No-Inventory') return message.editReply('There was a error, No data recieved!')
} else return message.editReply('Done! Successfully added `' + message.options.getString('name') + '` to the shop!')
}
exports.help = {
name: "additem",
data: {
name: 'additem',
description: "A way to additem to shop",
options: [{
name: 'name',
type: 'STRING',
description: 'Name of Item.',
required: true,
}, {
name: 'price',
type: 'INTEGER',
description: 'Price of item',
required: true,
},
{
name: 'description',
type: 'STRING',
description: 'Description of the item. (Can\'t be Changed later.)',
required: false,
}
]
}
};
exports.conf = {
aliases: [],
cooldown: 5 // This number is a seconds, not a milliseconds.
// 1 = 1 seconds.
}

Related

getNumber doesn't exists in CommandInteractionOptionResolver discord.js

I'm trying to create a simple add slash command with discord.js, but it seems that interaction.options.getNumber just doesn't exists (look at https://github.com/discordjs/discord.js/blob/main/packages/discord.js/src/structures/CommandInteractionOptionResolver.js#L181)
This is a piece of my code:
...
commands?.create({
name: 'add',
description: 'add two numbers',
options: [
{
name: 'num1',
description: 'The first num',
required: true,
type: DiscordJS.ApplicationCommandOptionType.Number
},
{
name: 'num2',
description: 'The second num',
required: true,
type: DiscordJS.ApplicationCommandOptionType.Number
} ]
})
})
...
client.on('interactionCreate', async (interaction) => {
if (!interaction.isCommand()) {
return
}
const { commandName, options } = interaction
if (commandName === 'add') {
console.log(options)
const num1 = options.getNumber('num1')!
const num2 = options.get('num2')!
// idk why but "get" method exists. So I was trying to use it,
// but js says that you couldn't add a string | number | boolean value to an another one
console.log(num1.value + num2.value)
console.log(typeof(num2.value)) // this print "number" btw
interaction.reply({
content: `The sum is ${num1.value}`
})
}
}
There is a solution, but it's intricated:
...
} else if (commandName === 'add') {
console.log(options)
const raw_num1 = options.get('num1')!
const raw_num2 = options.get('num2')!
const num1 = raw_num1.value!
const num2 = raw_num2.value!
interaction.reply({
content: `The sum is ${+(num1) + +(num2)}`
})
}
})

How can I prompts loop in Node.js?

I want the main.js loop to be re-selectable when the user has selected option.
Here is the code.
main.js
const prompts = require('prompts');
var option = require('./option.js');
(async () => {
const response = await prompts({
type: 'select',
name: 'value',
message: 'choice',
choices: [
{ title: 'option1', description: 'option1 description', value: '1' },
{ title: 'exit', description: 'exit from script',value: '0' }
],
initial: 1
}
).then(response => {
if(response.value == 1){
console.info('you select option1');
option.option1()
// i want to run main.js again here
}
else {
console.info('you select exit');
// i want to exit from main.js
}
});
})();
option.js
module.exports = {
option1:function() {
console.log("You have selected option 1")
}
}
When the user has selected option1, after the option.js script's function is done, I would like it to return to the new options page.
I've tried many ways but I still can't find a way. What can I try?
Is this the solution to your problem? Also notice when using await, dont use then.
const prompts = require('prompts');
var option = require('./option.js');
async function prompt () {
const response = await prompts({
type: 'select',
name: 'value',
message: 'choice',
choices: [
{ title: 'option1', description: 'option1 description', value: '1' },
{ title: 'exit', description: 'exit from script',value: '0' }
],
initial: 1
})
return response.value === '1'?option.option1() & prompt():false
}
prompt()

permission over write after channel creation, using discord.js

I'm having some issues with giving the message.author and staff permission to see the channel right after it's created, the issue is, when the channel's parent (category) is changed, it syncs the permissions of the parent (category), which disallows the user and staff to see the channel, I'm not sure how to fix this, I wish I explained well, if you have any questions, please ask.
Here is my code:
module.exports = {
name: 'new',
category: 'Ticket',
description: 'Creates a new ticket.',
aliases: ['newticket'],
usage: 'New',
userperms: [],
botperms: [],
run: async (client, message, args) => {
if(message.author.bot) return;
if(!message.channel.id == process.env.COMMAND_T) return;
if(!client.userTickets) {
client.userTickets = new Map();
const channels = message.guild.channels.cache.filter(channel => {
if(channel) return channel.name.startsWith('t-');
});
if(channels) {
for (i in Array.from(channels)) {
client.userTickets.set(i, +i + 1);
}
}
}
console.log(client.userTickets)
if(client.userTickets.has(message.author.id)) {
return message.channel.send('<#' + message.author.id + 'You already have a ticket, please close it then run this command again!').then(m => m.delete({timeout: 10000}));
}
message.guild.channels.create(`t-${client.userTickets.size + 1}`, {
permissionOverwrites: [
{
id: message.author.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
{
id: process.env.ROLE_STAFF,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
},
{
id: process.env.ROLE_MEMBER,
deny: ['VIEW_CHANNEL']
}
],
type: 'text',
}).then(async channel => {
channel.setParent(process.env.TICKET_C);
client.userTickets.set(message.author.id, client.userTickets.size + 1);
message.channel.send(`<#` + message.author.id + `>, Done, go to your ticket! ${channel}`).then(m => m.delete({timeout: 10000}));
client.users.cache.get(message.author.id).send(`Your ticket has been opened, go take a look: ${channel}`)
channel.send(`Hi <#` + message.author.id + `>, Hello and welcome to your DwaCraft ticket!`);
channel.send(`https://tenor.com/view/is-there-something-i-can-help-you-with-dan-levy-david-david-rose-schitts-creek-gif-20776045`);
const logchannel = message.guild.channels.cache.find(channel => channel.id === process.env.TICKET_L);
if(logchannel) {
logchannel.send(`There was a new ticket created by <#${message.author.id}>! Channel: <#${channel.id}>`);
}
});
}
}
Note: I've researched but I didn't find any answer.
Thanks for taking the time to read this.
Try this
message.guild.channels.create(`t-${client.userTickets.size + 1}`, {
type: 'GUILD_TEXT',
permissionOverwrites: [
{
id: process.env.ROLE_STAFF,
allow: ['VIEW_CHANNEL'],
},
{
id: message.author.id,
allow: ['VIEW_CHANNEL'],
},
],
parent: process.env.CATEGORY
});
This code is mine, but it is shortened, if you like the complete one send me DM
P.S I just have it for my ticket system

Discord.js-commando missing argument reply

I'm porting my commands from vanilla discord.js to commando framework. I had a command that, when the argument was missing, it warned the user.
const { Command } = require('discord.js-commando');
module.exports = class ServerCommand extends Command {
constructor(client) {
super(client, {
name: 'say',
aliases: ['s'],
group: 'mod',
memberName: 'say',
description: 'Make the bot speak for you.',
userPermissions: ['MANAGE_CHANNELS'],
examples: [client.commandPrefix + 'say <text>',client.commandPrefix + 'say hello world'],
args: [{
key: 'text',
prompt: 'What should the bot say?',
type: 'string',
}]
})
}
run(message, { text }) {
if (text == '' || !text)
message.say("You didn't specify what the bot should say.")
message.say(text);
message.delete();
}
}
Now, with commando, it automatically warns the user with a reply when the arg is missing.
My question is, how can I overwrite it?
Thanks in advance!
I handled this adding default property 'default': 'isempty' and then I catch it in the command's code. So, the code looks like it:
const { Command } = require('discord.js-commando');
module.exports = class ServerCommand extends Command {
constructor(client) {
super(client, {
name: 'say',
aliases: ['s'],
group: 'mod',
memberName: 'say',
description: 'Make the bot speak for you.',
userPermissions: ['MANAGE_CHANNELS'],
examples: [client.commandPrefix + 'say <text>',client.commandPrefix + 'say hello world'],
args: [{
key: 'text',
prompt: 'What should the bot say?',
type: 'string',
'default': 'isempty',
}]
})
}
run(message, { text }) {
if (text == 'isempty') return message.say("You didn't specify what the bot should say.");
message.say(text);
message.delete();
}
}

Sequelize save/create method only works at first time on CRUD app

General issue:
I've been having a hard time trying to build a simple CRUD app using JavaScript + node JS + express + sequelize (MySQL).
Contextualization about the project
My CRUD app is being developed to manage students from a particular English teacher.
There are some table models created: Alunos - English: Students, Boletos - English: Pay Order, Aulas - English: Classes, and others that are not mandatory to explain for this issue for now.
Specific issue:
There is a post route that takes some of my body contents and inserts a new student to table "Alunos". After the row containing student data is created, I need to create registries for "Boletos", it would be 12 month of Pay Orders registered into this table. There are two problems with this part: the first I register a student, it works fine, but I could not get the auto-increment id generated by the model to insert in the foreign key "AlunoId", so the foreign key for "Boletos" table is set to null. The other problem is that the both entries (1 into "Alunos" and 12 into "Boletos") works fine at first, to registry the first student, but after the page is refreshed and I try to registry another student, node JS throws an error:
(node:5720) UnhandledPromiseRejectionWarning: SequelizeUniqueConstraintError: Validation error
at Query.formatError (D:\ProgramacaoEstudos\ProjetoCRUD2\node_modules\sequelize\lib\dialects\mysql\query.js:242:16)
at Query.run (D:\ProgramacaoEstudos\ProjetoCRUD2\node_modules\sequelize\lib\dialects\mysql\query.js:77:18)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async D:\ProgramacaoEstudos\ProjetoCRUD2\node_modules\sequelize\lib\sequelize.js:619:16
at async MySQLQueryInterface.insert (D:\ProgramacaoEstudos\ProjetoCRUD2\node_modules\sequelize\lib\dialects\abstract\query-interface.js:749:21)
at async model.save (D:\ProgramacaoEstudos\ProjetoCRUD2\node_modules\sequelize\lib\model.js:3954:35)
at async D:\ProgramacaoEstudos\ProjetoCRUD2\routes\admin.js:101:30
(node:5720) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
Code:
Models - Alunos:
// Create Aluno table model and export to be called to other file
module.exports = (sequelize, DataTypes) => {
const Aluno = sequelize.define('Aluno', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
surname: {
type: DataTypes.STRING,
allowNull: false,
},
birth: {
type: DataTypes.DATEONLY,
allowNull: false,
},
phone_number: {
type: DataTypes.STRING,
allowNull: true,
unique: true,
},
mobile_number: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
residential_address: {
type: DataTypes.STRING,
allowNull: false,
},
profession: {
type: DataTypes.STRING,
allowNull: false,
},
company: {
type: DataTypes.STRING,
allowNull: false,
},
num_classes_week: {
type: DataTypes.INTEGER,
allowNull: false,
},
classes_day: {
type: DataTypes.STRING,
allowNull: false,
},
classes_time: {
type: DataTypes.TIME,
allowNull: false,
},
starts_at: {
type: DataTypes.DATEONLY,
allowNull: false,
},
value: {
type: DataTypes.FLOAT,
allowNull: false,
},
discount: {
type: DataTypes.FLOAT,
defaultValue: 0,
},
due_date: {
type: DataTypes.DATEONLY,
allowNull: false,
},
});
Aluno.associate = (models) => {
Aluno.hasMany(models.Aula, {
onDelete: 'CASCADE',
});
};
Aluno.associate = (models) => {
Aluno.hasMany(models.Boleto, {
onDelete: 'NO ACTION',
});
};
Aluno.associate = (models) => {
Aluno.hasMany(models.Assiste_Aula, {
onDelete: 'NO ACTION',
});
};
return Aluno;
};
Models - Boletos:
module.exports = (sequelize, DataTypes) => {
const Boleto = sequelize.define('Boleto', {
value: {
type: DataTypes.FLOAT,
allowNull: false
},
due_date: {
type: DataTypes.DATEONLY,
allowNull: false
},
status: {
type: DataTypes.INTEGER,
defaultValue: 0,
allowNull: false
}
})
Boleto.associate = (models) => {
Boleto.belongsTo(models.Aluno, {
foreignKey: 'AlunoId'
})
}
return Boleto
}
Routes - Post - registry:
// Post Routes
router.post('/realizado', async (req, res) => {
// Create Aluno
// Compute values of some attributes
var cls_day = req.body.classes_day;
var num_cls = cls_day.length;
var dias;
for (let i = 0; i < num_cls; i++) {
if (i + 1 < num_cls) {
dias += cls_day[i] + '-';
} else {
dias += cls_day[i];
}
}
// Instantiate Aluno model
const aluno = db.Aluno.build({
name: req.body.name,
surname: req.body.surname,
birth: req.body.birth,
phone_number: req.body.phone_number,
mobile_number: req.body.mobile_number,
email: req.body.email,
residential_address: req.body.residential_address,
profession: req.body.profession,
company: req.body.company,
num_classes_week: num_cls,
classes_day: dias,
classes_time: req.body.classes_time,
starts_at: req.body.starts_at,
value: req.body.value,
discount: req.body.discount,
due_date: req.body.due_date,
});
// Insert into database
const newAluno = await aluno.save();
// Create boleto
var objList = [];
for (var i = 0; i < 12; i++) {
var firstDt = new Date(req.body.due_date);
// Compute current date
var dt = firstDt.setMonth(firstDt.getMonth() + i);
//dt.setDate(dt.getMonth() + i)
// Build boleto object
var boleto;
boleto = db.Boleto.build({
value: req.body.value,
due_date: dt,
alunoId: newAluno.id,
});
objList.push(boleto);
}
for (var i = 0; i < objList.length; i++) {
try {
await objList[i].save();
} catch (err) {
console.log(err);
}
}
res.render('realizado');
});
Final Considerations:
Since I'm new with node JS and JavaScript I didn't know about the Promises and the syntactic sugar await/async. I've already studied with a bunch of videos and I think I got the basics concepts about it, but I'm not being able to apply it to the project.
You need to either use db.Aluno.create() or set db.Aluno.build({...}, { isNewRecord: true }) to let Sequelize know it's an insert and not a record with a primary key value of 0. Your DB likely sees the ID of 0 and either inserts it or sets it to 1, either way you will get a conflict on the second insert.
It's also a good idea to wrap your router/controller code in a try/catch to handle any errors. Use a transaction that is passed to all your queries/inserts so that you can roll them all back if there is an error at any stage - const transaction = await sequelize.transaction(); const aluno = await db.Aluno.create({...}, { transaction });. Commit at the end with await transaction.commit() or in the catch block roll back with await transaction.rollback().
Don't use await in a for loop - its the same as blocking for each call which is inefficient and slow. Instead you can pass an array of promises to Promise.all() and resolve them concurrently.... objList.push(boleto.save()); (don't await here) and then await Promise.all(objList);.
Some last notes - it's good to use const when a variable won't change and let when it might to make your results more consistent. You should also try to have an explicit return from arrow functions.
Here is your code with the changes applied.
// Post Routes
router.post('/realizado', async (req, res) => {
// we may or may not be able to create a transaction, so use let
let transaction;
try {
// start a new transaction an pass to all the create() calls
transaction = await sequelize.transaction();
// Compute values of some attributes
var cls_day = req.body.classes_day;
var num_cls = cls_day.length;
var dias;
for (let i = 0; i < num_cls; i++) {
if (i + 1 < num_cls) {
dias += cls_day[i] + '-';
} else {
dias += cls_day[i];
}
}
// Create Aluno model, use const since it won't change
const aluno = await db.Aluno.create(
{
name: req.body.name,
surname: req.body.surname,
birth: req.body.birth,
phone_number: req.body.phone_number,
mobile_number: req.body.mobile_number,
email: req.body.email,
residential_address: req.body.residential_address,
profession: req.body.profession,
company: req.body.company,
num_classes_week: num_cls,
classes_day: dias,
classes_time: req.body.classes_time,
starts_at: req.body.starts_at,
value: req.body.value,
discount: req.body.discount,
due_date: req.body.due_date,
},
{
// use the transaction
transaction,
}
);
// Create boleto insert promise array
// Use const because we will be adding items, but into the same const array
const promises = [];
for (let i = 0; i < 12; i++) {
const firstDt = new Date(req.body.due_date);
// put the promise into the promises array
promises.push(
// the create call here will start the insert but not wait for it to complete
db.Boleto.create(
{
value: req.body.value,
due_date: firstDt.setMonth(firstDt.getMonth() + i),
alunoId: aluno.id,
},
{
// use the transaction so we can rollback if there are errors
transaction,
}
)
);
}
// await the result of all the boleto inserts
await Promise.all(promises);
// no errors, we can commit the transaction
await transaction.commit();
return res.render('realizado');
} catch (err) {
console.log(err);
if (transaction) {
await transaction.rollback;
}
return res.status(500).send(err.message);
}
});

Categories