I am creating a node.js bot to track how long users have been on a game for. When I run this code sometimes the bot throws an error UnhandledPromiseRejectionWarning: MongoError: Cannot use a session that has ended
I can't see unreachable code or a session that is disconnected before everything has a chance to run. Here is my entire code for the function on a discord presence update:
const mongo = require('./mongo');
const exposeSchema = require('./schemas/expose-schema');
const { general } = require('./config.json');
module.exports = async client => {
client.on('presenceUpdate', async (oldPresence, newPresence) => {
const username = newPresence.user.username;
const guild = newPresence.guild.id;
console.log('Presence update detected:');
console.log(`Guild ID: ${guild} \nUser ID: ${newPresence.user.id} \nUsername: ${username}`);
await mongo().then(async mongoose => {
try {
await exposeSchema.where({ guildid: guild, username: username }).findOne(async function(err, sent) {
if (err) {
console.log(err);
}
if (sent == null) {
console.log('Writing to database');
await exposeSchema({
guildid: guild,
username: username,
sent: false,
}).save();
}
else if (sent.sent == false) {
const act = await newPresence.activities.find(activity => activity.timestamps != null);
if (act) {
const n = new Date();
const g = act.timestamps.start;
const hours = Math.abs(n - g) / 36e5;
if (hours >= 4) {
await exposeSchema.findOneAndUpdate({
guildid: guild,
username: username,
}, {
guildid: guild,
username: username,
sent: true,
}, {
upsert: true,
});
console.log(`${newPresence.user.username} has been playing ${act.name} for ${Math.round(hours)} hours, time to wrap it the fuck up and go outside or get some sleep.`);
if (newPresence.member.nickname == null) {
await client.channels.cache.get(general).send(`${newPresence.user.username} has been playing ${act.name} for ${Math.round((hours) * 100) / 100} hours, time to wrap it the fuck up and go outside or get some sleep.`);
}
else {
await client.channels.cache.get(general).send(`${newPresence.user.nickname} has been playing ${act.name} for ${Math.round((hours) * 100) / 100} hours, time to wrap it the fuck up and go outside or get some sleep.`);
}
}
}
}
});
}
finally {
mongoose.connection.close();
}
});
});
};
Related
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
I was coding a leveling system for my discord bot, but encountered a mongoerror on the way, does anyone know why this is occuring? (The addXp function runs whenever someone chatted, the error is logged in the removeTimeout function.) I have used mongoose in many more ways in my code but this hasn't yet occured before, I also did find others' issues with this error but found no fitting solution there.
async function removeTimeout(leveldataid) {
console.log("removetimeout")
await mongo().then(async (mongoose) => {
try {
await levelSchema.findByIdAndUpdate(
leveldataid,
{
_id: leveldataid,
oncooldown: false
},
{upsert: true}
)
} catch(err) {
console.log(err)
} finally {
mongoose.connection.close()
}
})
}
async function addXP(member, guild) {
let data = undefined
let changedleveldata = false
await mongo().then(async (mongoose) => {
try {
data = await levelenabledSchema.findById(guild.id)
if (data) {
if (data.enabled == true) {
let extraxp = Math.floor(Math.random() *20) + 15
let leveldata = await levelSchema.findById(`guild${guild.id}member${member.id}`)
if (!leveldata) {
await levelSchema.findByIdAndUpdate(
`guild${guild.id}member${member.id}`,
{
_id: `guild${guild.id}member${member.id}`,
guild: guild.id,
level: 1,
maxXp: 113,
xp: extraxp,
oncooldown: true
},
{upsert: true}
)
} else {
if (leveldata.oncooldown == false) {
let newlevel = leveldata.level
let newMaxXp = leveldata.maxXp
newMaxXp = Math.floor(newMaxXp)
let xp = leveldata.xp
xp +=extraxp
if (xp > leveldata.maxXp) {
xp -=Math.floor(100*1.135**newlevel)
newlevel++
newMaxXp = 100*1.13**newlevel
}
await levelSchema.findByIdAndUpdate(
`guild${guild.id}member${member.id}`,
{
level: newlevel,
maxXp: newMaxXp,
xp: xp,
oncooldown: true
},
{upsert: true}
)
}
}
}
}
changedleveldata = true
} catch(err) {
console.log(err)
} finally {
mongoose.connection.close()
}
if (changedleveldata == true) {
setTimeout(remoteTimeout(`guild${guild.id}member${member.id}`), 60000)
}
})
}
This basically means the connection between node server and mongoDB was interrupted while writing data.
The solution to your problem would be to remove the finally block from your code because it interrupts the connection when the bot is being used by a lot of users and the bot tries to write data while a previous connection is being closed.
await mongo().then(async (mongoose) => {
try { // code here
} catch(e) { console.log(e); }
});
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.
I have been trying to make a function where I tell the bot what channel to deploy the points system in. I am also using MongoDB so that when my bot restarts, it remembers what channel the points system was set in. However, I am getting errors such as 404: Not Found and it does not even update the schema, so as a result, I am looking for available solutions. Here's my code:
const {
prefix,
} = require('./config.json')
const Discord = require('discord.js')
var date = new Date().toLocaleString();
module.exports = (client) => {
const Mongo = require('mongoose')
const LeaderboardSequence = require('./leaderboard.js')
const SLSchema = require('./setLeaderboard.js')
const mongoose = require('mongoose')
mongoose.connect('insert URL here', {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
});
client.on('message', async message => {
if (message.content === `${prefix}setLeaderboardChannel`) {
// Destructure the guild and channel properties from the message object
const { guild, channel } = message
// Use find one and update to either update or insert the
// data depending on if it exists already
await SLSchema.findOneAndUpdate(
{
_id: guild.id,
},
{
_id: guild.id,
channelId: channel.id,
},
{
upsert: true,
}
)
message.reply(`The points channel has been set to <#${channel.id}>!`)
}
});
client.on('message', async message => {
const { guild, channel } = message
const channelId = await SLSchema.find({channelId: channel.id})
if (message.channel.id = channelId) {
if (message.attachments.size > 0) {
message.react('🔼')
message.react('🔽')
} else {
message.delete()
}
}
})
client.on('messageReactionAdd', async (reaction, user) => {
const { guild, channel } = message
const channelId = await SLSchema.find({channelId: channel.id})
if (reaction.partial) await reaction.fetch()
if (reaction.message.partial) await reaction.message.fetch()
if (reaction.message.channel.id !== channelId) return;
if (user.id === client.user.id) return;
if (reaction.message.author.id === user.id) return reaction.users.remove(user)
if (reaction.emoji.name === "🔼") {
await LeaderboardSequence.findOneAndUpdate({ userid: reaction.message.author.id, guildID: reaction.message.guild.id }, { $inc: { points: 1 } }, { upsert: true , new: true , setDefaultsOnInsert: true })
} else if (reaction.emoji.name === "🔽") {
await LeaderboardSequence.findOneAndUpdate({ userid: reaction.message.author.id, guildID: reaction.message.guild.id }, { $inc: { points: -1 } }, { upsert: true , new: true , setDefaultsOnInsert: true})
}
});
client.on('messageReactionRemove', async (reaction, user) => {
const { guild, channel } = message
const channelId = await SLSchema.find({channelId: channel.id})
if (reaction.partial) await reaction.fetch()
if (reaction.message.partial) await reaction.message.fetch()
if (reaction.message.channel.id !== channelId) return;
if (reaction.message.author.id === user.id) return reaction.users.remove(user)
if (user.id === client.user.id) return;
if (reaction.emoji.name === "🔼") {
await LeaderboardSequence.findOneAndUpdate({ userid: reaction.message.author.id, guildID: reaction.message.guild.id }, { $inc: { points: -1 } }, { upsert: true , new: true , setDefaultsOnInsert: true })
} else if (reaction.emoji.name === "🔽") {
await LeaderboardSequence.findOneAndUpdate({ userid: reaction.message.author.id, guildID: reaction.message.guild.id }, { $inc: { points: 1 } }, { upsert: true , new: true , setDefaultsOnInsert: true})
}
});
client.on('message', async message => {
if (message.content === `${prefix}leaderboard`) {
const Users = await LeaderboardSequence.find({guildID: message.guild.id}).sort({ points: -1 })
const embedArray = []
for (var i = 0; i < Users.length % 10 + 1; i++) {
const leaderboard = new Discord.MessageEmbed()
.setTitle(`Here is ${message.guild}'s points leaderboard!`)
.setColor("RANDOM")
.setThumbnail("https://pbs.twimg.com/media/D7ShRPYXoAA-XXB.jpg")
let text = ""
for (var j = 0; j < 10; j++) {
if (!Users[ i * 10 + j ]) break;
text += `${i * 10 + j + 1}. <#${Users[ i * 10 + j ].userid}>: ${Users[ i * 10 + j ].points}\n`
}
leaderboard.setDescription(text)
.setFooter("By (username) and (username), for everyone with the magic of discord.js.")
.setTimestamp()
embedArray.push(leaderboard)
}
paginate(message, embedArray)
}
});
const reactions = ['◀️', '⏸️', '▶️']
async function paginate(message, embeds, options) {
const pageMsg = await message.channel.send({ embed: embeds[0] })
await pageMsg.react(reactions[0])
await pageMsg.react(reactions[1])
await pageMsg.react(reactions[2])
let pageIndex = 0;
let time = 30000;
const filter = (reaction, user) => {
return reactions.includes(reaction.emoji.name) && user.id === message.author.id;
};
if (options) {
if (options.time) time = options.time
}
const collector = pageMsg.createReactionCollector(filter, { time: time });
collector.on('collect', (reaction, user) => {
reaction.users.remove(user)
if (reaction.emoji.name === '▶️') {
if (pageIndex < embeds.length-1) {
pageIndex++
pageMsg.edit({ embed: embeds[pageIndex] })
} else {
pageIndex = 0
pageMsg.edit({ embed: embeds[pageIndex] })
}
} else if (reaction.emoji.name === '⏸️') {
collector.stop()
} else if (reaction.emoji.name === '◀️') {
if (pageIndex > 0) {
pageIndex--
pageMsg.edit({ embed: embeds[pageIndex] })
} else {
pageIndex = embeds.length-1
pageMsg.edit({ embed: embeds[pageIndex]})
}
}
});
collector.on('end', () => pageMsg.reactions.removeAll().catch(err => console.log(err)));
}``
}
In the question, I did not mention that I was also checking for the points channel through an if statement:
(const { guild, channel } = message
const channelId = await SLSchema.find({channelId: channel.id}))
But this does not work as well.
Here is the schema:
const { Schema, model } = require('mongoose')
// We are using this multiple times so define
// it in an object to clean up our code
const reqString = {
type: String,
required: true,
}
const SLSchema = Schema({
_id: reqString, // Guild ID
channelId: reqString,
})
module.exports = model('setLeaderboard', SLSchema)
In the first piece of code, I have pasted the entire script so you guys have an understanding of the thing I am trying to pull off here.
I am new to node.js and javascript. I get confused in my code as It give me empty response. I am trying to implement the promise and async and await feature however getting respones {}.
Could anybody help me to understand where I am wrong.
Please see below code may be it will long however I need help on issue of await where I am not getting empty result
var response = {};
var newSecret ='';
class FabricClientRegister {
constructor() {
console.log("called constructer");
}
async RegisterUser(Username, roleid) {
try {
const setAsyncTimeout = (cb, timeout = 0) => new Promise(resolve => {
setTimeout(() => {
cb();
resolve();
}, timeout);
});
let query1 = {}
query1.RoleID = roleid;
// query1.name = '';
var name ='';
console.log('roleid',roleid)
// console.log('Username',Username);
var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('./config/Config.json', 'utf8'));
// var Username = req.body.username;
console.log('Username',Username)
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists(Username);
if (userExists) {
response.data = null;
response.httpstatus = 400;
response.message = `An identity for the ${Username} already exists in the wallet`;
return response;
}
console.log("Username1",Username)
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.exists(appAdmin);
if (!adminExists) {
response.data = null;
response.httpstatus = 400;
response.message = "Am admin identity is not registered . please register admin first";
return response;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: appAdmin, discovery: { enabled: false, asLocalhost: true }
/*** Uncomment lines below to disable commit listener on submit ****/
, eventHandlerOptions: {
strategy: null
}
});
// Get the CA client object from the gateway for interacting with the CA.
const ca = gateway.getClient().getCertificateAuthority();
const adminIdentity = gateway.getCurrentIdentity();
console.log("Username4",Username)
MongoClient.connect(config.Database.DFARM.connectString, async function (err, client) {
if (err) {
let connError = new Error(500, "Error connecting to DFARM database", err);
res.status(connError.status).json(connError);
}
else {
client.db(config.Database.DFARM.dbName).collection("Role").find(query1).toArray(function (err, docs) {
if(err) {
console.log('err db',err);
} else{
console.log('Role name DB',docs);
name = docs[0].name;
query1.name = name;
console.log('Role',query1);
}
client.close();
})
}
})
setTimeout(() => console.log('Role 10',query1.name), 5 * 1000);
const doStuffAsync = async () => {
setAsyncTimeout( async () => {
console.log('Role Name',query1.name);
const secret = await ca.register({enrollmentID: Username, role: query1.name}, adminIdentity);
console.log('secret',secret);
response.secret = secret;
newSecret = secret;
console.log('newSecret', newSecret );
response.httpstatus = 200;
response.message = `Successfully registered admin user ${Username} and imported it into the wallet`;
return response;
}, 10000);
};
doStuffAsync();
// .then(function(result) {
// // console.log('promise result',result) // error here undefined
// }).catch(err)
// {
// console.log("eee", err)
// };
console.log('newSecret1', newSecret)
console.log('respones', response)
return newSecret;
} catch (error) {
response.error = error;
response.httpstatus = 500;
response.message = "Failed to enroll admin due to above error";
return response;
}
}
};
Please see below output in CLI
Username Abhinav345
called constructer
roleid 1
Username Abhinav345
Wallet path: /vagrant/Dfarm-app/dFarmUserService/dFarmUserService/wallet
Username1 Abhinav345
Username4 Abhinav345
newSecret1
respones {} //getting empty one however need some data
data result
Role name DB [ { _id: 5d029dec7e8409b489e04cff,
appName: 'Farmer',
RoleID: 1,
name: 'farmer',
routes: [ [Object], [Object], [Object], [Object] ],
tabs: [ [Object], [Object], [Object], [Object] ] } ]
Role { RoleID: 1, name: 'farmer' }
Role 10 farmer
Role Name farmer
secret XXCephExVetS
newSecret XXCephExVetS
Maybe you should consider put await before doStuffAsync().