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

41
bot.js
View File

@ -1,39 +1,40 @@
import {createRequire} from "module";
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";
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 cfg = require('./config.json');
const dir = dirname(import.meta.url);
const bot = new Eris(cfg.token);
const ctx = {
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 parse = new CommandParser(ctx);
const checkGuild = guild => {
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('ready', () => {
log.info('ready recieved.');
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();
@ -43,30 +44,30 @@ async function load_commands() {
log.debug(p);
let obj;
try {
obj = await import ("file:////" + p);
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") {
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") {
} else if (cmds.constructor.name == 'Array') {
for (let cmd of cmds) {
parse.addCommand(cmd);
}
}
}
} 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);
let files = fs.readdirSync(cmd_dir);
load_commands();

View File

@ -1,23 +1,39 @@
import {CommandInitializer, Command} from "../parser.js";
import parse, {instructions} from "../lights/light_parser.js";
import { CommandInitializer, Command } from '../parser.js';
import parse, { initialize, instructions } from '../lights/light_parser.js';
import req from '../lights/request.js';
const initializer = new CommandInitializer();
class LightsParser extends Command {
init(ctx, log) {
this.log = log;
initialize(ctx);
}
name = "lights";
name = 'lights';
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);
let res = "```\n";
instructions.forEach(instruction => {
res += JSON.stringify(instruction) + "\n";
let res = '```\n';
instructions.forEach((instruction) => {
res += JSON.stringify(instruction) + '\n';
});
res += "```";
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());

View File

@ -1,12 +1,16 @@
import {CommandInitializer, Command} from "../parser.js";
import { CommandInitializer, Command } from '../parser.js';
const initializer = new CommandInitializer();
class PingCommand extends Command {
name = "ping";
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}`);
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
}`
);
});
}
}

View File

@ -1,3 +1,8 @@
import Logger, { levels } from '../logger.js';
import { filename } from '../utils.js';
const log = new Logger(filename(import.meta.url), levels.PANIC);
class Target {
constructor(channel) {
this.channel = channel;
@ -7,43 +12,126 @@ class Target {
}
const available_targets = {
r: new Target("r"),
g: new Target("g"),
b: new Target("b")
r: new Target('r'),
g: new Target('g'),
b: new Target('b'),
stack: new Target('stack'),
};
class Instruction {
constructor(t1ets, args) {
constructor(name, targets, args) {
let valid_targets = [];
targets.forEach(t => {
targets.forEach((t) => {
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) {
valid_targets.push(t);
}
}
});
this.name = name;
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);
}
export const instructions = [
{ n: 'CONSTANT', a: true },
{ 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;
}
class ConstantColor extends Instruction {
name = "CONSTANT";
transform(index, time, channel_target) {}
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) {
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

@ -3,35 +3,32 @@ export const levels = {
INFO: 3,
WARN: 2,
ERROR: 1,
PANIC: 0
}
PANIC: 0,
};
export default class Logger {
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.s(level);
}
n = "DEFAULT";
n = 'DEFAULT';
l = 0;
sn(n) {
this.n = n;
}
s(l) {
if (l && l.constructor === Number) {
this.l = l
}
else {
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;
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}`);
}
}

View File

@ -1,12 +1,13 @@
import Logger, {levels} from "./logger.js";
import {filename} from "./utils.js";
import Logger, { levels } from './logger.js';
import { filename } from './utils.js';
export class Command {
init(ctx, log) {
this.log = log;
}
log;
name = "DEFAULT";
name = 'DEFAULT';
whitelist = false;
func() {}
}
@ -36,11 +37,9 @@ export class CommandInitializer {
}
export default class CommandParser {
constructor(ctx, prefix = ";") {
constructor(ctx, prefix = ';') {
this.log = new Logger(filename(import.meta.url), ctx.log_level);
this.prefix = prefix
? prefix
: this.prefix;
this.prefix = prefix ? prefix : this.prefix;
}
log;
prefix;
@ -54,19 +53,38 @@ export default class CommandParser {
}
hasCmd(str) {
let results = this.commands.filter(c => c.name == str);
let results = this.commands.filter((c) => c.name == str);
return results.length
? results[0]
: undefined;
return results.length ? results[0] : undefined;
}
isCmd(cmd) {
return typeof cmd == "object" && cmd instanceof Command;
return typeof cmd == 'object' && cmd instanceof Command;
}
getArgsList(args) {
return [args];
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) {
@ -79,17 +97,21 @@ export default class CommandParser {
this.log.debug(this.prefix);
if (msg.content.startsWith(this.prefix)) {
let snip = msg.content.slice(this.prefix.length);
let unsep = snip.split(" ");
let unsep = snip.split(' ');
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(res);
this.log.debug(args);
if (res != undefined) {
this.log.debug(`execute function ${res.name}`);
if (res.whitelist && ctx.whitelist.indexOf(msg.author.id) == -1) {
msg.channel.createMessage('not whitelisted');
} else {
res.func(msg, args, ctx);
}
}
}
}
}