I am merging a bot under discord.js v12 to a newer bot with discord.js v14.
However it's my first experience on the node and I don't understand everything, I'm doing well in lua but I don't understand...
The events return me errors either it does not find the guild or it is impossible to rename a player, or a player is not found...
Here is how it is, I comment you the events according to the return of log that I have
on("DiscordBot:RenameMember", (guild, discordid, fullname) => {
let targetguild = client.guilds.cache.first(); // I got on log the name of GUILD
if (targetguild) {
let target = targetguild.members.fetch(discordid); // I got on log : [object Promise]
if (target) {
target.setNickname(fullname); // I got on log : TypeError: target.setNickname is not a function
target.member.setNickname(fullname); // I got on log : TypeError: Cannot read properties of undefined (reading 'setNickname')
}
}
});
I made a multitude of tests with cache, without cache but nothing makes it all I find is similar and does not work here...
Here you will find the launch of the bot :
https://hastebin.com/ovipelopam.js
And here is the file I made separately to find my way around :
https://hastebin.com/azaraqituh.js
Do you have an idea ?
In your case targetguild.members.fetch(discordid) seems to return a Promise, which is an async operation. Therefore target has no value right away, but instead, has to either be awaited, or the rest of the code has to be put in the then function, that can be set to the promise.
Here is an example where you await the promise to resolve. In order to achieve this you have to define your function as async, so that it itself returns a Promise:
on("DiscordBot:RenameMember", async (guild, discordid, fullname) => {
let targetguild = client.guilds.cache.first(); // I got on log the name of GUILD
if (targetguild) {
let target = await targetguild.members.fetch(discordid); // I got on log : [object Promise]
if (target) {
target.setNickname(fullname); // I got on log : TypeError: target.setNickname is not a function
target.member.setNickname(fullname); // I got on log : TypeError: Cannot read properties of undefined (reading 'setNickname')
}
}
});
Thank you for answering and explaining,
I still don't understand how it works, but it will come...
I had some problems with the setNickname and it started to work without understanding why either :)
Here is what I get in the end :
on("DiscordBot:RenameMember", async (guild, discordid, fullname) => {
let targetguild = client.guilds.cache.first();
if (targetguild) {
let target = await targetguild.members.fetch(discordid);
if (target) {
// target.setNickname(fullname); // I got on log : TypeError: target.setNickname is not a function
// target.members.setNickname(fullname); // I got on log : TypeError: Cannot read properties of undefined (reading 'setNickname')
let targetRename = await target.setNickname(fullname, 'Modification correspondant au profile InGame'); // That work
}
}
});
Thanks again :)
Related
I am having 10 different files and I need to read their content and merge it in one object (in NodeJS). I am successfully doing that with the code below:
const fs = require('fs');
const path = require('path');
const { promisify } = require("util");
const readFileAsync = promisify(fs.readFile);
let filePathArray = ['path/to/file/one', ... , 'path/to/file/ten'];
Promise.all(
filePathArray.map(filePath => {
return readFileAsync(filePath);
})
).then(responses => { //array of 10 reponses
let combinedFileContent = {};
responses.forEach((itemFileContent, index) => {
let tempContent = JSON.parse(itemFileContent);
//merge tempContent into combinedFileContent
}
});
But what I wonder is, how to catch if there is some error while trying to read the files? When reading a single file, this works like:
fs.readFile(singleFilePath, (singleFileErr, singleFileContent) => {
if (singleFileErr) {
//do something on error, while trying to read the file
}
});
So my question here is, how can I access to the error inn the first code snippet, which corresponds to singleFileErr from this second code snippet?
The issue I am facing is: in case some of the files does not exists, I want to check the error and to skip this file, but since I can not detect the error with current implementation, my whole block crashes and I am not able to merge the other 9 files because of this one. I want to use the error check I mentioned in the second snippet.
Check out the Promise.allSettled function, which will run every Promise passed to it, and will tell you at the end which ones succeeded and which ones failed.
Maybe try something like this:
in the map() callback, return a promise that resolves to null if the file is not found.
Introduce a middle stage in the promise chain filtering out null responses.
This would look something like this:
Promise.all(
filePathArray.map(filePath => {
return readFileAsync(filePath).catch(function(error){
if(isErrorFileDoesNotExist(error)) return null
throw error;
})
});
).then(responses => {
return responses.filter(response => response != null)
})
.then(filteredResponses => {
// .. do something
});
Would that work for you? Note this presupposes you are actually able to discriminate between missing file errors from other errors the promise returned by readFileAsync() may reject - presumably via the isErrorFileDoesNotExist() function in this snippet.
Currently in a professional transition, I'm working on a study project where I have to create a kind of mini forum. I used node.js/express and sequelize for my database.
In the code bellow, my API try to retrieve 10 last messages (with pagination stuff) to send to my welcome page. It perfectly works. The problem is that some messages have a null title because they are just answers of other messages. I'd like to change this null title by the parent_id_msg title I saved into db.
But because of async code, I receive promise object and I can't use it into my synchronous code (resulting of an undefined title at the end). After reading many ressources and trying some solutions for the last 3 days, I thinks I understand the problem about async/await used with sync code, but I still don't understand how to override it and progress.
PS : I'm not sure of my "async list" but I don't know where to put async :(
exports.lastsMessages = (req, res, next) => {
//find 10 last messages (responses includes)
let answer = {
count : 0,
list:[]
};
let tmp;
Message.findAndCountAll({
order:[['creation_date', 'DESC']],
offset: 10 * req.body.pageNbr - 10,
limit: 10
})
.then( async list=>{
answer.count = list.count;
for(let i = 0; i<list.rows.length;i++){
tmp = list.rows[i].dataValues;
if(tmp.title === null || tmp.title === ""){
console.log('before'+ tmp.title) // output NULL as expected
tmp.title = await findTitle(tmp.parent_msg_id);
console.log('after '+ tmp.title)// output undefined, not as expected :(
}
answer.list.push(tmp)
};
res.status(200).json({...answer, message:'10 derniers messages'})
})
.catch(error => res.status(400).json({error, message:'Messages non récupérés'}));
};
async function findTitle(parentId){
Message.findOne(
{attributes:['title'],
where:{id:parentId}})
.then(potatoes=> {
console.log('inside '+ potatoes.dataValues.title)
//output parent message title inside function, as excepted
return potatoes.dataValues.title});
};
Thank you in advance (and sorry as beginner for potential mistakes, misunderstanding and english level)
You are not returning anything from findTitle.
Try this on the first line of the findTitle function:
return Message.findOne(...
Also the findTitle function does not need to be async because you are not using await inside it. As another aside, it's generally a bad idea to use await inside loops.
I'm trying to use multiple user mentions and message.mention.members.first() cannot do this. So I did some digging and found this function from Parsing Mention Arguments:
function getUserFromMention(mention) {
if (!mention) return;
if (mention.startsWith('<#') && mention.endsWith('>')) {
mention = mention.slice(2, -1);
if (mention.startsWith('!')) {
mention = mention.slice(1);
}
return client.users.cache.get(mention);
}
}
When I try to use this function I get the "Discord JS - TypeError: Cannot read property 'setChannel' of undefined" here is the code causing the error
let channel = client.channels.cache.find(channel => channel.name === args[0]);
const user1 = getUserFromMention(args[1]);
const user2 = getUserFromMention(args[2]);
message.member.voice.setChannel(channel.id);
user1.voice.setChannel(channel.id);
user2.voice.setChannel(channel.id);
This code Is meant to move Myself and mentioned users to selected Voice Channel it works perfectly fine when using message.mention.members.first() but can only handle one out of two of the mentioned users.
I was wondering if there was a fix for my current error or if there is another way I should be working this out?
Remember that,
message.mentions.members- Returns a GuildMember whereas
client.users.cache.get - Returns a User
You can only move/disconnect GuildMembers across VCs.
Therefore you can use message.mentions.members, which returns a Collection of all mentioned Users.
let channel = client.channels.cache.find(channel => channel.name === args[0]);
message.member.voice.setChannel(channel.id);
message.mentions.members.each(u => {
u.voice.setChannel(channel.id);
})
The problem can be, that the user is not in cache, so you must use GuildMemberManager#fetch(id). Problem is, that this function is async. The easiest solution is to make getUserFromMention and the functions where you use it async and use await.
I have tried to get a result but I can't find how to solve SyntaxError: await is only valid in async function
static async searchYoutube(query, message, voiceChannel) {
await youtube.searchVideos(query, 5).catch(videos => {
await message.say(
':x: There was a problem searching the video you requested!'
);
return;
});
if (videos.length < 5 || !videos) {
message.say(
`:x: I had some trouble finding what you were looking for, please try again or be more specific.`
);
return;
}
Now, they also recommended color async on the front, I did it but it marks another error
TypeError: Cannot read property 'length' of undefined
static async searchYoutube(query, message, voiceChannel) {
await youtube.searchVideos(query, 5).catch(async (videos) => {
await message.say(
':x: There was a problem searching the video you requested!'
);
return;
});
if (videos.length < 5 || !videos) {
message.say(
`:x: I had some trouble finding what you were looking for, please try again or be more specific.`
);
return;
}
Ad SyntaxError: await is only valid in async function – this is pretty much self explanatory error, however, there's no need to await for message.say(...) in either of these cases.
Ad TypeError: Cannot read property 'length' of undefined – this is because videos on line 8 is not defined anywhere but inside (and only inside of) that .catch block.
I'd recommend using .then block same way you use .catch in order to process searchVideos results. The code is asynchronous (is run concurrently), but the wrapper function itself doesn't need to be async.
static searchYoutube(query, message, voiceChannel) {
youtube.searchVideos(query, 5)
.then(videos => {
if (!videos || videos.length < 5) // first check !videos, then videos.length
message.say(`:x: I had some trouble finding what you were looking for, please try again or be more specific.`)
else {
... // continue your code
}
})
.catch(error => { // catch gives an error, not the result
message.say(':x: There was a problem searching the video you requested!')
})
}
I have a problem with version 12 of discord JavaScript.
I get this error but I changed the find function.
What else can he have?
upBot.send is not a function
let upBot = bot.channels.cache.find(ch => ch.id = "");
let upBotEmbed = new Discord.MessageEmbed()
.setColor(colours.red_light)
.addField(`${bot.user.username} online`, datetime)
.setFooter(`Test`, bot.user.displayAvatarURL);
upBot.send(upBotEmbed).then(m => m.delete(900000))
The reason you are getting this error is because you are not using the delete timeout correctly.
Change
.delete(900000)
to
.delete({ timeout: 900000 })
The delete property takes an object in version v12.
find function should returns a list of object. Try this:
...
for(const upBot of upBots) {
upBot.send(upBotEmbed).then(m => m.delete(900000))
}