diff --git a/index.js b/index.js index 02bcdf9..c5ab635 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ const config = require("./config.json"); const discord = require("discord.js"); -const { app, answers, messages, challenge, points } = require("./src"); +const { app, answers, challenge, points } = require("./src"); const client = new discord.Client({ presence: { @@ -27,7 +27,7 @@ client.on("message", async msg => { function check(member, bonus = 0) { var pointNum = bonus + (answers.get(member.user.id) ? (0.5 + ((challenge.get("num") || 1) * 0.5)) : 0); if(points.get(member.user.id) === pointNum) return; - if(points.get(member.user.id) && points.get(member.user.id) > 1) return; + if(points.get(member.user.id) && pointNum < points.get(member.user.id)) return; var diff = pointNum - (points.get(member.user.id) || 0); points.set(pointNum); member.setNickname(member.displayName.replace(/\[([0-9.]+)\]/, (match, num) => { @@ -35,80 +35,106 @@ function check(member, bonus = 0) { })); } -client.on("messageDelete", msg => { - if(messages.get(msg.id)) { - messages.delete(msg.id); - messages.delete(msg.id); - var an = answers.get(msg.author.id) || 0; - if(an) answers.set(msg.author.id, an - 1); - check(msg.member); +/** + * @param {discord.Collection} arr + * @param {(val: any) => boolean} predicate + * @returns {discord.Collection} + *//** + * @param {discord.Collection} arr + * @param {(val: discord.Message) => boolean} predicate + * @returns {discord.Collection} + */ +async function asyncFilter(arr, predicate) { + var mapped = arr.mapValues(predicate); + var keys = Array.from(mapped.keys()); + const results = await Promise.all(mapped.values()); + + var col = new discord.Collection(); + for(var key in results) { + col.set(keys[key], results[key]); } -}); + + return arr.filter((_v, index) => col.get(index)); +} client.on("messageReactionAdd", async (react, user) => { - if(react.message.channel.id !== "745989024099074068") return; - if(user.id !== "694395936809418816") { - if(user.id !== client.user.id) { - await react.users.remove(user); - } - return; - } + if(react.message.channel.id !== "750720332943458648") return; if(user.id === client.user.id) return; + if(!react.message.embeds.length) return; if(react.emoji.name !== "❌" && react.emoji.name !== "✅") return; if(react.emoji.name === "✅") { var r = await react.message.reactions.resolve("❌"); await r.remove(); var points = 0; + var hint = false; if(challenge.get("hint")) { var msg = await react.message.channel.messages.fetch(challenge.get("hint")); if(msg.createdTimestamp < react.message.createdTimestamp) { points -= 0.5; + hint = true; } } if(!challenge.get("answered")) { challenge.set("answered", 0); } + var member = await react.message.guild.members.fetch(react.message.embeds[0].footer.text); + switch(challenge.get("answered")) { case 0: points += 2; + member.user.send(`Congratulations! You got the first place at the challenge #${challenge.get("type")} for your answer. ${hint ? "(However you lost 0.5 points because you're answer is given after the ADVANCED HINT)." : ""} You got ${points + (answers.get(member.user.id) ? (0.5 + ((challenge.get("num") || 1) * 0.5)) : 0)} points!`); break; case 1: points += 1.5; + member.user.send(`Congratulations! You got the second place at the challenge #${challenge.get("type")} for your answer. ${hint ? "(However you lost 0.5 points because you're answer is given after the ADVANCED HINT)." : ""} You got ${points + (answers.get(member.user.id) ? (0.5 + ((challenge.get("num") || 1) * 0.5)) : 0)} points!`); break; case 2: points += 1; + member.user.send(`Congratulations! You got the third place at the challenge #${challenge.get("type")} for your answer. ${hint ? "(However you lost 0.5 points because you're answer is given after the ADVANCED HINT)." : ""} You got ${points + (answers.get(member.user.id) ? (0.5 + ((challenge.get("num") || 1) * 0.5)) : 0)} points!`); break; default: points += 0.5; + member.user.send(`Congratulations! You got the right answer for challenge #${challenge.get("type")}. ${hint ? "(However you lost 0.5 points because you're answer is given after the ADVANCED HINT)." : ""} You got ${points + (answers.get(member.user.id) ? (0.5 + ((challenge.get("num") || 1) * 0.5)) : 0)} points!`); } challenge.set("answered", challenge.get("answered") + 1); if(points > 0) { - check(react.message.member, points); + check(member, points); } - react.message.channel.messages.cache.filter(val => val.author.id === react.message.author.id) + react.message.channel.messages.cache.filter(val => val.author.id === val.client.user.id) + .filter(val => val.embeds) + .filter(val => val.embeds[0].footer.text === react.message.embeds[0].footer.text) .filter(val => val.id !== react.message.id) .forEach(msg => msg.reactions.removeAll()); } else { var r = await react.message.reactions.resolve("✅"); await r.remove(); - } -}) + + var preFiltered = react.message.channel.messages.cache.filter(val => val.author.id === val.client.user.id) + .filter(val => val.embeds) + .filter(val => val.embeds[0].footer.text === react.message.embeds[0].footer.text) + .filter(val => val.embeds[0].fields[1].value === react.message.embeds[0].fields[1].value) + .filter(val => val.id !== react.message.id); -client.on("messageUpdate", (msg, msg2) => { - if(msg.channel.id === "745989024099074068") { - if(messages.get(msg.id)) { - messages.delete(msg.id); - var an = answers.get(msg.author.id) || 0; - if(an) answers.set(msg.author.id, an - 1); - check(msg.member); + var wrong = (await asyncFilter( + preFiltered, + val => { + var r = val.reactions.resolve("✅"); + console.log("r", !r?.count); + return !r?.count; + } + )).size; + + if(wrong + 1 >= answers.get(react.message.embeds[0].footer.text)) { + var member = await react.message.guild.members.fetch(react.message.embeds[0].footer.text); + await member.user.send(`Sadly, none of your answers are correct. But as a gift for joining the challenge #${react.message.embeds[0].fields[1].value}, you still get ${(answers.get(member.user.id) ? (0.5 + ((challenge.get("num") || 1) * 0.5)) : 0)} points!`); } - msg.author.send("You've edited the messages so it got deleted."); - msg.delete(); + + check(react.message.member, 0); } }); diff --git a/src/index.js b/src/index.js index 0033840..fb16aa7 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,17 @@ +const { MessageEmbed } = require("discord.js"); const App = require("../lib/middleware"); const app = new App(); const answers = new Map(); -const messages = new Map(); const challenge = new Map(); const points = new Map(); app .use(msg => !msg.author.bot) // ignore bots .use(async msg => { + if(!challenge.get("type")) challenge.set("type", "0"); if(msg.author.id === "694395936809418816" && msg.content === "!reset") { answers.clear(); - messages.clear(); challenge.clear(); msg.reply("done."); return false; @@ -22,11 +22,16 @@ app return false; } challenge.set("num", num); + challenge.set("type", msg.content.split(" ")[1]); msg.reply("challenge type set."); return false; } }) - .use(msg => msg.channel.id === "745989024099074068") + .use(msg => msg.channel.type === "dm") + .use(async msg => { + msg.cguild = await msg.client.guilds.fetch("745985920116850781"); + msg.cmember = await msg.cguild.members.fetch(msg.author.id); + }) .use(msg => { if(challenge.get("hint")) return; if(msg.author.id === "694395936809418816") { @@ -35,9 +40,27 @@ app } }) .use(msg => { - if(!/^\[[0-9.]+\]/.test(msg.member.displayName)) { + if(!/^\[[0-9.]+\]/.test(msg.cmember.displayName)) { msg.author.send("You must register first"); - msg.delete(); + return false; + } + }) + .use(msg => { + if(!challenge.get("type")) { + msg.author.send("No challenge is currently active."); + return false; + } + }) + .use(msg => { + var answerCount = answers.get(msg.author.id) || 0; + if(answerCount >= 3) { + msg.author.send("You've already used all your attempts for challenge `" + challenge.get("type") + "`."); + return false; + } + }) + .use(msg => { + if(!msg.content.startsWith(challenge.get("type") + ". ")) { + msg.author.send("Invalid format. The question must start with challenge number: `" + challenge.get("type") + ". `."); return false; } }) @@ -48,11 +71,21 @@ app if(answerCount > 3) return await msg.delete(); if(answerCount === 3) { await msg.author.send("You've used all your 3 answers, you won't be able to add any more."); + } else { + await msg.author.send("Answer recorded, wait for results."); } - console.log("New answer:", msg.content, "by", msg.member.displayName); - messages.set(msg.id, 1); - msg.react("✅"); - msg.react("❌"); + console.log("New answer:", msg.content, "by", msg.cmember.displayName); + var channel = msg.cguild.channels.resolve("750720332943458648"); + var embed = new MessageEmbed(); + embed.setTitle("New answer"); + embed.setDescription(msg.content.match(/[0-9]+\. (.*)/)[1]); + embed.setAuthor(msg.cmember.displayName, msg.author.avatarURL()); + embed.setFooter(msg.author.id); + embed.addField("Try", answerCount, true); + embed.addField("Challenge", challenge.get("type"), true); + var m = await channel.send(embed); + m.react("✅"); + m.react("❌"); }) -module.exports = { app, answers, messages, challenge, points }; \ No newline at end of file +module.exports = { app, answers, challenge, points }; \ No newline at end of file