initial bot commit

This commit is contained in:
janeptrv 2020-11-07 18:12:27 -05:00
commit 9eda4abcf7
10 changed files with 503 additions and 0 deletions

119
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}