Skip to content

Instantly share code, notes, and snippets.

@idkjs
Created February 25, 2020 16:55
Show Gist options
  • Save idkjs/c42ed479c7bc5ff48a644e92ca6d2581 to your computer and use it in GitHub Desktop.
Save idkjs/c42ed479c7bc5ff48a644e92ca6d2581 to your computer and use it in GitHub Desktop.
SQLite Points Bot

SQLite-based Points Bot

This is the example code for This Guide. Please read that guide to understand the code provided here.

On the other hand, if you know what you're doing, here's a quick how-to:

  • In an admin command prompt or powershell, run npm i -g --production windows-build-tools.
  • Close all open command prompts for your bot, or the following won't work.
  • npm i discord.js better-sqlite3
  • Create app.js and config.json per below.
  • Make sure to get your bot token in the config.json.
  • Invite your bot.
  • Start node app.js
  • Enjoy your mee6 ripoff, you monster.

Support

All support for this code is offered in the Idiot's Guide Official Server in the #guide-support channel:

NO SUPPORT FOR THIS CODE WILL BE GIVEN IN THE COMMENTS BELOW.

const Discord = require("discord.js");
const client = new Discord.Client();
const config = require("./config.json");
const SQLite = require("better-sqlite3");
const sql = new SQLite('./scores.sqlite');
client.on("ready", () => {
// Check if the table "points" exists.
const table = sql.prepare("SELECT count(*) FROM sqlite_master WHERE type='table' AND name = 'scores';").get();
if (!table['count(*)']) {
// If the table isn't there, create it and setup the database correctly.
sql.prepare("CREATE TABLE scores (id TEXT PRIMARY KEY, user TEXT, guild TEXT, points INTEGER, level INTEGER);").run();
// Ensure that the "id" row is always unique and indexed.
sql.prepare("CREATE UNIQUE INDEX idx_scores_id ON scores (id);").run();
sql.pragma("synchronous = 1");
sql.pragma("journal_mode = wal");
}
// And then we have two prepared statements to get and set the score data.
client.getScore = sql.prepare("SELECT * FROM scores WHERE user = ? AND guild = ?");
client.setScore = sql.prepare("INSERT OR REPLACE INTO scores (id, user, guild, points, level) VALUES (@id, @user, @guild, @points, @level);");
});
client.on("message", message => {
// Ignore bots, DMs and group messages.
if (message.author.bot || !message.guild) return;
/*
START Points CODE
*/
// Initialize ("declare") the points. If we did this in the condition it would not be
// available later in commands. Because "scopes"!
let score;
if (message.guild) {
// Try to get the current user's score.
score = client.getScore.get(message.author.id, message.guild.id);
// If the score doesn't exist (new user), initialize with defaults.
if (!score) {
score = { id: `${message.guild.id}-${message.author.id}`, user: message.author.id, guild: message.guild.id, points: 0, level: 1 };
}
// Increment points.
score.points++;
// Calculate the current level through MATH OMG HALP.
const curLevel = Math.floor(0.1 * Math.sqrt(score.points));
// Check if the user has leveled up, and let them know if they have:
if(score.level < curLevel) {
// Level up!
message.reply(`You've leveled up to level **${curLevel}**! Ain't that dandy?`);
}
// Save data to the sqlite table.
// This looks super simple because it's calling upon the prepared statement!
client.setScore.run(score);
}
if (message.content.indexOf(config.prefix) !== 0) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if(command === "points") {
return message.reply(`You currently have ${score.points} points and are level ${score.level}!`);
}
if(command === "give") {
// Limited to guild owner - adjust to your own preference!
if(!message.author.id === message.guild.owner) return message.reply("You're not the boss of me, you can't do that!");
// Try to get the user from mention. If not found, get the ID given and get a user from that ID.
const user = message.mentions.users.first() || client.users.get(args[0]);
if(!user) return message.reply("You must mention someone or give their ID!");
// Read the amount of points to give to the user.
const pointsToAdd = parseInt(args[1], 10);
if(!pointsToAdd) return message.reply("You didn't tell me how many points to give...");
// Get their current points. This can't use `score` because it's not the same user ;)
let userscore = client.getScore.get(user.id, message.guild.id);
// It's possible to give points to a user we haven't seen, so we need to initiate defaults here too!
if (!userscore) {
userscore = { id: `${message.guild.id}-${user.id}`, user: user.id, guild: message.guild.id, points: 0, level: 1 };
}
// Increment the score.
userscore.points += pointsToAdd;
// We also want to update their level (but we won't notify them if it changes)
let userLevel = Math.floor(0.1 * Math.sqrt(score.points));
userscore.level = userLevel;
// And we save it!
client.setScore.run(userscore);
return message.channel.send(`${user.tag} has received ${pointsToAdd} points and now stands at ${userscore.points} points.`);
}
if(command === "leaderboard") {
// Grab the
const top10 = sql.prepare("SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10;").all(message.guild.id);
// Now shake it and show it! (as a nice embed, too!)
const embed = new Discord.RichEmbed()
.setTitle("Leaderboard")
.setAuthor(client.user.username, client.user.avatarURL)
.setDescription("Our top 10 points leaders!")
.setColor(0x00AE86);
for(const data of top10) {
embed.addField(client.users.get(data.user).tag, `${data.points} points (level ${data.level})`);
}
return message.channel.send({embed});
}
});
client.login(config.token);
{
"token" : "MTg-this-IzNzU3OTA5NjA-is.not-DCeFB-a.real-r4DQlO-t0ken-qerT0",
"prefix" : "+"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment