light command

This commit is contained in:
jane 2020-11-07 22:29:13 -05:00
parent 9eda4abcf7
commit 6c7bbc2304
7 changed files with 378 additions and 232 deletions

95
bot.js
View file

@ -1,72 +1,73 @@
import {createRequire} from "module"; import { createRequire } from 'module';
const require = createRequire(import.meta.url); const require = createRequire(import.meta.url);
import Eris from "eris"; import Eris from 'eris';
import Logger, {levels} from "./logger.js"; import Logger, { levels } from './logger.js';
import CommandParser, {Command} from "./parser.js"; import CommandParser, { Command } from './parser.js';
import {filename, dirname} from "./utils.js"; import { filename, dirname } from './utils.js';
import path from "path"; import path from 'path';
import fs from "fs"; import fs from 'fs';
const cfg = require("./config.json"); const cfg = require('./config.json');
const dir = dirname(import.meta.url); const dir = dirname(import.meta.url);
const bot = new Eris(cfg.token); const bot = new Eris(cfg.token);
const ctx = { const ctx = {
bot: bot, bot: bot,
log_level: levels.DEBUG log_level: levels.DEBUG,
whitelist: cfg.user_whitelist || []
}; };
const log = new Logger(filename(import.meta.url), ctx.log_level); const log = new Logger(filename(import.meta.url), ctx.log_level);
const parse = new CommandParser(ctx); const parse = new CommandParser(ctx);
const checkGuild = guild => { const checkGuild = (guild) => {
if (!cfg.whitelist.includes(guild.id)) { if (!cfg.whitelist.includes(guild.id)) {
log.info(`Leaving guild not on whitelist: ${guild.name}`); log.info(`Leaving guild not on whitelist: ${guild.name}`);
guild.leave(); guild.leave();
} }
}; };
bot.on("ready", () => { bot.on('ready', () => {
log.info("ready recieved."); log.info('ready recieved.');
bot.guilds.forEach(guild => checkGuild(guild)); bot.guilds.forEach((guild) => checkGuild(guild));
}); });
bot.on("guildAvaliable", guild => checkGuild(guild)); bot.on('guildAvaliable', (guild) => checkGuild(guild));
bot.on("messageCreate", msg => parse.parseMsg(msg, ctx)); bot.on('messageCreate', (msg) => parse.parseMsg(msg, ctx));
bot.connect(); bot.connect();
async function load_commands() { async function load_commands() {
for (let file of files) { for (let file of files) {
let p = path.join(cmd_dir, file); let p = path.join(cmd_dir, file);
log.debug(p); log.debug(p);
let obj; let obj;
try { try {
obj = await import ("file:////" + p); obj = await import('file:////' + p);
} catch (e) { } catch (e) {
log.warn(`loading file ${file}, ran into issue: ${e.message}`); log.warn(`loading file ${file}, ran into issue: ${e.message}`);
continue; continue;
} }
if (obj.default != undefined) { if (obj.default != undefined) {
if (obj.default.constructor.name == "CommandInitializer") { if (obj.default.constructor.name == 'CommandInitializer') {
obj.default.initialize(ctx); obj.default.initialize(ctx);
let cmds = obj.default.getCommands(); let cmds = obj.default.getCommands();
if (parse.isCmd(cmds)) { if (parse.isCmd(cmds)) {
parse.addCommand(cmds); parse.addCommand(cmds);
} else if (cmds.constructor.name == "Array") { } else if (cmds.constructor.name == 'Array') {
for (let cmd of cmds) { for (let cmd of cmds) {
parse.addCommand(cmd); parse.addCommand(cmd);
} }
} }
} }
} else { } else {
log.warn("module " + file + " returned an undefined module."); log.warn('module ' + file + ' returned an undefined module.');
} }
} }
} }
let cmd_dir = path.join(dir, "cmd"); let cmd_dir = path.join(dir, 'cmd');
log.debug(dir); log.debug(dir);
let files = fs.readdirSync(cmd_dir); let files = fs.readdirSync(cmd_dir);
load_commands(); load_commands();

View file

@ -1,24 +1,40 @@
import {CommandInitializer, Command} from "../parser.js"; import { CommandInitializer, Command } from '../parser.js';
import parse, {instructions} from "../lights/light_parser.js"; import parse, { initialize, instructions } from '../lights/light_parser.js';
import req from '../lights/request.js';
const initializer = new CommandInitializer(); const initializer = new CommandInitializer();
class LightsParser extends Command { class LightsParser extends Command {
init(ctx, log) { init(ctx, log) {
this.log = log; this.log = log;
} initialize(ctx);
name = "lights"; }
func(msg, args, ctx) { name = 'lights';
let instructions = parse(args[0]); whitelist = true;
func(msg, args, ctx) {
if (!args.length) {
msg.channel.createMessage('no args found.');
return;
}
let instructions = parse(args[0]);
this.log.debug(instructions); this.log.debug(instructions);
let res = "```\n"; let res = '```\n';
instructions.forEach(instruction => { instructions.forEach((instruction) => {
res += JSON.stringify(instruction) + "\n"; res += JSON.stringify(instruction) + '\n';
}); });
res += "```"; res += '```';
msg.channel.createMessage(`parsed instructions:\n${res}`); msg.channel.createMessage(`parsed instructions:\n${res}`);
} req(
instructions.filter((i) => i.valid),
(response) => {
msg.channel.createMessage(`${response.statusCode}`);
},
(error) => {
msg.channel.createMessage(`error.`);
}
);
}
} }
initializer.addCommand(new LightsParser()); initializer.addCommand(new LightsParser());

View file

@ -1,14 +1,18 @@
import {CommandInitializer, Command} from "../parser.js"; import { CommandInitializer, Command } from '../parser.js';
const initializer = new CommandInitializer(); const initializer = new CommandInitializer();
class PingCommand extends Command { class PingCommand extends Command {
name = "ping"; name = 'ping';
func(msg, args, ctx) { func(msg, args, ctx) {
msg.channel.createMessage("p").then(m => { 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}`); 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()); initializer.addCommand(new PingCommand());

View file

@ -1,49 +1,137 @@
import Logger, { levels } from '../logger.js';
import { filename } from '../utils.js';
const log = new Logger(filename(import.meta.url), levels.PANIC);
class Target { class Target {
constructor(channel) { constructor(channel) {
this.channel = channel; this.channel = channel;
} }
channel; channel;
value; value;
} }
const available_targets = { const available_targets = {
r: new Target("r"), r: new Target('r'),
g: new Target("g"), g: new Target('g'),
b: new Target("b") b: new Target('b'),
stack: new Target('stack'),
}; };
class Instruction { class Instruction {
constructor(t1ets, args) { constructor(name, targets, args) {
let valid_targets = []; let valid_targets = [];
targets.forEach(t => { targets.forEach((t) => {
if (t instanceof Target) { if (t instanceof Target) {
let match = Object.keys(available_targets).find(key => available_targets[key].channel === t.channel); let match = Object.keys(available_targets).find((key) => available_targets[key].channel === t.channel);
if (match) { if (match) {
valid_targets.push(t); valid_targets.push(t);
} }
} }
}); });
this.targets = valid_targets; this.name = name;
this.args = args; this.targets = valid_targets;
} this.args = args;
name; }
targets; name;
args; targets;
transform(index, time, channel_target, channel_in) {} args;
transformAll(index, time) {
let new_targets = [];
this.targets.forEach(target => {
this.transform(index, time, target, this.args);
});
}
} }
class ConstantColor extends Instruction { export const instructions = [
name = "CONSTANT"; { n: 'CONSTANT', a: true },
transform(index, time, channel_target) {} { n: 'ADD', a: true },
{ n: 'SUB', a: true },
{ n: 'RAND', a: false },
];
export function initialize(ctx) {
log.s(ctx.log_level);
}
function parseSingleInstruction(str = '') {
let item = {
valid: false,
instruction: undefined,
errors: undefined,
};
let split = str.split(' ');
let cmd = split[0];
let match = instructions.filter((i) => i.n == cmd.toUpperCase());
split = split.slice(1);
if (match.length) {
let inst_targets = [];
let inst_args = [];
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;
}
}
inst_targets = parsed_args[0]
.split(',')
.map((s) => s.trim())
.map((t) => new Target(t));
if (!inst_targets.length) {
item.errors = 'No valid targets.';
}
inst_targets.forEach((t) => {
let match = Object.keys(available_targets).find((key) => available_targets[key].channel === t.channel);
if (!match) {
item.errors = `Invalid target: ${t.channel}`;
}
});
if (match[0].a) {
if (parsed_args.length < 2) {
item.errors = 'Not enough arguments.';
return item;
}
inst_args = parsed_args[1].split(',').map((s) => (s == 'stack' ? 'stack' : parseInt(s.trim())));
if (!inst_args.length) {
item.errors = 'No valid args.';
}
inst_args.forEach((arg) => {
if (!arg) {
item.errors = 'An argument is null or undefined.';
}
});
}
if (item.errors) {
return item;
}
item.instruction = new Instruction(match[0].n, inst_targets, inst_args || []);
} else {
item.errors = 'No command matched.';
return item;
}
item.valid = true;
return item;
} }
export const instructions = [ConstantColor];
export default function parse(str) { export default function parse(str) {
return [{}]; let parsed = [];
let split = str.split('\n');
split.forEach((item) => {
let parsedItem = parseSingleInstruction(item);
parsed.push(parsedItem);
log.debug(item);
});
return parsed;
} }

18
lights/request.js Normal file
View file

@ -0,0 +1,18 @@
import * as https from 'https';
const options = {
hostname: '192.168.1.219',
port: '29999',
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
};
export default function req(data, callback, errorCallback) {
const request = https.request(options, (res) => callback(res));
request.on('error', (error) => errorCallback(error));
request.write(JSON.stringify(data));
request.end();
}

View file

@ -1,54 +1,51 @@
export const levels = { export const levels = {
DEBUG: 4, DEBUG: 4,
INFO: 3, INFO: 3,
WARN: 2, WARN: 2,
ERROR: 1, ERROR: 1,
PANIC: 0 PANIC: 0,
} };
export default class Logger { export default class Logger {
constructor(name, level) { constructor(name, level) {
console.log(`created new logger for ${name} with level ${level}`) console.log(`created new logger for ${name} with level ${level}`);
this.sn(name); this.sn(name);
this.s(level); this.s(level);
} }
n = "DEFAULT"; n = 'DEFAULT';
l = 0; l = 0;
sn(n) { sn(n) {
this.n = n; this.n = n;
} }
s(l) { s(l) {
if(l && l.constructor === Number) { if (l && l.constructor === Number) {
this.l = l this.l = l;
} } else {
else { this.l = levels[l];
this.l = levels[l]; }
} }
}
lo(l, m) { lo(l, m) {
if (l <= this.l) { if (l <= this.l) {
let level = Object.keys(levels).find(key => levels[key] === l); let level = Object.keys(levels).find((key) => levels[key] === l);
let ms = typeof m == "object" let ms = typeof m == 'object' ? JSON.stringify(m) : m;
? JSON.stringify(m) console.log(`${level} [${this.n}]: ${ms}`);
: m; }
console.log(`${level} [${this.n}]: ${ms}`); }
}
}
debug(msg) { debug(msg) {
this.lo(levels.DEBUG, msg); this.lo(levels.DEBUG, msg);
} }
info(msg) { info(msg) {
this.lo(levels.INFO, msg); this.lo(levels.INFO, msg);
} }
warn(msg) { warn(msg) {
this.lo(levels.WARN, msg); this.lo(levels.WARN, msg);
} }
error(msg) { error(msg) {
this.lo(levels.ERROR, msg); this.lo(levels.ERROR, msg);
} }
panic(msg) { panic(msg) {
this.lo(levels.PANIC, msg); this.lo(levels.PANIC, msg);
} }
} }

174
parser.js
View file

@ -1,95 +1,117 @@
import Logger, {levels} from "./logger.js"; import Logger, { levels } from './logger.js';
import {filename} from "./utils.js"; import { filename } from './utils.js';
export class Command { export class Command {
init(ctx, log) { init(ctx, log) {
this.log = log; this.log = log;
} }
log; log;
name = "DEFAULT"; name = 'DEFAULT';
func() {} whitelist = false;
func() {}
} }
export class CommandInitializer { export class CommandInitializer {
commands = []; commands = [];
uninitialized = []; uninitialized = [];
initialize(ctx) { initialize(ctx) {
for (let index in this.uninitialized) { for (let index in this.uninitialized) {
this.initCommand(this.uninitialized[index], ctx); this.initCommand(this.uninitialized[index], ctx);
delete this.uninitialized[index]; delete this.uninitialized[index];
} }
} }
initCommand(cmd, ctx) { initCommand(cmd, ctx) {
cmd.init(ctx, new Logger(`cmd.${cmd.name}`, ctx.log_level)); cmd.init(ctx, new Logger(`cmd.${cmd.name}`, ctx.log_level));
this.commands.push(cmd); this.commands.push(cmd);
} }
addCommand(cmd) { addCommand(cmd) {
this.uninitialized.push(cmd); this.uninitialized.push(cmd);
} }
getCommands() { getCommands() {
return this.commands; return this.commands;
} }
} }
export default class CommandParser { export default class CommandParser {
constructor(ctx, prefix = ";") { constructor(ctx, prefix = ';') {
this.log = new Logger(filename(import.meta.url), ctx.log_level); this.log = new Logger(filename(import.meta.url), ctx.log_level);
this.prefix = prefix this.prefix = prefix ? prefix : this.prefix;
? prefix }
: this.prefix; log;
} prefix;
log; commands = [];
prefix;
commands = [];
addCommand(cmd) { addCommand(cmd) {
this.log.debug(`cmd to add: ${JSON.stringify(cmd)}`); this.log.debug(`cmd to add: ${JSON.stringify(cmd)}`);
if (this.isCmd(cmd)) { if (this.isCmd(cmd)) {
this.commands.push(cmd); this.commands.push(cmd);
} }
} }
hasCmd(str) { hasCmd(str) {
let results = this.commands.filter(c => c.name == str); let results = this.commands.filter((c) => c.name == str);
return results.length return results.length ? results[0] : undefined;
? results[0] }
: undefined;
}
isCmd(cmd) { isCmd(cmd) {
return typeof cmd == "object" && cmd instanceof Command; return typeof cmd == 'object' && cmd instanceof Command;
} }
getArgsList(args) { getArgsList(split) {
return [args]; 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) { parseMsg(msg, ctx) {
if (msg.author.bot) { if (msg.author.bot) {
return; return;
} }
this.log.debug(msg.content); this.log.debug(msg.content);
this.log.debug(msg.content.startsWith(this.prefix)); this.log.debug(msg.content.startsWith(this.prefix));
this.log.debug(msg.content[0]); this.log.debug(msg.content[0]);
this.log.debug(this.prefix); this.log.debug(this.prefix);
if (msg.content.startsWith(this.prefix)) { if (msg.content.startsWith(this.prefix)) {
let snip = msg.content.slice(this.prefix.length); let snip = msg.content.slice(this.prefix.length);
let unsep = snip.split(" "); let unsep = snip.split(' ');
let res = this.hasCmd(unsep[0]); let res = this.hasCmd(unsep[0]);
let args = this.getArgsList(unsep.slice(1).join(" ")); let args = this.getArgsList(unsep.slice(1));
this.log.debug(snip); this.log.debug(snip);
this.log.debug(res); this.log.debug(res);
this.log.debug(args); this.log.debug(args);
if (res != undefined) { if (res != undefined) {
this.log.debug(`execute function ${res.name}`); this.log.debug(`execute function ${res.name}`);
res.func(msg, args, ctx); if (res.whitelist && ctx.whitelist.indexOf(msg.author.id) == -1) {
} msg.channel.createMessage('not whitelisted');
} } else {
} res.func(msg, args, ctx);
} }
}
}
}
}