Skip to content

Instantly share code, notes, and snippets.

@ianjsikes
Last active June 7, 2020 04:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ianjsikes/07ccd857142c903b4125ee302257b2aa to your computer and use it in GitHub Desktop.
Save ianjsikes/07ccd857142c903b4125ee302257b2aa to your computer and use it in GitHub Desktop.
class CommandParser {
constructor(trigger) {
this.trigger = trigger;
this.defaultCmd;
this.subCmds = {};
}
default(action) {
this.defaultCmd = { action };
return this;
}
command(name, action) {
this.subCmds[name] = { action };
return this;
}
handleMessage(msg) {
if (msg.type !== 'api') return;
let content = msg.content.trim();
if (!content.startsWith(this.trigger)) return;
let [_trigger, subCommand, ...args] = content.split(' ');
if (
!subCommand ||
subCommand.startsWith('--') ||
!(subCommand in this.subCmds)
) {
if (this.defaultCmd) {
const opts = this.parseArgs([subCommand, ...args]);
this.defaultCmd.action(opts, msg);
} else {
this.showHelp();
}
} else {
if (subCommand in this.subCmds) {
const opts = this.parseArgs(args);
this.subCmds[subCommand].action(opts, msg);
} else {
this.showHelp();
}
}
}
parseArgs(args) {
let options = args.reduce(
(opts, arg) => {
if (!arg) return opts;
if (arg.startsWith('--')) {
let [key, val] = arg.slice(2).split('=');
return { ...opts, [key]: val === undefined ? true : val };
}
return {
...opts,
_: [...opts._, arg],
};
},
{ _: [] }
);
return options;
}
showHelp() {}
}
const ScriptBase = ({ name, version, stateKey = name, initialState = {} }) =>
class {
version = version;
name = name;
get state() {
if (!state[stateKey]) {
state[stateKey] = initialState;
}
return state[stateKey];
}
onMessage = (msg) => {
if (!this.parser) return;
try {
this.parser.handleMessage(msg);
} catch (err) {
log(`${name} ERROR: ${err.message}`);
sendChat(
`${name} ERROR:`,
`/w ${msg.who.replace(/\(GM\)/, '').trim()} ${err.message}`
);
}
};
constructor() {
on('chat:message', this.onMessage);
on('ready', () => {
log(`\n[====== ${name} v${version} ======]`);
});
}
resetState(newState = initialState) {
state[stateKey] = newState;
}
};
class _MyCoolScript extends ScriptBase({
name: 'MyCoolScript',
version: '0.1.0',
stateKey: 'MY_COOL_SCRIPT',
initialState: { favoriteColor: 'blue' },
}) {
constructor() {
super();
// Here is where you can register additional event handlers:
// on('change:graphic', this.onChangeGraphic);
}
parser = new CommandParser('!cool-script')
.default(() => {
sendChat(this.name, `My favorite color is ${this.state.favoriteColor}`);
})
.command('set', this.setColor);
setColor = (opts, msg) => {
// CommandParser puts arguments into the `opts` parameter. If the argument
// is a flag like `--name=Bob`, opts will be an object like `{ name: 'Bob', _: [] }`
// If the argument is NOT a flag, it will go into the array like `{ _: ['First', 'Second'] }`
// Here, the usage is `!cool-script set blue`, so opts looks like `{ _: ['blue'] }`
const newColor = opts._[0];
if (!newColor) {
throw new Error("Please specify a color!")
}
this.state.favoriteColor = newColor;
}
}
const MyCoolScript = new _MyCoolScript();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment