Permission Error Handler - Bot Crashes how to use try catch properly - discord.js

I want it so my bot can only send embeds in specific channels with the permissions granted but if a user sends the message in a channel where the permissions are not granted the bot stops working and cuts off. I am trying to make it so a try catch works so even if an error is thrown it continues to work, the error I am getting is "UnhandledPromiseRejectionWarning: DiscordAPIError: Missing Permissions - I want to be able to ignore this error.
function catchErr (err, emessage, a){
console.log("Someone tried to use the embed in the");}
let args = message.content.slice(PREFIX.length).split(' ');
switch(args[0]){
case 'discordbot ':
try {
const discordbot = new Discord.MessageEmbed()
.setTitle('My Discord Bot*')
.addFields(
{ name: 'Test Bot:', value: 'Test' },
message.channel.send(discordbot );
} catch (err) {
catchErr(err, message);
}

.send returns a Promise, if you want to catch errors you can either go for Promise.catch or use async / await (this requires your top level function to be async)
// Using Promise.catch
const catchErr = err => {
console.log(err)
}
message.channel.send(embed).catch(catchErr)
// Using async / await
try {
await message.channel.send(embed)
} catch(err) {
catchErr(err)
}

function sendMessage(message,content){
const permissions = message.channel.permissionsFor(message.client.user);
if (permissions.has("SEND_MESSAGES")){
if(content){
message.channel.send(content);
}
}
else{
console.log("[ERR] no msg perms")
message.author.send("I can't send messages on this channel or guild!, Try another channel or contact the server staff to check bot's permissions.");
}
}

Related

How do you delete certain messages from a specific username not ID

twitchClient.on('timeout', async (channel, username, user, reason, duration) => {
discordClient.on('message', async (message, messages) => {
async function deleteMessage() {
await discordClient.channels.cache.get("901568598538063932")
.messages.fetch({limit: null})
.then(message.delete(messages.first(user["display-name"]).author.name))
}
await deleteMessage()
})
async function sendMessage() {
const request = new XMLHttpRequest();
request.open("POST", "API url");
request.setRequestHeader('Content-type', 'application/json');
const users = {
username: "User Timed Out",
avatar_url: 'https://i.imgur.com/GUrbNsB.jpg',
content: `**${username} has been timed out for ${duration} seconds.**`
}
request.send(JSON.stringify(users));
}
await sendMessage()
});
I have this code for twitch chat to sync in discord and I want to do on event timeout on twitch
I want it to delete the messages of a certain name on the channel is it possible without ID
I am lost on how to do it like I can delete the last message but not from a specific user and I
only have one webhook so the id of all usernames will be the same
TypeError: Cannot read properties of undefined (reading 'first')
Note: This code is for Discord.js v13.3.0
As stated by the error, you're trying to access an undefined variable called messages. This is because you did not define it in the then() arguments, you instantly went to a callback.
then() is a function that allows for you to provide parameters to add. You can simply put the collection of messages as one variable called messages and pass it to the callback accordingly.
// DON'T do this
messages.fetch({limit: null})
.then(message.delete(messages.first(user["display-name"]).author.name))
// DO this
messages.fetch({limit: null})
.then((messages) => message.delete(messages.first(user["display-name"]).author.name))

How to make a raw event run only once

I have a raw event:
this.on('raw', packet => {
if (!['MESSAGE_REACTION_ADD', 'MESSAGE_REACTION_REMOVE'].includes(packet.t)) return;
const channel = this.channels.cache.get(packet.d.channel_id);
if (channel.messages.cache.has(packet.d.message_id)) return;
channel.messages.fetch(packet.d.message_id).then(message => {
const emoji = packet.d.emoji.id ? `${packet.d.emoji.name}:${packet.d.emoji.id}` : packet.d.emoji.name;
const reaction = message.reactions.cache.get(emoji);
if (reaction) reaction.users.cache.set(packet.d.user_id, this.users.cache.get(packet.d.user_id));
if (packet.t === 'MESSAGE_REACTION_ADD') {
this.emit('messageReactionAdd', reaction, this.users.cache.get(packet.d.user_id));
}
if (packet.t === 'MESSAGE_REACTION_REMOVE') {
this.emit('messageReactionRemove', reaction, this.users.cache.get(packet.d.user_id));
}
});
});
This event spams continuously when one reaction is added, I want to make it so if you react it will run once. How can I do this?
You should not use the raw event past discord.js version 12. As there are some issues when your bot grows.
Instead use Partials as explained in the offical Discord.js Guide
const Discord = require('discord.js');
const client = new Discord.Client({ partials: ['MESSAGE', 'CHANNEL', 'REACTION'] });
client.on('messageReactionAdd', async (reaction, user) => {
// When we receive a reaction we check if the reaction is partial or not
if (reaction.partial) {
// If the message this reaction belongs to was removed the fetching might result in an API error, which we need to handle
try {
await reaction.fetch();
} catch (error) {
console.error('Something went wrong when fetching the message: ', error);
// Return as `reaction.message.author` may be undefined/null
return;
}
}
// Now the message has been cached and is fully available
console.log(`${reaction.message.author}'s message "${reaction.message.content}" gained a reaction!`);
// The reaction is now also fully available and the properties will be reflected accurately:
console.log(`${reaction.count} user(s) have given the same reaction to this message!`);
});
Source and more information: https://discordjs.guide/popular-topics/reactions.html#listening-for-reactions-on-old-messages

TypeError: Cannot read property 'id' of undefined | Discord.js

Aim: To ban every time a user is caught on the audit log attempting to create a channel
Code:
// Channel Create
client.on("channelCreate", async (channel) => {
const FetchingLogs = await client.guilds.cache.get(channel.guild.id).fetchAuditLogs({
limit: 1,
type: "CHANNEL_CREATE",
})
const ChannelLog = FetchingLogs.entries.first();
if (!ChannelLog) {
return console.log(red(`CHANNEL: ${channel.id} was created.`));
}
const { executor, target, createdAt } = ChannelLog;
if (target.id === channel.id) {
console.log(greenBright(`${channel.id} got created, by ${executor.tag}`));
} else if (target.id === executor.id) {
return
}
if (executor.id !== client.user.id) {
channel.guild.member(executor.id).ban({
reason: `Unauthorised Channel Created`
}).then(channel.guild.owner.send(`**Unauthorised Channel Created By:** ${executor.tag} \n**Channel ID:** ${channel.id} \n**Time:** ${createdAt.toDateString()} \n**Sentence:** Ban.`)).catch();
}
});
Result:
It bans the user successfully but still throws an error.
Error:
TypeError: Cannot read property 'id' of undefined
Code: Error Specified | Referring to channel.guild.id
const FetchingLogs = await client.guilds.cache.get(channel.guild.id).fetchAuditLogs({
limit: 1,
type: "CHANNEL_CREATE",
})
I'm guessing the reason for this is that the parameter ,channel, type is DMChannel and not GuildChannel
Is there any way to fix this or be able to change the parameter type to GuildChannel??? I've checked the Docs and I can't seem to find anything that indicates this is possible. Any help is appreciated ;)
Your assumption of why this error is occurring is correct. The channelCreate event does indeed handle the creation of both GuildChannel and DMChannel, and your code sends the guild owner a DM after banning the user. That's why the ban works but you get an error afterwards; because the DM creates a DMChannel with the owner, triggering the event handler again but with channel.guild being undefined since DMs do not have guilds.
So let me state the problem again. You are getting the error Cannot read property 'id' of undefined which you've figured out means channel.guild is undefined. You don't want the error to occur, so you don't want channel.guild to be undefined. But in your question you're asking:
Is there any way to fix this or be able to change the parameter type to GuildChannel???
That's not the approach you want to take. Doing that would mean users would get banned for DMing your bot because it would trigger your channelCreate event handler; plus, the bot would try to ban the guild owner since it sends the owner a DM. And you only want to ban users for creating channels in the guild.
When we put the problem that way, the solution is simple: check if the channel is a DMChannel, and discontinue if it is. Only allow users to get banned for creating a GuildChannel. So how do you do that? Well, as you've seen from your error already, channel.guild is undefined when the channel is a DMChannel. So simply check for this condition, and return if it is the case. Here's an example:
// Channel Create
client.on("channelCreate", async (channel) => {
if (!channel.guild) return; //<- added this
const FetchingLogs = await client.guilds.cache.get(channel.guild.id).fetchAuditLogs({
limit: 1,
type: "CHANNEL_CREATE",
})
const ChannelLog = FetchingLogs.entries.first();
if (!ChannelLog) {
return console.log(red(`CHANNEL: ${channel.id} was created.`));
}
const { executor, target, createdAt } = ChannelLog;
if (target.id === channel.id) {
console.log(greenBright(`${channel.id} got created, by ${executor.tag}`));
} else if (target.id === executor.id) {
return
}
if (executor.id !== client.user.id) {
channel.guild.member(executor.id).ban({
reason: `Unauthorised Channel Created`
}).then(channel.guild.owner.send(`**Unauthorised Channel Created By:** ${executor.tag} \n**Channel ID:** ${channel.id} \n**Time:** ${createdAt.toDateString()} \n**Sentence:** Ban.`)).catch();
}
});
This prevents the error from occurring, prevents users from getting banned for DMing the bot, and prevents the guild owner from being infinitely DM'd (if the DMChannel were to be somehow converted into a GuildChannel, the bot would DM the owner after banning the user that created the channel, which would trigger the event again and ban the user again, and DM the owner again, in an infinite loop).

Always getting back an, "Internal Server Error," when trying to run ban command on my Discord bot

I have tried many different ways of formatting the code, however, whenever I add code so that I must provide a reasoning to ban someone, I am always given an Internal Server Error. Here is my code.
module.exports.run = async (client, message, args) => {
const member = message.mentions.members.first();
const reason = args.slice(1).join(" ")
if (!message.member.hasPermission("BAN_MEMBERS")) {
return message.reply("you lack sufficiant permissions to execute this command.");
} else if (member.hasPermission("ADMINISTRATOR")) {
message.reply("you cannot ban this member.")
}
member.ban(reason).then((member) => {
message.channel.send(`${member} has been banned.`);
});
I use a command handler, and all my other commands work fine.
first step: Define the user
let user = message.mentions.members.first() || message.guild.members.cache.get(args.join(' '));
Second step: Create embed message or normal message
const userbanned = new Discord.MessageEmbed()
.setColor('#FF0000')
.setAuthor('User Banned')
.setDescription(`**${user.user.username}#${user.user.discriminator}** is now banned from this server`)
.setFooter(`bot_name`);
Third step: Send message
user.send(`You were banned from **${message.guild.name}** by ${message.author.username}#${message.author.discriminator}`)
return user
.ban()
.then(() => message.channel.send(userbanned))
.catch(error => message.reply("ERROR"));
Try changing
member.ban().then((member) =>//
to
member.ban({reason : args.slice(1).join(' ')}).then((member) =>//

How to do restart function with client.destroy and client.login when you already have a listener?

I've done a shutdown command, but now I want to create a restart command that destroy's my client, then reconnects to the websocket. I'm just having a bit of trouble with it since I have command/event handlers set up with a ready listener.
I typed the code out, and started getting errors for the specific command. Or, i'd get the bot up and it would crash upon trying to use the command.
const { prefix } = require("../../botconfig.json");
module.exports = {
config: {
name: "restart",
description: "restarts the bot",
usage: "wrestart",
category: "moderation",
accessableby: "Bot Owner",
aliases: ["rs"]
},
run: async (bot, message, args) => {
if(message.author.id != "id") return message.channel.send("You're not bot the owner!")
try {
//I want to do the destroy/login command here...
//client.destroy()
//client.login('token') <--- and do I really have to define the token if I already have it in my botconfig?
} catch(e) {
message.channel.send(`ERROR: ${e.message}`)
}
}
}
I want to issue a command "wrestart" and it restart my application. Results so far are basically typing the code and getting it incorrect...so starting from scratch basically.
Use:
const token = bot.token; // Copies the token into the Variable
bot.destroy(); // Stops the Bot
bot.login(token); // Uses the token we saved before to reauth
I was able to figure it out with this...
run: async (client, message, args) => {
if(message.author.id != "299957385215344640") return message.channel.send("You're not bot the owner! https://i.imgur.com/8ep8YbI.gif")
try {
message.channel.send("<a:Loading:575715719103381506> Attempting a restart...").then(msg => {
//msg.react('🆗');
setTimeout(function(){
msg.edit("<:CheckMark:550460857625346066> I should be back up now!");
}, 10000);
})
.then(client.destroy())
.then(client.login('tokengoeshere'))
} catch(e) {
message.channel.send(`ERROR: ${e.message}`)
}
}
This is what I use for my bot, a simple one line of code.
client.destroy().then(client.login(process.env.BOT_TOKEN))

Resources