So i am coding a bot , in Node.js with Visual Studio Code. I want to have a channel, that when a user joins the guild , will send 'Welcome user and invited by thisuser(Total Invites: 5)
The code is :
module.exports = (client) => {
const invites = {} // { guildId: { memberId: count } }
const getInviteCounts = async (guild) => {
return await new Promise((resolve) => {
guild.fetchInvites().then((invites) => {
const inviteCounter = {} // { memberId: count }
invites.forEach((invite) => {
const { uses, inviter } = invite
const { username, discriminator } = inviter
const name = `${username}#${discriminator}`
inviteCounter[name] = (inviteCounter[name] || 0) + uses
})
resolve(inviteCounter)
})
})
}
client.guilds.cache.forEach(async (guild) => {
invites[guild.id] = await getInviteCounts(guild)
})
client.on('guildMemberAdd', async (member) => {
const { guild, id } = member
const invitesBefore = invites[guild.id]
const invitesAfter = await getInviteCounts(guild)
console.log('BEFORE:', invitesBefore)
console.log('AFTER:', invitesAfter)
for (const inviter in invitesAfter) {
if (invitesBefore[inviter] === invitesAfter[inviter] - 1) {
const channelId = '731801004462571602'
const channel = guild.channels.cache.get(channelId)
const count = invitesAfter[inviter]
channel.send(
`Please welcome <#${id}> to the Discord! Invited by ${inviter} (${count} invites)`
)
invites[guild.id] = invitesAfter
return
}
}
})
}
This code works perfectly with console but i am facing a problem,never post the message in the channel!
The message might not be being sent because of the channel ID double check you are using the right channel ID and you might want to try changing
const channel = guild.channels.cache.get(channelId) to this
const channel = client.channels.cache.get(channelId)
Related
so what I am trying to do is when a user write a command such as
!setchannel #test or !setchannel 86xxxxxxxxxxxxxxx
then the bot will send the random messages to that channel every certain time.
Note that I did the random messages code but I still stuck on creating the !setchannel command.
I am using discord.js v12.5.3
index.js main file
require('events').EventEmitter.prototype._maxListeners = 30;
const Discord = require('discord.js')
const client = new Discord.Client()
require('discord-buttons')(client);
const ytdl = require('ytdl-core');
const config = require('./config.json')
const mongo = require('./mongo')
const command = require('./command')
const loadCommands = require('./commands/load-commands')
const commandBase = require('./commands/command-base')
const { permission, permissionError } = require('./commands/command-base')
const cron = require('node-cron')
const zkrList = require('./zkr.json')
const logo =
'URL HERE'
const db = require(`quick.db`)
let cid;
const { prefix } = config
client.on('ready', async () => {
await mongo().then((mongoose) => {
try {
console.log('Connected to mongo!')
} finally {
mongoose.connection.close()
}
})
console.log(`${client.user.tag} is online`);
console.log(`${client.guilds.cache.size} Servers`);
console.log(`Server Names:\n[ ${client.guilds.cache.map(g => g.name).join(", \n ")} ]`);
loadCommands(client)
cid = db.get(`${message.guild.id}_channel_`)
cron.schedule('*/10 * * * * *', () => {
const zkrRandom = zkrList[Math.floor(Math.random() * zkrList.length)]
const zkrEmbed = new Discord.MessageEmbed()
.setDescription(zkrRandom)
.setAuthor('xx', logo)
.setColor('#447a88')
client.channels.cache.get(cid).send(zkrEmbed);
})
client.on("message", async message => {
if (message.author.bot) {
return
}
try {if (!message.member.hasPermission('ADMINISTRATOR') && message.content.startsWith('!s')) return message.reply('you do not have the required permission') } catch (err) {console.log(err)}
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).trim().split(/ +/g)
const cmd = args[0]
if (cmd === "s") {
let c_id = args[1]
if (!c_id) return message.reply("you need to mention the text channel")
c_id = c_id.replace(/[<#>]/g, '')
const channelObject = message.guild.channels.cache.get(c_id);
if (client.channels.cache.get(c_id) === client.channels.cache.get(cid)) return message.reply(`we already sending to the mentioned text channel`);
if (client.channels.cache.get(c_id)) {
await db.set(`${message.guild.id}_channel_`, c_id); //Set in the database
console.log(db.set(`${message.guild.id}_channel_`))
message.reply(`sending to ${message.guild.channels.cache.get(c_id)}`);
cid = db.get(`${message.guild.id}_channel_`)
const zkrRandom = zkrList[Math.floor(Math.random() * zkrList.length)]
const zkrEmbed = new Discord.MessageEmbed()
.setDescription(zkrRandom)
.setAuthor('xx', logo)
.setColor('#447a88')
client.channels.cache.get(cid).send(zkrEmbed);
} else {
return message.reply("Error")
}
}
})
})
client.login(config.token)
zkr.json json file
[
"message 1",
"message 2",
"message 3"
]
You'll have to use a database to achieve what you're trying to do
An example using quick.db
const db = require(`quick.db`)
const prefix = "!"
client.on("message", async message => {
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).trim().split(/ +/g)
const cmd = args[0]
if (cmd === "setchannel") {
let c_id = args[1]
if (!c_id) return message.reply("You need to mention a channel/provide id")
c_id = c_id.replace(/[<#>]/g, '')
if (client.channels.cache.get(c_id)) {
await db.set(`_channel_`, c_id) //Set in the database
} else {
return message.reply("Not a valid channel")
}
}
})
Changes to make in your code
client.on('ready', async () => {
let c_id = await db.get(`_channel_`)
cron.schedule('*/10 * * * * *', () => {
const zkrRandom = zkrList[Math.floor(Math.random() * zkrList.length)]
const zkrEmbed = new Discord.MessageEmbed()
.setTitle('xx')
.setDescription(zkrRandom)
.setFooter("xx")
.setColor('#447a88')
.setAuthor('xx#8752')
client.channels.cache.get(c_id).send(zkrEmbed)
})
})
The above sample of quick.db is just an example
If you're using repl.it, I recommend you to use quickreplit
Edit
require('events').EventEmitter.prototype._maxListeners = 30;
const Discord = require('discord.js')
const client = new Discord.Client()
const ytdl = require('ytdl-core');
const config = require('./config.json')
const mongo = require('./mongo')
const command = require('./command')
const loadCommands = require('./commands/load-commands')
const commandBase = require('./commands/command-base')
const cron = require('node-cron')
const zkrList = require('./zkr.json')
const db = require(`quick.db`)
const prefix = "!"
let cid;
client.on('ready', async () => {
await mongo().then((mongoose) => {
try {
console.log('Connected to mongo!')
} finally {
mongoose.connection.close()
}
})
console.log(`${client.user.tag} is online`);
console.log(`${client.guilds.cache.size} Servers`);
console.log(`Server Names:\n[ ${client.guilds.cache.map(g => g.name).join(", \n ")} ]`);
cid = db.get('_channel_')
loadCommands(client)
//commandBase.listen(client);
})
cron.schedule('*/10 * * * * *', () => {
const zkrRandom = zkrList[Math.floor(Math.random() * zkrList.length)]
const zkrEmbed = new Discord.MessageEmbed()
.setTitle('xx')
.setDescription(zkrRandom)
.setFooter("xx")
.setColor('#447a88')
.setAuthor('xx#8752')
client.channels.cache.get(cid).send(zkrEmbed);
})
client.on("message", async message => {
console.log(db.get('_channel_'))
if (!message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).trim().split(/ +/g)
const cmd = args[0]
if (cmd === "s") {
let c_id = args[1]
if (!c_id) return message.reply("You need to mention a channel/provide id")
c_id = c_id.replace(/[<#>]/g, '')
if (client.channels.cache.get(c_id)) {
console.log('old channel')
console.log(db.get('_channel_'))
await db.set(`_channel_`, c_id); //Set in the database
message.reply(`sending in this channel ${message.guild.channels.cache.get(c_id)}`);
} else {
return message.reply("Not a valid channel")
}
}
})
All I want is my bot saying the name of the person who joined the vocal. I want my bot to "read" a string.
Here is my code:
const Discord = require('discord.js');
const say = require('say')
const bot = new Discord.Client();
require("dotenv").config()
let prefix = "!"
// officiel test
let global = /*"276150994189025302"*/ "847683020928450590"
bot.on("ready", () => {
console.log("Bot online!")
})
bot.on("message", (message) => {
if(message.author.bot) return
if(!message.content.startsWith(prefix)) return
let MessageArray = message.content.split(" ")
let cmd = MessageArray[0].slice(prefix.length)
let args = MessageArray.slice(1)
let globalchan = message.guild.channels.cache.get(global)
if(cmd == "ping") {
globalchan.send("Pong")
}
})
bot.on("voiceStateUpdate", async (oldMember, newMember) => {
if(newMember.member.user.bot) return
if(newMember.channelID == null) {
let channel = bot.channels.cache.get(oldMember.channelID)
channel.leave()
}else{
newMember.member.voice.channel.join()
}
})
bot.on("guildMemberSpeaking", (member, state) => {
if(member.user.bot) return
if(state.bitfield == 1) {
console.log("parle")
say.speak(member.user.username)
}
})
I am making a Discord Bot that informs Moderators when a user joins a specific voice channel. The Bot is supposed to also have a spam protection that the bot will only log a message once per minute per user.
This is what I have tried before:
const { Client } = require("discord.js");
const { config } = require("dotenv");
const fs = require('fs');
const client = new Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION']
});
config({
path: __dirname + "/.env"
})
var supportchannel = '827574015526567947'
var dutychannel = '847445933969113118'
var ondutyrole = '847447374925398016'
client.on("ready", () => {
console.log(`Hi, ${client.user.username} is now online!`);
global.timer = 0;
client.user.setStatus('online');
client.user.setActivity('me getting developed', { type: "WATCHING"})
.then(presence => console.log('status set'))
.catch(console.error);
});
client.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.channelID;
let oldUserChannel = oldMember.channelID;
if(newUserChannel === supportchannel)
{
if (timer == 0){
timer = 1
setTimeout(() => {
timer = 0
}, 60000);
const Userfm = client.users.cache.get(newMember.id);
if (Userfm) {
const channelfx = client.channels.cache.get(dutychannel)
let roleId = ondutyrole
channelfx.send(`<#&${roleId}> **${Userfm.tag}** requires Support`);
}
}else{
return;
}
}
console.log("User joined vc with id "+newUserChannel)
});
client.login(process.env.TOKEN);
This doesn't work the way intended because the cooldown is not separate for every user but sets a countdown that blocks every user from getting the Moderator's attention for 60 seconds (the users all share a cooldown).
I thought that the code ran asynchronously for every user.
The same goes for this code in which I made use of the wait-sync npm library:
const { Client } = require("discord.js");
const { config } = require("dotenv");
const fs = require('fs');
const waitSync = require('wait-sync');
const client = new Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION']
});
config({
path: __dirname + "/.env"
})
var supportchannel = '827574015526567947'
var dutychannel = '847445933969113118'
var ondutyrole = '847447374925398016'
client.on("ready", () => {
console.log(`Hi, ${client.user.username} is now online!`);
global.timer = 0;
client.user.setStatus('online');
client.user.setActivity('me getting developed', { type: "WATCHING"})
.then(presence => console.log('status set'))
.catch(console.error);
});
client.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.channelID;
let oldUserChannel = oldMember.channelID;
if(newUserChannel === supportchannel)
{
const Userfm = client.users.cache.get(newMember.id);
if (Userfm) {
const channelfx = client.channels.cache.get(dutychannel)
let roleId = ondutyrole
channelfx.send(`<#&${roleId}> **${Userfm.tag}** requires Support`);
waitSync(60);
}
}
console.log("User joined vc with id "+newUserChannel)
});
client.login(process.env.TOKEN);
If you know how to solve this problem please let me know.
Thanks in advance ;)
What you can do is probably to have some sort of mapping that keeps track of the timer for each user and have the user IDs be the keys:
const timers = {};
client.on('voiceStateUpdate', (oldMember, newMember) => {
...
// If we don't have any timer set for this user, go ahead and set it
if (!timers[newMember.id]) {
timers[newMember.id] = 1;
setTimeout(() => {
// Delete the timer from the mapping
delete timers[newMember.id];
}, 60000);
...
I made a bot that verifies people with API and stores the data in mongoose but I want the code to work in discord DMS but I have no clue how to make it give roles in a specific server when the command is run in DMS this is my code:
const fetch = require('node-fetch')
const ignSchema = require('../schemas/ign-schema')
const mongo = require('../mongo')
module.exports = {
commands: ['verifyme'],
minArgs: 0,
maxArgs: null,
expectedArgs: "<minecraft name>",
callback: async(message, arguments, text) => {
const playerName = arguments.join(' ')
fetch(`https://api.hypixel.net/player?key=MYAPIKEY&name=${playerName}`)
.then(response => response.json())
.then(async data => {
player = data
const target = message.author
const author2 = message.author.tag
const uuid = data["player"]["uuid"]
const discordid = data["player"]["socialMedia"]["links"]["DISCORD"]
let verifyRole = message.guild.roles.cache.find(role => role.name === '[Verified]');
let memberTarget = message.guild.members.cache.get(target.id);
const guildId = message.guild.id
const userId = message.author.id
const UUID = uuid
const _id = UUID
if (discordid == author2) {
await mongo().then(async mongoose => {
try {
const results2 = await ignSchema.findOne({
_id,
})
const {
UUID,
userData,
discordName
} = results2
if (UUID == uuid) {
if (author2 == discordName) {
if (message.member.roles.cache.some(role => role.name === "[Verified]")) {
message.reply('you are already verified')
} else {
memberTarget.roles.add(verifyRole)
message.reply('welcome back')
}
} else {
message.reply(`you already used this minecraft account to verify ${discordName}, if you want to change this please contact <#390929478790152192>`)
mongoose.connection.close()
return
}
} else {}
} catch {
const userData = {
timestamp: new Date().getTime(),
}
await mongo().then(async(mongoose) => {
try {
await ignSchema.findOneAndUpdate({
_id
}, {
UUID,
discordName: author2,
HypixelName: playerName,
userId: userId,
guildId: guildId,
$push: {
userData: userData
},
}, {
upsert: true
})
memberTarget.roles.add(verifyRole)
message.reply('you are succesfully verified')
} finally {
mongoose.connection.close()
}
})
}
})
} else {
message.reply(`change your linked discord account in hypixel from ${discordid} to ${author2},`)
}
console.log(`${discordid}`)
})
},
}
and this is the error I get:
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'roles' of null
If there is more than one server the bot is in, this is not possible without making major assumptions as to the guild they are in.
If there is only one server, message.guild.roles can be changed to client.guilds.cache.get('your_servers_id').roles.
How do I make it so that when someone reacts with the first emoji in this command, the bot deletes the message and sends it to another channel?
Current Code:
const Discord = require("discord.js");
module.exports.run = async (bot, message, args) => {
if (!message.member.hasPermission("MANAGE_MESSAGES"))
return message.channel.send("You are not allowed to run this command.");
let botmessage = args.join(" ");
let pollchannel = bot.channels.cache.get("716348362219323443");
let avatar = message.author.avatarURL({ size: 2048 });
let helpembed = new Discord.MessageEmbed()
.setAuthor(message.author.tag, avatar)
.setColor("#8c52ff")
.setDescription(botmessage);
pollchannel.send(helpembed).then(async msg => {
await msg.react("715383579059945512");
await msg.react("715383579059683349");
});
};
module.exports.help = {
name: "poll"
};
You can use awaitReactions, createReactionCollector or messageReactionAdd event, I think awaitReactions is the best option here since the other two are for more global purposes,
const emojis = ["715383579059945512", "715383579059683349"];
pollchannel.send(helpembed).then(async msg => {
await msg.react(emojis[0]);
await msg.react(emojis[1]);
//generic filter customize to your own wants
const filter = (reaction, user) => emojis.includes(reaction.emoji.id) && user.id === message.author.id;
const options = { errors: ["time"], time: 5000, max: 1 };
msg.awaitReactions(filter, options)
.then(collected => {
const first = collected.first();
if(emojis.indexOf(first.emoji.id) === 0) {
msg.delete();
// certainChannel = <TextChannel>
certainChannel.send(helpembed);
} else {
//case you wanted to do something if they reacted with the second one
}
})
.catch(err => {
//time up, no reactions
});
});