I've been looking around, can't quite seem to find the answer to this issue I am having with a discord bot I am making with Typescript. I have all of my commands in their own folder using a separate file for each command. Helps to keep things organised.
I've seen people say client.channels.get(`channelID`).send(`Text`)
but that's giving me
Object is possibly 'undefined'. and Property 'send' does not exist on type 'Channel'.
I'm actually trying to make a bot message every text channel (given from a list) whenever someone runs a reboot command because for whatever reason people keep rebooting the bot. I implemented it as a funny thing to do every now and again as a troll if someone needs to use it. The bot goes offline for 3 minutes but I don't like having people spam it and pretty much have the bot un-usable.
I'm using client.channels.get(channels.channelnames[5]).send("This is a message.")
Solution:
if(msgObject.member.guild.channels.find(channel => channel.name === channels.channelnames[5]) as Discord.TextChannel) {
var txtchannel = msgObject.member.guild.channels.find(channel => channel.name === channels.channelnames[5]) as Discord.TextChannel
txtchannel.send("This is a message in a channel. Don't know why you read this.")
}
so I was on the right track mostly. just had to do as Discord.TextChannel and I think that's why Cynthia was saying about casting the variable as a TextChannel
This code works. thanks for all your help guys!
According to https://discord.js.org/#/docs/main/stable/class/Collection it seems like there is no get method.
Try client.channels[channels.channelnames[5]].send("This is a message.")
In other words try to replace .get with the square brackets.
EDIT: Sorry I was a bit quick, I think the issue is type casting, try casting the Channel to a TextChannel if you know that it is a text channel.
This should work assuming your channels are text ones.
client.on('ready',(e)=>{
let channel_ids = ['123','456','789'];
// loop through the list of channel ids.
for(let i=0, l=channel_ids.length; i<l; i++){
let channel_id = channel_ids[i];
let this_channel = client.channels.get( channel_id );
// if exists, and type in list send message
if(this_channel && ['dm', 'group', 'text'].indexOf( this_channel.type ) != -1){
this_channel.send('a cool message')
.then(message => console.log(`Sent message: ${message.content}`))
.catch(console.error);
}
}
});
Related
So my problem is I want to create a bot that disconnects people from a VC on Discord server if they are being defeaned for 10 minutes.
I know a thing or two about programming because I learnt it in school, but I never used python.
I have a working music bot, with index.js and everything. So I was wondering if you could help me write a code for that I can paste into it so it'll work?
Thanks in advance!
I found this code:
client.on('voiceStateUpdate', (oldState, newState) => {
if (newState.deafened && newState.member.manageable) {
newState.kick();
}
});
But it didn't work for some reason, and it wouldn't even let me set user afk time.
You don't have to fix this, you can write a new code instead for the whole concept :)
First of all, VoiceState doesn't have a property called 'deafened'. You can use VoiceState.selfDeaf instead, which returns a boolean.
Second of all, VoiceState.kick() wont do anything, as it's not a method of VoiceState. Assuming you want to kick the member from the vc, you can use VoiceState.disconnect().
You can read the VoiceState documentation here
I'm trying to make my Discord bot send an emoji when I tell it the name. E.g., say I send !emoji hello, I want the bot to send back the emoji called hello.
If I send an emoji the bot will send it back but I'm not sure how to grab an emoji from its name being sent to the bot.
I use discord.js v12 for reference.
You could try something like this
bot.on("messageCreate", (message) => {
const exampleEmoji = message.guild.emojis.cache.find(emoji => emoji.name === message.content);
channel.message.send(`Is this the emoji you want? ${exampleEmoji}`);
});
You can then nest it inside of your if statement as you please with whatever command you are using. This also should be v12/v13 compatible and I believe the only differences with older versions is whether you add cache or not to the find function.
You can also use the same function to find the emoji as a boolean to determine if the emoji exists or not and if not send a different message for feedback.
I also found this really interesting function which helped me when deciphering which emojis I have and which are not in the scope I am presenting.
if (message.content === "listemojis") {
const emojiList = message.guild.emojis.cache.map((e, x) => `${x} = ${e} | ${e.name}`).join("\n");
message.channel.send(emojiList);
}
Which will output this for every emoji within the scope you searched.
450661466287112204 = :image: | name
Which I found here.
Hope this helps
I made a blacklist for the bot, it "works", it blocks the blacklisted user from using the bot but ended up causing a loop and the blacklisted message to get spammed, both when a blacklisted user uses it and when someone that isnt on the blacklist uses it
heres the code
client.on('message', async message => {
let blacklist = new Discord.MessageEmbed()
.setColor("#e31212")
.setDescription(
"ERROR: You are not allowed to use this bot | Reason: BLACKLISTED"
);
var blacklistids = ["402639792552017920", "711957885722296360"];
if (blacklistids.includes(message.author.id)) {
message.channel.send(blacklist).then(msg => {
msg.delete({ timeout: 3000 })
})
}
// Rest of the code
})
Your code seems correct - but by how you've described it, it would seem to me your code is wrapped in a loop somewhere else. Have you tried creating another client.on() with different conditions to see if those messages also get looped/spammed?.
This is something that can easily occur, especially if you are a beginner.
EDIT: you are however missing }); at the end of your client.on() declaration.
It looks like one of your IDs in the array might be the bot's ID... if this is the case, you might also want to have a if(message.author.bot) return after the client.on(...
I am currently coding my first discord bot, it can already play YouTube music.
if (message.content.includes("Good Job") ||
message.content.includes("good job")) {
message.channel.sendMessage("Good Job everyone :smirk:");
}
As you see, if someone types "good job" (this is just an example) then the bot will reply with "good job everyone :smirk:), but then the spam will begin: the bot reads his own message and replies to it.
How can I prevent the bot from answering itself?
Use this in the on message event:
if (message.author.bot) return;
for more info:
https://anidiotsguide.gitbooks.io/discord-js-bot-guide/coding-guides/a-basic-command-handler.html
The reason why your bot replies to yourself is because where you put:
if (message.content.includes("Good Job") ||
message.content.includes("good job"))
It is basically checking the chat if a piece of text includes the words "Good Job" or "good job". As your bot sends:
message.channel.sendMessage("Good Job everyone :smirk:");
as an answer, it creates a loop because that message includes the words "Good Job", basically running the code again and again and again.
Of course, the easiest way of fixing this is for you to change the answer it gives to not include the words Good Job, but there is better solution to make sure it doesn't happen for all of the commands you might make.
As #Jörmungandr said, under the message event include:
if (message.author.bot) return;
to make sure it doesn't happen. It essentially checks if the author of the message is a bot and if it is, it ignores it.
discord.js
// In message event
if(message.author.id === client.user.id) return;
// I would recommend a variable like this for splits on words
// const args = message.content.trim().split(/\s+/g);
// You could also .slice() off a prefix if you have one
if(/good job/i.test(message.content)) {
message.channel.send('Good job everyone :smirk:'); // sendMessage is deprecated, use send instead
}
You can simply just check if the user sending the message is a bot. For example:
if (!msg.author.bot) {
<Your code to execute if the user is not a bot.>
}
Hope this was helpful, thank you!
You may use this code which avoids doing anything if the author is a bot:
if(message.author.bot) return;
There are quite a lot of ways to solve this.
1: Stopping the Bot from Responding to ANY bot.
Right under your message callback (the client.once('message')), you can just add:
if (message.author.bot) return;
2: Stopping the Bot from Responding to itself
Once again, right under your message callback, you just add:
if (message.author.id == client.user.id) return;
Please note the client that I am referring to is your bot's client, created when you type
const client = new Discord.Client()
...or whatever your client is. It's basically the thing that you login to (ex: client.login(yourtokenhere))
Most tutorials will call this Client, client, or maybe even bot. The discord.js guide will call it a Client.
I'm looking to create a 'say' command that allows me to directly message through the bot to a specific (or any, perhaps) channel. For beginner, and general testing purposes, my goal is to be able to use a standard if(commandIs("command", message) to directly message a channel in my test server, eventually evolving to all channels on a server.
Through my research I've stumbled upon the:
var channel = client.servers.get("name", "My Server").defaultChannel;
client.sendMessage(channel, "Hello");
code, which is exactly what I'm looking to do as a base since I can swap out the .get("name", "My server") for the actual channel ID, but doing this through a say-like command sets the var as a Channel class in my code, which doesn't support .sendMessage()
My current command code looks like:
if(commandIs("speak", message)){
var chat = client.channels.get(18numberID);
if(args.length === 1){
message.channel.sendMessage('You did not say anything. Usage: `a~speak [message]`')
} else {
chat.sendMessage(args.join(" ").substring(8));
-but this brings up an undefinederror on the .sendMessage(), which I figured it would. I've tried message.chat.sendMessage() and every other possible variation I could, even going to the bare two lines of code to test at on.ready(), but that continued to give me the same error. I've looked for a way around the Channel class created once the ID is found and that led me to the TextChannel and GuildChannel extensions, but I'm pretty sure there's an easier way around it considering all the code (even a couple examples here) do not contain all that extra information. I feel like I'm looking over something, or possibly complicating the code more than needed, but I'm not sure.
Any ideas or help would be appreciated.
Edit: It seems I was right and I looked over a few key points, specifically the channelID not having quotes around it to be a string. Tried the command alone and everything went great; tweaked the main code and it all worked out.
First of all, I just have to outline a few things that no longer work in the Discord.JS library (Thanks for the heads-up Ty Q.!)
First of all, .sendMessage() has been deprecated, and will more than likely not work at all anymore / soon. The working equivalent of this is .send() - which is simpler, and is an easy change to make.
Second: .defaultChannel is unfortunately no longer a thing. We will have to be more specific when we want to send a message.
I'm not great at talking about these kinds of issues, so if anyone else wants to pick it up, please do.
Alright, let's let your command be set out like this:a~speak [ChannelID] <Message>
Let's say we use this command: a~speak 12345689 I has a bucket
What we want to do is find out whether we can find the channel with the ID, and if we can, send the message to it.
To do that, I think we should see if we can use the client.channels.find("id", ID) function.
Let's Start by Setting Up Our Command
if(commandIs("speak", message)){
args = args.shift();
/* ["a~speak", "CHANNELID", "I", "has", "a", "bucket"]
BECOMES
["123456789", "I", "has", "a", "bucket"]
args [0] [1] [2] [3] [4]*/
let chan = client.channels.find("id", args[0]); // Find the channel ID "123456789"
if(chan) { // Check if that channel exists
chan.send(args.shift().join(" "));
} else {
message.channel.send(args.join(" "));
}
}
Let's Follow That Command
If we type in a~speak 12345689 I has a bucket, our bot will look for a channel that it has access to with the id "123456789".
If your bot found the channel with the id "123456789":
chan.send(args.shift().join(" "));
We defined earlier that chan = args[0] - which would be "123456789", and we don't want to send that in the message, so we use args.shift() - this removes the first argument from the rest, leaving us with ["I", "has", "a", "bucket"].
After that, we use .join(" ") - this connects ["I", "has", "a", "bucket"] with spaces to form I has a bucket.
We then simply send that message to the channel we defined, with chan.send().
If your bot did not find the channel with the id "12456789"
message.channel.send(args.join(" "));
This one's a bit different in a few ways, first of all, we forget about the chan variable, because we couldn't find that channel. If we know this, we can deduce that the user may have instead said something like a~speak I has a bucket - without the ID altogether.
Knowing that, we (unlike before), don't want to args.shift() - we would remove the "I" bit! Instead, we just want to args.join(" ") to once again join the words together into a sentence, then send it away with message.channel.send() - which just sends it in the server it got the message from.
If you need any more help, just comment with your Discord name, and I'll be happy to give you a little push in the right direction.
Sources of Information:
Some good places to look for help on these kinds of topics (Discord.JS), are the Official Discord.JS Server and AnIdiotsGuide. Both of which will be able to solve your problems.