In the main bot file, I created the voice Collection property
require('dotenv').config();
const Discord = require('discord.js');
const { Client, IntentsBitField, Collection } = require('discord.js');
const eventHandler = require('./handlers/eventHandler');
const client = new Client({
intents: [
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.GuildMembers,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.MessageContent,
IntentsBitField.Flags.GuildVoiceStates,
],
});
client.voiceCollection = new Discord.Collection();
eventHandler(client);
client.login(process.env.TOKEN);
When I try to access it in an event or a team, it says: cannot read properties of undefined (reading 'voiceCollection'). For example, here is one of the calls in another file: client.voiceCollection.get(member.id); I pass the client through a parameter
Trying to access a collection in the main file from another event/command file.
Related
How to send a separate embed message to a channel different from where the slash command was executed? My current code is the following block.
const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, Guild } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('arrest')
.setDescription('puts the member to jail')
.addUserOption(option =>
option
.setName('target')
.setDescription('The member to arrest')
.setRequired(true))
.addStringOption(option =>
option
.setName('reason')
.setDescription('The reason for arrest'))
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
async execute(interaction) {
const messageEmbed = new EmbedBuilder()
.setTitle('ARRESTED!')
.setDescription(`***${interaction.options.getUser('target').tag}*** *broke a leg. Oops.*`)
.setColor(0xBD7A21)
.setImage('https://eca.astrookai.repl.co/media/arrest.gif')
await interaction.reply({embeds: [ messageEmbed ]});
},
};
Sending a separate embed object to a different channel is intended for channel logging for moderation actions in the server and I would like to know how to achieve this, thank you.
You can use <channel>.send() for this. In which <channel> is your channel object. You can get the channel in a multiple of different ways but this is probably the easiest:
logChannel = <interaction>.guild.channels.fetch(SNOWFLAKE_ID)
Then, you can send your embed to the logchannel like so:
logChannel.send({ embeds: [YOUR_EMBED] });
To account for every command, the easiest way is to do this in your interactionCreate event
If you need more context, you can check out this example which "logs" an embed to the logChannel.
My goal is to have a file run every few minutes on a schedule(cron). The cron isn't the issue, the issue is when I try and retrieve the members, I get Collection(0) [Map] {} Which is odd, there are members and my intents are set correctly.
const dotenvFlow = require('dotenv-flow');
const { Client, Partials, GatewayIntentBits } = require('discord.js');
dotenvFlow.config();
// Create a new client instance
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildIntegrations, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.DirectMessageTyping, GatewayIntentBits.DirectMessages], partials: [Partials.Channel] });
// Get the guild object
async function updateMembers() {
console.log("Starting...")
const guild = await client.guilds.fetch(process.env.hostDiscordServer);
// Get the members of the guild
const members = guild.members.cache;
// Insert or update each member in the database
members.forEach(member => {
// Check if the member belongs to the specified guild
if (member.guild.id === guild.id) {
// Get the member's premium role
const pRole = member.roles.cache.find(role => [process.env.pPremiumRole1, process.env.pPremiumRole2, process.env.pPremiumRole3].includes(role.name))?.name;
console.log("Inserting into DB")
// Insert or update the member's record in the database
console.log(member.id)
console.log(pRole)
}
});
}
// Log in to Discord with your client's token
client.login(process.env.DISCORD_TOKEN);
// Start the code
updateMembers();
You are iterating through the cached members of the guild.
If you want to iterate through all members (even the uncached) you need to fetch them first.
You just need to replace
const members = guild.members.cache;
with
const members = await guild.members.fetch();
discord.js docs
EDIT: I would also recommend changing
updateMembers();
to
client.once("ready", updateMembers);
so that the code only runs when the bot ready.
(Thanks to #Zsolt Meszaros for correcting me on that one)
I'm trying to set up a welcome message function on my discord bot, but no matter what I do, the bot doesn't seem to be able to use guildMemberAdd. I'm aware of the new update, and as suggested I've turned on both options under Private Giveaway Intents. But it still does not work. Here is my code:
client.on('guildMemberAdd', member => {
const emb = new MessageEmbed()
.setColor('#FFBCC9')
.setTitle("new member")
.setDescription("welcome to the server!")
member.guild.channels.get('780902470657376298').send(emb);
});
I have also found an answer online suggesting to use this:
const { Client, Intents } = require("discord.js");
const client = new Discord.Client({ ws: { intents: new Discord.Intents(Discord.Intents.ALL) }});
But no matter how I write that, my bot just won't even come online unless I use const client = new Discord.Client(); with nothing in the parentheses.
With v12 coming along, in order to get your full channels list you're only able to get the cached ones in your server. Hence why you should change this line:
member.guild.channels.get('780902470657376298').send(emb);
to:
member.guild.channels.cache.get('780902470657376298').send(emb);
You passed in the intents params wrong. Here is the correct way to do it.
const { Client, Intents } = require("discord.js");
const client = new Discord.Client({ ws: { intents: ['GUILDS', 'GUILD_MESSAGES', 'GUILD_MEMBERS', 'GUILD_PRESENCES'] } });
If you use this the guildMemberAdd event will emit.
Make sure you have intents turned on in the developer portal. As Shown in this image https://i.imgur.com/WfBLtXY.png.
So I have this command that shows the riches users in a server this command worked yesterday however recently it has stopped working.
const { MessageEmbed } = require("discord.js");
const { stripIndents } = require("common-tags");
const { prefix } = require("../../botconfig.json");
const db = require('quick.db')
let bal = require('../../database/balance');
let rep = require('../../database/rep');
let work = require('../../database/works');
module.exports = {
config:{
name: "rich",
aliases: ["r"],
category: "currency",
description: "Tells who is rich",
usage: ""
},
run: async (client, message, args) => {
// Get all members of the server before doing anything
message.guild.members.fetch().then(guildMembers => {
let board = [];
for (let key of Object.keys(bal)) {
// Checks if the collection of GuildMembers contains the key.
if (guildMembers.has(key)) {
let value = Object.assign({user: guildMembers.get(key).user}, bal[key]);
board.push(value);
}
}
const emojis = [':first_place:', ':second_place:', ':third_place:', ':small_blue_diamond:', ':small_blue_diamond:']
board = board.sort((a,b) => b.balance-a.balance).splice(0, 5);
let top = board.map((x, i) => `${emojis[i]} **${x.balance.toLocaleString()}** - ${x.user.tag}`).join('\n');
let embed = new MessageEmbed()
.setColor("RANDOM")
.addField(`Richest users in **${message.guild.name}**`, `${top}`)
.setFooter('Switch Version 1.1');
return message.channel.send(embed);
}).catch(console.error)
}
}
The error code when the !rich command is used is as follows:
Guild_Members_Timeout: Members didn't arrive in time
I don't know if this is an issue within the bot or if it is an issue with discord.
Okay I have found the answer to my own problem it seems I needed to add intents to my discord bot to fetch the members.
All I did was add this line of code and it worked.
const intents = new Intents([
Intents.NON_PRIVILEGED, // include all non-privileged intents, would be better to specify which ones you actually need
"GUILD_MEMBERS", // lets you request guild members (i.e. fixes the issue)
]);
const client = new Client({ ws: { intents } });
None of my discord.js guildmember events are emitting, my user caches are basically empty, and my functions are timing out? . In this post it is explained in great detail and that helped me out a lot.TLDR:go to discord developer portal on your particular application ,go to bot , on bot permissions tick whatever is needed and copy the number.Then use this number as a constructor parameter for new Discord.Intents('insert the number here').This worked for me.
Im using the discordjs-commando and
client.setProvider(
sqlite.open(path.join(__dirname, 'settings.sqlite3')).then(db => new Commando.SQLiteProvider(db))
).catch(console.error);
is giving me this error
Error: sqlite: filename is not defined
Any idea how to make it work?
I think I know a way to fix it
client.setProvider(
sqlite.open({ filename: path.join(__dirname, 'settings.sqlite3')}).then(db => new Commando.SQLiteProvider(db))
).catch(console.error);
use this
Yo, so this reply is probably late asf. But, I got this working by doing the following:
// This line simply checks to see if my Node.js version is version 12.
// If it isn't, it then tells me to update Node.js
if (Number(process.version.slice(1).split(".")[0]) < 12) throw new Error("Node 12.0.0 or higher is required. Update Node on your system.");
// These are my imports
const { CommandoClient, Commando } = require('discord.js-commando');
const { promisify } = require("util");
const readdir = promisify(require("fs").readdir);
const Enmap = require("enmap");
const path = require('path');
require('./.eslintrc.json');
require('dotenv').config();// I used dotenv to store my more secure info
const TOKEN = process.env.CLIENT_TOKEN;// This line reads my Client Token from dotenv
const PREFIX = process.env.CLIENT_PREFIX;// This line reads my Client Prefix from dotenv
const OWNER_ID = process.env.OWNER;// This line reads the bot's owner id from dotenv
const init = async () => {// I crteated an async wrapper for my client here
const sqlite = require('sqlite');// I imported SQLite here
const client = await new CommandoClient({// I set my client here
commandPrefix: PREFIX,
owner: OWNER_ID,
disableEveryone: true,
unknownCommandResponse: false
});
client.setProvider(// This line of code sets my SQLite DB Provider
sqlite.open({ filename: path.join(__dirname, 'settings.sqlite3') }).then(db => new Commando.SQLiteProvider(db))
).then(console.log).catch(console.error);
// Since I'm wrapping my client in an async wrapper, my commands and groups are registered here
client.registry
.registerDefaultTypes()
.registerGroups([
['admin', 'Administration'],
['mod', 'Moderation'],
['util', 'Utility'],
['misc', 'Miscellaneous'],
['twitch', 'Twitch']
])
.registerDefaultGroups()
.registerDefaultCommands()
.registerCommandsIn(path.join(__dirname, 'commands'));
client.commands = new Enmap();// This sets a new Enmap for my commands
client.aliases = new Enmap();// This sets a new Enmap for my command aliases
client.settings = new Enmap({ name: "settings" });//This sets a new Enmap for my settings
client.logger = require("./modules/Logger.js");//This line makes my bot require the internal Logger.js file I have in my bot's modules folder
require("./modules/functions.js")(client);// This line makes my bot require the internal functions.js file I have in my bot's modules folder
const evtFiles = await readdir("./events/");
client.logger.log(`Loading a total of ${evtFiles.length} events.`);
evtFiles.forEach(file => {
const eventName = file.split(".")[0];
client.logger.log(`Loading Event: ${eventName}`);
const event = require(`./events/${file}`);
// Bind the client to any event, before the existing arguments
// provided by the discord.js event.
client.on(eventName, event.bind(null, client));
client.login(TOKEN).catch(console.error);// Since my client is in an async wrapper, I imported my TOKEN here
});
};
init();// Now that I've finished with the rest of my index.js file I have ended the async wrapper here
It may not be of much use to you anymore but I hope this helps others in the future.
client.setProvider(
sqlite.open({ filename: 'database.db', driver: sqlite3.Database }).then(db => new Commando.SQLiteProvider(db))
).catch(console.error);
This will fix it for sure