Edit is not a function - javascript

Trying to make a discord bot that will send a message to a specific channel on startup. I have the message sent to the specific channel on startup, however, when I try to edit it a error is thrown saying message.edit is not a function. I am following the direct steps from the documentation and it is not working. Why and how do I fix this issue?
let message: any;
if (isTextChannel(channel) && !isStageChannel(channel)) {
message = channel.send({ embeds: [ playerCountEmbedLoading() ] });
}
setInterval(() => {
if (isTextChannel(channel) && !isStageChannel(channel)) {
return message.edit({ embeds: [ playerCountEmbed() ] })
}

You're not awaiting the promise returned from sending the message.
message = await channel.send({ embeds: [ playerCountEmbedLoading() ] });
Source
Documentation

You should do type checking before defining the message. In this example I will use a typegaurd to filter out non text based channels.
Also, Channel.send() returns a promise containing the sent message. You need to await the promise.
import { ChannelTypes } from "discord.js";
if (channel.type !== ChannelTypes.GuildText) return console.warn("Channel is not a text channel");
let message = await channel.send({ embeds: [ playerCountEmbedLoading() ] });
setInterval(async() => {
try {
await message.edit({ embeds: [ playerCountEmbed() ] })
} catch (err) {
console.error(err);
}
}, ...);
Lastly, why use TypeScript if you're going to type a variable as any when you know exactly what it needs to be? Take advantage of the language you utilize by typing your variables.
import type { Message } from "discord.js";
let message: Message;

Related

Node.js - Discord.js v14 - fetching a channel returns undefined / does not work

Attempting to define channel with this code will return undefined.
const { Events, InteractionType, Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
],
})
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
if(interaction.type == InteractionType.ApplicationCommand){
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
}
else if(interaction.isAutocomplete()){
const command = interaction.client.commands.get(interaction.commandName);
if(!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try{
await command.autocomplete(interaction);
} catch(error) {
console.error(error);
}
}
else if(interaction.isButton()){
console.log(client.channels);
const channel = await client.channels.fetch('1074044721535656016 ');
console.log(client.channels);
console.log(channel);
}
},
};
const channel = await client.channels.fetch('1074044721535656016 '); Is the main line here.
At the bottom and top of the code is where the important stuff for this question is. I believe I am not properly using the fetch method.
As evidenced by console.log(client.channels); I'm trying to look at the channels cache, but for some reason the channel isn't there, hence I'm using fetch() instead of cache.get().
Thank you for the help!
Other info:
Running npm list shows:
discord.js#14.7.1, dotenv#16.0.3
Node.js v19.6.0
How I got my channel id
Error Message:
ChannelManager {} //<--- this is from the first console.log
node:events:491
throw er; // Unhandled 'error' event
^
Error: Expected token to be set for this request, but none was present
Is the problem because the channel is undefined or because it hasn't resolved yet?
Check your channel ID it may be formatted like:
guild id / channel id
Use interaction.client instead of making a new client object. The interaction already has its own client object with the related properties.

MongoDB findOneAndDelete() will not delete the specified query-- I can't quite figure out why?

I'm trying to write a Discord.JS bot that lists and removes specific channels/threads using MongoDB's Model and Schema functionality. I've gotten everything else figured out, the actual message deletion, channel deletion, and everything else I needed for the remove function, but for some reason prompting MongoDB to delete the ChatListing schema using ids specified doesn't work.
case 'remove':
modal.setTitle('Remove a Listing');
const listingIDInput = new TextInputBuilder()
.setCustomId('listingIDInput')
.setLabel(`What's the ID of your listing?`)
.setPlaceholder('EX... 14309')
.setMinLength(5)
.setStyle(TextInputStyle.Short)
.setRequired(true);
const rmrow = new ActionRowBuilder().addComponents(listingIDInput);
modal.addComponents(rmrow);
await interaction.showModal(modal);
try {
await interaction.awaitModalSubmit({ time: 120_000 }).then( (interaction) => {
const listingToRemove = interaction.fields.getTextInputValue('listingIDInput');
ChatListing.findOne({ GuildID: guild.id, ListingID: listingToRemove }, async(err, data) =>{
if(err) throw err;
if(!data) return;
if(data.MemberID == member.id) {
const channel = await guild.channels.cache.get(data.Channel);
const msg = await channel.messages.fetch(data.MessageID);
msg.delete();
var id = data._id;
ChatListing.findByIdAndDelete({_id: mongoose.Types.ObjectId(id)});
embed.setTitle('Listing successfully removed.')
.setColor('Green')
.setDescription('⚠️ | Your chat listing has been removed successufully. We\'re sorry to see it go! | ⚠️')
.setTimestamp();
await interaction.reply({ embeds: [embed], ephemeral: true });
} else {
embed.setTitle('You aren\'t the owner of the listing!')
.setColor('Red')
.setDescription('You aren\'t capable of removing this listing because you aren\'t the user that posted it.')
.setTimestamp();
await interaction.reply({ embeds: [embed], ephemeral: true });
}
});
});
} catch (err) {
console.error(err);
}
break;
This is just the snippet in the switch case used for the slash command I've built around this functionality, and the case for listing removal.
It doesn't cause any errors in the console, however when I check the database, the test listing I put up is still there and doesn't seem to go.
Is there anything I'm doing wrong? Wherever I've looked I can't quite seem to find anything that solves this problem for me. Is the reason it's not working because it's listed within a ChatListing.findOne() function? If so, how can I modify it to work outside of that function and still keep the removal functionality?
Try using findOneAndDelete and use the returned Promise to handle success or failure:
ChatListing.findOneAndDelete({_id: mongoose.Types.ObjectId(id)})
.then(() => {
embed.setTitle('Listing successfully removed.')
.setColor('Green')
.setDescription('⚠️ | Your chat listing has been removed successufully. We\'re sorry to see it go! | ⚠️')
.setTimestamp();
interaction.reply({ embeds: [embed], ephemeral: true });
})
.catch(error => {
console.error(error);
});

How do I check if a user has their DM's open? | discord.js v 14

I am making a bot that can dm a user. If the dm's of the user are off it says the message is successfully sent but in the console it returns an error.
So, what can I do to check if a user's dm is open?
The code I'm trying to run:
const rec = interaction.options.getUser('user')
const user = interaction.user.id
try {
rec.send({ embeds:[ new EmbedBuilder().setDescription(`<#${user}> says to you: ${message} `).setColor("#f05c51")
.then(interaction.reply(({ content: 'Successfully sent', ephemeral: true })))
] })
} catch (error) {
interaction.reply(({ content: `Could not send message, maybe dm's off? -> ${error}`, ephemeral: true }))
}
You can't. You need to use .catch()
rec.send({ embeds: [YOUREMBED] })
.then(message => console.log(`Sent message: ${message.content}`))
.catch(console.error);
I used unhandledRejection to know if my bot can't send a message to a specific user, also can use it all of unhandledRejection errors
process.on('unhandledRejection', async(error) => {
const admin = client.channels.cache.get('-----')
const embed = new MessageEmbed()
.setDescription(`\`\`\`\j\s\n${error.message || error.name || error }\n\`\`\``)
.setColor('RANDOM')
.setTimestamp()
admin.send({embeds: [embed]})
console.log(error)
});
You can also try it on your code.

TypeError: Cannot read property 'mentions' of undefined

first time poster looking for some help, struggling to get this to work. I'm wanting to create a command which followed by a channel mention and Raw JSON will then post an embed in the mention channel. The code itself throws up no errors, until the point I initiate the command, where I get "TypeError: Cannot read property 'mentions' of undefined". Any ideas where I've gone wrong?
const DiscordJS = require('discord.js')
const WOKCommands = require('wokcommands')
require('dotenv').config();
module.exports = {
name: "embedjson",
category: "info",
description: "post embed from json data",
minArgs: 2,
expectedArgs: '<Channel mention> <JSON>',
run: async ({client, message, args, level }) => {
// get the target channel
const targetChannel = message.mentions.channels.first()
if (!targetChannel) {
message.reply('Please specify a channel to send the embed in')
return
}
// removes the channel mention
args.shift()
try {
// get the JSON data
const json = JSON.parse(args.join(' '))
const { text = '' } = json
// send the embed
targetChannel.send(text, {
embed: json,
})
} catch (error) {
message.reply(`Invalid JSON ${error.message}`)
}
},
}

Discord.js Embed error Cannot send an empty message

so I'm trying to make a help command with list of commands showed in embed. My code kinda works but it throws an error "DiscordAPIError: Cannot send an empty message" and I've tried already everything I know and what I've found but I can't fix it.
Here's the code
const Discord = require('discord.js');
const { prefix } = require('../config.json');
module.exports = {
name: 'help',
description: 'List all of my commands or info about a specific command.',
aliases: ['commands', 'cmds'],
usage: '[command name]',
cooldown: 5,
execute(msg, args) {
const data = [];
const { commands } = msg.client;
if (!args.length) {
const helpEmbed = new Discord.MessageEmbed()
.setColor('YELLOW')
.setTitle('Here\'s a list of all my commands:')
.setDescription(commands.map(cmd => cmd.name).join('\n'))
.setTimestamp()
.setFooter(`You can send \`${prefix}help [command name]\` to get info on a specific command!`);
msg.author.send(helpEmbed);
return msg.author.send(data, { split: true })
.then(() => {
if (msg.channel.type === 'dm') return;
msg.reply('I\'ve sent you a DM with all my commands!');
})
.catch(error => {
console.error(`Could not send help DM to ${msg.author.tag}.\n`, error);
msg.reply('it seems like I can\'t DM you! Do you have DMs disabled?');
});
}
const name = args[0].toLowerCase();
const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name));
if (!command) {
return msg.reply('that\'s not a valid command!');
}
data.push(`**Name:** ${command.name}`);
if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`);
if (command.description) data.push(`**Description:** ${command.description}`);
if (command.usage) data.push(`**Usage:** ${prefix}${command.name} ${command.usage}`);
data.push(`**Cooldown:** ${command.cooldown || 3} second(s)`);
msg.channel.send(data, { split: true });
},
};
You should try replace this line :
msg.channel.send(data, { split: true });
with
msg.channel.send(data.join(' '), { split: true }); since your data variable is an array and not a string
The problem is as the error states. You are trying to send an empty message somewhere.
You can try replacing msg.channel.send(data) with msg.channel.send(data.join('\n')), since the data variable is an array.
I don't see why sending an array doesn't work though.

Categories