initial commit; add events system
This commit is contained in:
parent
2e7834b17e
commit
fc1f05ae0c
11 changed files with 532 additions and 0 deletions
112
bot.js
Normal file
112
bot.js
Normal file
|
@ -0,0 +1,112 @@
|
|||
import { createRequire } from 'module';
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
import Eris from 'eris';
|
||||
import Logger, { levels } from './logger.js';
|
||||
import CommandParser, { Command } from './parser.js';
|
||||
import { filename, dirname } from './utils.js';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
const cfg = require('./config.json');
|
||||
if (!fs.existsSync('./whitelist.json')) {
|
||||
fs.writeFileSync('./whitelist.json', '{}');
|
||||
}
|
||||
|
||||
const whitelist = require('./whitelist.json');
|
||||
const dir = dirname(import.meta.url);
|
||||
|
||||
const bot = new Eris(cfg.token);
|
||||
|
||||
global.ctx = {
|
||||
bot: bot,
|
||||
log_level: levels[cfg.log_level.toUpperCase()] || levels.WARN,
|
||||
set_ctx: (key, value) => {
|
||||
global.ctx[key] = value;
|
||||
},
|
||||
};
|
||||
const log = new Logger(filename(import.meta.url), global.ctx.log_level);
|
||||
const parse = new CommandParser(global.ctx, cfg.prefix || undefined);
|
||||
|
||||
const checkUser = (user) => {
|
||||
if (cfg.user_whitelist.includes(user.id) || (whitelist.user && whitelist.user.includes(user.id))) {
|
||||
return true;
|
||||
}
|
||||
log.info(`user not on whitelist: ${user.username}`);
|
||||
return false;
|
||||
};
|
||||
const checkGuild = (guild) => {
|
||||
if (cfg.whitelist.includes(guild.id) || (whitelist.guild && whitelist.guild.includes(guild.id))) {
|
||||
return true;
|
||||
}
|
||||
log.info(`guild not on whitelist: ${guild.name}`);
|
||||
return false;
|
||||
};
|
||||
|
||||
const saveWhitelist = () => {
|
||||
let data = JSON.stringify(whitelist);
|
||||
fs.writeFileSync('./whitelist.json', data);
|
||||
};
|
||||
|
||||
global.ctx.whitelist = {
|
||||
guild: checkGuild,
|
||||
user: checkUser,
|
||||
save: saveWhitelist,
|
||||
wl: whitelist,
|
||||
};
|
||||
|
||||
const listeners = {}
|
||||
|
||||
bot.on('ready', () => {
|
||||
log.info('ready recieved.');
|
||||
bot.guilds.forEach((guild) => checkGuild(guild));
|
||||
});
|
||||
|
||||
bot.on('messageCreate', (msg) => parse.parseMsg(msg, global.ctx));
|
||||
|
||||
bot.on('error', (err) => log.error(err.toString()));
|
||||
|
||||
bot.connect();
|
||||
|
||||
async function load_commands() {
|
||||
for (let file of files) {
|
||||
let p = path.join(cmd_dir, file);
|
||||
log.debug('loading ' + p);
|
||||
let obj;
|
||||
try {
|
||||
obj = await import('file:////' + p);
|
||||
} catch (e) {
|
||||
log.warn(`loading file ${file}, ran into issue: ${e.stack}`);
|
||||
continue;
|
||||
}
|
||||
if (obj.default != undefined) {
|
||||
if (obj.default.constructor.name == 'CommandInitializer') {
|
||||
obj.default.initialize(global.ctx);
|
||||
let cmds = obj.default.getCommands();
|
||||
if (parse.isCmd(cmds)) {
|
||||
parse.addCommand(cmds);
|
||||
} else if (cmds.constructor.name == 'Array') {
|
||||
for (let cmd of cmds) {
|
||||
parse.addCommand(cmd);
|
||||
}
|
||||
}
|
||||
let events = obj.default.getEvents();
|
||||
if (events != undefined) {
|
||||
for (let event in events) {
|
||||
if (!listeners[event]) {
|
||||
listeners[event] = []
|
||||
}
|
||||
listeners[event].push(events[event])
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn('module ' + file + ' returned an undefined module.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let cmd_dir = path.join(dir, 'cmd');
|
||||
log.trace(dir);
|
||||
let files = fs.readdirSync(cmd_dir);
|
||||
load_commands();
|
94
cmd/perm.js
Normal file
94
cmd/perm.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
import { CommandInitializer, Command } from '../parser.js';
|
||||
|
||||
const initializer = new CommandInitializer();
|
||||
|
||||
class WhitelistUser extends Command {
|
||||
name = 'wu';
|
||||
whitelist = true;
|
||||
func = async function (msg, args, ctx) {
|
||||
let user = await ctx.bot.users.get(args[0].trim());
|
||||
this.log.debug(msg.channel.guild.members);
|
||||
this.log.debug(user);
|
||||
if (!user) {
|
||||
user = msg.channel.guild.members.get(args[0].trim());
|
||||
this.log.debug(user);
|
||||
if (!user) {
|
||||
user = (await msg.channel.guild.fetchMembers({ userIDs: [args[0]] }))[0];
|
||||
this.log.debug(user);
|
||||
}
|
||||
}
|
||||
if (user.username) {
|
||||
if (!ctx.whitelist.wl) {
|
||||
ctx.whitelist.wl = {
|
||||
user: [],
|
||||
guild: [],
|
||||
};
|
||||
}
|
||||
let list = ctx.whitelist.wl.user || [];
|
||||
if (!list.includes(args[0])) {
|
||||
list.push(args[0]);
|
||||
ctx.whitelist.wl.user = list;
|
||||
ctx.whitelist.save();
|
||||
msg.channel.createMessage(`added user "${user.username}#${user.discriminator}" (${args[0]}) to whitelist`);
|
||||
} else {
|
||||
msg.channel.createMessage('user already whitelisted');
|
||||
}
|
||||
} else {
|
||||
msg.channel.createMessage(`user with id ${args[0]} could not be found`);
|
||||
}
|
||||
};
|
||||
}
|
||||
initializer.addCommand(new WhitelistUser());
|
||||
|
||||
class WhitelistGuild extends Command {
|
||||
name = 'wg';
|
||||
whitelist = true;
|
||||
func = async function (msg, args, ctx) {
|
||||
let guild = await ctx.bot.guilds.get(args[0]);
|
||||
if (guild && guild.name) {
|
||||
if (!ctx.whitelist.wl) {
|
||||
ctx.whitelist.wl = {
|
||||
user: [],
|
||||
guild: [],
|
||||
};
|
||||
}
|
||||
let list = ctx.whitelist.wl.guild || [];
|
||||
if (!list.includes(args[0])) {
|
||||
list.push(args[0]);
|
||||
ctx.whitelist.wl.guild = list;
|
||||
ctx.whitelist.save();
|
||||
msg.channel.createMessage(`added guild "${guild.name}" (${args[0]}) to whitelist`);
|
||||
} else {
|
||||
msg.channel.createMessage('guild already whitelisted');
|
||||
}
|
||||
} else {
|
||||
msg.channel.createMessage(`guild with id ${args[0]} could not be found`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
initializer.addCommand(new WhitelistGuild());
|
||||
|
||||
class Purge extends Command {
|
||||
name = 'purge';
|
||||
whitelist = true;
|
||||
func = async function (msg, args, ctx) {
|
||||
let guilds = await ctx.bot.guilds;
|
||||
let whitelist = ctx.whitelist.guild;
|
||||
let purged = 0;
|
||||
guilds.forEach((guild) => {
|
||||
if (!whitelist(guild)) {
|
||||
this.log.info(`purging guild ${guild.name} (${guild.id})`);
|
||||
guild.leave();
|
||||
purged++;
|
||||
} else {
|
||||
this.log.debug(`keeping guild ${guild.name} (${guild.id})`);
|
||||
}
|
||||
});
|
||||
msg.channel.createMessage(`purged ${purged} guilds.`);
|
||||
};
|
||||
}
|
||||
|
||||
initializer.addCommand(new Purge());
|
||||
|
||||
export default initializer;
|
52
cmd/reg.js
Normal file
52
cmd/reg.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { CommandInitializer, Command } from '../parser.js';
|
||||
import Logger, { levels } from '../logger.js';
|
||||
import { filename } from '../utils.js';
|
||||
|
||||
const initializer = new CommandInitializer();
|
||||
const log = new Logger(filename(import.meta.url), global.ctx.log_level);
|
||||
|
||||
class PingCommand extends Command {
|
||||
name = 'ping';
|
||||
func(msg, args, ctx) {
|
||||
msg.channel.createMessage('p').then((m) => {
|
||||
m.edit(
|
||||
`rtt: ${Math.floor(m.timestamp - msg.timestamp)}, gateway: ${
|
||||
ctx.bot.shards.get(ctx.bot.guildShardMap[ctx.bot.channelGuildMap[msg.channel.id]] || 0).latency
|
||||
}`
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initializer.addCommand(new PingCommand());
|
||||
|
||||
class RestartCommand extends Command {
|
||||
name = 'restart';
|
||||
func(msg, args, ctx) {
|
||||
msg.channel.createMessage('restarting.').then(() => {
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initializer.addCommand(new RestartCommand());
|
||||
|
||||
class EvalCommand extends Command {
|
||||
name = 'eval';
|
||||
whitelist = true;
|
||||
func(msg, args, ctx) {
|
||||
log.debug('evaluating ' + args[0]);
|
||||
let result = eval(args[0]);
|
||||
log.debug('result is: \n' + result);
|
||||
if (result.length <= 1999) {
|
||||
msg.channel.createMessage(result);
|
||||
}
|
||||
else {
|
||||
msg.channel.createMessage("result too long, see logs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initializer.addCommand(new EvalCommand());
|
||||
|
||||
export default initializer;
|
7
config.json
Normal file
7
config.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"token": "MjY3Mzg2MTUyMzIxOTQxNTA1.WHFMwg.KgEUojOa43UL43yqUy9-TKz05tY",
|
||||
"log_level": "DEBUG",
|
||||
"prefix": "p.",
|
||||
"whitelist": ["656579275008245830"],
|
||||
"user_whitelist": ["123601647258697730"]
|
||||
}
|
56
logger.js
Normal file
56
logger.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
export const levels = {
|
||||
TRACE: 5,
|
||||
DEBUG: 4,
|
||||
INFO: 3,
|
||||
WARN: 2,
|
||||
ERROR: 1,
|
||||
PANIC: 0,
|
||||
};
|
||||
|
||||
export default class Logger {
|
||||
constructor(name, level) {
|
||||
console.log(`created new logger for ${name} with level ${level}`);
|
||||
this.sn(name);
|
||||
this.s(level);
|
||||
}
|
||||
n = 'DEFAULT';
|
||||
l = 0;
|
||||
sn(n) {
|
||||
this.n = n;
|
||||
}
|
||||
s(l) {
|
||||
if (l && l.constructor === Number) {
|
||||
this.l = l;
|
||||
} else {
|
||||
this.l = levels[l];
|
||||
}
|
||||
}
|
||||
|
||||
lo(l, m) {
|
||||
if (l <= this.l) {
|
||||
let level = Object.keys(levels).find((key) => levels[key] === l);
|
||||
let ms = typeof m == 'object' ? JSON.stringify(m) : m;
|
||||
console.log(`${level} [${this.n}]: ${ms}`);
|
||||
}
|
||||
}
|
||||
|
||||
trace(msg) {
|
||||
this.lo(levels.TRACE, msg);
|
||||
}
|
||||
|
||||
debug(msg) {
|
||||
this.lo(levels.DEBUG, msg);
|
||||
}
|
||||
info(msg) {
|
||||
this.lo(levels.INFO, msg);
|
||||
}
|
||||
warn(msg) {
|
||||
this.lo(levels.WARN, msg);
|
||||
}
|
||||
error(msg) {
|
||||
this.lo(levels.ERROR, msg);
|
||||
}
|
||||
panic(msg) {
|
||||
this.lo(levels.PANIC, msg);
|
||||
}
|
||||
}
|
19
package.json
Normal file
19
package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "module",
|
||||
"name": "pinbot",
|
||||
"version": "1.0.0",
|
||||
"description": "a bot to manage pins (and also other stuff!)",
|
||||
"main": "bot.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@ssh.gitdab.com:jane/pinbot.git"
|
||||
},
|
||||
"author": "jane petrovna (jane@j4.pm)",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"dependencies": {
|
||||
"eris": "^0.15.0"
|
||||
}
|
||||
}
|
133
parser.js
Normal file
133
parser.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
import Logger, { levels } from './logger.js';
|
||||
import { filename } from './utils.js';
|
||||
|
||||
export class Command {
|
||||
init(ctx, log) {
|
||||
this.log = log;
|
||||
}
|
||||
log;
|
||||
name = 'DEFAULT';
|
||||
whitelist = false;
|
||||
func() {}
|
||||
}
|
||||
|
||||
export class CommandInitializer {
|
||||
commands = [];
|
||||
uninitialized = [];
|
||||
events = {};
|
||||
|
||||
initialize(ctx) {
|
||||
for (let index in this.uninitialized) {
|
||||
this.initCommand(this.uninitialized[index], ctx);
|
||||
delete this.uninitialized[index];
|
||||
}
|
||||
}
|
||||
|
||||
initCommand(cmd, ctx) {
|
||||
cmd.init(ctx, new Logger(`cmd.${cmd.name}`, ctx.log_level));
|
||||
this.commands.push(cmd);
|
||||
}
|
||||
|
||||
addCommand(cmd) {
|
||||
this.uninitialized.push(cmd);
|
||||
}
|
||||
|
||||
addEvent(event, func) {
|
||||
if (!events[event]) {
|
||||
events[event] = [];
|
||||
}
|
||||
events[event].push(func);
|
||||
}
|
||||
|
||||
getCommands() {
|
||||
return this.commands;
|
||||
}
|
||||
|
||||
getEvents() {
|
||||
return this.events;
|
||||
}
|
||||
}
|
||||
|
||||
export default class CommandParser {
|
||||
constructor(ctx, prefix = ';') {
|
||||
this.log = new Logger(filename(import.meta.url), ctx.log_level);
|
||||
this.prefix = prefix ? prefix : this.prefix || ';';
|
||||
}
|
||||
log;
|
||||
prefix;
|
||||
commands = [];
|
||||
|
||||
addCommand(cmd) {
|
||||
this.log.trace(`cmd to add: ${JSON.stringify(cmd)}`);
|
||||
if (this.isCmd(cmd)) {
|
||||
this.commands.push(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
hasCmd(str) {
|
||||
let results = this.commands.filter((c) => c.name == str);
|
||||
|
||||
return results.length ? results[0] : undefined;
|
||||
}
|
||||
|
||||
isCmd(cmd) {
|
||||
return typeof cmd == 'object' && cmd instanceof Command;
|
||||
}
|
||||
|
||||
getArgsList(split) {
|
||||
let parsed_args = [];
|
||||
let join_index = -1;
|
||||
let add = true;
|
||||
for (let index in split) {
|
||||
if (split[index].startsWith('```')) {
|
||||
join_index = index;
|
||||
add = false;
|
||||
}
|
||||
if (add) {
|
||||
parsed_args.push(split[index]);
|
||||
}
|
||||
if (split[index].endsWith('```') && join_index != -1) {
|
||||
let joined = split
|
||||
.slice(join_index, index + 1)
|
||||
.join(' ')
|
||||
.replace(/```/g, '');
|
||||
parsed_args.push(joined);
|
||||
add = true;
|
||||
join_index = -1;
|
||||
}
|
||||
}
|
||||
return parsed_args;
|
||||
}
|
||||
|
||||
parseMsg(msg, ctx) {
|
||||
if (msg.author.bot) {
|
||||
return;
|
||||
}
|
||||
if (msg.channel.guild && !ctx.whitelist.guild(msg.channel.guild)) {
|
||||
msg.channel.createMessage('guild not whitelisted');
|
||||
return;
|
||||
}
|
||||
this.log.trace(msg.content);
|
||||
this.log.trace(msg.content.startsWith(this.prefix));
|
||||
this.log.trace(msg.content[0]);
|
||||
this.log.trace(this.prefix);
|
||||
if (msg.content.startsWith(this.prefix)) {
|
||||
let snip = msg.content.slice(this.prefix.length);
|
||||
let unsep = snip.split(' ');
|
||||
let res = this.hasCmd(unsep[0]);
|
||||
let args = this.getArgsList(unsep.slice(1));
|
||||
this.log.trace(snip);
|
||||
this.log.trace(res);
|
||||
this.log.trace(args);
|
||||
|
||||
if (res != undefined) {
|
||||
this.log.debug(`execute function ${res.name}`);
|
||||
if (res.whitelist && !ctx.whitelist.user(msg.author)) {
|
||||
msg.channel.createMessage('not whitelisted');
|
||||
} else {
|
||||
res.func(msg, args, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
pnpm-lock.yaml
Normal file
41
pnpm-lock.yaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
dependencies:
|
||||
eris: 0.15.0
|
||||
lockfileVersion: 5.2
|
||||
packages:
|
||||
/eris/0.15.0:
|
||||
dependencies:
|
||||
ws: 7.4.4
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=10.4.0'
|
||||
optionalDependencies:
|
||||
opusscript: 0.0.8
|
||||
tweetnacl: 1.0.3
|
||||
resolution:
|
||||
integrity: sha512-muBdi5XyMXdxFQ8xUG6yofq40/Z02CHlqJP7zIdHhpdDiHvFM/mybGiFAHuoSYcsVTTvEfbUaAJ+SDEmMjARYw==
|
||||
/opusscript/0.0.8:
|
||||
dev: false
|
||||
optional: true
|
||||
resolution:
|
||||
integrity: sha512-VSTi1aWFuCkRCVq+tx/BQ5q9fMnQ9pVZ3JU4UHKqTkf0ED3fKEPdr+gKAAl3IA2hj9rrP6iyq3hlcJq3HELtNQ==
|
||||
/tweetnacl/1.0.3:
|
||||
dev: false
|
||||
optional: true
|
||||
resolution:
|
||||
integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
|
||||
/ws/7.4.4:
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=8.3.0'
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: ^5.0.2
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
resolution:
|
||||
integrity: sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
|
||||
specifiers:
|
||||
eris: ^0.15.0
|
2
start.sh
Normal file
2
start.sh
Normal file
|
@ -0,0 +1,2 @@
|
|||
git pull
|
||||
pnpm start
|
15
utils.js
Normal file
15
utils.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import path from "path";
|
||||
import {platform} from "process";
|
||||
|
||||
export function filename(url) {
|
||||
let __filename = new URL(url).pathname;
|
||||
return path.basename(__filename, ".js");
|
||||
}
|
||||
|
||||
export function dirname(url) {
|
||||
let __filename = new URL(url).pathname;
|
||||
let __dirname = path.dirname(__filename);
|
||||
return platform == "win32"
|
||||
? __dirname.slice(1)
|
||||
: __dirname;
|
||||
}
|
1
whitelist.json
Normal file
1
whitelist.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"guild":["656579275008245830","823796249832194088"],"user":["123601647258697730"]}
|
Loading…
Reference in a new issue