Add rank and leaderboard commands

This commit is contained in:
danbulant 2020-09-06 21:06:34 +02:00
parent 1bccc6009f
commit 5b1ea0f681
3 changed files with 183 additions and 3 deletions

View file

@ -16,6 +16,10 @@ module.exports = class Router {
*/
middlewares = [];
constructor(name) {
this.name = name;
}
/**
* Registers a command
* @param {string} path command format
@ -37,6 +41,16 @@ module.exports = class Router {
return this;
}
/**
* Registers a middleware
* @param {string} path
* @param {function|Router} router
* @param {{
guildOnly: boolean,
permissions: string[],
clientPermissions: string[]
}} opts
*/
use(path, router, opts = {}) {
if(typeof path !== "string") {
[router, opts] = [path, router];
@ -51,11 +65,21 @@ module.exports = class Router {
});
return this;
}
if(router instanceof Router) {
this.middlewares.push({
callback: (...args) => router.message(...args),
path: (path).trim(),
opts: Object.assign(router.opts, opts),
break: opts ? !!opts.break : false
})
return this;
}
if(!router.middlewares) throw new Error("Unknown middleware type");
for(var middleware of router.middlewares) {
this.middlewares.push({
...middleware,
path: (path + " " + middleware.path).trim(),
opts: Object.assign(middleware.opts, opts)
opts: Object.assign({}, middleware.opts, opts)
});
}
return this;
@ -113,7 +137,9 @@ module.exports = class Router {
if(typeof result === "string") {
await msg.channel.send(result);
}
if(result === false || middleware.break) break;
if(middleware.break || result === false) {
return false;
}
}
}
}

135
src/commands.js Normal file
View file

@ -0,0 +1,135 @@
const App = require("../lib/middleware");
const app = new App("commands");
const discord = require("discord.js");
/**
* Gets top members
* @param {discord.Guild} guild
*/
function getLeaderboard(guild) {
return guild.members.cache
.filter(m => !m.user.bot)
.filter(m => /\[[0-9.]+\].*/.test(m.displayName))
.map(m => {
m.score = parseFloat(m.displayName.match(/\[([0-9.]+)\].*/)[1]);
return m;
})
.map((m, i, self) => {
m.name = m.displayName.match(/\[[0-9.]+\](.*)/)[1].trim();
m.rank = self.filter((m, i) => {
return self.indexOf(self.filter(e => e.score === m.score)[0]) === i;
}).filter(e => e.score > m.score).length + 1;
return m;
})
.sort((a, b) => b.score - a.score)
}
/**
* Tests if given string is a number
* @param {string} str to test
*/
function isNumber(str) {
if (typeof str != "string") return false;
return !isNaN(str) && !isNaN(parseFloat(str))
}
/**
* Gets leaderboard embed
* @param {discord.Guild} guild
* @param {number} page
*/
function getLeaderboardEmbed(guild, page = 1) {
page--;
const leaderboard = getLeaderboard(guild).slice(page * 10, (page + 1) * 10);
const maxPage = Math.ceil(getLeaderboard(guild).length / 10);
if(!leaderboard.length) return "Couldn't find any results.";
const embed = new discord.MessageEmbed();
embed.setTitle("Leaderboard - Page " + (page+1));
embed.setDescription(leaderboard
.map((m, i) => {
switch(m.rank) {
case 1:
m.rank = ":first_place:";
break;
case 2:
m.rank = ":second_place:";
break;
case 3:
m.rank = ":third_place:";
break;
default:
m.rank += ".";
}
return m;
})
.map(
(m, i) => `**${m.rank} ${m.name}** - ${m.score} point${m.score === 1 ? "" : "s"}`
).join("\n")
);
embed.setFooter(`Page ${page+1} out of ${maxPage}.`);
return embed;
}
/**
* Gets user rank embed
* @param {discord.GuildMember} member
* @param {discord.Guild} guild
* @param {boolean} motivation
*/
function getUserEmbed(omember, guild, motivation) {
var leaderboard = getLeaderboard(guild);
var member = leaderboard.filter(m => m.id === omember.id)[0];
var index = leaderboard.indexOf(member);
member.rankNumber = member.rank;
switch(member.rank) {
case 1:
member.rank = ":first_place:";
break;
case 2:
member.rank = ":second_place:";
break;
case 3:
member.rank = ":third_place:";
break;
}
const embed = new discord.MessageEmbed();
embed.setAuthor(member.name, member.user.avatarURL());
embed.setDescription(`Rank: **${member.rank}**\nScore: **${member.score}**`)
if(member.rankNumber !== 1 && motivation) {
var before = leaderboard.filter((m, i) => {
return leaderboard.indexOf(leaderboard.filter(e => e.score === m.score)[0]) === i;
}).filter(e => e.score > member.score).pop();
embed.setFooter(`\n${before.score - member.score} points needed to get rank ${before.rank}.`);
}
return embed;
}
app
.command("leaderboard :page", async (msg, { page }) => {
if(!isNumber(page)) return msg.channel.send("Invalid page argument. Use number.");
msg.channel.send(getLeaderboardEmbed(msg.guild, parseInt(page)));
})
.command("leaderboard", async msg => {
msg.channel.send(getLeaderboardEmbed(msg.guild));
})
.command("rank :user", async (msg, { user }) => {
var members = await msg.guild.members.fetch({
query: user,
limit: 5
});
if(members.size > 1) {
return msg.channel.send("Multiple users found, be more specific: " + members.map(m => "`" + m.displayName + "`").join(", ") + ".");
}
if(!members.size) return msg.channel.send("Couldn't find any user");
msg.channel.send(getUserEmbed(members.first(), msg.guild, msg.member.id === members.first().id));
})
.command("rank", async msg => {
msg.channel.send(getUserEmbed(msg.member, msg.guild, true));
})
module.exports = app;

View file

@ -1,13 +1,32 @@
const { MessageEmbed } = require("discord.js");
const App = require("../lib/middleware");
const app = new App();
const app = new App("main");
const commands = require("./commands");
const answers = new Map();
const challenge = new Map();
const points = new Map();
function makeWriteable(object, property) {
var val;
var proto = Object.getPrototypeOf(object);
Object.defineProperty(object, property, {
get: function () { return typeof val !== "undefined" ? val : proto[property]; },
set: function(value) { val = value; }
});
}
app
.use(msg => !msg.author.bot) // ignore bots
.use(msg => {
if(msg.channel.type === "dm") return;
if(!msg.content.startsWith("!")) return;
msg.content = msg.content.substr(1);
makeWriteable(msg, "guild");
msg.guild = msg.client.guilds.resolve("745985920116850781");
commands.message(msg);
return false;
})
.use(async msg => {
if(!challenge.get("type")) challenge.set("type", null);
if(msg.author.id === "694395936809418816" && msg.content === "!reset") {