How to await Messages from DM? - discord.js

How to await Messages from member in Private Messages?
I tried this but it is not working
client.on('message', async message => {
if(message.content === prefix + "apply"){
await message.author.send("Working !");
await message.channel.awaitMessages(Response => message.content, {
max: 1,
time: 50000
})
.then((collected) => {
if(collected.first().content === "cancel") return message.reply("Canceled");
message.author.send("Done !");
})
.catch(() => {
message.author.send("Timeout");
})
}
});

message.channel is still the Channel where apply was run, so use:
const msg = await message.author.send('Working !');
const filter = collected => collected.author.id === message.author.id;
const collected = await msg.channel.awaitMessages(filter, {
max: 1,
time: 50000,
}).catch(() => {
message.author.send('Timeout');
});
if(collected.first().content === 'cancel') return message.reply('Canceled');
message.author.send('Done !');

Related

Wait for get request response before continuing with a post request in axios

I have tried to use async/await in the createSwap function but it did not work for me. Before creating a request, I want to run the getSlotDetails function to set the slotDets so that it can be used in the post request below. However, the createSwap function does not wait for the getSlotDetails function to complete before sending the post request. How do I fix this?
const [slotDets, setSlotDets] = useState([]);
const getSlotDetails = (moduleCode, slotId, slotType) => {
axios
.get(`https://api.nusmods.com/v2/2020-2021/modules/${moduleCode}.json`)
.then((response) => response.data)
.then((data) => data.semesterData[0])
.then((semesterData) => semesterData.timetable)
.then((timetable) =>
timetable.filter(
(slot) => slot.classNo === slotId && slot.lessonType == slotType
)
)
.then((result) => {
setSlotDets(result);
});
};
const createSwap = (
moduleCode,
slotType,
currentSlot,
desiredSlots,
completed,
reserved
) => {
dispatch(createRequest());
getSlotDetails(moduleCode, currentSlot, slotType);
axios
.post(
"http://localhost:3001/api/v1/swaps",
{
module_code: moduleCode,
slot_type: slotType,
current_slot: currentSlot,
desired_slots: desiredSlots,
completed: completed,
reserved: reserved,
venue: slotDets.venue,
startTime: slotDets.startTime,
endTime: slotDets.endTime,
day: slotDets.day,
},
{
headers,
}
)
.then((response) => {
console.log(response.data);
dispatch(createSuccess());
setTimeout(() => {
dispatch(resetSwap());
}, 2000);
})
.catch((error) => {
console.log(error.response.data);
dispatch(createFail(error.response.data));
setTimeout(() => {
dispatch(resetSwap());
}, 2000);
});
};
const makeTwoRequests = async () => {
try{
const firstResponse = await axios.get(FIRST_URL);
if(firstResponse.status === 200){
const firstResponseData = firstResponse.data;
const secondResponse = await axios.get(SECOND_URL);
if(secondResponse.status === 200){
const secondResponseData = secondResponse.data;
}
}
}
catch(error){
console.log(error)
}
}
maketwoRequests()
firstResponseData and secondResponseData can be state variables instead of const for better access throughout the Component

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'text' of null

I'm making a starboard with discord.js. I keep getting this error ("UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'text' of null") whenever I add the star reaction to my message, and I'm not sure why. I tried changing the channel and it works, but whenever I try to set it up in the channel - ﹗﹗starboard it sends the error message. I also made sure my bot had all the permissions it needed to send messages in the channel. Here is my code:
const { Client, MessageEmbed } = require('discord.js');
const client = new Client({ partials: ['MESSAGE', 'REACTION']});
const { token } = require('./config.json');
client.login(token)
const activities_list = [
"Starboard",
"Music",
"Stars",
];
client.on('ready', () => {
console.log(`${client.user.tag} has logged in.`);
});
client.once('ready', () => {
setInterval(() => {
const index = Math.floor(Math.random() * (activities_list.length - 1) + 1);
client.user.setActivity(activities_list[index], {
type: "LISTENING",
});
}, 10000);
client.user.setStatus('dnd');
console.log(`${client.user.tag}'s status / activity was set.`)
})
client.on('messageReactionAdd', async (reaction, user) => {
const handleStarboard = async () => {
if (!reaction.message.content) reaction.message.content = '・image (click **link**)'
let embed2 = new MessageEmbed()
.setColor('#2f3136')
.setTitle(`Starboard!`)
.setAuthor(reaction.message.author.tag, reaction.message.author.displayAvatarURL())
.setDescription(`> \`⭐\`・${reaction.count}`)
.addField('> Message', reaction.message.content)
.addField('> Message __Info__', `・channel: ${reaction.message.channel}\n・link: [click here](${reaction.message.url})`)
.setFooter(reaction.message.id)
.setTimestamp()
const starboard = client.channels.cache.find(c => c.name === '﹗﹗starboard');
const msgs = await starboard.messages.fetch({ limit: 100 });
const existingMsg = msgs.find(msg =>
msg.embeds.length === 1 ?
(msg.embeds[0].footer.text.startsWith(reaction.message.id) ? true : false) : false);
if(existingMsg) existingMsg.edit(embed2);
else {
const embed = new MessageEmbed()
.setColor('#2f3136')
.setTitle(`Starboard!`)
.setAuthor(reaction.message.author.tag, reaction.message.author.displayAvatarURL())
.setDescription('> \`⭐\`・1')
.addField('> Message', reaction.message.content)
.addField('> Message __Info__', `・channel: ${reaction.message.channel}\n・link: [click here](${reaction.message.url})`)
.setFooter(reaction.message.id)
.setTimestamp()
if(starboard)
starboard.send(embed);
}
}
if(reaction.emoji.name === '⭐') {
if(reaction.message.channel.name === '﹗﹗starboard') return;
if(reaction.message.partial) {
await reaction.fetch();
await reaction.message.fetch();
handleStarboard();
}
else
handleStarboard();
}
});
client.on('messageReactionRemove', async (reaction, user) => {
const handleStarboard = async () => {
if (!reaction.message.content) reaction.message.content = '・・image (click **link**) (click **link**)'
let embed3 = new MessageEmbed()
.setColor('#2f3136')
.setTitle(`Starboard!`)
.setAuthor(reaction.message.author.tag, reaction.message.author.displayAvatarURL())
.setDescription(`> \`⭐\`・${reaction.count}`)
.addField('> Message', reaction.message.content)
.addField('> Message __Info__', `・channel: ${reaction.message.channel}\n・link: [click here](${reaction.message.url})`)
.setFooter(reaction.message.id)
.setTimestamp()
const starboard = client.channels.cache.find(c => c.name === '﹗﹗starboard');
const msgs = await starboard.messages.fetch({ limit: 100 });
const existingMsg = msgs.find(msg =>
msg.embeds.length === 1 ?
(msg.embeds[0].footer.text.startsWith(reaction.message.id) ? true : false) : false);
if(existingMsg) {
if(reaction.count === 0)
existingMsg.delete({ timeout: 2500 });
else
existingMsg.edit(embed3)
};
}
if(reaction.emoji.name === '⭐') {
if(reaction.message.channel.name === '﹗﹗starboard') return;
if(reaction.message.partial) {
await reaction.fetch();
await reaction.message.fetch();
handleStarboard();
}
else
handleStarboard();
}
});

Render array's nested object values react

Here is how my savedLinksData array prints in my console:
Here is my code that attempts to get the linkType value:
{savedLinksData.map((saved) => {
return <h1>{saved.linkType}</h1>;
})}
What I'm doing wrong?
I think there may be something wrong with the way I stored the values in the array. It doesn't look like the value are inside of the array.
Picture of console.log("----->", saved)
const [savedLinksData, setSavedLinksData] = useState([]);
// query for saved links data
useEffect(() => {
if (user) {
async function fetchData() {
const request = await db
.collection("users")
.doc(user)
.collection("saved")
.onSnapshot((snapshot) =>
setSavedLinks(
snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id }))
)
);
}
fetchData();
} else {
setSavedLinks([]);
}
}, [user]);
useEffect(() => {
if (savedLinks.length > 0) {
let newArray = [];
savedLinks.map((saved) => {
db.collection("users")
.doc(saved.savedUser)
.collection("links")
.doc(saved.savedLinkId)
.get()
.then(function (doc) {
if (doc.exists) {
// console.log("Document data:", doc.data());
newArray.push(doc.data());
// setSavedLinksData([...savedLinksData, doc.data()]);
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function (error) {
console.log("Error getting document:", error);
});
});
setSavedLinksData(newArray);
}
}, [savedLinks]);

Iterate over array with nested objects

PROBLEM: I need to access the linkTitle values for each object in my array.
Here is how my savedLinksData array is structured:
And here is my code:
{savedLinksData.map((saved, key) => (
<h1>{saved.linkType}</h1>
))}
Full Code:
// query for saved links data
useEffect(() => {
if (user) {
async function fetchData() {
const request = await db
.collection("users")
.doc(user)
.collection("saved")
.onSnapshot((snapshot) =>
setSavedLinks(
snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id }))
)
);
}
fetchData();
} else {
setSavedLinks([]);
}
}, [user]);
useEffect(() => {
if (savedLinks.length > 0) {
let newArray = [];
savedLinks.map((saved) => {
db.collection("users")
.doc(saved.savedUser)
.collection("links")
.doc(saved.savedLinkId)
.get()
.then(function (doc) {
if (doc.exists) {
// console.log("Document data:", doc.data());
newArray.push(doc.data());
// setSavedLinksData([...savedLinksData, doc.data()]);
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function (error) {
console.log("Error getting document:", error);
});
});
setSavedLinksData(newArray);
}
}, [savedLinks]);
console.log("RETURNED LINKS DATA", savedLinksData);
console.log("SAVED", savedLinks);
You can do {savedLinksData.map((saved, key) => ( <h1>{saved.linkInfo.linkTitle}</h1> ))}

action is triggering a series of remote methods and returning rejected

I have an action that is getting dispatched that is triggering multiple remote methods and returning'TALK_SUBMIT_REJECTED' The strange thing however, is that all of the data that I am getting is still returned and updating the store as expected.
I am however getting these two errors in the process:
xhr.js:178 POST http://localhost:3000/api/talks/talkSubmit 500
(Internal Server Error)
createError.js:16 Uncaught (in promise) Error: Request failed with
status code 500
at e.exports (createError.js:16)
at e.exports (settle.js:18)
at XMLHttpRequest.m.(:3000/anonymous function)
(http://localhost:3000/bundle.js:6:2169)
I have thrown in two dozen console.logs recording all of the data I am sending and receiving and everything returning as expected.
I apologize in advance for the long post but I have been struggling with this bug for a while.
to give a brief summery of what my code is doing:
I have a form that upon submission, triggers an action that starts a chain of remote methods.
This is the first method:
function talkSubmit(speakerInfo, talkInfo, date) {
return new Promise((resolve, reject) => {
const { Talk, Speaker, Event } = app.models;
return Speaker.create(speakerInfo)
.then(response => {
let speakerId = response.id
return getMeetups()
.then(meetups => {
const index = meetups.findIndex((item) =>
item.date == date);
let name = meetups[index].name;
let details = meetups[index].description;
let meetupId = meetups[index].meetupId;
if (index === -1)
return reject(new Error('NO meetup with that
date found!'));
return Event.findOrCreate({ date, name, details,
meetupId })
.then(event => {
let eventId = event[0].id
return Talk.create({ ...talkInfo,
speakerId, eventId })
.then(talk => resolve(talk))
.catch(err => console.log(err))
})
.catch(err => reject(err))
})
.catch(err => reject(err))
})
.catch(err => reject(err))
})
}
module.exports = { talkSubmit };
//this is the get meetups function that is called by talkSubmit
function getMeetups() {
return new Promise((resolve, reject) => {
let currentDate = new Date();
currentDate.setMonth(currentDate.getMonth() + 3);
const date ='${ currentDate.getFullYear() } -${
currentDate.getMonth() } -${
currentDate.
getDay()
} ';
axios.get(`https://api.meetup.com/sandiegojs/events?
no_later_than = ${ date } `)
return resolve(response.data.map(event => ({
meetupId: event.id,
name: event.name,
date: event.local_date,
time: event.local_time,
link: event.link,
description: event.description,
})))
.catch(err => reject(new Error('getMeetups failed to get SDJS
meetups')))
})
}
module.exports = { getMeetups };
//This is the after remote method that is triggered when talkSubmit is
//completed.
Talk.afterRemote('talkSubmit', function (ctx, modelInstance, next) {
const speakerId = ctx.result.speakerId;
const eventId = ctx.result.eventId;
const approved = false;
const pending = true;
formatTalkForEmail(speakerId, eventId)
.then((response) => {
const speakerName = response.speakerName;
const speakerEmail = response.speakerEmail;
const meetupTitle = response.meetupTitle;
const meetupDate = response.meetupDate;
sendEmailToSpeaker(process.env.ADMIN_EMAIL, approved,
pending, speakerEmail, speakerName, meetupTitle, meetupDate)
.then(() => next())
.catch(err => next(err));
})
.catch(err => next(err));
});
//this is the formatTalkForEmail method called in the remote method
function formatTalkForEmail(speakerId, eventId) {
return new Promise((resolve, reject) => {
if (speakerId == undefined) {
return reject(new Error('speakerId is undefined'));
}
if (eventId == undefined) {
return reject(new Error('eventId is undefined'));
}
const { Speaker, Event } = app.models;
Speaker.findById(speakerId)
.then(speaker => {
const speakerName = speaker.speakerName;
const speakerEmail = speaker.speakerEmail
return Event.findById(eventId)
.then(selectedEvent => {
const meetupTitle = selectedEvent.name;
const meetupDate = selectedEvent.date;
resolve({
speakerName,
speakerEmail,
meetupTitle,
meetupDate
})
})
.catch(err => reject( err ))
})
.catch(err => reject(err))
})
}
module.exports = { formatTalkForEmail };
//and finally this is the sendEmailToSpeaker method:
function sendEmailToSpeaker(adminEmail, approved, pending,
speakerEmail, speakerName, meetupTitle, meetupDate) {
return new Promise((resolve, reject) => {
let emailContent;
if (approved && !pending) {
emailContent = `Congratulations! Your request to speak at
${ meetupTitle } on ${ meetupDate } has been approved.`
}
if (!approved && !pending) {
emailContent = `We're sorry your request to speak at
${ meetupTitle } on ${ meetupDate } has been denied.`
}
if (pending) {
emailContent = `Thank you for signing up to speak
${ meetupTitle } on ${ meetupDate }.You will be notified as soon as
a
SDJS admin reviews your request.`
sendEmailToAdmin(adminEmail, meetupDate, meetupTitle,
speakerEmail, speakerName)
.catch(err => console.log(err));
}
const email = {
to: speakerEmail,
from: adminEmail,
subject: 'SDJS Meetup Speaker Request',
templateId: process.env.ADMIN_SPEAKER_EMAIL_TEMPLATE,
dynamic_template_data: {
emailContent: emailContent,
sdjsBtn: false,
title: 'SDJS Meetup Speaker Request'
}
}
sgMail.send(email)
.then(() => resolve({ email }))
.catch(err => {
console.log(err);
reject(err);
});
})
}
in conclusion I have no clue what part of talkSubmit is throwing those two errors and yet both emails are getting automatically sent and the store is updating with all the proper data despite the initial action creator returning rejected. I appreciate any help anyone can offer.
Ok so I think the main problem is here:
axios.get(`https://api.meetup.com/sandiegojs/events?no_later_than = ${ date } `)
return resolve(response.data.map(event => ({
meetupId: event.id,
name: event.name,
date: event.local_date,
time: event.local_time,
link: event.link,
description: event.description,
})))
it should look like that (I recommend to extract mapping method):
axios.get(`https://api.meetup.com/sandiegojs/events?no_later_than = ${ date} `)
.then( response => resolve(response.data.map(event => ({
meetupId: event.id,
name: event.name,
date: event.local_date,
time: event.local_time,
link: event.link,
description: event.description,
}))))
.catch(err => reject(new Error('getMeetups failed to get SDJS meetups')))
and a few words about Promises. You can chain them like that:
method()
.then(method2())
.then(method3())
.then(method4())
...
.catch(err =>...
also I don't understand why you wrap content of method in return new Promise((resolve, reject) => { I think is not needed in your case
so you can change talkSubmit method to something like that (this is just a draft, I recommend to extract methods from then blocks)
function talkSubmit(speakerInfo, talkInfo, date) {
const { Talk, Speaker, Event } = app.models;
return getMeetups()
.then(meetups => {
const index = meetups.findIndex((item) => item.date == date);
let name = meetups[index].name;
let details = meetups[index].description;
let meetupId = meetups[index].meetupId;
if (index === -1)
return reject(new Error('NO meetup with that date found!'));
return Promise.all([
Event.findOrCreate({
date, name, details,
meetupId
}),
Speaker.create(speakerInfo)])
})
.then(([event, speaker]) => {
let eventId = event[0].id
let speakerId = speaker.id
return Talk.create({
...talkInfo,
speakerId, eventId
})
})
}

Resources