initial bot commit
This commit is contained in:
commit
9eda4abcf7
10 changed files with 503 additions and 0 deletions
119
.gitignore
vendored
Normal file
119
.gitignore
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# config file
|
||||
config.json
|
72
bot.js
Normal file
72
bot.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
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");
|
||||
const dir = dirname(import.meta.url);
|
||||
|
||||
const bot = new Eris(cfg.token);
|
||||
const ctx = {
|
||||
bot: bot,
|
||||
log_level: levels.DEBUG
|
||||
};
|
||||
const log = new Logger(filename(import.meta.url), ctx.log_level);
|
||||
const parse = new CommandParser(ctx);
|
||||
|
||||
const checkGuild = guild => {
|
||||
if (!cfg.whitelist.includes(guild.id)) {
|
||||
log.info(`Leaving guild not on whitelist: ${guild.name}`);
|
||||
guild.leave();
|
||||
}
|
||||
};
|
||||
|
||||
bot.on("ready", () => {
|
||||
log.info("ready recieved.");
|
||||
bot.guilds.forEach(guild => checkGuild(guild));
|
||||
});
|
||||
|
||||
bot.on("guildAvaliable", guild => checkGuild(guild));
|
||||
|
||||
bot.on("messageCreate", msg => parse.parseMsg(msg, ctx));
|
||||
|
||||
bot.connect();
|
||||
|
||||
async function load_commands() {
|
||||
for (let file of files) {
|
||||
let p = path.join(cmd_dir, file);
|
||||
log.debug(p);
|
||||
let obj;
|
||||
try {
|
||||
obj = await import ("file:////" + p);
|
||||
} catch (e) {
|
||||
log.warn(`loading file ${file}, ran into issue: ${e.message}`);
|
||||
continue;
|
||||
}
|
||||
if (obj.default != undefined) {
|
||||
if (obj.default.constructor.name == "CommandInitializer") {
|
||||
obj.default.initialize(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("module " + file + " returned an undefined module.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let cmd_dir = path.join(dir, "cmd");
|
||||
log.debug(dir);
|
||||
let files = fs.readdirSync(cmd_dir);
|
||||
load_commands();
|
25
cmd/lights.js
Normal file
25
cmd/lights.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import {CommandInitializer, Command} from "../parser.js";
|
||||
import parse, {instructions} from "../lights/light_parser.js";
|
||||
|
||||
const initializer = new CommandInitializer();
|
||||
|
||||
class LightsParser extends Command {
|
||||
init(ctx, log) {
|
||||
this.log = log;
|
||||
}
|
||||
name = "lights";
|
||||
func(msg, args, ctx) {
|
||||
let instructions = parse(args[0]);
|
||||
|
||||
this.log.debug(instructions);
|
||||
let res = "```\n";
|
||||
instructions.forEach(instruction => {
|
||||
res += JSON.stringify(instruction) + "\n";
|
||||
});
|
||||
res += "```";
|
||||
msg.channel.createMessage(`parsed instructions:\n${res}`);
|
||||
}
|
||||
}
|
||||
initializer.addCommand(new LightsParser());
|
||||
|
||||
export default initializer;
|
16
cmd/reg.js
Normal file
16
cmd/reg.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import {CommandInitializer, Command} from "../parser.js";
|
||||
|
||||
const initializer = new CommandInitializer();
|
||||
|
||||
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());
|
||||
|
||||
export default initializer;
|
49
lights/light_parser.js
Normal file
49
lights/light_parser.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
class Target {
|
||||
constructor(channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
channel;
|
||||
value;
|
||||
}
|
||||
|
||||
const available_targets = {
|
||||
r: new Target("r"),
|
||||
g: new Target("g"),
|
||||
b: new Target("b")
|
||||
};
|
||||
|
||||
class Instruction {
|
||||
constructor(t1ets, args) {
|
||||
let valid_targets = [];
|
||||
targets.forEach(t => {
|
||||
if (t instanceof Target) {
|
||||
let match = Object.keys(available_targets).find(key => available_targets[key].channel === t.channel);
|
||||
if (match) {
|
||||
valid_targets.push(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.targets = valid_targets;
|
||||
this.args = args;
|
||||
}
|
||||
name;
|
||||
targets;
|
||||
args;
|
||||
transform(index, time, channel_target, channel_in) {}
|
||||
transformAll(index, time) {
|
||||
let new_targets = [];
|
||||
this.targets.forEach(target => {
|
||||
this.transform(index, time, target, this.args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ConstantColor extends Instruction {
|
||||
name = "CONSTANT";
|
||||
transform(index, time, channel_target) {}
|
||||
}
|
||||
export const instructions = [ConstantColor];
|
||||
|
||||
export default function parse(str) {
|
||||
return [{}];
|
||||
}
|
54
logger.js
Normal file
54
logger.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
export const levels = {
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
17
package.json
Normal file
17
package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"eris": "^0.14.0"
|
||||
},
|
||||
"name": "lights",
|
||||
"version": "1.0.0",
|
||||
"main": "bot.js",
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node bot.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": ""
|
||||
}
|
95
parser.js
Normal file
95
parser.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
import Logger, {levels} from "./logger.js";
|
||||
import {filename} from "./utils.js";
|
||||
|
||||
export class Command {
|
||||
init(ctx, log) {
|
||||
this.log = log;
|
||||
}
|
||||
log;
|
||||
name = "DEFAULT";
|
||||
func() {}
|
||||
}
|
||||
|
||||
export class CommandInitializer {
|
||||
commands = [];
|
||||
uninitialized = [];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
getCommands() {
|
||||
return this.commands;
|
||||
}
|
||||
}
|
||||
|
||||
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.debug(`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(args) {
|
||||
return [args];
|
||||
}
|
||||
|
||||
parseMsg(msg, ctx) {
|
||||
if (msg.author.bot) {
|
||||
return;
|
||||
}
|
||||
this.log.debug(msg.content);
|
||||
this.log.debug(msg.content.startsWith(this.prefix));
|
||||
this.log.debug(msg.content[0]);
|
||||
this.log.debug(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).join(" "));
|
||||
this.log.debug(snip);
|
||||
this.log.debug(res);
|
||||
this.log.debug(args);
|
||||
|
||||
if (res != undefined) {
|
||||
this.log.debug(`execute function ${res.name}`);
|
||||
res.func(msg, args, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
pnpm-lock.yaml
Normal file
41
pnpm-lock.yaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
dependencies:
|
||||
eris: 0.14.0
|
||||
lockfileVersion: 5.1
|
||||
packages:
|
||||
/eris/0.14.0:
|
||||
dependencies:
|
||||
ws: 7.3.1
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=8.0.0'
|
||||
optionalDependencies:
|
||||
opusscript: 0.0.7
|
||||
tweetnacl: 1.0.3
|
||||
resolution:
|
||||
integrity: sha512-/W6X0SFR2swtA9oc4ga5Wh1TQcZtPgbUaDDdwYc67fvFUAtwC+V1xzWUZq2yDeJnTfB8Uot9SJWA8Lthe2sDtQ==
|
||||
/opusscript/0.0.7:
|
||||
dev: false
|
||||
optional: true
|
||||
resolution:
|
||||
integrity: sha512-DcBadTdYTUuH9zQtepsLjQn4Ll6rs3dmeFvN+SD0ThPnxRBRm/WC1zXWPg+wgAJimB784gdZvUMA57gDP7FdVg==
|
||||
/tweetnacl/1.0.3:
|
||||
dev: false
|
||||
optional: true
|
||||
resolution:
|
||||
integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
|
||||
/ws/7.3.1:
|
||||
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-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==
|
||||
specifiers:
|
||||
eris: ^0.14.0
|
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;
|
||||
}
|
Loading…
Reference in a new issue