How to use If statement and for loop in Nodejs? - node.js

I have two collections Developer and project. I want to assign more then one project to developer but i don't want to repeatedly assign any project.
/*#Submit assign project to developer */
exports.putDevAssign = (req, res, next) => {
const {projectId, teamId} = req.body
Team.findById(teamId)
.then(result => {
if(result.project.length == 0 ) {
Team.findByIdAndUpdate(teamId, {$push: { project : projectId } }, { new: true }).populate('project')
.then(result => {
res.redirect('/Assigned-Developer/' + teamId)
})
.catch(err => console.log(err))
} else {
for(let i = 0; i < result.project.length; i++) {
if( projectId == result.project[i] ) {
req.flash('message', 'Already Assigned')
return res.redirect('/Assigned-Developer/' + teamId)
} else {
console.log('hello')
Team.findByIdAndUpdate(teamId, {$push: { project : projectId } }, { new: true }).populate('project')
.then(result => {
return res.redirect('/Assigned-Developer/' + teamId)
})
.catch(err => console.log(err))
}
}
}
})
.catch(err => console.log)
}
But in above code i can assign first project and it is neither repeatedly stored. but from second project it is stored repeatedly . I don't want this to happen. i want to assign only unique project. Help me with this silly error that i have made. Thank you in advance.

When you're comparing the existing projects, you're checking each element and adding the project if that element does not match. You should compare all the current projects before adding the new one.
Try this code:
/*#Submit assign project to developer */
exports.putDevAssign = (req, res, next) => {
const {projectId, teamId} = req.body
Team.findById(teamId)
.then(result => {
if(result.project.length == 0 ) {
Team.findByIdAndUpdate(teamId, {$push: { project : projectId } }, { new: true }).populate('project')
.then(result => {
res.redirect('/Assigned-Developer/' + teamId)
})
.catch(err => console.log(err))
} else {
for(let i = 0; i < result.project.length; i++) {
if( projectId == result.project[i] ) {
req.flash('message', 'Already Assigned')
return res.redirect('/Assigned-Developer/' + teamId) // project already in list
}
}
// if code reached here, project not in current project list, must add it
console.log('hello')
Team.findByIdAndUpdate(teamId, {$push: { project : projectId } }, { new: true }).populate('project')
.then(result => {
return res.redirect('/Assigned-Developer/' + teamId)
})
.catch(err => console.log(err))
}
}
})
.catch(err => console.log)
}

Related

Compare data after sequelize asynchronous query

I have this code :
VerificationKey.getCode = async (visitorData, visitorCode, res) => {
console.log("Verif model visitorCode" + visitorCode);
const data = visitorData;
const testCode = visitorCode;
const findVisitor = await VerificationKey.findOne({ where: { data } })
.catch((err) => {
console.log(err);
})
.then(() => {
if (testCode == findVisitor.key) {
res.status(200).json({ response: true });
}
});
};
What I need is to compare testCode and findVisitor.key values.
If they are equal, I want to return a boolean to the front end.
But I can't write it like this because it is not possible to access findVisitor.key before initialization.
I believe you have to change your code to use async/await syntax only - without then and catch:
VerificationKey.getCode = async (visitorData, visitorCode, res) => {
console.log("Verif model visitorCode" + visitorCode);
const data = visitorData;
const testCode = visitorCode;
try {
const findVisitor = await VerificationKey.findOne({ where: { data } });
if(!findVisitor) {
res.status(404).json({ response: false });
} else if(testCode == findVisitor.key) {
res.status(200).json({ response: true });
} else {
res.status(403).json({ response: false });
}
} catch(err) {
console.log(err);
}
};

Discord button only works once discord.js

I have posted a button but it only works once
but after that when I use it again
Also
How can I reply to message if I use deferUpdate it shows
Code
client.on('ready', () => {
client.user.setActivity('people and managing the server', {
type: 'WATCHING',
});
const channel = client.channels.cache.get('894171605608042496');
const row = new MessageActionRow().addComponents(
new MessageButton()
.setCustomId('openTicket')
.setLabel('Create ticket')
.setEmoji('📩')
.setStyle('SECONDARY')
);
channel
.send({
embeds: [
{
title: 'SGAS Tickets',
color: '#388e3c',
description: 'To create a ticket react with 📩',
},
],
components: [row],
})
.then(() => {
const filter = () => {
return true;
};
const collector = channel.createMessageComponentCollector({
filter,
time: 15 * 1000,
});
collector.on('collect', (i) => {
i.deferUpdate().then(() => {
Ticket.count({}, (err, result) => {
if (err) {
console.log(err);
} else {
const ticketNumber = result + 1;
const ticketString = convertNumber(ticketNumber);
const ticket = new Ticket({
tickedId: ticketString,
});
ticket.save((err) => {
if (err) {
console.log(err);
} else {
const myguild = client.guilds.cache.get('887277806386565150');
if (!myguild) {
console.log('guild not found');
return;
}
const category = myguild.channels.cache.find(
(c) =>
c.id === '887277807279947826' &&
c.type == 'GUILD_CATEGORY'
);
if (!category) {
console.log('category not found');
return;
}
myguild.channels
.create(`Ticket#${ticketString}`, {
type: 'GUILD_TEXT',
})
.then(async (myc) => {
myc.setParent(category).then(() => {
myc.send(
`Hello <#${i.user.id}>, your question will be solved here shortly`
);
i.reply({
content: `Go to <#${myc.id}>, for your question`,
ephemeral: true,
});
});
});
}
});
}
});
});
});
});
});
you are using a component collector - which expires in 15 seconds, as seen in your code. That means after 15 seconds your bot stops listening for button clicks. My recommendation is to use the interactionCreate event to listen for that button: see docs https://discord.js.org/#/docs/main/stable/class/ButtonInteraction
Example:
client.on("interactionCreate", (interaction) => {
if(!interaction.isButton()) return;
if(interaction.customId === "openTicket") {
// your ticket code here
}
});

Trouble with promise in firebase functions

This code either runs once or a max of 100 times. I have a dummy data file with 6000 records as this is the average that it will have to handle.
Currently using the Blaze plan.
The code was working somewhat, I set up a new project and now I get this issue.
export const uploadPatrons = functions.storage
.object()
.onFinalize((object, context) => {
let patronPromise: any[];
patronPromise = [];
if (object.name === 'patrons/upload.csv') {
admin
.storage()
.bucket()
.file('/patrons/upload.csv')
.download({})
.then(data => {
Papa.parse(data.toString(), {
header: true,
skipEmptyLines: true,
complete: result => {
result.data.forEach(x => {
x.inside = false;
x.arrived = false;
x.img = false;
x.arrivedTime = null;
const newPromise = admin
.firestore()
.collection('patrons')
.add({ ...x })
.then(doc => {
console.log(doc);
})
.catch(err => {
console.log(err);
});
patronPromise.push(newPromise);
});
}
});
})
.catch(err => {
console.log(err);
});
}
return Promise.all(patronPromise)
.catch(err => {
console.log(err);
});
});
All it has to do is read the file from the storage, parse it and add each record to the firebase collection
Function returned undefined, expected Promise or value
This is the error I get in the logs
Because of your first promise may be shutdown even it not finish. So try to follow the rule promise/always-return
export const uploadPatrons = functions.storage
.object()
.onFinalize((object, context) => {
if (object.name === 'patrons/upload.csv') {
return admin.storage().bucket()
.file('/patrons/upload.csv')
.download({})
.then(data => {
let patronPromise: any[];
patronPromise = [];
Papa.parse(data.toString(), {
header: true,
skipEmptyLines: true,
complete: result => {
result.data.forEach(x => {
x.inside = false;
x.arrived = false;
x.img = false;
x.arrivedTime = null;
const newPromise = admin.firestore()
.collection('patrons')
.add({
...x
})
patronPromise.push(newPromise);
});
}
});
return Promise.all(patronPromise)
})
.then(result=>{
//return Promise.resolve or something
})
.catch(err=>{
console.log(err)
})
}
else{
//also return if it's nothing
}
});
You're ignoring the promise that admin.storage().bucket().file('/patrons/upload.csv').download({}) returns, which means that the function may get aborted.
I think it should be closer to this:
export const uploadPatrons = functions.storage
.object()
.onFinalize((object, context) => {
let patronPromise: any[];
patronPromise = [];
if (object.name === 'patrons/upload.csv') {
return admin.storage().bucket()
.file('/patrons/upload.csv')
.download({})
.then(data => {
Papa.parse(data.toString(), {
header: true,
skipEmptyLines: true,
complete: result => {
result.data.forEach(x => {
x.inside = false;
x.arrived = false;
x.img = false;
x.arrivedTime = null;
const newPromise = admin.firestore()
.collection('patrons')
.add({
...x
})
patronPromise.push(newPromise);
});
// TODO: return the Promise.all(patronPromise) here
}
});
})
}
});

How to get json data from multiple url-pages Node.js?

I am quite new to Node.js and haven't been working with json data before so really hope that you can help me.
I am trying to get all event information from Ticketmaster's API and add specific variables to mongoDB. However, the APIs' that I am currently using are limited to 200 events per page. It is therefore not possible for me to connect the event information with venue information since these are added seperately to mongoDB and are not exhaustive of all event and venue information (not able to connect on ids because of missing event and venue data).
My question is therefore in regards to how I can get all pages into my database at once?
The code that I have written so far looks something like below:
app.get('/tm', (req, res) => {
axios // getting venues
.get('https://app.ticketmaster.com/discovery/v2/venues.json?apikey=myApiKey&page=0&size=200&countryCode=DK')
.then(response => {
const venuesToBeInserted = response.data._embedded.venues.map(venue => { // preparing venues
return {
sourceID: venue.id,
venue: venue.name,
postalCode: venue.postalCode,
city: venue.city.name,
country: venue.country.name,
countryCode: venue.country.countryCode,
address: !!venue.address ? venue.address.line1 : null,
longitude: !!venue.location ? venue.location.longitude : null,
latitude: !!venue.location ? venue.location.latitude : null,
source: 'ticketmaster'
}
})
// Create all venues at once
Venue.create(venuesToBeInserted).then(venues => {
console.log("venues inserted")
axios // getting events and shows - note the page parameter in the api link
.get('https://app.ticketmaster.com/discovery/v2/events.json?apikey=myApiKey&countryCode=DK&size=200&page=0')
.then(response => {
const eventsToBeInserted = response.data._embedded.events.map(events => { // preparing events
const event = events._embedded.attractions[0]
return {
sourceID: event.id,
name: event.name,
slug: slugify(event.name).toLowerCase(),
tags: !!event.classifications ? [event.classifications[0].genre.name, event.classifications[0].subGenre.nam] : [], // duplicate genres occur
// possible tags from ticketmaster: type and subtype
}
})
// Create all events at once
Event.create(eventsToBeInserted).then(events => {
console.log("events inserted")
const showsToBeInserted = response.data._embedded.events.map(show => {
const event = events.find(event => event.sourceID == show._embedded.attractions[0].id);
const venue = venues.find(venue => venue.sourceID == show._embedded.venues[0].id);
if (!!event && !!venue) {
return {
event: event._id,
venue: venue._id,
timezone: show.dates.timezone,
dateStart: !!show.dates.start.dateTime ? show.dates.start.dateTime : show.dates.start.localDate,
tickets: !!show.priceRanges ? {
minPrice: show.priceRanges[0].min,
maxPrice: show.priceRanges[0].max,
currency: show.priceRanges[0].currency
}: {}
}
}
})
// Let's see what we have created in the database
Venue.find({}).select({
name: 1,
slug: -1
}).limit(10).populate('event').populate('venue').then(events => {
console.log(util.inspect(events));
}).catch(err => {
console.error(err);
});
}).catch( err => {
console.error(err)
})
}).catch( err => {
console.error(err)
})
}).catch(err => {
console.error(err)
});
}).catch(err => {
console.error(err)
})
})
EDIT
Using the approach that Jake suggested gave me an error (Error: Requested failed with status code 401). I have tried to search for it online but I cannot figure out why the error happens.. See picture below of part of the error message in my console.log.
error message
You can do this using promises, which you already are using, you just need to chain them together using recursion.
function getVenues(page, size, venues) {
page = page || 0;
size = size || 200;
venues = venues || [];
return axios
.get(`https://app.ticketmaster.com/discovery/v2/venues.json?apikey=myApiKey&page=${page}&size=${size}&countryCode=DK`)
.then(response => response.data._embedded.venues)
.then(rawVenues => {
rawVenues.forEach(venue => venues.push(venue));
if (rawVenues.length < size) {
// All done return the compiled list.
return venues;
}
// Recurse over the next set of venues by adding another promise to the chain.
return getVenues(page + 1, size, venues);
});
}
function getEvents(page, size, events) {
page = page || 0;
size = size || 200;
events = events || [];
return axios
.get(`https://app.ticketmaster.com/discovery/v2/events.json?apikey=myApiKey&countryCode=DK&size=${size}&page=${page}`)
.then(response => response.data._embedded.events)
.then(rawEvents => {
rawEvents.forEach(event => events.push(event));
if (rawEvents.length < size) {
// All done return the compiled list.
return events;
}
// Recurse over the next set of events by adding another promise to the chain.
return getEvents(page + 1, size, events);
});
}
app.get('/tm', (req, res) => {
getVenues().then(rawVenues => {
const venuesToBeInserted = rawVenues.map(venue => {
return {
sourceID: venue.id,
venue: venue.name,
postalCode: venue.postalCode,
city: venue.city.name,
country: venue.country.name,
countryCode: venue.country.countryCode,
address: !!venue.address ? venue.address.line1 : null,
longitude: !!venue.location ? venue.location.longitude : null,
latitude: !!venue.location ? venue.location.latitude : null,
source: 'ticketmaster'
};
});
// Return promise so errors bubble up the chain...
return Venue.create(venuesToBeInserted).then(venues => {
console.log("venues inserted");
// Return promise so errors bubble up the chain...
return getEvents().then(rawEvents => {
const eventsToBeInserted = rawEvents.map(rawEvent => {
const event = events._embedded.attractions[0];
return {
sourceID: event.id,
name: event.name,
slug: slugify(event.name).toLowerCase(),
tags: !!event.classifications ? [event.classifications[0].genre.name, event.classifications[0].subGenre.nam] : []
};
});
// Return promise so errors bubble up the chain...
return Event.create(eventsToBeInserted).then(events => {
console.log("events inserted");
const showsToBeInserted = rawEvents.map(show => {
const event = events.find(event => event.sourceID == show._embedded.attractions[0].id);
const venue = venues.find(venue => venue.sourceID == show._embedded.venues[0].id);
if (!!event && !!venue) {
return {
event: event._id,
venue: venue._id,
timezone: show.dates.timezone,
dateStart: !!show.dates.start.dateTime ? show.dates.start.dateTime : show.dates.start.localDate,
tickets: !!show.priceRanges ? {
minPrice: show.priceRanges[0].min,
maxPrice: show.priceRanges[0].max,
currency: show.priceRanges[0].currency
} : {}
}
}
});
// Do something with the found shows...
});
});
});
}).then(() => { // This then is fired after all of the promises above have resolved...
return Venue.find({}).select({
name: 1,
slug: -1
}).limit(10).populate('event').populate('venue').then(events => {
console.log(util.inspect(events));
res.send(events);
});
}).catch(err => { // Catches any error during execution.
console.error(err);
res.status(500).send(err);
});;
});

How to generate unique key in mongoose on node js?

The flow is:
I generate currentKey (key consist from 3 words separated by -)
I check if any document in my collection already have currentKey.
If it is not - currentKey will be pasted into my specific document in my collection.
But if it is - currentKey will be regenerated and all over again.
And the problem is mongoose have asynchronous callback that will run when query will finish executing. And i don't know how to implement my flow with this asynchronously flow. As the example (this is just example for convenience, it's not a existing framework or etc.) what i did on php is like next:
$currentKey = someService.GenerateKey();
//exists() returns true or false
while($db->find('tablename', ['key' => $currentKey])->exists())
{
$currentKey = someService.GenerateKey();
}
//It's update 'tablename' where `id` equals to $someUserId and set `key` to $currentKey value
$db->update('tablename', ['id' => $someUserId], ['key' => $currentKey]);
Can you help me, pls?
Promises are designed for that.
function generateUniqueKey(modelId) {
return new Promise((resolve, reject) => {
currentKey = someService.GenerateKey();
MyModel.count({ key: currentKey })
.then(count => {
if (count > 0) {
generateUniqueKey(modelId);
} else {
MyModel.update({ id: modelId }, { $set: { key: currentKey } })
.then(resolve(currentKey));
}
})
.catch(err => reject(err));
});
}
generateUniqueKey(someUserId).then(key => console.log('Generated unique key:', key));
But if you don't care about the result you can just remove the Promise mechanism and let the generateUniqueKey() method end on its own.
function generateUniqueKey(modelId) {
currentKey = someService.GenerateKey();
MyModel.count({ key: currentKey })
.then(count => {
if (count > 0) {
generateUniqueKey(modelId);
} else {
MyModel.update({ id: modelId }, { $set: { key: currentKey } })
.then(() => console.log('Generated unique key:', currentKey))
.catch(err => console.log(err));
}
})
.catch(err => console.log(err));
}
generateUniqueKey(someUserId);

Resources