I'm creating a logging system for my Discord server of over 12k members. What I would like to achieve is that whenever a moderator uses the .lock command, the bot sends a message to the logs channel and DM's me. Both work, but I can't figure out how to attach the message url so that I can click on that and immediately jump to the .lock command itself so I can review what happened.
This is the code that I have thus far:
// Message url to be used in logging later.
const msgURL = 'empty';
// Send lock message
const embed = new Discord.MessageEmbed()
.setTitle("LOCKDOWN")
.setColor('#ff0000')
.setDescription("There have been a large number of infringements in this channel. Please be patient as we review the sent messages and take appropriate action.")
.setFooter("Please do not DM staff asking when the lockdown will be over. ");
message.channel.send({embed}).then(msgURL => {
msgURL = embed.url;
})
// Send unlock notification to #staff-logs.
// async method to get the channel id (in case of delay.)
function getStaffLogChannel(){
return message.guild.channels.cache.get('ID');
}
// Staff logs channel
let staffLogs = await getStaffLogChannel();
// User who issued the command
let commandIssuer = message.member.user.tag;
// message published in staff-logs
staffLogs.send(commandIssuer + " has used the **.lock** command in: " + message.channel.name)
// send notification in DM
client.users.cache.get('ID').send(commandIssuer + " has used the **.lock** command in: " + message.channel.name + " ( " + msgURL + " )");
I have also tried to change the
message.channel.send({embed}).then(msgURL => {
msgURL = embed.url;
})
to:
message.channel.send({embed}).then(msgURL => {
msgURL = embed.url.get;
})
But that unfortunately doesn't work either. Here you get this error:
TypeError: Cannot read property 'get' of null`
You can just use Message#url. There is no need for the .get().
You are trying to get the URL of the embed, not the message.
Related
Here's an image explaining the error:-
output image
So, s.gw is the command which triggers the first embed. After this embed, typing an ok message would then lead to the display of a new embed. Not typing an ok or end message would lead to the display of the "invalid input" message.
But, because of this bug, entering s.gw AND ok together will only result in the display of the second embed. I also added a few more embeds which the user would trigger using certain keywords, but they all only get triggered when all of the command messages are entered at once.
Any sort of help would do. I'm new to JavaScript and Discord bot dev in general.
Here's the code for the "game":-
const Discord = require('discord.js');
const animalArray = ["lion", "mongoose", "chimpanzee"];
const foodArray = ["bread", "applie pie", "cake"];
exports.run=async(bot, message, args)=>{
const embedTemp = new Discord.MessageEmbed();
const beginEmbed = new Discord.MessageEmbed();
const embedEnd = new Discord.MessageEmbed();
const aniEmbed = new Discord.MessageEmbed();
const fooEmbed = new Discord.MessageEmbed();
const animal = animalArray[Math.floor(Math.random()*animalArray.length)];
const food = foodArray[Math.floor(Math.random()*foodArray.length)];
embedTemp.setColor("#EC5CA6");
embedTemp.setTitle("Welcome to Guess-The-Word!");
embedTemp.setDescription("Guess the word generated by the computer! \nYou only get 3 tries! \nGood Luck! \n\nReply with **ok** to start or **end** to stop.");
message.channel.send(embedTemp);
let ok = ' ok ';
let end = ' end ';
// let play = false;
if(message.content.includes(ok))
{
beginEmbed.setColor("#EC5CA6");
beginEmbed.setTitle("Choose a topic: (reply with no. given alongside topic)");
beginEmbed.setDescription("**1.** Animals \n\n**2.** Food");
message.channel.send(beginEmbed);
if(message.content.includes('1'))
{
aniEmbed.setColor("#EC5CA6");
aniEmbed.setTitle("Guess the animal:");
message.channel.send(aniEmbed);
}
else if(message.content.includes('2'))
{
fooEmbed.setColor("#EC5CA6");
fooEmbed.setTitle("Guess the food item:");
message.channel.send(fooEmbed);
}
}
else
{
if(message.content.includes(end))
{
embedEnd.setColor("#EC5CA6");
embedEnd.setTitle("Thanks for playing :)");
embedEnd.setDescription("The game has ended.");
message.channel.send(embedEnd);
}
else
{
message.channel.send("invalid input");
}
}
}
exports.help={
name: 'gw'
}
Still have a lot to do, but getting this out of the way seemed like the better idea.
Your current code is just fetching the content of the message that contains the command, meaning it will not register any other response outside of the command input. You are checking for "message.content", and message.content will only be registered for the command, for example:
User1 types the command "/say Test" and you have "console.log(message.content)" written for the /say command, the bot will log "say test" and not any message sent after the command.
As stated in the comments, what you need is a message collector, so the bot will listen to responses for x amount of time after the command has been sent.
You must make sure that the message collector fetches for lower cased responses, this way if a user inputs a letter in capital, it won't affect the response.
I'm making a discord.js scheduling bot. I am using node-schedule for this. It's not throwing any errors but it's still not sending a message. What am I doing wrong, and how do I get rid of this issue? (thank you in advance)
My code is:
const Discord = require('discord.js');
const client = new Discord.Client();
const schedule = require('node-schedule');
client.once('ready', () => {
console.log('Ready!');
});
client.login('TOKEN IS HERE');
const rule = new schedule.RecurrenceRule();
rule.tz = 'EDT';
client.on('message', message => {
if (message.content === '!schedule 9pm meeting') {
message.channel.send('Alright. I will announce it for you, friend! :smiley:');
const job = schedule.scheduleJob('00 21 * * *', function () {
client.channels.cache.get("channel id is here").send("This is a test message. Does it work?");
});
}
});
You can't run the schedule.scheduleJob from inside the client.on function and expect the message to still exist. Discord API expects a response to a webhook within a specific time before it times out.
Also, if the bot runs on a cloud service, the node it runs on might be restarting once in a while, which messes up in-memory data like attaching cron jobs in node-schedule.
Persisting the data
You should probably get scheduled time by the user and persist the data in some sort of database. You should use database read\writes in order to save the data between your cloud provider restarts (unless you have a paid subscription).
Have a global cron job or interval
Since you can potentialy have thousands of scheduled meetings, it's better in your case to check for meetings withing a certain interval and send all the reminders at the same time.
Let's say a user can't give us a time more specific than a certain minute. Then we can check for reminders every minute, knowing we'll inform users before the meeting starts.
// Run checkForReminders every 60 seconds to scan DB for outstanding reminders
setInterval(checkForReminders, 60000);
// Parse reminder request, save to DB, DM confirmation to user
client.on('message', (msg) => {
createNewReminder(msg);
});
New reminders handling
const createNewReminder = (msg) => {
const formattedMessage = formatMessage(msg)
// If message isn't a remindme command, cease function execution
if (!formattedMessage.startsWith('!remindme')) {
return
}
// Determine if message contains a number to assign to intervalInteger
checkForNumbersInMessage(formattedMessage)
// Final format for message to be sent at reminderTime
const messageToDeliverToUser = formattedMessage.replace('!remindme', '')
// Set integer and verb values for moment.add() parameters
const intervalInteger = parseInt(checkForNumbersInMessage(formattedMessage))
const intervalVerb = setIntervalVerb(formattedMessage)
// Format time to send reminder to UTC timezone
const reminderTime = moment().utc().add(intervalInteger, intervalVerb).format('YYYY-MM-DD HH:mm:ss')
// Save reminder to DB
saveNewReminder(msg.author.id, msg.author.username, messageToDeliverToUser, reminderTime)
// Send embedded message to author & notify author in channel of remindertime request
const embed = createEmbed(messageToDeliverToUser, reminderTime)
msg.author.send(embed)
msg.channel.send(`${msg.author} - A reminder confirmation has been sent to your DMs. I will DM you again at the requested reminder time`)
}
Send a message to a guild or user later
In order to send a message later, save either the userId or guildId to the database, then, retrieve the user or guild from the discord client, and send the message.
const checkForReminders = () => {
db.serialize(() => {
// Select all messages older than the current dateTime
db.each("SELECT id, reminderTime, userID, message FROM reminders WHERE reminderTime < DATETIME()", (error, row) => {
if (error || !row) {
return console.log('Error or no row found')
}
// If reminders are found, fetch userIDs, then send the requested reminder through DM
client.users.fetch(row.userID).then((user) => {
user.send(`Hi, you asked to be reminded "${row.message}" - That's right now!`).catch(console.error)
console.log(`Message delivered: ${row.message}`)
console.log(`Message deleted successfully`)
// Delete message after DMing to user
db.run("DELETE FROM reminders WHERE id = ?", [row.id])
console.log('Message sent and removed successfully')
})
})
})
}
Code examples where taken from NathanDennis/discord-reminder-bot. check out the repository for a complete example. He comments on his code so it's easy to understand.
I've been making a discord bot in Discord.js and I'm trying to make a welcome command. I'm trying to send a message to a specific channel in my server. I don't know how to do this since the update in discord.js because I've done this before. Can you help me?
Here is a chunk of my code:
bot.on('guildMemberAdd', (member) => {
let embed = new Discord.MessageEmbed()
.setColor(0xcccccc)
.setThumbnail(member.user.avatarURL)
.setTitle("Welcome " + member.user.tag + "!")
.setDescription("Hello, welcome to this server!")
.addField("Welcome", "imageurl")
.setFooter("Server Name")
bot.channels.find('XXXXX').send(embed)
})
The introduction of managers is likely the cause of confustion. Try something like this:
// assuming 'bot' is client object in this context
client.channels.fetch( CHANNEL_ID ).then(channel =>{
channel.send( YOUR_EMBED )
}).catch(err =>{
// do something with err
})
// if you need to fetch by channel name
let channelsCollection = client.channels.cache; // returns collection
let channel = channelsCollection.find(channel => channel.name === YOUR_CHANNEL_NAME );
channel.send( YOUR_EMBED );
I'm attempting to make a discord bot that checks messages sent in channels for a prefix and argument (!send #Usermention "message"), but despite running, the program closes out as soon as a message is typed in my discord server, not outputting any error messages, so I'm not really sure what to do...
const Discord = require('discord.js');
const client = new Discord.Client();
const auth = require('./auth.json');
const prefix = "!";
client.on("message", (message) =>
{
msg = message.content.toLowerCase();
if (message.author.bot) { return; }
mention = message.mention.users.first(); //gets the first mention of the user's message
if (msg.startsWith (prefix + "send")) //!send #name [message]
{
if (mention == null) { return; } //prevents an error sending a message to nothing
message.delete();
mentionMessage = message.content.slice (6); //removes the command from the message to be sent
mention.sendMessage (mentionMessage); //sends message to mentioned user
message.channel.send ("message sent :)");
}
});
client.login(auth.token);
mention = message.mention.users.first();
It is message.mention**s**. You were missing an s.
Also, you might want to use send, rather than sendMessage, since sendMessage is deprecated.
help me with discord-api. Sending private messages to the user who just logged on to the server. I have the following code:
const robot = new Discord.Client();
robot.on("guildMemberAdd", (gMembAdd) =>
{
gMembAdd.guild.channels.find("name", "test").sendMessage(gMembAdd.toString() + "hello guys");
});
Added the following code:
robot.on("guildMemberAdd", (gMembAdd) =>
{
gMembAdd.guild.channels.find("name", "test").sendMessage(gMembAdd.toString() + "hello guys");
gMembAdd.mentions.users.first().sendMessage("Test");
});
I received an error message. Help me please.
First thing you shouldn't use .sendMessage() as it was deprecated in newer versions. You need to use .send().
When you subscribing to guildMemberAdd you will recieve a GuildMember, from there you can directly send a message:
robot.on("guildMemberAdd", (gMembAdd) => {
gMembAdd.guild.channels.find("name", "test").send(gMembAdd.toString() + "hello guys");
gMembAdd.send("Test");
});
This should send a message directly to the member that joined.