I'm working on a project in React and ran into a problem that has me stumped.
I want to add new user but want to check if user is present or not I tried to give custom message but still not giving me my custom message.
so here is my code and i am not able to figure out how to give custom message.
if any one have some solution it will be really great if you help me
const Employee = require("../models/employeeSchema");
//custom imports
const AppError = require("../helpers/appErrorClass");
const sendErrorMessage = require("../helpers/sendError");
const sendResponse = require("../helpers/sendResponse");
const addEmployees = async (req, res, next) => {
try {
let data = req.body;
let newEmployee = {};
newEmployee.firstName = data.firstName.trim();
newEmployee.lastName = data.lastName.trim();
newEmployee.company = data.company.trim();
newEmployee.email = data.email.trim();
newEmployee.contact = data.contact;
newEmployee.skills = data.skills.split(",").map((skill) => {
return skill.trim();
});
newEmployee.altDescription = data.altDescription.trim();
newEmployee.hobbies = data.hobbies.split(",").map((hobby) => {
return hobby.trim();
});
newEmployee.socialLinks = [
{
gitHub: data.gitHub,
linkedIn: data.linkedIn,
website: data.website,
},
];
newEmployee.imageUrl = req.image;
let employee = await Employee.find({ email: newEmployee.email });
if (employee.email === newEmployee.email) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
} else {
let data = await Employee.create(newEmployee);
sendResponse(200, "Employee added Succesfully", data, req, res);
}
} catch (err) {
return sendErrorMessage(new AppError(400, "unsuccessful", err), req, res);
}
};
module.exports.addEmployees = addEmployees;
I have no idea why this is happening, if anyone has experienced this I would be grateful.
Edit:
console.log(employee) outputs the following:
[{
employeeId: 'c88wgb4ocuw01609613746852',
contact: 123456789,
imageUrl: 'http://res.cloudinary.com/altafshaikh/image/upload/v1609613765/qbl7ujyz0wi6cy0xt3rf.jpg',
skills: [ 'sleep', 'laziness' ],
altDescription: 'Hello Saurav',
hobbies: [ 'Nautanki', 'doubtfull' ],
socialLinks: [ {} ],
_id: 5ff0c1c5327f300a55f6259a,
firstName: 'Saurav',
lastName: 'Upadhyay',
company: 'Raw',
email: 'sourav23#gmail.com',
__v: 0
}]
It's because employee is an array. You need to access the first element.
if (employee.length && employee[0].email === newEmployee.email) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
}
Since the db query condition is email, we can assume that it will return empty array if no matches are found. It also means that the array will be populated only if a match is found. So we can also avoid the unnecessary check of emails being equal. You can do this.
if (employee.length) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
}
Related
so I'm making a message count command with discord.js and MongoDB but the "messageCount" value just never gets created. I searched it up and looked at docs but I couldn't find what was wrong.
Codes:
message-counter.js file:
const mongo = require("mongoose")
const schema = require("./schemas/rank/message-count-schema")
module.exports = client => {
client.on('messageCreate', async (message) => {
const { author } = message
const { id } = author
mongo.connect(
process.env.MONGO_URI,
{ keepAlive: true }
)
const dataQuery = await schema.findOne({ _id: id })
if (!dataQuery) {
const newSchem = schema(
{
_id: id
},
{
$setOnInsert: { messageCount: 1 }
},
{
$inc: { messageCount: 1 }
},
{
upsert: true
}
)
await newSchem.save()
}
else {
dataQuery.updateOne(
{
$inc: { messageCount: 1 }
},
{
upsert: true
}
)
}
})
}
message-count-schema.js file:
const mongoose = require('mongoose');
const messageCountSchema = new mongoose.Schema({
_id: {
type: String,
required: true
},
messageCount: {
type: Number,
required: true
}
})
module.exports = mongoose.model('message-count', messageCountSchema);
Can someone tell me what's wrong and how to fix it? I'm not asking to be spoon fed, just what's wrong.
The thing is $setOnInsert is only valid for update operations when the upsert value is set to true. It exists in these methods => updateOne(), updateMany, findAndModify(). In this case, when it not an update operation, the $setOnInsert doesn't run which is why your data doesn't have the messageCount value.
Like caladan said before, and adding to that you need .findbyId() if you want to use _id, is your message count is per user or per guild?
if per user you can add to your schema a userID String item and use
const member = await message.mentions.members.first() || message.guild.members.cache.get(args[0]) || message.author;
const dataQuery = await schema.findOne({ UserID: member.id })
const messagecount = dataQuery.messageCount;
console.log(messagecount)
If per guild, you can add GildId item in your schema, and use:
const dataQuery = await schema.findOne({ GuildId: message.guild.id })
const messagecount = dataQuery.messageCount;
console.log(messagecount)
I have this function on my express route that update a user information and its role. The role is another Sequelize Object and I have set up a relationship as one to many:
User.belongsTo(Role);
Role.hasMany(User);
In my route this is my updatefunction:
const UpdateUser = async user => {
if (Object.keys(user).length !== 0) {
const { id, firstName, lastName, phone, email, role } = user;
let modUser = await User.findOne({ where: { id }, include: [{ model: Role}] });
if (modUser.firstName !== firstName) modUser.firstName = firstName;
if (modUser.lastName !== lastName) modUser.lastName = lastName;
if (modUser.phone !== phone) modUser.phone = phone;
if (modUser.email !== email && UniqueEmail(email)) modUser.email = email;
if(modUser.Role.id !== role) {
await modUser.setRole(await Role.findByPk(role));
}
modUser.save();
modUser = await User.findOne(
{
where: { id },
include: [{ model: Role}],
attributes: { exclude: ['RoleId', 'password'] }
},
);
return modUser.reload();
}
return { error: "No user found" };
}
The function works fine updating the info and the new role in the DB, the problem is that the returning User, sometimes doesn't have the updated info, but the previos info. I am not sure if I am implementing this wrong, or trying to update the User model and then asigning a new Role at the the time is breaking something.
Any ideas? Thanks!
Most methods in sequelize are async... I wasn't using my await keywords to let the asynchronos code resolve before moving on.
await modUser.reload();
await modUser.save();
Thanks to #Heiko TheiBen
My customizable welcome channel feature for my Discord bot isn't working. I use MongoDB so I can make it customizable per-server.
There are 3 relevant files: welcome.js (my schema file), guildMemberAdd.js (my event file) and setwelcome.js (the command I use to set the welcome channel.)
The welcome.js file:
const mongoose = require('mongoose');
const schema = mongoose.Schema({
_id: {
type: String,
required: true
},
welcomeChannelId: {
type: String,
required: true
},
welcomeText: {
type: String,
required: true
}
});
module.exports = mongoose.model('welcome', schema);
The guildMemberAdd.js file:
const { MessageEmbed } = require('discord.js');
const schema = require('../models/welcome.js')
const welcomeData = {}
module.exports = {
name: 'guildMemberAdd',
async execute(member) {
const g = member.guild;
const ms = require('ms');
const timeSpan = ms('10 days');
//Alt detection
const createdAt = new Date(member.user.createdAt).getTime();
const difference = Date.now() - createdAt;
if (difference < timeSpan) {
member.send('Bye, alt.');
member.ban({ reason: 'This is an alt.' });
}
//Welcome Users
let data = welcomeData[member.guild.id]
if (!data) {
const results = await schema.find({
_id: member.guild.id
})
if (!results) {
return
}
const { welcomeChannelId, welcomeText } = results
const channel = member.guild.channels.cache.get(welcomeChannelId)
data = welcomeData[member.guild.id] = [channel, welcomeText]
}
data[0].send({
content: data[1].replace(/#/g, `<#${member.id}>`)
})
},
};
The setwelcome.js file
const { MessageEmbed } = require('discord.js');
const schema = require('../../models/welcome.js')
module.exports = {
name: 'setwelcome',
description: 'Sets the welcome message for the server.',
options: [{
name: 'channel',
description: 'The channel to set as the welcome channel.',
type: 'CHANNEL',
required: true
},
{
name: 'message',
description: 'The welcome message.',
type: 'STRING',
required: true
}],
async execute(interaction) {
const channel = await interaction.options.getChannel('channel')
const message = await interaction.options.getString('message')
if (
channel.type !== 'GUILD_TEXT' &&
channel.type !== 'GUILD_NEWS' &&
channel.type !== 'GUILD_NEWS_THREAD' &&
channel.type !== 'GUILD_PUBLIC_THREAD' &&
channel.type !== 'GUILD_PRIVATE_THREAD'
)
return interaction.reply('That is not a valid channel type.');
await schema.findOneAndUpdate({
_id: interaction.guild.id,
},
{
_id: interaction.guild.id,
welcomeChannelId: channel.id,
welcomeText: message
},
{
upsert: true
})
await interaction.reply(`Welcome channel is set to ${channel} and welcome message is set to \`${message}\`.`)
},
};
When a new member joins the guild, it throws this error:
/home/runner/MultiBot/events/guildMemberAdd.js:38
data[0].send({
^
TypeError: Cannot read properties of undefined (reading 'send')
at Object.execute (/home/runner/MultiBot/events/guildMemberAdd.js:38:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Please help me out, thanks in advance!
This means that message is nullish. Make sure the argument is actually there. There are 3 ways:
Making the slash command options required (recommended)
Returning early if the argument is not found
if (!message) return; //after the 'message' declaration
Setting a default value, this uses the logical OR operator (the nullish coalescing operator will also suffice)
const message = await interaction.options.getString('message') || "Welcome to the server!"
It might be because data is an array/object and doesn't have a send method. You would need to find the channel before sending it with something like
const channel = await client.channels.fetch(welcomeChannelId);
replace const { welcomeChannelId, welcomeText } = results with const { welcomeChannelId, welcomeText } = results[0] as results is an array
or
use const results = await schema.findOne({ _id: member.guild.id })
to have results be only one object
I'm creating API tests with async-await using Supertest and Mocha.
In the accountsData.js file I created a function to generate random test accounts.
In the accountsHelper.js file I created a function to create unlimited accounts using a while loop
When I run tests on the post_accounts.js file, the first account is created successfully, but from the second account, the data generated in the accountsData.js file is already repeated.
Why isn't data randomly generated when I create more than one account using data from the accountsData.js file?
accountsData.js
const casual = require('casual');
function randomAccount() {
return {
'email': casual.email,
'password': '123456',
};
}
module.exports = {
randomAccount,
};
accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
/* eslint-disable no-console */
const accountList = [];
let counterAccounts;
module.exports = {
async createAccount(account, accountsToCreate = 2, validateResponse = true) {
counterAccounts = 0;
while (counterAccounts < accountsToCreate) {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
.send(account);
if (validateResponse === true) {
if (res.status === commonData.statusCode.ok) {
accountList.push(res.body);
} else {
throw new Error('Email already exists\n\n' + JSON.stringify(res.body, null, ' '));
}
} else {
return res.body;
}
} catch (err) {
console.log(err);
}
counterAccounts++;
}
return accountList;
},
};
post_accounts.js
const accountsData = require('../../data/accountsData');
const accountsHelper = require('../../helpers/accountsHelper');
const account = accountsData.randomAccount();
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async() => {
const res = await accountsHelper.createAccount(account);
// eslint-disable-next-line no-console
console.log(res);
});
});
});
API response:
Create accounts with email and password
valid accounts
Error: Email already exists
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `account` instance is not valid. Details: `email` Email already exists (value: \"Lemuel.Lynch#Susan.net\").",
"details": {
"context": "account",
"codes": {
"email": [
"uniqueness"
]
},
"messages": {
"email": [
"Email already exists"
]
}
}
}
}
at Object.createAccount (/Users/rafael/Desktop/projects/services/test/helpers/accountsHelper.js:24:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
[ { 'privacy-terms': false,
'created-date': '2019-08-24T10:00:34.094Z',
admin: false,
isQueued: false,
lastReleaseAttempt: '1970-01-01T00:00:00.000Z',
'agreed-to-rules': { agreed: false },
email: 'Lemuel.Lynch#Susan.net',
id: '5d610ac213c07d752ae53d91' } ]
✓ should create an account successfully (2243ms)
1 passing (2s)
The code that you posted doesn't correspond to the code that you're describing in prose.
However, I tested your accountsData.js file, in the way that your words (but not your code) say that you're using it, and it works fine.
// main.js
const { createPerson } = require(__dirname + '/accountsData')
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
Output from running it once:
$ node main.js
{ email: 'Anne_Ebert#Macie.com', password: '123456' }
{ email: 'Manley.Lindgren#Kshlerin.info', password: '123456' }
{ email: 'McClure_Thurman#Zboncak.net', password: '123456' }
{ email: 'Breitenberg.Alexander#Savannah.com', password: '123456' }
{ email: 'Keely.Mann#Stark.io', password: '123456' }
And again:
$ node main.js
{ email: 'Destany_Herman#Penelope.net', password: '123456' }
{ email: 'Narciso_Roob#gmail.com', password: '123456' }
{ email: 'Burnice_Rice#yahoo.com', password: '123456' }
{ email: 'Roma_Nolan#yahoo.com', password: '123456' }
{ email: 'Lilla_Beier#yahoo.com', password: '123456' }
Nothing in the code that you posted is actually requiring or using accountsData.js. If you change your code to use it, I think you'll see, like I do, that it works.
Problem is, you are generating the random account and storing it in a variable 'post_accounts.js(line 3)'. So, when you create an account, you are using the same payload to create multiple accounts, which obviously throws an error.
I just modified the accountHelper to properly handle your scenario. Hope this helps.
Note: The code is not tested, I just wrote it from my mind. Please test and let me know if it works.
// accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
const accountsData = require('../../data/accountsData');
/* eslint-disable no-console */
const accountList = [];
module.exports = {
async createAccount(account, accountsToCreate = 1, validateResponse = true) {
// creates an array of length passed in accountsToCreate param
return (await Promise.all(Array(accountsToCreate)
.fill()
.map(async () => {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
// takes account if passed or generates a random account
.send(account || accountsData.randomAccount());
// validates and throw error if validateResponse is true
if (validateResponse === true && (res.status !== commonData.statusCode.ok)) {
throw new Error(
'Email already exists\n\n' +
JSON.stringify(res.body, null, ' ')
);
}
// return response body by default
return res.body;
} catch (e) {
console.error(e);
// return null if the create account service errors out, just to make sure the all other create account call doesnt fail
return null;
}
})))
// filter out the null(error) responses
.filter(acc => acc);
}
};
//post_accounts.js
const accountsHelper = require('../../helpers/accountsHelper');
const accountsData = require('../../data/accountsData');
const GENERATE_RANDOM_ACCOUNT = null;
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async () => {
const result = await accountsHelper.createAccount();
expect(result.length).toEquals(1);
});
it('should create 2 accounts successfully', async () => {
const result = await accountsHelper.createAccount(GENERATE_RANDOM_ACCOUNT, 2);
expect(result.length).toEquals(2);
});
it('should not create duplicate accounts', async () => {
const account = accountsData.randomAccount();
// here we are trying to create same account twice
const result = await accountsHelper.createAccount(account, 2);
// expected result should be one as the second attempt will fail with duplicate account
expect(result.length).toEquals(1);
});
});
});
I'm working on an tiny app that allows user to participate in polls, but I'm having problems checking if the current user has already voted in the poll. Everything else works fine, save for the IIFE that checks for said condition, as seen in the code snippet included. Indeed, I'm getting false as opposed to true with the data I have i.e. I already seeded the DB with sample data, including a random poll that contains the array of IDs for users who've already voted. I tried testing one ID against said array, which returns false as opposed to the expected true. What gives?
Below are the relevant snippets.
Model
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const ChoiceSchema = new Schema({
name: { type: String },
votes: { type: Number }
});
const PollSchema = new Schema({
title: { type: String },
category: { type: String },
choices: [ChoiceSchema],
addedBy: { type: Schema.Types.ObjectId, ref: 'User' },
votedBy: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});
const Poll = mongoose.model('Poll', PollSchema);
export default Poll;
Controllers
import Poll from '../models/poll';
export default {
fetchAllPolls: async (req, res) => {
/*...*/
},
fetchSpecificPoll: async (req, res) => {
/*...*/
},
voteInPoll: async (req, res) => {
const { category, pollId } = req.params;
const { name, choiceId, voterId } = req.body;
try {
const poll = await Poll.findById(pollId);
const choice = await poll.choices.id(choiceId);
const votedChoice = {
name,
votes: choice.votes + 1,
};
// Check if user has already voted in poll
const hasVoted = ((votersIds, id) => votersIds.includes(id))(
poll.votedBy,
voterId
);
if (!voterId) {
res
.status(400)
.json({ message: 'Sorry, you must be logged in to vote' });
} else if (voterId && hasVoted) {
res.status(400).json({ message: 'Sorry, you can only vote once' });
} else {
await choice.set(votedChoice);
await poll.votedBy.push(voterId);
poll.save();
res.status(200).json({
message: 'Thank you for voting. Find other polls at: ',
poll,
});
}
} catch (error) {
res.status(404).json({ error: error.message });
}
},
createNewPoll: async (req, res) => {
/*...*/
},
};
I think you are trying to compare ObjectId with String representing the mongo id.
This should work:
const hasVoted = ((votersIds, id) => votersIds.findIndex((item) => item.toString() === id) !== -1)(
poll.votedBy,
voterId
);
or
const hasVoted = ((votersIds, id) => votersIds.findIndex((item) => item.equals(new ObjectId(id))) !== -1)(
poll.votedBy,
voterId
);
EDIT:
As #JasonCust suggested, a simpler form should be:
const hasVoted = poll.votedBy.some(voter => voter.equals(voterId));
It is more than likely that poll.votedBy is not an array of ID strings. If you are using it as a reference field then it is an array of BSON objects which would fail using includes because it uses the sameValueZero algorithm to compare values. If that is true then you could either convert all of the IDs to strings first or you could use find and the equals methods to find a match.
Update: showing actual code example
Also, some would provide an easier method for returning a boolean value.
const hasVoted = poll.votedBy.some((voter) => voter.equals(voterId));