Discord JS - forEach looped embed - discord

I'm quite new to Javascript, normally a Python person. I've looked at some other answers but my embed does not add the fields as expected. The embed itself is sent.
My Discord bot follows the guide provided by the devs (primary file, slash commands, command files). I am trying to loop through the entries in an SQLite query and add them as fields.
My command file is below.
const { SlashCommandBuilder } = require('#discordjs/builders');
const { MessageEmbed } = require('discord.js')
const sqlite = require('sqlite3').verbose();
module.exports = {
data: new SlashCommandBuilder()
.setName('rank')
.setDescription('Rank all points.'),
async execute(interaction) {
const rankEmbed = new MessageEmbed()
.setColor('#0099ff')
.setTitle('Rank Board')
let db = new sqlite.Database('./databases/ranktest.db', sqlite.OPEN_READWRITE);
let queryall = 'SELECT name, points FROM pointstable ORDER BY points DESC'
db.all(queryall, [], (err, rows) => {
if (err) {
console.log('There was an error');
} else {
rows.forEach((row) => {
console.log(row.name, row.points)
rankEmbed.addField('\u200b', `${row.name}: ${row.points}`, true);
});
}
})
return interaction.reply({embeds: [ rankEmbed ] });
}
}
I would also like to convert row.name - held as Discord IDs - to usernames i.e. MYNAME#0001. How do I do this by interaction? I was able to obtain the User ID in another command by using interaction.member.id, but in this case I need to grab them from the guild. In Python I did this with await client.fetch_user but in this case the error await is only valid in async functions and the top level bodies of modules is thrown.
Thanks.

OK I've solved the first aspect, I had the return interaction.reply in the wrong place.
Relevant snippet:
rows.forEach((row) => {
console.log(row.name, row.points)
rankEmbed.addField('\u200b', `${row.name}: ${row.points}`, false);
})
return interaction.reply({embeds: [rankEmbed ]} );
Would still appreciate an answer to the converting row.name (user ID) to user name via fetch.
I've solved the second aspect also. Add the below into the loop.
rows.forEach((row) => {
let client = interaction.client
const uname = client.users.cache.get(row.name);
rankEmbed.addField('\u200b', `${uname}: ${row.points}`, false);

Related

Property 'body' does not exist on type 'Observable<Object>'. Angular.js Discord OAuth2

Im making a Discord Bot Dashboard and implementing Discord OAuth2. I'm following the guide here: https://discordjs.guide/oauth2/#a-quick-example and the code is essentially the same.
async getJSONResponse(body) {
let fullBody = '';
for await(const data of body) {
fullBody += data.toString();
}
return JSON.parse(fullBody)
}
async getAccessToken(code) {
if (code) {
try {
let body = new URLSearchParams();
body.append('client_id', environment.discord.clientId)
body.append('client_secret', environment.discord.clientSecret)
body.append('code', code)
body.append('grant_type', 'authorization_code')
body.append('redirect_uri', environment.discord.redirect)
body.append('scope', 'identify')
let options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
};
const tokenResponseData = await this.http.post('https://discord.com/api/oauth2/token', body.toString(), options)
const oauthData = await this.getJSONResponse(tokenResponseData.body)
console.log(oauthData)
} catch(err) {
console.error('an error')
console.error(err)
}
}
}
However, I get this error: Property 'body' does not exist on type 'Observable<Object>'.
As you can see, the guide above clearly shows that body does in fact exist on the object.
I'm out of ideas, any help is appreciated.
Thanks

Discordjs mentions not always resolving

I am trying to implement a list of users inside a Discord Embed. The list contains a mention for each user and I have been partially successful in accomplishing that. However, it appears that my bot cannot mention everyone, some of the mentions aren't being resolved, and I wonder why is that so. Is it related to the cache? Is there a way to fetch the mentions like fetching users that aren't cached by the bot?
An image of the bot output
leastActiveMembers.forEach((member, index) => {
let mention = `<#${member.user.id}>`;
let lastActive = "";
if (member.user.activity) {
lastActive = new Date(member.user.activity.latestActivityTimestamp).toLocaleString("en-GB");
} else {
lastActive = "Never";
}
lastActive = lastActive.padEnd(20, " ");
leaderBoardRepresentation += `\`${lastActive} ⌛ \`${mention}\n`;
});
const embed = new Discord.MessageEmbed()
.setColor('#DAA520')
.setTitle("🕒 Activity Board ")
.setDescription(leaderBoardRepresentation)
.setThumbnail('https://i.imgur.com/v5RR3ro.png')
.setFooter({ text: footer, iconURL: "" })
I am using discordjs v13.
As #NotTrixxie said, this is Discord's built-in code which we cannot modify. If a user has no relation to the bot (not in the server), it will display it. If you want the username to show, you can display the username instead of mentioning which will work. See below for an example of this:
leastActiveMembers.forEach((member, index) => {
const mention = member.user.username;
let lastActive = '';
if (member.user.activity) {
lastActive = new Date(member.user.activity.latestActivityTimestamp).toLocaleString('en-GB');
} else {
lastActive = 'Never';
}
lastActive = lastActive.padEnd(20, ' ');
leaderBoardRepresentation += `\`${lastActive} ⌛ \`${mention}\n`;
});
const embed = new Discord.MessageEmbed()
.setColor('#DAA520')
.setTitle('🕒 Activity Board ')
.setDescription(leaderBoardRepresentation)
.setThumbnail('https://i.imgur.com/v5RR3ro.png')
.setFooter({
text: footer,
})
Hoped this helped!

Discord.JS bot not responding to several commmands

My bot is not responding to any commands except for the .purge command.
Here is my code.
const { Client, MessageEmbed } = require('discord.js');
const client = new Client();
const { prefix, token } = require('./config.json');
client.on('ready', () => {
client.user.setStatus('invisible');
console.log('Bot ready!');
client.user.setActivity('Bot is in WIP Do not expect stuff to work', {
type: 'STREAMING',
url: "https://www.twitch.tv/jonkps4"
});
console.log('Changed status!');
});
client.on('message', message => {
if (message.content.startsWith(".") || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
if (message === 'apply') {
message.reply("The Small Developers Application form link is:")
message.reply("https://forms.gle/nb6QwNySjC63wSMUA")
}
if (message === 'kick') {
const user = message.mentions.users.first();
// If we have a user mentioned
if (user) {
// Now we get the member from the user
const member = message.guild.member(user);
// If the member is in the guild
if (member) {
member
.kick('Optional reason that will display in the audit logs')
.then(() => {
// We let the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
.catch(err => {
message.reply('I was unable to kick the member \n Maybe due to I having missing permissions or My role is not the higher than the role the person to kick has');
// Log the error
console.error(err);
});
} else {
// The mentioned user isn't in this guild
message.reply("That user isn't in this guild!");
}
// Otherwise, if no user was mentioned
} else {
message.reply("You didn't mention the user to kick!");
}
}
if (command === 'purge') {
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply('Not a valid number');
} else if (amount > 100) {
return message.reply('Too many messages to clear. \n In order to clear the whole channel or clear more please either ```1. Right click on the channel and click Clone Channel``` or ```2. Execute this command again but more times and a number less than 100.```');
} else if (amount <= 1) {
return message.reply('Amount of messages to clear **MUST** not be less than 1 or more than 100.')
}
message.channel.bulkDelete(amount, true).catch(err => {
console.error(err);
message.channel.send('**There was an error trying to prune messages in this channel!**');
});
}
});
client.login(token);
I need a specific command to work which is the .apply command
and i would like to know why my embeds do not work.
I tried this embed example It didn't work.
const embed = new MessageEmbed()
// Set the title of the field
.setTitle('A slick little embed')
// Set the color of the embed
.setColor(0xff0000)
// Set the main content of the embed
.setDescription('Hello, this is a slick embed!');
.setThumbnail('https://tr.rbxcdn.com/23e104f6348dd71d597c3246990b9d84/420/420/Decal/Png')
// Send the embed to the same channel as the message
message.channel.send(embed);
What did I do wrong? I am quite new to Discord.JS Any help would be needed.
You used the message parameter instead of command. Instead of message === 'xxx' put command === 'xxx'. Simple mistake, I think that was what you meant anyways. Of course the purge command worked because you put command === 'purge' there

Bot readout for who used a command

Wanting to have a readout channel for my bot to keep track of what happens, just like a second console log. Want to be able to have it read out in the message the username of the person who used the command. Any ideas? Also, in a similar note, is there a way to copy the console readout and possibly just paste that instead?
var Scraper = require('images-scraper');
const google = new Scraper({
puppeteer: {
headless: true
},
})
module.exports = {
name: 'image',
description: 'Google image scraper',
async execute(message, args){
const readout = message.guild.channels.cache.find(c => c.name === 'bot-readout');
const image_query = args.join(' ');
if(!image_query) return message.channel.send('Please enter a valid image search.');
const image_results = await google.scrape(image_query, 1);
message.channel.send(image_results[0].url);
readout.send('Image sent');
}
}
I think you want
message.author.username (It gives username who sent the message)
or message.member (it gives user as a guildmember)
Just access the author property of the message object and include it via a template string into the message:
readout.send(`Image sent to ${message.author.username}`);
Ended up doing an embed system in a separate channel on my discord.
const Discord = require('discord.js');
module.exports = {
name: 'suggestionlog',
description: 'logs suggestion',
execute(message){
const readout = message.guild.channels.cache.find(c => c.name === 'bot-readout');
const embed = new Discord.MessageEmbed()
.setColor('FADF2E')
.setTitle(message.channel.name)
.setAuthor(message.author.username, message.author.displayAvatarURL({ dynamic: true }))
.setDescription(message);
readout.send(embed)
.catch((err)=>{
throw err;
});
}
}

Call Exports.run async from a member phrase

Please help me understand how can i call that ping.js from user input, like if a user type ping it will Trigger cuz of the aliases but if a user types a full phrase it won't trigger.
Or in a non headic question how can i implent this to work -> if (message.content.includes('ping'))
Sorry in advance and thanks a lot
ping.js
const Discord = require('discord.js')
const colors = require('../lib/colors.json')
exports.run = async (client, message, args, level) => {
try {
const pingEmbed = new Discord.RichEmbed()
.setColor(colors.default)
.setFooter('ping)
.addField(`${message.author.id}`, 'hey')
const msg = await message.channel.send(pingEmbed)
const embed = new Discord.RichEmbed()
.setColor(colors.default)
.addField('...',
`${msg.createdTimestamp - message.createdTimestamp}ms`)
msg.edit(embed)
} catch (err) {
message.channel.send('There was an error!\n' + err).catch()
}
}
exports.conf = {
enabled: true,
aliases: ['ping'],
guildOnly: false,
permLevel: 'User'
}
exports.help = {
name: 'ping,
category: 'tools,
description: 'ping pong',
usage: 'ping'
}
If you want to check whether a message contains any of the aliases you can just use Array.some() like this:
let aliases = ['your', 'command', 'aliases']
client.on('message', message => {
if (aliases.some(trigger => message.content.includes(trigger))) {
// The message includes at least one of your keywords
}
})
In this example is just declared aliases, but you can use the array from your command and integrate this method in your normal command handler.

Resources