I'm trying to create a modmail system and whenever I try to make it, it says "channel.send is not a function, here is my code."
const Discord = require("discord.js")
const client = new Discord.Client()
const db = require('quick.db')
// ...
client.on('message', message => {
if(db.fetch(`ticket-${message.author.id}`)){
if(message.channel.type == "dm"){
const channel = client.channels.cache.get(id => id.name == `ticket-${message.author.id}`)
channel.send(message.content)
}
}
})
// ...
client.login("MYTOKEN")
I'm trying this with version 12.0.0
EDIT:
I found my issue, for some reason the saved ID is the bots ID, not my ID
As MrMythical said, you should use the find function instead of get. I believe the issue is that you're grabbing a non-text channel, since channel is defined, you just can't send anything to it.
You could fix this by adding an additional catch to ensure you are getting a text channel, and not a category or voice channel. I would also return (or do an error message of sorts) if channel is undefined.
Discord.js v12:
const channel = client.channels.cache.find(c => c.name === `ticket-${message.author.id}` && c.type === 'text');
Discord.js v13:
const channel = client.channels.cache.find(c => c.name === `ticket-${message.author.id}` && c.type === 'GUILD_TEXT');
Edit:
You can tell channel is defined because if it weren't it would say something along the lines of: Cannot read property 'send' of undefined.
You are trying to find it with a function. Use .find for that instead:
const channel = client.channels.cache.find(id => id.name == `ticket-${message.author.id}`)
Related
I am working on a discord bot who is supposed to ban members that reacted to a specific message with a specific emote. The file I created for the messageReactionAdd event currently contains the following code:
module.exports = {
name: 'messageReactionAdd',
execute(client, reaction, user) {
const channel = client.channels.cache.find(channel => channel.name === 'test');
let message = 874736592542105640;
let emotes = ['kannathinking', '🍎'];
let roleID = (reaction.emoji.name == emotes[0] ? '874730080486686730' : '874729987310235738')
if (message == reaction.message.id && (emotes[0] == reaction.emoji.name || emotes[1] == reaction.emoji.name)) {
user.ban();
channel.send(`${user} was banned`);
}
}
}
However this code doesn't work and throws me the following error:
user.ban() is not a function
After doing some research I found out that the ba command only works on GuildMember objects. Unfortunately those aren't created when messageReactionAdd is called. Does anyone have an idea how to work around it?
You don't have to get the GuildMember object, you can just ban the user by id from GuildMemberManager which can be found from the reaction object via reaction.message.guild.members
So instead of using user.ban() you can use
reaction.message.guild.members.ban(user.id)
I am making a Discord bot with discord.js V12. I want to make a command to await to fetch all channels with X people or more, but I am not familiar with awaiting and fetching. Here is my code so far:
Command:
else if (command === 'find') {
if (!args.length) {
const findHelp = new Discord.MessageEmbed()
.setTitle('Finding')
.setDescription('Help')
.addField('Usage', 'Find a free spot on a voice channel & automaticly join for best Among Us experience!')
.addField('Commands', '`/find <members>` Find a voice channel with minimum of `<members>` people in it.')
.setColor(0xE92323);
message.channel.send(findHelp);
} else if (args.length === 1) {
const memberMin = args[0];
const channel = await (fetch(channels.first.members.length(memberMin)))
message.author.join(channel);
}
}
I tried without awaiting or fetching but it still doesn't work, while giving an error.
Thanks for taking your time to help me :)
Assuming your message comes from a guild, you can use the channel cache.
const memberMin = args[0]
const voiceChannels = message.guild.channels.cache.filter(c => c.type == 'voice') // Collection<VoiceChannel>
const yourVoiceChannels = voiceChannels.filter(c => c.members.length >= memberMin) // Collection<VoiceChannel>
If you've edited the caching behavior, you'll need to fetch the channels and/or the guild before reading their properties. You can do that with, for example:
const guild = await message.guild.fetch()
I would like to have some kind of reaction roles into my bot. For that I have to test If the message ID that the User sends to the bot is valid. Can someone tell me how to do that?
You can do that with .fetch() as long as you also know what channel you're looking in.
If the message is in the same channel the user sent the ID in then you can use message.channel to get the channel or if it's in another channel then you have to get that channel using its ID using message.guild.channels.cache.get(CHANNEL_ID).
So your code could be like this if it's in the same channel:
const msg = message.channel.messages.fetch(MESSAGE_ID)
or if it's in a different channel:
const channel = message.guild.channels.cache.get(CHANNEL_ID)
const msg = channel.messages.fetch(MESSAGE_ID)
This works for me (Discord.js v12)
First you need to define the channel where you want your bot to search for a message.
(You can find it like this)
const targetedChannel = client.channels.cache.find((channel) => channel.name === "<Channel Name>");
Then you need to add this function:
async function setMessageValue (_messageID, _targetedChannel) {
let foundMessage = new String();
// Check if the message contains only numbers (Beacause ID contains only numbers)
if (!Number(_messageID)) return 'FAIL_ID=NAN';
// Check if the Message with the targeted ID is found from the Discord.js API
try {
await Promise.all([_targetedChannel.messages.fetch(_messageID)]);
} catch (error) {
// Error: Message not found
if (error.code == 10008) {
console.error('Failed to find the message! Setting value to error message...');
foundMessage = 'FAIL_ID';
}
} finally {
// If the type of variable is string (Contains an error message inside) then just return the fail message.
if (typeof foundMessage == 'string') return foundMessage;
// Else if the type of the variable is not a string (beacause is an object with the message props) return back the targeted message object.
return _targetedChannel.messages.fetch(_messageID);
}
}
After this procedure, just get the function value to another variable:
const messageReturn = await setMessageValue("MessageID", targetedChannel);
And then you can do with it whetever you want.Just for example you can edit that message with the following code:
messageReturn.edit("<Your text here>");
I'm actually making a discord bot with discord.js, and I was wondering how to do a command to delete a specific channel with a name
ex : !delete #general
I already tried to do the following:
if (command == "delete") {
channel.delete(args.join(" "))
}
but it doesn't work so I'm kinda stuck
thank you
You have to use the .delete method to delete a guild textchannel.
I added a new variable fetchedChannel which tries to fetch the channel by its name from args.
Try to use the following code:
const fetchedChannel = message.guild.channels.find(r => r.name === args.join(' '));
if (command === 'delete') {
fetchedChannel.delete();
}
That code now is old if you are going to up-date(with discord.js v12) it try with:
const fetchedChannel = message.guild.channels.cache.get(channel_id);
fetchedChannel.delete();
If you want to delete a specific channel with eval command then use this code
t!eval
const fetchedChannel = message.guild.channels.cache.get("CHANNEL_ID");
fetchedChannel.delete();
use:
message.channel.delete();
you can put it in client.on like this
client.on("message", message => {
message.channel.delete()
})
I have been wondering how can I send messages when someone invites my bot to their server.
Please help me in this area I can't figure it out it's there in Python but I have not used to it.
Thank you for your help
All the above answers assume you know something about the server and in most cases you do not!
What you need to do is loop through the channels in the guild and find one that you have permission to text in.
You can get the channel cache from the guild.
Take the below example:
bot.on("guildCreate", guild => {
let defaultChannel = "";
guild.channels.cache.forEach((channel) => {
if(channel.type == "text" && defaultChannel == "") {
if(channel.permissionsFor(guild.me).has("SEND_MESSAGES")) {
defaultChannel = channel;
}
}
})
//defaultChannel will be the channel object that the bot first finds permissions for
defaultChannel.send('Hello, Im a Bot!')
});
You can of course do further checks to ensure you can text before texting but this will get you on the right path
Update discord.js 12+
Discord.JS now uses cache - here is the same answer for 12+
bot.on("guildCreate", guild => {
let found = 0;
guild.channels.cache.map((channel) => {
if (found === 0) {
if (channel.type === "text") {
if (channel.permissionsFor(bot.user).has("VIEW_CHANNEL") === true) {
if (channel.permissionsFor(bot.user).has("SEND_MESSAGES") === true) {
channel.send(`Hello - I'm a Bot!`);
found = 1;
}
}
}
}
});
})
You can simply send the owner for example a message using guild.author.send("Thanks for inviting my bot");
Or you can also send a message to a specific user:
client.users.get("USER ID").send("My bot has been invited to a new server!");
I'm not sure if you're using a command handler or not since you seem new to JS I'm going to assume you're not. The following is a code snippet for what you're trying to do:
client.on('guildCreate', (guild) => {
guild.channels.find(t => t.name == 'general').send('Hey their Im here now!'); // Change where it says 'general' if you wan't to look for a different channel name.
});