· 7 years ago · Jan 21, 2019, 05:24 PM
1const Discord = require("discord.js");
2const client = new Discord.Client();
3const config = require("./config.json");
4const SQLite = require("better-sqlite3");
5const sql = new SQLite('./scores.sqlite');
6
7client.on("ready", () => {
8 // Check if the table "points" exists.
9 const table = sql.prepare("SELECT count(*) FROM sqlite_master WHERE type='table' AND name = 'scores';").get();
10 if (!table['count(*)']) {
11 // If the table isn't there, create it and setup the database correctly.
12 sql.prepare("CREATE TABLE scores (id TEXT PRIMARY KEY, user TEXT, guild TEXT, points INTEGER, level INTEGER);").run();
13 // Ensure that the "id" row is always unique and indexed.
14 sql.prepare("CREATE UNIQUE INDEX idx_scores_id ON scores (id);").run();
15 sql.pragma("synchronous = 1");
16 sql.pragma("journal_mode = wal");
17 }
18 // And then we have two prepared statements to get and set the score data.
19 client.getScore = sql.prepare("SELECT * FROM scores WHERE user = ? AND guild = ?");
20 client.setScore = sql.prepare("INSERT OR REPLACE INTO scores (id, user, guild, points, level) VALUES (@id, @user, @guild, @points, @level);");
21
22 // This event will run if the bot starts, and logs in, successfully.
23 console.log('\x1b[32m%s\x1b[0m',`Bot has started, with ${client.users.size} users, in ${client.channels.size} channels of ${client.guilds.size} guilds.`);
24 // Example of changing the bot's playing game to something useful. `client.user` is what the
25 // docs refer to as the "ClientUser".
26 client.user.setActivity(`Serving ${client.guilds.size} servers`);
27
28});
29
30client.on("guildCreate", guild => {
31 // This event triggers when the bot joins a guild.
32 console.log(`New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`);
33 client.user.setActivity(`Serving ${client.guilds.size} servers`);
34});
35
36client.on("guildDelete", guild => {
37 // this event triggers when the bot is removed from a guild.
38 console.log(`I have been removed from: ${guild.name} (id: ${guild.id})`);
39 client.user.setActivity(`Serving ${client.guilds.size} servers`);
40});
41
42client.on("message", async message => {
43 // Ignore bots, DMs and group messages.
44 if (message.author.bot || !message.guild) return;
45
46 /*
47 START Points CODE
48 */
49
50 // Initialize ("declare") the points. If we did this in the condition it would not be
51 // available later in commands. Because "scopes"!
52 let score;
53
54 if (message.guild) {
55 // Try to get the current user's score.
56 score = client.getScore.get(message.author.id, message.guild.id);
57
58 // If the score doesn't exist (new user), initialize with defaults.
59 if (!score) {
60 score = { id: `${message.guild.id}-${message.author.id}`, user: message.author.id, guild: message.guild.id, points: 0, level: 1 };
61 }
62
63 // Increment points.
64 score.points++;
65
66 // Calculate the current level through MATH OMG HALP.
67 const curLevel = Math.floor(0.1 * Math.sqrt(score.points));
68
69 // Check if the user has leveled up, and let them know if they have:
70 if(score.level < curLevel) {
71 // Level up!
72 message.reply(`You've leveled up to level **${curLevel}**! Ain't that dandy?`);
73 }
74
75 // Save data to the sqlite table.
76 // This looks super simple because it's calling upon the prepared statement!
77 client.setScore.run(score);
78 }
79 // Ignore any message that does not start with our prefix,
80 if (message.content.indexOf(config.prefix) !== 0) return;
81
82 const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
83 const command = args.shift().toLowerCase();
84
85 if(command === "points") {
86 return message.reply(`You currently have ${score.points} points and are level ${score.level}!`);
87 }
88
89 if(command === "give") {
90 // Limited to guild owner - adjust to your own preference!
91 if(!message.author.id === message.guild.owner) return message.reply("You're not the boss of me, you can't do that!");
92
93 // Try to get the user from mention. If not found, get the ID given and get a user from that ID.
94 const user = message.mentions.users.first() || client.users.get(args[0]);
95 if(!user) return message.reply("You must mention someone or give their ID!");
96
97 // Read the amount of points to give to the user.
98 const pointsToAdd = parseInt(args[1], 10);
99 if(!pointsToAdd) return message.reply("You didn't tell me how many points to give...");
100
101 // Get their current points. This can't use `score` because it's not the same user ;)
102 let userscore = client.getScore.get(user.id, message.guild.id);
103
104 // It's possible to give points to a user we haven't seen, so we need to initiate defaults here too!
105 if (!userscore) {
106 userscore = { id: `${message.guild.id}-${user.id}`, user: user.id, guild: message.guild.id, points: 0, level: 1 };
107 }
108
109 // Increment the score.
110 userscore.points += pointsToAdd;
111
112 // We also want to update their level (but we won't notify them if it changes)
113 let userLevel = Math.floor(0.1 * Math.sqrt(score.points));
114 userscore.level = userLevel;
115
116 // And we save it!
117 client.setScore.run(userscore);
118
119 return message.channel.send(`${user.tag} has received ${pointsToAdd} points and now stands at ${userscore.points} points.`);
120 }
121
122 if(command === "leaderboard") {
123 // Grab the
124 const top10 = sql.prepare("SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10;").all(message.guild.id);
125
126 // Now shake it and show it! (as a nice embed, too!)
127 const embed = new Discord.RichEmbed()
128 .setTitle("Leaderboard")
129 .setAuthor(client.user.username, client.user.avatarURL)
130 .setDescription("Our top 10 points leaders!")
131 .setColor(0x00AE86);
132
133 for(const data of top10) {
134 embed.addField(client.users.get(data.user).tag, `${data.points} points (level ${data.level})`);
135 }
136 return message.channel.send({embed});
137 }
138});
139
140client.login("You Bot Token Here");