MongoServerSelectionError: getaddrinfo ENOTFOUND at Timeout._onTimeout - javascript

So you may have seen this question type somewhere else. but the thing here is I tried all of the things we need to do according to docs and saw other posts with similar errors but still my error is not fixed. So I use keyv and use MongoDB atlas as storage adapter in this code, but the error is from MongoDB. Also, there is no error in the "keyv" because it works for other people, there is error in the MongoDB
So now I will list whatever I tried:
1. Made sure there is IP access
2. The userid and passcode are correct
3. The MongoDB atlas is running
4. Read the docs and code multiple times
5. If u think adding the +srv with the code will fix the error, it won't, it doesn't work with keyql idk why also it is not present in many codes, I already tried it
So this is the code
const { Client, Intents, MessageEmbed, Collection } = require('discord.js');
let client = new Client({ intents: [Intents.FLAGS.GUILDS,Intents.FLAGS.GUILD_MESSAGES] });
const dotenv = require('dotenv');
const Keyv = require('keyv');
const keyv = new Keyv('mongodb://Discord:password#cluster0.auifa.mongodb.net/Cluster0');
dotenv.config();
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('messageCreate', async (msg) => {
if (msg.author.bot) return;
let number = msg.content.split(' ')[1];
if (msg.content === '!ping') {
msg.channel.send('ping!')
}
// Use like const prefix = await getGuildPrefix(); `
const getGuildPrefix = async () => {
const prefixMap = await keyv.get('prefix');
return prefixMap ?. [msg.guild.id] || "!"
}
// Sets the prefix to the current guild.
const setGuildPrefix = async (prefix) => {
let prefixMap = await keyv.get('prefix');
if (!prefixMap)
{
prefixMap = "!";
}
prefixMap[msg.guild.id] = prefix;
await keyv.set('prefix', `${prefixMap}`);
}
let prefix = await getGuildPrefix();
// Get prefix command.
if ((msg.content === `${process.env.prefix}prefix`) || (msg.content === `${prefix}prefix`)) {
msg.channel.send(`Your server prefix is ${prefix}`)
}
// Change prefix command
const commandPrefix = await getGuildPrefix();
if ((msg.content.startsWith(`${process.env.prefix}setprefix`)) || (msg.content.startsWith(`${commandPrefix}setprefix`))) {
const newPrefix = number;
if (newPrefix.length === 0) {
msg.channel.send(`Please enter a valid prefix`);
}
await setGuildPrefix(newPrefix)
msg.channel.send(`Your server prefix is now '${newPrefix}'`);
}
})
client.login(process.env.token);
And this is the error message
Keyv connection error: MongoServerSelectionError: getaddrinfo ENOTFOUND cluster0.auifa.mongodb.net
at Timeout._onTimeout (D:\javascript\node_modules\mongojs\node_modules\mongodb\lib\core\sdam\topology.js:438:30)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7) {
reason: TopologyDescription

Connection string does not look like an Atlas one.
It has to be something like: mongodb+srv://<username>:<password>#cluster0.auifa.mongodb.net/YOUR-DB
Login to your Atlas account then:
Go to Databases page
Click on Connect button
Choose "Connect your application"
Copy your connection string
Docs about Mongo Atlas connection: https://docs.atlas.mongodb.com/connect-to-cluster/#connect-to-a-cluster

Related

How to store the ID of the user who sent a slash command and compare with user who interacted with a button in Discord.js

I'm using the following code to create a quick database to store the ID of the user who called a bot via a slash command. I then want to compare this ID with the ID of the person interacting with the bot. My aim is to prevent anyone but the user that called the bot being able to interact with it.
The following code works but it's temperamental in that it fails without a clear reason on occasion (i.e. it returns the error which states that the person interacting isn't the person who sent the slash command even if they are).
I'm new to discord.js and quick.db tables so I'm hoping someone more competent than me has a better way of achieving this.
const { Client, Intents, MessageEmbed, MessageActionRow, MessageButton } = require('discord.js'),
client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES ] });
client.db = require("quick.db");
var quiz = require("./quiz.json");
client.login(config.token);
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
if ([null, undefined].includes(client.db.get(`quiz`))) client.db.set(`quiz`, {});
if ([null, undefined].includes(client.db.get(`quiz.spawns`))) client.db.set(`quiz.spawns`, {});
});
client.on('messageCreate', async (message) => {
if (!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift();
if (command == "unlock") {
message.delete();
const m = await message.channel.send(getMMenuPage());
client.db.set(`quiz.spawns.m${m.id}`, message.author.id);
}
});
client.on('interactionCreate', async (interaction) => {
if (interaction.isButton()) {
if (client.db.get(`quiz.spawns.m${interaction.message.id}`) != interaction.user.id) return interaction.reply(getMessagePermissionError(client.db.get(`quiz.spawns.m${interaction.message.id}`)));
const q = quiz;
Please let me know if you need more information.
Thanks.
Instead of using:
const db = require("quick.db");
You should be using:
const { QuickDB } = require("quick.db");
const db = new QuickDB();
Other than that I haven't see any problems.

Getting UUID’s by providing only the crypto coins name/ticker

I’m building a Discord bot using the Discord.JS module, and using NodeJS. I’m trying to add a simple crypto-price feature to my bot.
For now, I’m using the following code:
const unirest = require("unirest");
const req = unirest("GET", "https://coinranking1.p.rapidapi.com/coin/Qwsogvtv82FCd/price");
req.query({
"referenceCurrencyUuid": "yhjMzLPhuIDl"
});
req.headers({
"X-RapidAPI-Host": "coinranking1.p.rapidapi.com",
"X-RapidAPI-Key": "X",
"useQueryString": true
});
req.end(function (res) {
if (res.error) throw new Error(res.error);
console.log(res.body);
});
So basically, you have to provide the UUID of the desired crypto coin to request information, but I want my users to be able to do (for example) !price bitcoin or !price btc, but this requires the command to be like !price Qwsogvtv82FCd.
How do I resolve this issue?
If you check the API documentation, you can see that instead of using the coin price endpoint, you could use the search suggestion (https://coinranking1.p.rapidapi.com/search-suggestions), where you can search for a coin by its name or symbol. It returns an object like the one below. If you check the objects in data.coins, they have keys like uuid, name, symbol, and price:
{
"status":"success",
"data":{
"coins":[
{
"uuid":"Qwsogvtv82FCd",
"iconUrl":"https://cdn.coinranking.com/gNsKAuE-W/bitcoin_btc.svg",
"name":"Bitcoin",
"symbol":"BTC",
"price":"65955.43592725793773050345"
},
{...}
],
"exchanges":[
{...},
{...}
],
"markets":[...]
}
}
Your current code doesn't really do anything and it doesn't even have discord.js code. Here is a sample code with some explanation:
const { Client, Intents } = require('discord.js');
// I'm using node-fetch instead of unirest
// make sure you install it using npm i node-fetch
const fetch = require('node-fetch');
const RAPID_API_KEY = 'YOUR RAPID API KEY';
const TOKEN = 'YOUR DISCORD API TOKEN';
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
const prefix = '!';
client.on('messageCreate', async (message) => {
if (message.author.bot || !message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if (command !== 'price') return;
if (!args[0]) return message.reply('Please provide a coin!');
try {
// get the search query
let query = args[0].toLowerCase();
// call the API
let coins = await searchCoin(query);
// if there is no search result, or something went wrong, exit w/ a message
if (!coins || coins.length === 0)
return message.reply(`No result for \`"${query}"\``);
// check the first result only
let coin = coins[0];
// if there is an exact match, send the price returned from the API
if (
coin.name.toLowerCase() === query ||
coin.symbol.toLowerCase() === query
)
return message.reply(
`The current price of **${coin.name} (${coin.symbol})** is **${coin.price} USD**`,
);
// if there is no exact match, just send the coin name and symbol in a message
message.reply(
`No exact result found. Did you mean **${coin.name} (${coin.symbol})**?`,
);
} catch (err) {
console.error(err);
message.reply('Oops, there was an error. Please try again later.');
}
});
client.once('ready', () => {
console.log('Bot is connected...');
});
client.login(TOKEN);
async function searchCoin(query) {
const url = `https://coinranking1.p.rapidapi.com/search-suggestions?query=${query}`;
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Host': 'coinranking1.p.rapidapi.com',
'X-RapidAPI-Key': RAPID_API_KEY,
},
};
try {
const response = await fetch(url, options);
const json = await response.json();
return json.status === 'success' ? json.data?.coins : null;
} catch (err) {
console.error(err);
return null;
}
}
And here is the result:

Cannot read property 'prefix' of null discord.js

Hello, I had this problem like 1 week ago, and still can't solve it. So, I'm trying to do per-server prefixes, but when I boot up the bot, it sends the boot-up confirmation message, but then it says the error and it shuts down. Here is the error:
guildPrefixes[guildId] = result.prefix
^
TypeError: Cannot read property 'prefix' of null
I can't see anything wrong here, but anyways, here is the code:
module.exports.loadPrefixes = async (client) => {
await mongo().then(async (mongoose) => {
try {
for (const guild of client.guilds.cache) {
const guildId = guild[1].id
const guildPrefixes = {}
const result = await commandPrefixSchema.findOne({_id: guildId})
guildPrefixes[guildId] = result?.prefix || dprefix
console.log(result)
}
console.log('[INFO] Prefixes have been loaded')
} finally {
mongoose.connection.close()
}
})
}

node-telegram-bot-api deprecated Automatic enabling of cancellation of promises is deprecated

I'm trying to create a Telegram bot but when I run the code I get these errors:
"node-telegram-bot-api deprecated Automatic enabling of cancellation of promises is deprecated
In the future, you will have to enable it yourself.
See https://github.com/yagop/node-telegram-bot-api/issues/319. internal\modules\cjs\loader.js:1063:30"
"error: [polling_error] {"code":"ETELEGRAM","message":"ETELEGRAM: 409 Conflict: terminated by
other getUpdates request; make sure that only one bot instance is running"}"
I have no idea what that means. I've followed the link but I still don't know how to solve the problem, please help me, I don't know what to do.
Here is my bot.js code if that helps:
const TelegramBot = require('node-telegram-bot-api');
const axios = require('axios');
const parser = require('./parser.js');
require('dotenv').config();
const token = process.env.TELEGRAM_TOKEN;
let bot;
if (process.env.NODE_ENV === 'production') {
bot = new TelegramBot(token);
bot.setWebHook(process.env.HEROKU_URL + bot.token);
} else {
bot = new TelegramBot(token, { polling: true });
}
// Matches "/word whatever"
bot.onText(/\/word (.+)/, (msg, match) => {
const chatId = msg.chat.id;
const word = match[1];
axios
.get(`${process.env.OXFORD_API_URL}/entries/en-gb/${word}`, {
params: {
fields: 'definitions',
strictMatch: 'false'
},
headers: {
app_id: process.env.OXFORD_APP_ID,
app_key: process.env.OXFORD_APP_KEY
}
})
.then(response => {
const parsedHtml = parser(response.data);
bot.sendMessage(chatId, parsedHtml, { parse_mode: 'HTML' });
})
.catch(error => {
const errorText = error.response.status === 404 ? `No definition found for the word: <b>${word}</b>` : `<b>An error occured, please try again later</b>`;
bot.sendMessage(chatId, errorText, { parse_mode:'HTML'})
});
});
Install this package npm I dotenv
Create a file called .env at the root of your project.
Add to that file this NTBA_FIX_319=1
Add to the top of your index.js file (or whatever file that contains your bot instance): require('dotenv').config()
Restart your bot.
So your code will look like
require('dotenv').config();
const TelegramBot = require('node-telegram-bot-api');
// replace the value below with the Telegram token you receive from #BotFather
const token = 'YOUR_TELEGRAM_BOT_TOKEN';
// Create a bot that uses 'polling' to fetch new updates
const bot = new TelegramBot(token, {polling: true});
bot.on('message', (msg) => {
const chatId = msg.chat.id;
// send a message to the chat acknowledging receipt of their message
bot.sendMessage(chatId, 'Received your message');
});
1) Get rid of the promise cancellation warning
The simplest, is to add that line at the top of your bot file:
process.env.NTBA_FIX_319 = 1 // this line SHOULD be above all imports
const TelegramBot = require('node-telegram-bot-api')
// ...rest of your telegram bot code
2) The 409 conflict error
In short, there are two version of your telegram bot running at the same time, so:
check if there is not multiple instance of your server running your bot, which can be the case when using workers, pm2...
check that your bot script is not started twice
Other causes and explanations can be found here and here

TypeError: ping is not a function

Im trying to make a discord bot that shows my minecraft server stats and stuff. It is almost done but when i do the command it comes up with this in the terminal: TypeError: ping is not a function. Here is my code:
const {Client, RichEmbed } = require('discord.js')
const bot = new Client()
const ping = require('minecraft-server-util')
const token = 'not gunna tell u my token'
const ip = 'or ip'
const PREFIX = '!'
bot.on('ready', () =>{
console.log('Bot has come online.')
})
bot.on('message', message =>{
let args = message.content.substring(PREFIX.length).split(' ')
switch(args[0]){
case 'mc':
ping(ip, parseInt(25565), (error, reponse) =>{
if(error) throw error
const Embed = new RichEmbed()
.setTitle('Server Status')
.addField('Server IP', reponse.host)
.addField('Server Version', reponse.version)
.addField('Online Players', reponse.onlinePlayers)
.addField('Max Players', reponse.maxPlayers)
message.channel.send(Embed)
})
break
}
})
bot.login(token)
As the docs say, ping is a property of that module's exports: it's not the whole export:
const util = require('minecraft-server-util');
util.ping('play.hypixel.net', { port: 25565 })
For your code, either destructure out the ping property on import:
const { ping } = require('minecraft-server-util')
Or give it some other name, then call .ping on the imported object:
const util = require('minecraft-server-util');
// ...
util.ping(ip, /* etc */
Also, if you want the port to be the default 25565, there's no need to pass it at all. The module also returns a Promise, which you should use instead of the callback form:
ping(ip)
.then((response) => {
// handle response
})
.catch((error) => {
// handle errors
});

Categories