Trying to make my command only accessible by server owner - discord.js

Trying to make my command only accessible by server owner. Currently anybody is accessible to run the "reset" command and reset all the server stats. Im trying to make it so only myself as the server owner can run this command. Heres the code, your help would be appreciated.
var db = require('../db_helper');
const db_checker = require('../db_checker');
module.exports = async (msg) => {
var existing = db_checker(msg);
existing.then(async function(result) {
if (result) {
var sql = 'TRUNCATE TABLE kills_' + msg.guild.id;
db.query(sql, async function(err) {
if (err) throw err;
var sql = 'TRUNCATE TABLE players_' + msg.guild.id;
db.query(sql, async function(err) {
if (err) throw err;
await msg.channel.send('Your team kill data has been reset');
});
});
} else {
await msg.channel.send('Goose TK Bot has not been set up on this server. Run `!tkstart` to do so.');
}
});
};

The line:
if (!message.member.owner) return; should do the trick :D
(If not, log message.member, and search for the owner property)

You can use these two commands
if (message.author.id !== "YOUR DISCORD ID")
or
if(!message.member.roles.find(r => r.name === "OWNER ROL NAME"))

Related

Discord JS - forEach looped embed

I'm quite new to Javascript, normally a Python person. I've looked at some other answers but my embed does not add the fields as expected. The embed itself is sent.
My Discord bot follows the guide provided by the devs (primary file, slash commands, command files). I am trying to loop through the entries in an SQLite query and add them as fields.
My command file is below.
const { SlashCommandBuilder } = require('#discordjs/builders');
const { MessageEmbed } = require('discord.js')
const sqlite = require('sqlite3').verbose();
module.exports = {
data: new SlashCommandBuilder()
.setName('rank')
.setDescription('Rank all points.'),
async execute(interaction) {
const rankEmbed = new MessageEmbed()
.setColor('#0099ff')
.setTitle('Rank Board')
let db = new sqlite.Database('./databases/ranktest.db', sqlite.OPEN_READWRITE);
let queryall = 'SELECT name, points FROM pointstable ORDER BY points DESC'
db.all(queryall, [], (err, rows) => {
if (err) {
console.log('There was an error');
} else {
rows.forEach((row) => {
console.log(row.name, row.points)
rankEmbed.addField('\u200b', `${row.name}: ${row.points}`, true);
});
}
})
return interaction.reply({embeds: [ rankEmbed ] });
}
}
I would also like to convert row.name - held as Discord IDs - to usernames i.e. MYNAME#0001. How do I do this by interaction? I was able to obtain the User ID in another command by using interaction.member.id, but in this case I need to grab them from the guild. In Python I did this with await client.fetch_user but in this case the error await is only valid in async functions and the top level bodies of modules is thrown.
Thanks.
OK I've solved the first aspect, I had the return interaction.reply in the wrong place.
Relevant snippet:
rows.forEach((row) => {
console.log(row.name, row.points)
rankEmbed.addField('\u200b', `${row.name}: ${row.points}`, false);
})
return interaction.reply({embeds: [rankEmbed ]} );
Would still appreciate an answer to the converting row.name (user ID) to user name via fetch.
I've solved the second aspect also. Add the below into the loop.
rows.forEach((row) => {
let client = interaction.client
const uname = client.users.cache.get(row.name);
rankEmbed.addField('\u200b', `${uname}: ${row.points}`, false);

Node.js SQL server crashes when receiving multiple requests

I have a NodeJS application which is my server and I created a Database class to help me handle querying my SQL DB. If I send requests a second between each other, everything runs fine.. no problems.. But if I start spamming requests to my server it crashes due to Error: Cannot enqueue Quit after invoking quit.
Here's my query function inside my Database class
static query(query: string): Promise<any> {
console.log('Query: ' + query);
return new Promise((resolve, reject) => {
this.connect().then(success => {
sqlConn.query(query, (err, results) => {
if (err) { return reject(err);
} else {
return resolve(results);
}
});
}).catch(err => {
return reject(err);
}).then( () => {
if (sqlConn.state !== 'disconnected') {
sqlConn.end();
}
});
});
};
and here's the this.connect() function
static connect(): Promise<any> {
return new Promise((resolve, reject) => {
sqlConn = mysql.createConnection(this.connectionData);
sqlConn.connect(err => {
if (err) { return reject(err); } else {
return resolve('SQL connection established');
}
});
});
};
I'm pretty sure the problem appears sometimes, it would still be
processing one query, and then another query comes before the first
one finishes, so it would call sqlConn.end() twice, even when it's
already disconnected? Any help is greatly appreciated...
> Main goal is for the query to wait till it's 100% done before it runs
the next one..
You can simplify your code by using the npm module mysql and use it's built-in connection pool.
From the documentation:
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'example.org',
user : 'bob',
password : 'secret',
database : 'my_db'
});
pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
You can, of course, create your own function that promisifies that call like this:
function query (sql) {
return new Promise((resolve, reject) => {
pool.query(sql, (error, results, fields) =>
error ? reject(error) : resolve({ results, fields });
};
}
If you really wants to use this approach then please use eachSeries function of async library.
var chunkedArray= [];
async.eachSeries(chunkedArray, startUpload, endUpload);
funtion startUpload(data,cb){
//iterate over every single item in array 1 at a time
}
function endUplaod(err){
//finally call this
}
This might help:-
https://caolan.github.io/async/docs.html#eachSeries
But i rather suggest you to use pooling of connection which make less overhead on your db and you can use your mysql more efficiently then making multiple connection.
// Load module
var mysql = require('mysql');
// Initialize pool
var pool = mysql.createPool({
connectionLimit : 10,
host : '127.0.0.1',
user : 'root',
password : 'root',
database : 'db_name',
debug : false
});
module.exports = pool;

Global connection already exists. Call sql.close() first

I'm trying to build a node.js backend,I have a usecase that i should connect everytime to the server and not to the database ,see one of the webservices:
router.get('/CriticalityGraph/:server/:user/:password/:database/', function(req, res, next) {
user = req.params.user;
password = req.params.password;
server = req.params.server;
database = req.params.database;
criticalityState=req.params.criticalityState
// config for your database
var config = {
user: user,
password: password,
server: server,
database:database
};
sql.connect(config, function (err) {
var request = new sql.Request();
request.query("SELECT MachineName, alarmState, criticality FROM MachineTable  ORDER BY criticality DESC"
, function (err, recordset) {
if (err) console.log(err);
else {
for(i=0;i<recordset.recordsets.length;i++) {
res.send(recordset.recordsets[i])
}
sql.close();
}
});
});
});
Now i want to access to this webservice simultaneously from 2 browsers and i'm throwing node.js Global connection already exists. Call sql.close() first.
Any suggestions to fix the problem?
Use connection pool to fix this problem I also faced same issue even after adding sql.close()
Use below connection pool code to fix this issue.
new sql.ConnectionPool(config).connect().then(pool => {
return pool.request().query("")
}).then(result => {
let rows = result.recordset
res.setHeader('Access-Control-Allow-Origin', '*')
res.status(200).json(rows);
sql.close();
}).catch(err => {
res.status(500).send({ message: "${err}"})
sql.close();
});

Global connection already exists issue node.js

I have connected MSSQl with node.js using below code
var sql = require('mssql')
var config ={
server:'xxxx',
database:'xxxx',
user:'xxx',
password:'xxx',
port:'xx'
};
sql.connect(dbconfig, function (err) {
if (err) console.log(err);
var sqlquery='';
const request = new sql.Request();
if(condition)
{
//query to the database and get the repo value
sqlquery='select * from verylargetable';
request.query(sqlquery, function (err, result) {
if (err) console.log(err)
var repo=result.recordset[0].Repo;
//query to the database and get the comm value
sqlquery="select commit from verylargetable where Repo='"+repo+"'";
request.query(sqlquery, function (err, result) {
if (err) console.log(err)
var comm=result.recordset[0].Comm;
if (result.recordset.length > 0)
{
//query to the database and update the table
sqlquery="UPDATE verylargetable set Repo='"+repo+"', WHERE Comm='"+comm+"'";
request.query(sqlquery, function (err,result){
if (err) console.log(err)
console.log("record(s) updated");
});
}
});
});
}
else
{
//query to the database and get the repo value
sqlquery='select * from verylargetable';
request.query(sqlquery, function (err, result) {
if (err) console.log(err)
var repo=result.recordset[0].Repo;
//query to the databaseto insert new record
sqlquery ="INSERT INTO verylargetable VALUES("+repo+"','"+comm+"',1)";
request.query(sqlquery, function (err, result) {
if (err) console.log(err)
});
});
}
});
Based on some conditions have to execute queries. while executing, these queries are updated properly.but sometimes facing below issue
global connection already exists. call sql.close() first.
when i used sql.close() at the end i couldn't initialize connection next time.
Facing connection is closed issue.
I have separate method for database changes.I need to establish the connection at the start of the method and have to close at the end.In between have to execute all the queries.
please let me know how to open and close the connection properly?
sql.connect returns connection, in order to close the connection, just call close on the result.
var pool = sql.connect(dbconfig, function (err) {
if (err) console.log(err);
const request = new sql.Request()
var sqlquery='select * from verylargetable';
request.query(sqlquery, function (err, result) {
if (err) console.log(err)
});
});
pool.close();
I was facing the same issue and solved it with below implementation,
For handling global connection already exists. call sql.close() first we need to create a connection pool for mssql npm version 4.0.4
const config = {
user: '**',
password: '**',
server: '** or localhost',
database: '**',
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
}}
router.get('/SQLConnection1', function (req, res, next) {
const pool1 = new sql.ConnectionPool(config, err => {
// ... error checks
// Query
pool1.request() // or: new sql.Request(pool1)
.query('SELECT ID,Name from Avatar', (err, result) => {
// ... error checks
console.dir(result)
res.json({'Result': result})
})
})
pool1.on('error', err => {
// ... error handler
console.log('Error ' + err);
})
});

How can I prevent SQL injection with Node.JS?

How could I select a row of MS SQL server database with Node.JS with preventing SQL injection? I use the express framework and the package mssql.
Here is a part of my code I use now with a possibility to SQL injection written in ES 6.
const express = require('express'),
app = express(),
sql = require('mssql'),
config = require('./config');
let connect = (f, next) => {
sql.connect(config.database.connectionstring).then(f).catch((err) => {
next(err);
});
};
app.get('/locations/get/:id', (req, res, next) => {
let f = () => {
new sql.Request().query(`select * from mytable where id = ${req.params.id}`)
.then((recordset) => {
console.dir(recordset);
}).catch((err) => {
next(err);
});
};
connect(f, next);
});
Use a PreparedStatement. Here is how you do it from the docs https://www.npmjs.com/package/mssql#prepared-statement :
var ps = new sql.PreparedStatement(/* [connection] */);
ps.input('id', sql.Int);
ps.prepare('select * from mytable where id = #id', function(err) {
ps.execute({id: req.params.id}, function(err, recordset) {
ps.unprepare(function(err) {
// ... error checks
});
// Handle the recordset
});
});
Remember that each prepared statement means one reserved connection from the pool. Don't forget to unprepare a prepared statement!
You can also create prepared statements in transactions (new sql.PreparedStatement(transaction)), but keep in mind you can't execute other requests in the transaction until you call unprepare.
The docs are written in ES5 but I', sure you can Promisify it :)

Resources