Initial commit

This commit is contained in:
danbulant 2020-09-01 13:04:00 +02:00
commit 3f7a3134e4
6 changed files with 312 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
node_modules
package-lock.json

3
config.json Normal file
View file

@ -0,0 +1,3 @@
{
"token": "NzQ5MTc3MzEzNjE4NTU4OTk3.X0oLvg.ux4hH4E43YCj0xy3xAAJ6QkEQmQ"
}

115
index.js Normal file
View file

@ -0,0 +1,115 @@
const config = require("./config.json");
const discord = require("discord.js");
const { app, answers, messages, challenge, points } = require("./src");
const client = new discord.Client({
presence: {
status: "online",
activity: {
name: "CNMC",
type: "PLAYING"
}
}
});
client.on("ready", () => {
console.log("Ready");
});
client.on("message", async msg => {
try {
await app.message(msg);
} catch(e) {
console.error("APP", e);
}
});
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;
var diff = pointNum - (points.get(member.user.id) || 0);
points.set(pointNum);
member.setNickname(member.displayName.replace(/\[([0-9.]+)\]/, (match, num) => {
return `[${parseFloat(num) + diff}]`;
}));
}
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);
}
});
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(user.id === client.user.id) 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;
if(challenge.get("hint")) {
var msg = await react.message.channel.messages.fetch(challenge.get("hint"));
if(msg.createdTimestamp < react.message.createdTimestamp) {
points -= 0.5;
}
}
if(!challenge.get("answered")) {
challenge.set("answered", 0);
}
switch(challenge.get("answered")) {
case 0:
points += 2;
break;
case 1:
points += 1.5;
break;
case 2:
points += 1;
break;
default:
points += 0.5;
}
challenge.set("answered", challenge.get("answered") + 1);
if(points > 0) {
check(react.message.member, points);
}
react.message.channel.messages.cache.filter(val => val.author.id === react.message.author.id)
.filter(val => val.id !== react.message.id)
.forEach(msg => msg.reactions.removeAll());
} else {
var r = await react.message.reactions.resolve("✅");
await r.remove();
}
})
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);
}
msg.author.send("You've edited the messages so it got deleted.");
msg.delete();
}
});
client.login(config.token);

119
lib/middleware.js Normal file
View file

@ -0,0 +1,119 @@
module.exports = class Router {
/**
* @type {{
path: string,
callback: function(Message): boolean | string,
break: boolean,
opts: {
guildOnly: boolean,
permissions: string[],
clientPermissions: string[],
ownerOnly: boolean
}
}[]} middlewares
*/
middlewares = [];
/**
* Registers a command
* @param {string} path command format
* @param {function(Message): boolean | string} callback to call on match
* @param {{
guildOnly: boolean,
permissions: string[],
clientPermissions: string[]
}} opts options to use
*/
command(path, callback, opts = {}) {
this.middlewares.push({
path,
callback,
opts,
break: true
});
return this;
}
use(path, router, opts = {}) {
if(typeof path !== "string") {
[router, opts] = [path, router];
path = "";
}
if(typeof router === "function") {
this.middlewares.push({
path,
callback: router,
opts,
break: false
});
return this;
}
for(var middleware of router.middlewares) {
this.middlewares.push({
...middleware,
path: (path + " " + middleware.path).trim(),
opts: Object.assign(middleware.opts, opts)
});
}
return this;
}
processPath(path, content) {
if(!path) return {};
var segments = path.split(" ");
var contentSegments = content.split(" ");
if(!contentSegments) return null;
if(segments.length > contentSegments.length) return null;
var args = {};
for(var segmentID in segments) {
var segment = segments[segmentID];
if(segment.startsWith(":")) {
args[segment.substr(1)] = contentSegments[segmentID];
} else if(segment !== contentSegments[segmentID]) return null;
}
var keys = segments.filter(segment => segment.startsWith(":")).map(segment => segment.substr(1));
if(contentSegments.length > segments.length && keys.length) {
args[keys[keys.length - 1]] += contentSegments.splice(segments.length).join(" ");
}
return args;
}
/**
*
* @param {Message} msg
* @param {{
guildOnly: boolean,
permissions: string[],
clientPermissions: string[]
}} opts options to use
*/
async checkOpts(msg, opts) {
if(!opts) return true;
if(!msg.guild && opts.guildOnly) return false;
if(opts.permissions && msg.member)
for(var permission of opts.permissions)
if(!msg.member.hasPermission(permission)) return false;
if(opts.clientPermissions && msg.guild.me)
for(var permission of opts.clientPermissions)
if(!msg.guild.me.hasPermission(permission)) return false;
return true;
}
async message(msg) {
var middlewares = this.middlewares;
for(var middleware of middlewares) {
var args = this.processPath(middleware.path, msg.content);
if(args === null) continue;
if(!this.checkOpts(msg, middleware.opts)) continue;
var result = await middleware.callback(msg, args);
if(typeof result === "string") {
await msg.channel.send(result);
}
if(result === false || middleware.break) break;
}
}
}

15
package.json Normal file
View file

@ -0,0 +1,15 @@
{
"name": "cnmc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"discord.js": "^12.3.1"
}
}

58
src/index.js Normal file
View file

@ -0,0 +1,58 @@
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(msg.author.id === "694395936809418816" && msg.content === "!reset") {
answers.clear();
messages.clear();
challenge.clear();
msg.reply("done.");
return false;
} else if(msg.author.id === "694395936809418816" && msg.content.startsWith("!start")) {
var num = msg.content.split(" ")[1][0];
if(isNaN(parseInt(num))) {
msg.reply("Invalid type, must start with a number");
return false;
}
challenge.set("num", num);
msg.reply("challenge type set.");
return false;
}
})
.use(msg => msg.channel.id === "745989024099074068")
.use(msg => {
if(challenge.get("hint")) return;
if(msg.author.id === "694395936809418816") {
challenge.set("hint", msg.id);
return false;
}
})
.use(msg => {
if(!/^\[[0-9.]+\]/.test(msg.member.displayName)) {
msg.author.send("You must register first");
msg.delete();
return false;
}
})
.use(async msg => {
var answerCount = answers.get(msg.author.id) || 0;
answerCount++;
answers.set(msg.author.id, answerCount);
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.");
}
console.log("New answer:", msg.content, "by", msg.member.displayName);
messages.set(msg.id, 1);
msg.react("✅");
msg.react("❌");
})
module.exports = { app, answers, messages, challenge, points };