mirror of
https://github.com/danbulant/cnmc-bot
synced 2026-05-19 03:48:33 +00:00
Initial commit
This commit is contained in:
commit
3f7a3134e4
6 changed files with 312 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
package-lock.json
|
||||
3
config.json
Normal file
3
config.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"token": "NzQ5MTc3MzEzNjE4NTU4OTk3.X0oLvg.ux4hH4E43YCj0xy3xAAJ6QkEQmQ"
|
||||
}
|
||||
115
index.js
Normal file
115
index.js
Normal 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
119
lib/middleware.js
Normal 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
15
package.json
Normal 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
58
src/index.js
Normal 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 };
|
||||
Loading…
Reference in a new issue