switch cases with push method discord.js v12 - javascript

Versions - Discord.js#v12.5.3 | Node v14.17.3
The problem is with switch cases. We have two questions after the user has had answered them bot sends a message that the user has to try again, no matter if the user has typed the right answer.
If the user has typed the wrong answer then the bot ignores it and continues to ask questions from the list. After the list is empty he sends a message to the channel that the application has been sent and that the user had typed the wrong answer.
I know the code isn't short, but please have a look. Any help would help, thanks!
const { Client, Message, MessageEmberd, MessageEmbed, ReactionCollector } = require('discord.js');
const button = require('./button');
module.exports = {
name: 'apply',
/**
* #param {Client} client
* #param {Message} message
* #param {String[]} args
*/
run: async (client, message, args) => {
let index = 1;
const Moduliai = [
`${index++}) lt?`,
`it?`
];
let collectCounter = 0;
let endCounter = 0;
const filter = (m) => m.author.id === message.author.id;
const appsChannel = client.channels.cache.get('904003816876285973');
const appStart = await message.channel.send(Moduliai[collectCounter++]);
const channel = appStart.channel;
const collector = channel.createMessageCollector(filter);
const answers = [];
const geraFunkcija = (expr) => {
switch (expr) {
case "lt":
case "Lietuvių":
case "Lietuviu":
message.channel.send('lt')
break;
case "it":
case "Info":
case "informacinės":
case "informacinių":
case "informaciniu tech":
case "informaciniu technologiju":
case "informacinių technologijų":
message.channel.send('it')
break;
default:
console.log('Try again')
message.channel.send('wrong answer, try again');
channel.send(Moduliai[collectCounter-1]);
break;
}}
collector.on("collect", async (m) => {
if(collectCounter < Moduliai.length) {
await channel.send(Moduliai[collectCounter++])
console.log(`${m.content}`)
} else {
message.reply('application was sent.')
collector.stop("fulfilled");
}
});
// collector.on("collect", async (collected) => {
// if(collectCounter < Moduliai.length) {
// await channel.send(Moduliai[collectCounter++])
// geraFunkcija(collected[index-1]);
// } else {
// message.reply('aplikacija buvo išsiųsta.')
// collector.stop("fulfilled");
// }
// });
collector.on('end', async (collected, reason) => {
console.log(`${collected.size}`)
geraFunkcija(collected[index-1]);
if(reason === "fulfilled") {
collected.map((msg) => {
// geraFunkcija(msg.content);
// answers.push(msg.content);
answers.push(msg.content);
// return msg.content;
})
console.log(answers);
const answersStep = collected.map((msg) => {
return `${Moduliai[endCounter++]}\n-> ${answers}`;
})
appsChannel.send(
new MessageEmbed()
.setAuthor(message.author.tag,
message.author.displayAvatarURL({dynamic: true})
)
.setTitle('New Application')
.setDescription(answersStep)
.setTimestamp()
).then(sent => {
sent.react("✅")
sent.react("❌")
});
client.on('messageReactionAdd', async (reaction, user) => {
if(reaction.message.channel.id === "904003816876285973") {
if (reaction.emoji.name === '✅' && user.id === message.guild.ownerID) {
for (let i=0; i<2; i++) {
geraFunkcija(answers[i].toLowerCase())
}
} if (reaction.message.channel.id === "904003816876285973") {
if (reaction.emoji.name === '❌' && user.id === message.guild.ownerID) {
message.reply('your application was cancelled.')
}
}
}
})
}
});
}};

Your code runs the switch statement function (further called sFunction) on the end event and you pass just one of the answers to it from the collected, which is Map and you can't interpret it as an Array, so actually you don't even pass an answer but an undefined value to sFunction, that's why you get dropped to default case.
What I suggest doing is removing sFunction from end event and putting it on collect event. Then you would pass m.content to the sFunction and you should be good to go.

Related

bot send msg when someone speaks

I have another question concerning my catch cmd. If I wanted to make it so that it was no longer an activable command but instead had a small chance of triggering when anyone speaks ever, how would I go about that? Would I need to put it in my message.js file? I know if I put it there as is it will trigger every time someone uses a command. However, I don't want it limited to someone using a command and I don't want it to happen every time. I've also heard of putting it in a separate json file and linking it back somehow. Any help is appreciated.
const profileModel = require("../models/profileSchema");
module.exports = {
name: "catch",
description: "users must type catch first to catch the animal",
async execute(client, message, msg, args, cmd, Discord, profileData) {
const prey = [
"rabbit",
"rat",
"bird",
];
const caught = [
"catch",
];
const chosenPrey = prey.sort(() => Math.random() - Math.random()).slice(0, 1);
const whenCaught = caught.sort(() => Math.random() - Math.random()).slice(0, 1);
const filter = ({ content }) => whenCaught.some((caught) => caught.toLowerCase() == content.toLowerCase());
const collector = message.channel.createMessageCollector({ max: 1, filter, time: 15000 });
const earnings = Math.floor(Math.random() * (20 - 5 + 1)) + 5;
collector.on('collect', async (m) => {
if(m.content?.toLowerCase() === 'catch') {
const user = m.author;
const userData = await profileModel.findOne({ userID: user.id });
message.channel.send(`${userData.name} caught the ${chosenPrey}! You gained ${earnings} coins.`);
}
await profileModel.findOneAndUpdate(
{
userID: m.author.id,
},
{
$inc: {
coins: earnings,
},
}
);
});
collector.on('end', (collected, reason) => {
if (reason == "time") {
message.channel.send('Too slow');
}
});
message.channel.send(`Look out, a ${chosenPrey}! Type CATCH before it gets away!`);
}
}
message.js file just in case
const profileModel = require("../../models/profileSchema");
const cooldowns = new Map();
module.exports = async (Discord, client, message) => {
let profileData;
try {
profileData = await profileModel.findOne({ userID: message.author.id });
if(!profileData){
let profile = await profileModel.create({
name: message.member.user.tag,
userID: message.author.id,
serverID: message.guild.id,
coins: 0,
});
profile.save();
}
} catch (err) {
console.log(err);
}
const prefix = '-';
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const cmd = args.shift().toLowerCase();
const command = client.commands.get(cmd) || client.commands.find(a => a.aliases && a.aliases.includes(cmd));
if(!command) return;
if(!cooldowns.has(command.name)){
cooldowns.set(command.name, new Discord.Collection());
}
const current_time = Date.now();
const time_stamps = cooldowns.get(command.name);
const cooldown_amount = (command.cooldown) * 1000;
if(time_stamps.has(message.author.id)){
const expiration_time = time_stamps.get(message.author.id) + cooldown_amount;
if(current_time < expiration_time){
const time_left = (expiration_time - current_time) / 1000;
return message.reply(`Slow down there! You have to wait ${time_left.toFixed(0)} seconds before you can perform ${command.name} again.`);
}
}
if(command) command.execute(client, message, args, cmd, Discord, profileData);
}
Yes...that can be possible. In your command handler, create and export a variable with a boolean
Make sure to do this in global scope (outside any function)
let canBeActivated = true;
module.exports.getCanBeActivated = function () { return canBeActivated };
module.exports.setCanBeActivated = function(value) { canBeActivated = value };
Then, in your command file, import it and check whether it can be activated
const { getCanBeActivated, setCanBeActivated } = require("path/to/message.js")
module.exports = {
...
execute(...) {
// command wont run
if(!getCanBeActivated()) return
}
You can make some logic to make the command run if canBeActivated is false (like get a random number between 1-100 and if it matches 4 run it).In case you need to change it, just run, setCanBeActivated

How to stop MessageCollector with custom message

I have slash command that collects messages from users. Users should input their nicknames from the game, and then bot should return in embeded 2 teams. I managed to filter and collect nicknames, and call calculation functions. This works if I enter maximum number of nicknames, but now I want to add feature, where I would manually stop collecting by sending message "stop". Now I don't know where to add condition
if(m.content==="stop") {collector.stop();}
const { SlashCommandBuilder } = require("#discordjs/builders");
const { getSummonerProfile } = require("./../functions/summonerData");
const { MessageEmbed } = require("discord.js");
let arrayOfSummoners = [];
let arrayOfNicknames = [];
async function checkIfSummonerExist(m) {
const test = await getSummonerProfile(m.content);
if (test && m.author.bot == false && !arrayOfNicknames.includes(m.content)) {
m.react("👍");
return true;
} else if (test == false && m.author.bot == false) {
m.react("👎");
return false;
}
if (arrayOfNicknames.includes(m.content)) {
m.react("👎");
}
}
module.exports = {
data: new SlashCommandBuilder()
.setName("custom")
.setDescription("Enter the name of the user."),
async execute(interaction) {
await interaction.deferReply();
interaction.editReply("Insert users");
const exampleEmbed = new MessageEmbed()
.setColor("#0099ff")
.setTimestamp();
// `m` is a message object that will be passed through the filter function
const filter = (m) => checkIfSummonerExist(m);
const collector = interaction.channel.createMessageCollector({
filter,
max: 4,
});
if(m.content==="stop")
{
collector.stop();
}
collector.on("collect", (m) => {
arrayOfNicknames.push(m.content);
exampleEmbed.addFields({
name: "Regular field title",
value: m.content, inline:true
});
});
collector.on("end", (collected) => {
interaction.followUp({ embeds: [exampleEmbed] });
});
},
};
If I add this condition in filter fuction (checkIfSummonerExist(m), I get error collector is not defined and I if call it in execute, like in example above, I get error m is not defined
I would put the if statement inside the collector.on callback. Something like this:
collector.on("collect", m => {
if(m.content === "stop") return collector.stop()
// Other code
})

How would I go about programming a "stop/start" command for a chatbot in discord.js?

The Problem-
I've been working on a small project (A discord chatbot named AEIOU), and the people I'm working with tend to find that she interrupts conversations by reacting to trigger words every time. I've been looking for ways to add in a !stop and !start command so she'd only react to trigger words when active, and would only listen to commands when the trigger word activation is disabled.
The problem: I have no clue how to go about it, and when I try to code in "if (command === stop/start)", the console log displays an error "can't run commands before initialization".
But, I have to put the trigger words before the commands of the bot will not work at all.
The Code-
console.clear();
const prefix = "au>";
const Me = "865241446335512616";
const Secondary = "589180215956078612"
const Zach = "755977853518086244"
const AEIOU = "792278833877221416"
const Discord = require("discord.js");
const fs = require('fs');
const chalk = require('chalk');
const ytdl = require('ytdl-core');
const GIFEncoder = require('gifencoder')
const Canvas = require ('canvas')
const client = new Discord.Client();
const hi = require("./chatbot/hi.js")
const horny = require("./chatbot/horny.js")
const cute = require("./chatbot/cute.js")
const funny = require("./chatbot/funny.js")
const loli = require("./chatbot/loli.js")
const food = require("./chatbot/food.js")
const drink = require("./chatbot/drink.js")
const hotdog = require("./chatbot/hotdog.js")
client.commands = new Discord.Collection();
const sleep = function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const getRandomInt = function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
var totalCommands = 0;
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
async function load() {
await console.log(chalk.green('AEIOU, Here to sing for you!'))
await console.log('\n\n');
await console.log('Booting up ' + chalk.cyan(__filename));
await sleep(250);
await console.log(chalk.bgCyan(chalk.black('[Command Loader]')), 'Loading Abilities...');
await sleep(1000);
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
await sleep(10);
await console.log(chalk.bgGreen(chalk.black('[Command Loader]')), 'Got this one! ' + chalk.magentaBright(file));
totalCommands++;
}
console.log(chalk.cyan(totalCommands), 'commands loaded');
client.login("TOKEN_HERE");
}
load();
console.log(chalk.yellow(commandFiles))
client.once('ready', () => {
console.log(chalk.blueBright('AEIOU, here to talk to you!'))
});
process.on('unhandledRejection', error => console.error('Uncaught Promise Rejection', error));
client.on("message", async message => {
if (message.author.id == client.user.id) { return }
var msg = [];
var placeholder = message.content.toLowerCase().split(' ');
placeholder.forEach(string => {
string = string.replace(',', '');
string = string.replace('?', '');
string = string.replace('!', '');
string = string.replace('"', '');
msg.push(string);
});
if (msg.some(r => hi.messages.includes(r))) {
return message.channel.send(hi.responses[getRandomInt(hi.responses.length)]);
}
if (msg.some(r => funny.messages.includes(r))) {
return message.channel.send(funny.responses[getRandomInt(funny.responses.length)]);
}
if (msg.some(r => drink.messages.includes(r))) {
return message.channel.send(drink.responses[getRandomInt(drink.responses.length)]);
}
if (msg.some(r => food.messages.includes(r))) {
return message.channel.send(food.responses[getRandomInt(food.responses.length)]);
}
if (msg.some(r => cute.messages.includes(r))) {
return message.channel.send(cute.responses[getRandomInt(cute.responses.length)]);
}
if (msg.some(r => horny.messages.includes(r))) {
return message.channel.send(horny.responses[getRandomInt(horny.responses.length)]);
}
if (msg.some(r => loli.messages.includes(r))) {
return message.channel.send(loli.responses[getRandomInt(loli.responses.length)]);
}
if (message.mentions.has(client.user)) {
message.channel.send("Hi! I'm AEIOU, and I do have a prefix. It's `au>[command]`. Thanks for mentioning me!")
}
const commandBody = message.content.slice(prefix.length);
const args = commandBody.split(' ');
const command = args.shift().toLowerCase();
if (!message.content.startsWith(prefix) || message.author.bot) return;
if (command == 'credit' || command == 'credits') {
client.commands.get('credits').execute(message, args, Discord, client);
}
if (command == 'help' || command == 'menu') {
client.commands.get('help').execute(message, args, Discord, client);
}
if (command == 'link' || command == 'invite') {
client.commands.get('invite').execute(message, args, Discord, client);
}
if (command == 'headpat' || command == 'pat') {
client.commands.get('pet').execute(message, args, Discord, client);
}
if (command === "repeat") {
const echoMessage = args.join(" ");
message.delete();
message.channel.send(echoMessage);
};
if (command == 'suggest') {
const suggestionmsg = args.join(' ');
if (!args.length) {
return message.channel.send(`You didn't provide a suggestion, ${message.author}!`);
} else {
client.users.cache.get(me).send(message.author.tag + ' suggests: ' + suggestionmsg);
message.channel.send("Thanks for your suggestion, and for helping with my development! I'm always looking for ways to be a better bot!");
console.error();
}
}
});
I removed the actual key, and any names that aren't bots.
You can add a database wheres it has a key for enable/disable
and you can put the condition and then put the i assumed a chat if statement
inside that condition scope
for example
let db = require('quick.db');
let chatStatus = db.get('chatStatus')
// inside message event
if(chatStatus === null) chatStatus = false
if(chatStatus === true)
{
if (msg.some(r => hi.messages.includes(r))) {
return message.channel.send(hi.responses[getRandomInt(hi.responses.length)]);
}
/*
other chat code
*/
if (message.mentions.has(client.user)) {
message.channel.send("Hi! I'm AEIOU, and I do have a prefix. It's `au>[command]`. Thanks for mentioning me!")
}
}
// code for enabling or disabling it
if (command === "status") {
let status = db.get('chatStatus')
if(status === null) status = false
if(args[0] === undefined) return message.channel.send('true/false')
if(args[0] == 'true') {
db.set('chatStatus', true)
message.channel.send(`Successfully set Chatbot to ${args[0]}`);
}
if(args[0] == 'false') {
db.set('chatStatus', false)
message.channel.send(`Successfully set Chatbot to ${args[0]}`);
}
};
P.S: if theres a better way or remove some useless variables, whoever are you freely edit this answer

Need help adding a role to a user. (discord.js)

When I'm online the bot gives me a role, as soon as I go offline the bot removes that role from me.
When it removes the role, I want the bot to give the role to a specific user. How can I do that?
I have my current code below:
client.on('presenceUpdate', (oldPresence, newPresence) => {
const member = newPresence.member;
if (member.id === 'user.id') {
if (oldPresence.status !== newPresence.status) {
var gen = client.channels.cache.get('channel.id');
if (
newPresence.status == 'idle' ||
newPresence.status == 'online' ||
newPresence.status == 'dnd'
) {
gen.send('online');
member.roles.add('role.id');
} else if (newPresence.status === 'offline') {
gen.send('offline');
member.roles.remove('role.id');
}
}
}
});
You could get the other member by its ID. newPresence has a guild property that has a members property; by using its .fetch() method, you can get the member you want to assign the role to. Once you have this member, you can use .toles.add() again. Check the code below:
// use an async function so we don't have to deal with then() methods
client.on('presenceUpdate', async (oldPresence, newPresence) => {
// move all the variables to the top, it's just easier to maintain
const channelID = '81023493....0437';
const roleID = '85193451....5834';
const mainMemberID = '80412945....3019';
const secondaryMemberID = '82019504....8541';
const onlineStatuses = ['idle', 'online', 'dnd'];
const offlineStatus = 'offline';
const { member } = newPresence;
if (member.id !== mainMemberID || oldPresence.status === newPresence.status)
return;
try {
const channel = await client.channels.fetch(channelID);
if (!channel) return console.log('Channel not found');
// grab the other member
const secondaryMember = await newPresence.guild.members.fetch(secondaryMemberID);
if (onlineStatuses.includes(newPresence.status)) {
member.roles.add(roleID);
secondaryMember.roles.remove(roleID);
channel.send('online');
}
if (newPresence.status === offlineStatus) {
member.roles.remove(roleID);
secondaryMember.roles.add(roleID);
channel.send('offline');
}
} catch (error) {
console.log(error);
}
});

Take user image as argument, then send message with same image with Discord.JS

Let's just get this started off with.
I've been looking around Google trying to find a guide on how to take images as arguments and then sending that same image with the message the user provided.
I'm making an announcement command.
Right now, my command only takes text as input, not files/images.
Here's my announce command:
module.exports = {
name: "afv!announce",
description: "announce something",
execute(msg, args, bot) {
if (msg.member.roles.cache.find((r) => r.name === "Bot Perms")) {
const prevmsg = msg;
const text = args.join().replace(/,/g, " ");
msg
.reply(
"Would you like to do `#here` :shushing_face: or `#everyone` :loudspeaker:?\nIf you would like to ping something else, react with :person_shrugging:. (you will have to ping it yourself, sorry)\n*react with :x: to cancel*"
)
.then((msg) => {
const areusure = msg;
msg
.react("🤫")
.then(() => msg.react("📢"))
.then(() => msg.react("🤷"))
.then(() => msg.react("❌"));
const filter = (reaction, user) => {
return (
["🤫", "📢", "🤷", "❌"].includes(reaction.emoji.name) &&
user.id === prevmsg.author.id
);
};
msg
.awaitReactions(filter, { max: 1, time: 60000, errors: ["time"] })
.then((collected) => {
const reaction = collected.first();
if (reaction.emoji.name === "🤫") {
areusure.delete();
prevmsg
.reply("<a:AFVloading:748218375909539923> Give me a sec...")
.then((msg) => {
bot.channels.cache
.get("696135322240548874")
.send("#here\n\n" + text);
msg.edit("<a:AFVdone:748218438551601233> Done!");
});
} else if (reaction.emoji.name === "📢") {
areusure.delete();
prevmsg
.reply("<a:AFVloading:748218375909539923> Give me a sec...")
.then((msg) => {
bot.channels.cache
.get("696135322240548874")
.send("#everyone\n\n" + text);
msg.edit("<a:AFVdone:748218438551601233> Done!");
});
} else if (reaction.emoji.name === "🤷") {
areusure.delete();
prevmsg
.reply("<a:AFVloading:748218375909539923> Give me a sec...")
.then((msg) => {
bot.channels.cache
.get("696135322240548874")
.send(
"Important: https://afv.page.link/announcement\n\n" +
text
);
msg.edit("<a:AFVdone:748218438551601233> Done!");
});
} else if (reaction.emoji.name === "❌") {
areusure.delete();
prevmsg.reply("Cancelled.");
}
})
.catch((collected) => {
msg.delete();
prevmsg.reply("you didn't react with any of the emojis above.");
});
});
}
},
};
Message has a property called attachments, which contains all of the attachments in the message. (A image uploaded by the user is counted as an attachment, however, a URL to an image, is not.)
Here's an example:
client.on('message', (message) => {
if (message.author.bot) return false;
if (message.attachments.size == 0)
return message.channel.send('No attachments in this message.');
const AnnouncementChannel = new Discord.TextChannel(); // This shall be announcement channel / the channel you want to send the embed to.
const Embed = new Discord.MessageEmbed();
Embed.setTitle('Hey!');
Embed.setDescription('This is an announcement.');
Embed.setImage(message.attachments.first().url);
AnnouncementChannel.send(Embed);
});
Avatar
To use images you can use this function :
message.author.displayAvatarURL(
{ dynamic: true } /* In case the user avatar is animated we make it dynamic*/
);
Then it will return a link you can use for an embed thumbnail or image. If you want to use it in an embed
let link = message.author.displayAvatarURL({ dynamic: true });
const embed = new Discord.MessageEmbed().setThumbnail(link);
Use Image Links
If you want to use an image link you'll have to transform it into a discord attachement.
const args = message.content.split(' ').slice(1);
const attach = new Discord.Attachement(args.join(' '), 'image_name.png');
message.channel.send(attach);
Hope I helped you. If not you can still search in the discord.js guide ^^
Not sure where the image link is
If you don't really know where the image link is in the message content you can separate it (you already did with arguments) and use a forEach function :
const args = message.content.split(' ').slice(1);
// a function to see if it's an url
function isvalidurl(string) {
try {
const a = new URL(string);
} catch (err) {
return false;
}
return true;
}
// check the function for each argument
args.forEach((a) => {
if (isvalidurl(a)) link = a;
});
if (link) {
// code
} else {
// code
}

Categories