Private message commands in discord - javascript

I am making an RP profile creation setup for a discord bot using javascript. I have the conversation starting in a channel and moving to private messaging with the bot. The first question gets asked and the reply from the user is stored in a database. That is working fine.
What seems to be the problem comes when I try to use another command inside a private message with the bot to move to the next step of the RP profile creation. It doesn't seem to register the command is being used. Can commands even be used in private messaging with a bot?
I used the same code as the first question that worked, changed what needed to be, but nothing that should have broken the code. It just looks to not even see the second command, which is stored in a separate command file. How would I do this?
module.exports.run = async (bot, message, args) => {
message.author.send(` SECOND QUESTION, **What is the age of your Brawler or Character?**`)
.then((newmsg) => { //Now newmsg is the message you send to the bot
newmsg.channel.awaitMessages(response => response.content, {
max: 1,
time: 300000,
errors: ['time'],
}).then((collected) => {
newmsg.channel.send(`Your brawler's age is: **${collected.first().content}**
If you are okay with this age, type !profilegender to continue the profile creation process!
If you would like to edit your age, please type !profileage`)
con.query(`UPDATE profile SET age = '${collected.first().content}' WHERE id = ${message.author.id}`);
console.log("1 record updated!")
}).catch(() => {
newmsg.channel.send('Please submit an age for your character. To restart Profile creation, please type "!profilecreate" command in Profile Creation channel on the server.');
});
});
}
Thanks in advance for your time!
EDIT: This is part of the code that is the bot/client is listening for on message.
bot.on(`message`, async message => {
if(message.author.bot) return;
if(message.channel.type === "dm") return;
con.query(`SELECT * FROM profile WHERE id = '${message.author.id}'`, (err, rows) => {
if(err) throw err;
var sql;
if(rows.length < 1) {
var sql = (`INSERT INTO profile (id, username) VALUES (${message.author.id}, '${message.author.tag}')`);
} else {
var sql = (`UPDATE profile SET username = '${message.author.tag}' WHERE id = ${message.author.id}`);
};
//con.query(sql, console.log);
//if (err) throw err;
//console.log("1 record inserted!");
});

Answer from comments
Inside of your client.on("message") there's an if check that exits the function if the channel is a DMChannel
if(message.channel.type === "dm") return;
To avoid that, simply remove this line: in this way, the bot will execute the command regardless of the channel type. If you want to allow some commands only in certain channels, you can do that either in the client.on("message") or in the function of the command itself.

Related

Discord bot look for reactions

So its hard to explain my situation because i am new to discord.js and i have been trying to figure this out for hours
What i need is my bot to look at a certain channel and see that a staff member (or anyone because normal users cannot add reactions) reacted with "👍" and logs it.
Later my end goal is it sees this and replys and sends a command to a minecraft server. but ill figure all that out later. i just need the bot to see that there is that certain reaction on a message
Like i said i am new, and the docs to discord.js are not helping, all i could find/do is this:
const Discord = require('discord.js');
const client = new Discord.Client();
client.once('ready', () => {
console.log('Ready!');
});
const filter = (reaction, user) => {
return reaction.emoji.name === '👍' && user.id === Discord.Message.author.id;
};
const collector = Discord.Message.createReactionCollector(filter, { time: 15000 });
collector.on('collect', (reaction, user) => {
console.log(`Collected ${reaction.emoji.name} from ${user.tag}`);
});
And it throws errors about the Message.createReactionCollector
To use the ReactionCollector you will need an instance of Message to create the collector on.
If you don't have a specific message and want to collect the reactions globally, you could listen for an event messageReactionAdd.
client.on("messageReactionAdd", (reaction, user) => {
// Ignore the bot's reactions
if (client.user.id == user.id) return;
// Look only for thumbs up reaction
if (reaction.emoji.name != "👍") return;
// Accept reactions only from specific channel
if (reaction.message.channel.id != "870115890367176724") return;
console.log(`${user.tag} reacted with 👍.`);
});
Note that this won't work for reactions cast on messages sent before the bot was started. The solution is to enable Partial Structures. (If you are dealing with partial data, don't forget to fetch)

I'm making a schedule Discord.js bot, but it's not sending a message

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.

Move all users to your Channel (Discord JS)

I'd like to create a command, that moves all users in my Discord voice channel.
Here is what i tried.
...
client.on('message', async message =>{
//Check message is not Bot
if(message.author.bot) return;
if(message.content=="!movetome"){
if(message.member.voice.channel) {//Is user in voicechannel
message.guild.members.cache.forEach(member => { //Loop every user
if(member.id!=message.member.id&&member.voice.channel){//Is user in voicechannel and is user the command executer
member.setVoiceChannel(message.member.voice.channel)//Sets user to channel
}
});
}
}
});
...
After I tried to run the command "!movetome" in discord chat I got the following error message:
(node:12268) UnhandledPromiseRejectionWarning: TypeError: member.setVoiceChannel is not a function
Thanks for your help :)
Firstly this seems like a bad idea if any user can do it but regardless, .setVoiceChannel is v11, they moved it to <GuildMember>.voice.setChannel()
Change the contents inside of if(message.content=="!movetome") to this
const channel = message.member.voice.channel;
message.guild.members.cache.forEach(member => {
//guard clause, early return
if(member.id === message.member.id || !member.voice.channel) return;
member.voice.setChannel(channel);
});

Send a message with Discord.js

I am trying to make a discord bot, but I can't quite understand Discord.js.
My code looks like this:
client.on('message', function(message) {
if (message.content === 'ping') {
client.message.send(author, 'pong');
}
});
And the problem is that I can't quite understand how to send a message.
Can anybody help me ?
The send code has been changed again. Both the items in the question as well as in the answers are all outdated. For version 12, below will be the right code. The details about this code are available in this link.
To send a message to specific channel
const channel = <client>.channels.cache.get('<id>');
channel.send('<content>');
To send a message to a specific user in DM
const user = <client>.users.cache.get('<id>');
user.send('<content>');
If you want to DM a user, please note that the bot and the user should have at least one server in common.
Hope this answer helps people who come here after version 12.
You have an error in your .send() line. The current code that you have was used in an earlier version of the discord.js library, and the method to achieve this has been changed.
If you have a message object, such as in a message event handler, you can send a message to the channel of the message object like so:
message.channel.send("My Message");
An example of that from a message event handler:
client.on("message", function(message) {
message.channel.send("My Message");
});
You can also send a message to a specific channel, which you can do by first getting the channel using its ID, then sending a message to it:
(using async/await)
const channel = await client.channels.fetch(channelID);
channel.send("My Message");
(using Promise callbacks)
client.channels.fetch(channelID).then(channel => {
channel.send("My Message");
});
Works as of Discord.js version 12
The top answer is outdated
New way is:
const channel = await client.channels.fetch(<id>);
await channel.send('hi')
To add a little context on getting the channel Id;
The list of all the channels is stored in the client.channels property.
A simple console.log(client.channels) will reveal an array of all the channels on that server.
There are four ways you could approach what you are trying to achieve, you can use message.reply("Pong") which mentions the user or use message.channel.send("Pong") which will not mention the user, additionally in discord.js you have the option to send embeds which you do through:
client.on("message", () => {
var message = new Discord.MessageEmbed()
.setDescription("Pong") // sets the body of it
.setColor("somecolor")
.setThumbnail("./image");
.setAuthor("Random Person")
.setTitle("This is an embed")
msg.channel.send(message) // without mention
msg.reply(message) // with mention
})
There is also the option to dm the user which can be achieved by:
client.on("message", (msg) => {
msg.author.send("This is a dm")
})
See the official documentation.
Below is the code to dm the user:
(In this case our message is not a response but a new message sent directly to the selected user.)
require('dotenv').config({ path: __dirname + '/.env.local' });
const Discord = require("discord.js");
const client = new Discord.Client();
client.on("ready", () => {
console.log(client.users.get('ID_OF_USER').send("hello"));
});
client.login(process.env.DISCORD_BOT_TOKEN);
Further documentation:
https://github.com/AnIdiotsGuide/discordjs-bot-guide/blob/master/frequently-asked-questions.md#users-and-members
You can only send a message to a channel
client.on('message', function(message) {
if (message.content === 'ping') {
message.channel.send('pong');
}
});
If you want to DM the user, then you can use the User.send() function
client.on('message', function(message) {
if (message.content === 'ping') {
message.author.send('pong');
}
});
Types of ways to send a message:
DM'ing whoever ran the command:
client.on('message', function(message) {
if (message.content === 'ping') {
message.author.send('pong');
}
});
Sends the message in the channel that the command was used in:
client.on('message', function(message) {
if (message.content === 'ping') {
message.channel.send('pong');
}
});
Sends the message in a specific channel:
client.on('message', function(message) {
const channel = client.channels.get("<channel id>")
if (message.content === 'ping') {
channel.send("pong")
}
});
It's message.channel.send("content"); since you're sending a message to the current channel.

SQL Select a value from database

For a Discord bot I have a command that changes the prefix of that guild, it 'works fine' as in it updates it in my database (MySQL Workbench), but the commands still triggers for ANY prefix, so if you stick any character in-front of the command it triggers instead of the one in the database.
This is my code to check the prefix:
let prefix = "!";
connection.query(`SELECT * FROM guilds WHERE guildid = ${message.guild.id}`, (error, commands) => {
if (error) throw error;
if (commands.length) { //guild exists in database
commands.forEach(value =>
prefix = value.prefix;
console.log(value.prefix); // returns correct prefix from database
});
} else {
prefix = "!";
}
});
It's a little challenging trying to read your code with the arrow short hands. I'm rather sure this is where your error is coming form.
prefix = value.prefix; console.log(value.prefix);
Do you mean to be logging the original value.prefix before reassigning it?
Try this code.
commands.forEach(function(value){
console.log(value.prefix);
prefix = value.prefix;
})
Javascript Docs on .forEach()

Categories