User ID unique violation discord.js? - javascript

Here is my code for the two functions I have coded.
Reflect.defineProperty(hp, 'add', {
value: async function add(id, amount) {
const user = hp.get(id);
if (user) {
user.health += Number(amount);
return user.save();
}
const newUser = await Users.create({
user_id: id,
health: amount
});
hp.set(id, newUser);
return newUser;
},
});
Reflect.defineProperty(hp, 'getHealth', {
value: function getHealth(id) {
const user = hp.get(id);
return user ? user.health : 0;
},
});
And when I try this: hp.add(message.author.id, 100);, I get this error:
errors: [
ValidationErrorItem {
message: 'user_id must be unique',
type: 'unique violation',
path: 'user_id',
value: '648183573748121610',
origin: 'DB',
instance: [users],
validatorKey: 'not_unique',
validatorName: null,
validatorArgs: []
}
],
fields: ['user_id'],
parent: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: users.user_id] {
errno: 19,
code: 'SQLITE_CONSTRAINT',
sql: 'INSERT INTO `users` (`user_id`,`balance`) VALUES ($1,$2);'
},
original: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: users.user_id] {
errno: 19,
code: 'SQLITE_CONSTRAINT',
sql: 'INSERT INTO `users` (`user_id`,`balance`) VALUES ($1,$2);'
},
sql: 'INSERT INTO `users` (`user_id`,`balance`) VALUES ($1,$2);'
}
Could somebody tell me what is the problem? And also, could you please tell me the solution to the problem? More info: I'm creating a discord bot with discord.js. I am using Sequilize and SQLite to store the data.

I am quoting another user (Lioness100) on another question about ID's. It's actually not possible to get the ID of a discord user. You could make an array and then get the ID of a person you want, and then check from that array. But I think this image will resolve this question.
Quote:
Hoped this solved your question!

Related

Discordjs cooldown database with sequalize unique id error

I have made a cooldowns database with sequalize and sqlite3 for my discord bot. This is to add individual cooldowns for certain commands however I am getting an error that says "id must be unique" even when I turn off the unique: true to unique: false or even make a new database storage for the other command. Below is the full error.
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
Error
at Database.<anonymous> (C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\dialects\sqlite\query.js:179:27)
at C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\dialects\sqlite\query.js:177:50
at new Promise (<anonymous>)
at Query.run (C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\dialects\sqlite\query.js:177:12)
at C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\sequelize.js:311:28
at async SQLiteQueryInterface.insert (C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\dialects\abstract\query-interface.js:308:21)
at async model.save (C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\model.js:2432:35)
at async Function.create (C:\Users\brade\Desktop\Bear battles\node_modules\sequelize\lib\model.js:1344:12) {
name: 'SequelizeUniqueConstraintError',
errors: [
ValidationErrorItem {
message: 'id must be unique',
type: 'unique violation',
path: 'id',
value: '250412979835764738',
origin: 'DB',
instance: cooldown {
dataValues: {
id: '250412979835764738',
expiry: 1655869677206,
command: 'hunt',
updatedAt: 2022-06-22T03:42:57.207Z,
createdAt: 2022-06-22T03:42:57.207Z
},
_previousDataValues: { id: undefined, expiry: undefined, command: undefined },
uniqno: 1,
_changed: Set(3) { 'id', 'expiry', 'command' },
_options: {
isNewRecord: true,
_schema: null,
_schemaDelimiter: '',
attributes: undefined,
include: undefined,
raw: undefined,
silent: undefined
},
isNewRecord: true
},
validatorKey: 'not_unique',
validatorName: null,
validatorArgs: []
}
],
parent: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: cooldown.id] {
errno: 19,
code: 'SQLITE_CONSTRAINT',
sql: 'INSERT INTO `cooldown` (`id`,`expiry`,`command`,`createdAt`,`updatedAt`) VALUES ($1,$2,$3,$4,$5);'
},
original: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: cooldown.id] {
errno: 19,
code: 'SQLITE_CONSTRAINT',
sql: 'INSERT INTO `cooldown` (`id`,`expiry`,`command`,`createdAt`,`updatedAt`) VALUES ($1,$2,$3,$4,$5);'
},
fields: [ 'id' ],
sql: 'INSERT INTO `cooldown` (`id`,`expiry`,`command`,`createdAt`,`updatedAt`) VALUES ($1,$2,$3,$4,$5);'
}
Here is the code for my daily command.
const { SlashCommandBuilder } = require('#discordjs/builders')
const ms = require('ms')
const { defaultColor } = require('../../command-imports')
module.exports = {
data: new SlashCommandBuilder()
.setName('daily')
.setDescription('Claim your daily reward.'),
async execute (interaction, Cooldowns) {
let getCooldown = await Cooldowns.findOne({where: {id: interaction.user.id}}) // Finds if user has cooldown
let cooldownTime = getCooldown?.expiry
if(getCooldown && cooldownTime > new Date().getTime()) { // If cooldown is active run this
return interaction.reply({content: `You are still under cooldown! Please wait **${ms(cooldownTime - new Date().getTime(), {long: true})}**`})
} else if (getCooldown) { // If cooldown is expired remove from db and run rest of code
Cooldowns.destroy({where: {id: interaction.user.id, command: 'daily'}})
}
const claimedDaily = {
color: defaultColor,
description: "You have recieved N/A from your daily reward"
}
interaction.reply({embeds: [claimedDaily]})
Cooldowns.create({ // Creates 5 minute cooldown for hunt command
id: interaction.user.id,
expiry: new Date().getTime() + (60000 * 5),
command: 'daily'
})
}
}
Here is my hunt command.
const { SlashCommandBuilder } = require('#discordjs/builders')
const { errorColor, defaultColor } = require('../../command-imports')
const ms = require('ms')
module.exports = {
data: new SlashCommandBuilder()
.setName('hunt')
.setDescription('Hunt for a chance at finding a bear.'),
async execute(interaction, Cooldowns, Economy) {
let getCooldown = await Cooldowns.findOne({where: {id: interaction.user.id, command: 'hunt'}}) // Finds if user has cooldown
let getUser = await Economy.findOne({where: {id: interaction.user.id}})
if(!getUser) {
getUser = await Economy.create({id: interaction.user.id, coins: 0})
}
let cooldownTime = getCooldown?.expiry
if(getCooldown && cooldownTime > new Date().getTime()) { // If cooldown is active run this
return interaction.reply({content: `You are still under cooldown! Please wait **${ms(cooldownTime - new Date().getTime(), {long: true})}**`})
} else if (getCooldown) { // If cooldown is expired remove from db and run rest of code
Cooldowns.destroy({where: {id: interaction.user.id, command: 'hunt'}})
}
let whichExecute = Math.floor(Math.random() * 8) + 1 // 7/8 Chance for coins 1/8 Chance for bears
if(whichExecute <= 7) {
let coinsFound = Math.floor(Math.random() * 10) + 1 // Picks random coin amount between 1 - 10
const nothingFound = {
color: errorColor,
description: `No bear was found however you found ${coinsFound} :coin: \n You have ${getUser.coins} :coin:` // Displays coins earned and total coins
}
interaction.reply({embeds: [nothingFound]})
await Economy.update({coins: getUser.coins + coinsFound}, {where: {id: interaction.user.id}}) // Updates user in db
Cooldowns.create({ // Creates 5 minute cooldown for hunt command
id: interaction.user.id,
expiry: new Date().getTime() + (60000 * 5),
command: 'hunt'
})
}
else if(whichExecute === 8) {
const bearFound = { // Displays bear found
color: defaultColor,
description: "You found placeholder_beartype :bear:;;"
}
interaction.reply({embeds: [bearFound]})
Cooldowns.create({ // Creates 5 minute cooldown for hunt command
id: interaction.user.id,
expiry: new Date().getTime() + (60000 * 5),
command: 'hunt'
})
}
}
}
I still get the error for unique id even though it should be stored with the same id but under a different command name. This error doesn't appear until I run both commands (doesn't matter the order) for example I do /hunt and then do /daily later on. Any help fixing this would be great if you have any questions or stuff I can clarify let me know.
Note: This code is written for Discord.js v13.7.0 and Sequelize v6
Improperly altering tables
<Sequelize>.sync() is not executed with alter or force
Sequelize, according to their v6 documentation, provides a function called sync(). This function is used to ensure that your models are up to date with the database. However, there is one caveat to this. If you execute sync() with no arguments, the database will not overwrite existing data. This is where your issue stems from. When you first defined the models, most likely you did the following two things:
Defined id as DataTypes.INTEGER
Set id to be a unique field
Due to these and you executing .sync() with no arguments, the database's tables will not be overwritten, therefore preserving the old unique fields. Also, if you attempt to store a Discord ID as an Integer, you may encounter an issue where Discord IDs are shortened or rounded.
Solutions
Drop the table
As a one time fix, you can manually drop the tables from sqlite3 using this command and rerun the bot without modifying sync() which will create the table with the right data:
DROP TABLE 'Cooldowns'
Fixing outdated tables
In order to fix the outdated tables, you have two options. However, be careful as these are destructive actions. You can execute the sync() command with the following arguments:
<Sequelize>.sync({ alter: true }); // Alters tables
<Sequelize>.sync({ force: true }); // Forcefully recreates tables
As stated before, be careful with these actions as they are destructive and cannot be reverted if you do not have backups.
Properly storing Discord IDs
All you need to do is store the Discord IDs as a DataTypes.STRING or DataTypes.TEXT. This will preserve the Snowflake form of the ID and prevent shortening.
sequelize.define("User", {
id: {
type: DataTypes.STRING, // Or .TEXT
unique: false
},
// ...
});

How to use a SQL Result in Discord.JS SelectMenus?

I am trying to add Options to a SelectMenu from a SQL request. My code is the following:
case "edit":{
const editrow = new MessageActionRow();
let query = `SELECT * FROM tickettypes WHERE guild_id = '${interaction.guild.id}'`
const editmenu = new MessageSelectMenu()
.setCustomId('editselect')
.setPlaceholder('🔧 Select tickettype to edit')
.addOptions([
{
label: 'None',
description: 'Empty',
value: 'none',
},])
await sql.query(query, function(err, result) {
if(err) throw err;
console.log(result)
result.forEach(item => {
editmenu.addOptions([
{
label: '' + item.name,
description: '' + item.name,
emoji: '' + item.emoji,
value: '' + item.id,
},
]);
});
});
editmenu.addOptions([
{
label: '2 Test',
description: 'Empty',
value: 'test',
},
])
editrow.addComponents(editmenu);
const editembed = new MessageEmbed()
.setColor('YELLOW')
.setTitle('Edit tickettype')
.setAuthor({ name: interaction.user.username})
.setDescription('Select the tickettype you want to edit')
await interaction.reply({ embeds: [editembed], components: [editrow], ephemeral: true})
}
break;
My Console is giving me the following output:
[SQL] Connected to the MySQL server! Connection ID: 95
[DISCORD] Succesfully established connection to Discord!
[
RowDataPacket {
id: 1,
name: 'Test',
emoji: '<:thumbsup:>',
guild_id: 933323734322913300,
prefix: 'test',
openheader: 'Test Ticket',
openmsg: 'Welcome, this is a test.'
}
]
There are no Errors. Still Discord doesn't add it. It looks like this:
Discord View of the Select Menu
I have no clue, what i did wrong. Please help me out.
Thanks in advance
When you fetch the data from sql, your code doesn't wait for it. It instead continues on, and the callback function you provided in the query will only be executed once the query was completed. This is why you have the option of 2 Test but you don't have the result options. One way to fix it would be to move all the code after the result into the callback function, then they would only be executed once the query was completed

Mongo Db error validator Error: Masekhta validation failed: _id: Error, expected `_id`

I'm trying to do simple scripts that add an object to Mongo and I get this error
Error: Masekhta validation failed: _id: Error, expected _id
I don't understand why I think that it's because of the unique validator but mongoose should handle the _id as I know.
First is Schema
const mongoose = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");
const Schema = mongoose.Schema;
const masekhtaSchema = new Schema({
book: { type: String, required: true },
pesukim: { type: String, required: false },
selected: { type: Boolean, required: false },
});
masekhtaSchema.plugin(uniqueValidator);
module.exports = mongoose.model("Masekhta", masekhtaSchema);
Script:
const Masekhta = require("../models/masekhta");
const addMasekhta = async () => {
const createdMasekhta = new Masekhta({
book: "test",
pesukim: "test",
selected: false,
});
try {
console.log("adding");
await createdMasekhta.save();
} catch (err) {
console.log(err);
}
};
addMasekhta();
Just to help a bit I have another one that looks pretty the same and it's working so the connection to the DB is clean.
Full Error if needed.
Error: Masekhta validation failed: _id: Error, expected `_id` to be unique. Value: `60c1dbdc13a2a7392c0ac7ce`
at ValidationError.inspect (C:\Users\Admin\Desktop\All Projects\Coding\In Progress\Syium\backsiyum\node_modules\mongoose\lib\error\validation.js:47:26)
at internal/per_context/primordials.js:23:32
at formatValue (internal/util/inspect.js:774:19)
at inspect (internal/util/inspect.js:336:10)
at formatWithOptionsInternal (internal/util/inspect.js:2006:40)
at formatWithOptions (internal/util/inspect.js:1888:10)
at console.value (internal/console/constructor.js:313:14)
at console.log (internal/console/constructor.js:348:61)
at addMasekhta (C:\Users\Admin\Desktop\All Projects\Coding\In Progress\Syium\backsiyum\scripts\addMasekhta.js:14:13)
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
errors: {
_id: ValidatorError: Error, expected `_id` to be unique. Value: `60c1dbdc13a2a7392c0ac7ce`
at validate (C:\Users\Admin\Desktop\All Projects\Coding\In Progress\Syium\backsiyum\node_modules\mongoose\lib\schematype.js:1252:13)
at C:\Users\Admin\Desktop\All Projects\Coding\In Progress\Syium\backsiyum\node_modules\mongoose\lib\schematype.js:1227:24
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
properties: [Object],
kind: 'unique',
path: '_id',
value: 60c1dbdc13a2a7392c0ac7ce,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'Masekhta validation failed'
}
It seems that it comes from mongoose-unique-validator, the issue on github. This is an old package that hasn't been updated in 2 years, so I suggest you avoid it.
I had the same problem, my code worked using
await user.save({validatemodifyedOnly:true})
In Your case,
await createdMasektah.save({validatemodifyedOnly:true})
Hope this can help someone.

Inquirer.js populate list choices from sql database

I"m using inquirer.js to build a commandline employee database.
Is it possible to populate the choices array dynamically from a sql database in inquirer.js?
for example
inquirer.prompt([
{ type: 'list',
message: "Choose department to add Role to",
name: "department",
choices: [
`SELECT * FROM departments`
]
}
])
deparments is the table I want to acceess
I'd want it to return the list of all departments as the choices
I actually ran into this exact problem recently and have a functioning solution!!
Inquirer's choices key can be defined using a function but expects the function to return an array of objects; each object represents a choice and has a name: key to be shown to the user as an option for the choice, and a value: key which will be what inquirer stores as the answer value in the answer object (like a number, string, or boolean etc.). Here is an example of a structure the choices key expects to be returned from the function:
[
{
name: 'Choice 1',
value: 1,
},
{
name: 'Choice 2',
value: 'Something',
},
{
name: 'Choice 3',
value: false,
}
]
Make sure that you check the data that your function returns and ensure that you have this format so that inquirer's choice key accepts it!
Here is how I implemented it with a database:
I am using a .promise() on my connection so that I can use async/await syntax. Here is my connection setup for mysql2:
// use .promise() so that we can use await on connection
const connection = mysql.createConnection({
host: 'localhost',
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: 'employees_db',
}).promise();
Here is the particular question object that has choices: being defined by a function called departmentChoices() that is getting all the department choices from mysql database. Make sure this is defined in an async function as well so you can use await.
{
message: "Which Department's budget do you want to see?",
name: 'id',
type: 'list',
choices: await departmentChoices(),
when(answers) {
return answers.task === 'View a Department Budget';
},
},
Here is the function definition. I chose to use async/await for the database query for easy of readability. You should probably wrap it in a try/catch for better error handling and best practices. Notice I used an alias value for the id as this is the value I want to use for the value: key in the choice object. name did not need an alias as it is the value I want stored under the name: key in the choice object.
const departmentChoices = async () => {
const departmentQuery = `SELECT id AS value, name FROM department;`;
const departments = await connection.query(departmentQuery);
return departments[0];
};
This is the array this function will return from my database:
[
{ value: 1, name: 'Hair and Makeup' },
{ value: 2, name: 'Finance' },
{ value: 3, name: 'Set Design' },
{ value: 4, name: 'Wardrobe' }
]

Closing mongoose db connection erases schema

I got a weird behavior with mongoose, it seems that closing the db connection after saving my schema erases it.
Here's my schema brand.js:
var brandSchema = new db.Schema({
id: {type: String, required: true, index: {unique: true}},
products: [String]
});
I execute the following script to populate my database (important precision: before executing the script, my brand table is not defined in the DB):
var async = require('async');
//Get config
var middlewares = require('./middlewares');
var config = require('./config');
//Load model
require('./models/brand');
var db = middlewares.db(config);
// Load brand.json
var brands = require('./brands.json');
// Save each brand in the database
async.each(Object.keys(brands), function(brandId, callback){
var brand = new Brand({id: brandId, products: brands[brandsId]);
brand.save(function(err){
if(err) console.log(err);
else console.log('brand ' + brand.id + ' added');
callback();
});
}, function(){
//Properly close the connection so the script can terminate
db.connection.close();
});
This script gives the following logs:
Mongoose: brand.ensureIndex({ id: 1 }) { safe: undefined, background: true, uni
que: true }
Mongoose: brand.insert({ __v: 0, products: [ 'phone', 'tv'], _id: ObjectId(
"54524f612245da0c2f0d2ba7"), id: 'samsung' }) {}
Mongoose: brand.insert({ __v: 0, products: [ 'food', 'beverages' ], _id: ObjectId(
"54524f612245da0c2f0d2ba8"), id: '' }) {}
The first line of the logs suggests that an index id is created with the right parameters. But when I look into the DB, my brands are saved but the brand schema is empty. However, if I remove db.connection.close(), brands are still saved and the schema is saved like defined in Brand.
I don't really understand why. Could it be because of buffered data not sent to the db ?

Categories

Resources