Auto role when someone is playing? - javascript

I'm trying to get my bot to automatically add someone to a role when they start a game, and remove it from that role when they leave the game.
I have already tried several things but without success :
Some other bot change activity but I do not want the other bots of my server to be added in the role so I did that (and it seems to work):
let roleid = "ROLE BOT ID"
if (newMember.roles.has(roleid)) {}
else {console.log("my code here")}
I have the impression that discord.js "gathers" people who play a game (on desktop) and people connected to mobile. So I try to separate them like that but the "! =" does not seem to work :
if (newMember.presence.clientStatus = 'desktop') {console.log("my code here")}
Then I have one last problem is that my bot adds me to the role when I leave my game
Here is my whole code
client.on('presenceUpdate', (oldMember, newMember) => {
let guildChannels = newMember.guild;
let roleid = "ROLE BOT ID"
if (newMember.roles.has(roleid)) {}
else {
if (newMember.presence.clientStatus = 'desktop') {
if (newMember.presence.ActivityType = 'PLAYING') {
newMember.addRole(newMember.guild.roles.find (x => x.id == 'PLAYING ROLE ID'))
console.log(newMember.user.tag + ' -> "ROLE PLAYING NAME"')
}
else {newMember.removeRole(newMember.guild.roles.find (x => x.id == 'PLAYING ROLE ID'))
console.log(newMember.user.tag + ' / "ROLE PLAYING NAME"')
}
}
}
});
I'd like my bot to add all the people playing a role, and delete them when they're done playing
I do not have an error message only that my bot is not doing exactly what I want and I do not have an explanation

if (newMember.presence.clientStatus = 'desktop') {console.log("my code here")}
if (newMember.presence.ActivityType = 'PLAYING') {
The reason these pieces of code don't work is because you're using the assignment operator = instead of a comparison operator like === or ==. Essentially, the code is setting the properties instead of comparing them.
Use comparison operators to check the values of properties, not assignment operators.
Presence.ActivityType is not a valid property of Presence.
Check the user's game (Presence.game) to see if they're playing something.
Some other bot change activity but I do not want the other bots of my server to be added in the role...
Check if a User is a bot with the User.bot property.
If a user changes their status (i.e. Online --> DND) or starts listening to music, watching a stream, etc., your code will be executed even though their game has not changed.
You need to check the old presence and compare it with the new presence to make sure the user started or stopped playing a game.
You aren't catching any rejected Promises.
Use try...catch statements or attach catch() methods to Promises.
Code
client.on('presenceUpdate', (oldMember, newMember) => {
const guild = newMember.guild;
const playingRole = guild.roles.find(role => role.id === 'PLAYING ROLE ID');
if (newMember.user.bot || newMember.presence.clientStatus === 'mobile' || oldMember.presence.status !== newMember.presence.status) return;
const oldGame = oldMember.presence.game && [0, 1].includes(oldMember.presence.game.type) ? true : false;
const newGame = newMember.presence.game && [0, 1].includes(newMember.presence.game.type) ? true : false;
if (!oldGame && newGame) { // Started playing.
newMember.addRole(playingRole)
.then(() => console.log(`${playingRole.name} added to ${newMember.user.tag}.`))
.catch(console.error);
} else if (oldGame && !newGame) { // Stopped playing.
newMember.removeRole(playingRole)
.then(() => console.log(`${playingRole.name} removed from ${newMember.user.tag}.`))
.catch(console.error);
}
});

Related

discord.js v13 TypeError: Cannot read properties of undefined (reading 'presence')

I'm trying to make a joke command with my friends to ban people who are playing Roblox or if he has the Roblox game status. I've searched everything in the internet and in stack overflow if there's a solution but I can't find a single working one. Here's my code:
module.exports = async (client) => {
const guild = client.guilds.cache.get('877016354581004389');
if(guild){
setInterval(async () => {
if(!guild.me.permissions.has('ADMINISTRATOR')) return;
const channel = guild.channels.cache.get('877016354581004392');
if(!channel) return console.log('ANNOUNCEMENT CHANNEL NOT FOUND...')
let bannedAmount = 0;
await guild.members.fetch().then(members => {
members.forEach(member => {
for(const allMember of Object.keys(member)){
if(allMember.user.presence.activities){
const activity = allMember.user.presence.activities[0]
if(activity.name.toLowerCase() == "roblox"){
channel.send(`${allMember} got banned because he's playing ROBLOX!!`)
allMember.ban({ reason: `he played roblox lol`});
bannedAmount = bannedAmount + 1
break;
}
}
}
})
});
let members;
if(bannedAmount > 1) members = 'members';
let kid;
if(bannedAmount > 1) kid = 'kids';
if(bannedAmount <= 0 || null){
console.log(`No member banned for playing Roblox...`);
} else if(bannedAmount > 0) {
channel.send(`${bannedAmount} ${kid || 'kid'} got banned in this server for playing Roblox. Don't do it kids!`)
console.log(`${bannedAmount} ${members || 'member'} got banned for playing Roblox...`)
}
}, 20000);
}
}
I have no hate with the game Roblox guys just fooling around lol
PS: I have already enabled intents in both discord dev website and also in the index.js file and also had used <member>.presence.activities but it looks like only user has presence property.
Well, the problem is that GuildMember#presence returns or a Presence class OR undefined, because it's an optional property. What you do in your code is taking the presence property of a user who probably doesn't has any presence and that's why allMember.user.presence returns undefined and allMember.user.presence.activities[0] too. Also keep in mind that you take the User of a member, but presences go on GuildMembers and not on Users.
Debugging:
Just use allMember instead of allMember.user, so u take the presence of a GuildMember instead of a User, after this a Member who has a presence will return the presence data too.
Add a if statement that controls if a member has a presence or not, so you don't run in the same error again.
I don't know if you tought about this, but if a member has more than one presence and the first presence in the array isn't Roblox, but for example the second presence in the array is Roblox the member won't get banned.
I hope this helps you, if you have questions just contact me on Discord
~ Iliannnn#0001

Doesn't create the voice channel with no error

I am trying to build a bot with the discord.js library in node.js that will create a new voice channel in a certain category when a user joins a certain channel. After the creation of the channel, I want the bot to then move the user to the new channel!
I am trying the following code:
var temporary = [];
client.on('voiceStateUpdate', async (oldMember, newMember) => {
const mainCatagory = '815281015207624704';
const mainChannel = '814938402137833484';
if (newMember.voiceChannelID == mainChannel) {
await newMember.guild
.createChannel(`📞 ┋ Support Room`, { type: 'voice', parent: mainCatagory })
.then(async (channel) => {
temporary.push({ newID: channel.id, guild: newMember.guild.id });
await newMember.setVoiceChannel(channel.id);
});
}
if (temporary.length >= 0)
for (let i = 0; i < temporary.length; i++) {
let ch = client.guilds
.find((x) => x.id === temporary[i].guild)
.channels.find((x) => x.id === temporary[i].newID);
if (ch.members.size <= 0) {
await ch.delete();
return temporary.splice(i, 1);
}
}
});
The code comes with no error but doesn't create the voice channel!
The problem is that you are using discord.js v12, but your code is made for v11.
Client#voiceStateUpdate now passes VoiceStates as parameters, not GuildMembers. You should rename newMember and oldMember to newState and oldState respectively.
GuildMember#voiceChannelID is a deprecated property, which is why you don't get any errors. Your code never actually gets past the if statement. It has turned into GuildMember#voice#channelID (newState.channelID).
Guild#createChannel is also deprecated, being replaced with Guild#channels#create. The function still looks and acts the same, so you only need to change the name (newState.guild.channels.create).
GuildMember#setVoiceChannel has turned into GuildMember#voice#setChannel (newState.setChannel)
Client#guilds#find has turned into Client#guilds#cache#find (client.guilds.cache.find)
Guild#channels#find has turned into Guild#channels#cache#find (client.cache.find(...).channels.cache.find)
(As a side note, always use Collection#get instead of Collection#find when searching by IDs. .find((value) => value.id === '...') should always be converted to simply .get('...'). This also applies to switching Collection#some with Collection#has)
Guild#members#size has turned into Guild#members#cache#size (ch.members.cache.size)
Every single one of these deprecations occurred as a result of discord.js switching to a Manager/caching system. For example, Client#guilds now returns a GuildManager instead of a collection.
More information about switching from v11 to v12 (including Managers)

How do I make my discord bot send a message when a specific user plays a specific game?

I want to add a code to my bot where it will send a message when a specific user plays a specific game (i.e. Left 4 Dead 2). How do I do that? I don't want any commands anymore.
// Game Art Sender //
if (message.channel.id === '573671522116304901') {
if (msg.includes('!L4D2')) { // THIS is what I want to change.
message.channel.send('***[MATURE CONTENT]*** **Joining Game:**', {
files: [
"https://cdn.discordapp.com/attachments/573671522116304901/573676850920947733/SPOILER_l4d2.png"
]
});
}
});
Try this
if(GuildMember.username === 'Specific_Username_here')
if(GuildMember.presence.game === 'Specific_Game_here')
// do whatever here
GuildMember.id could also be used if you know that user's specific id string. I haven't tested this myself and I'd have rather posted this as a comment, but I don't have that permission yet.
To send a message to a specific channel, use this:
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE')
channel.send("MESSAGE GOES HERE")
or
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE')
channel.send(VARIABLE_GOES_HERE)
Summing it up, your code should be something like this:
if(GuildMember.username === 'Specific_Username_here')
if(GuildMember.presence.game === 'Specific_Game_here') {
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE)
channel.send("MESSAGE GOES HERE")
}
So I just figured it out. It was a long journey to figuring this one out.
Here's the code:
// Game Detector \\
client.on("presenceUpdate", (oldMember, newMember) => {
if(newMember.id === '406742915352756235') {
if(newMember.presence.game.name === 'ROBLOX') { // New Example: ROBLOX
console.log('ROBLOX detected!');
client.channels.get('573671522116304901').send('**Joining Game:**', {
files: [
"https://cdn.discordapp.com/attachments/567519197052272692/579177282283896842/rblx1.png"
]
});
}
}
});
However, I need one more problem solved:
It says "null" when I close the application.
How do I fix this?

How to send message in Discord.js event "guildCreate"

I have been wondering how can I send messages when someone invites my bot to their server.
Please help me in this area I can't figure it out it's there in Python but I have not used to it.
Thank you for your help
All the above answers assume you know something about the server and in most cases you do not!
What you need to do is loop through the channels in the guild and find one that you have permission to text in.
You can get the channel cache from the guild.
Take the below example:
bot.on("guildCreate", guild => {
let defaultChannel = "";
guild.channels.cache.forEach((channel) => {
if(channel.type == "text" && defaultChannel == "") {
if(channel.permissionsFor(guild.me).has("SEND_MESSAGES")) {
defaultChannel = channel;
}
}
})
//defaultChannel will be the channel object that the bot first finds permissions for
defaultChannel.send('Hello, Im a Bot!')
});
You can of course do further checks to ensure you can text before texting but this will get you on the right path
Update discord.js 12+
Discord.JS now uses cache - here is the same answer for 12+
bot.on("guildCreate", guild => {
let found = 0;
guild.channels.cache.map((channel) => {
if (found === 0) {
if (channel.type === "text") {
if (channel.permissionsFor(bot.user).has("VIEW_CHANNEL") === true) {
if (channel.permissionsFor(bot.user).has("SEND_MESSAGES") === true) {
channel.send(`Hello - I'm a Bot!`);
found = 1;
}
}
}
}
});
})
You can simply send the owner for example a message using guild.author.send("Thanks for inviting my bot");
Or you can also send a message to a specific user:
client.users.get("USER ID").send("My bot has been invited to a new server!");
I'm not sure if you're using a command handler or not since you seem new to JS I'm going to assume you're not. The following is a code snippet for what you're trying to do:
client.on('guildCreate', (guild) => {
guild.channels.find(t => t.name == 'general').send('Hey their Im here now!'); // Change where it says 'general' if you wan't to look for a different channel name.
});

discord.js spam command troubles

bot.on('message', message => {
if (message.content === 'spam') {
message.channel.send('spam');
while (message.channel.send('spam')) {
if (message.content === 'stop spam') {
return message.channel.send('stopped');
}
}
}
});
im still fairly new to javascript so im not sure if this is even possible the way ive been trying to do it ive looked through w3schools developers.mozilla and even a few questions that are already on here; ive tried using do while, and for loops and ive tried multiple versions of the code i have up there
the ultimate goal is if a user sends the word 'spam' the bot should continuously send the word 'spam' and keep doing so till the bot is turned off or a user sends the words 'stop spam'
Here are some things you should know about the code you're working with:
message.channel.send returns a Promise, so you can't put that in a while loop, because you need to have something that is true or false (a Boolean).
Right now you're trying to check if a message's content is equal to 'stop spam' while you're inside the if-statement checking if the content is equal to 'spam' - So you'll never get inside the inner if-statement.
I would recommend practicing basic javascript a bit more, then moving to Node.js, then coming back to Discord.js - However, it might be cool for you to see a spammer work, so I wrote a some spam code you could use - check this out:
First, create a new file named spamCtrl.js that looks like this (see comments in code for descriptions of what's going on):
let spamming = false;
let spamChannel = undefined;
// spam function repeats until variable spamming is false
function spam() {
return new Promise((resolve, reject) => {
// add check to make sure discord channel exists
if (!spamChannel)
reject('Channel is undefined!');
// send message on spam channel
spamChannel.send('spam')
.then(msg => {
// wait 100 ms until sending next spam message
setTimeout(() => {
// continue spamming if spamming variable is true
if (spamming) {
spam()
.then(resolve) // not entirely necessary, but good practice
.catch(console.log); // log error to console in case one shows up
}
// otherwise, just resolve promise to end this looping
else {
resolve();
}
}, 100)
})
.catch(console.log);
});
}
// public functions that will be used in your index.js file
module.exports = {
// pass in discord.js channel for spam function
setChannel: function(channel) {
spamChannel = channel;
},
// set spam status (true = start spamming, false = stop spamming)
setStatus: function (statusFlag) {
// get current status
let currentStatus = spamming;
// update spamming flag
spamming = statusFlag;
// if spamming should start, and it hasn't started already, call spam()
if (statusFlag && currentStatus != statusFlag) {
spam();
}
},
// not used in my commands, but you may find this useful somewhere
getStatus: function() {
return spamming;
}
};
Next, import that file into your index.js file (Must be in the same directory as your spamCtrl.js file - unless you change the require statement below).
// in index.js file, get controller for spam messages
let spamCtrl = require('./spamCtrl');
Final step: In your index.js file (or wherever you're handling your spam commands) set up your commands (this can be renamed as you like):
// 2 commands together make spamming work :)
case '?SPAM':
spamCtrl.setChannel(message.channel);
spamCtrl.setStatus(true);
break;
case '?STOP-SPAM':
spamCtrl.setStatus(false);
break;
Let me know if you would like any additional explanations on anything, or if you want to see some tweaks here 'n there.
Try using a variable instead. You cannot use message.channel.send('spam') for the while loop.
var spam = false;
if (message.content === 'spam') {
if (message.author.id !== bot.user.id) { // Replace bot with the instance of your bot Client.
spam = true;
} else {
if(spam) {
message.channel.send('spam');
}
}
if (message.content === 'stop spam') {
if(spam) {
message.channel.send('stopped');
}
spam = false;
}
}

Categories

Resources