initial push
This commit is contained in:
commit
09dae249ef
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{bat,cmd}]
|
||||
end_of_line = crlf
|
3
.eslintrc.json
Normal file
3
.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends" : "@edenjs/eden"
|
||||
}
|
22
.gitattributes
vendored
Normal file
22
.gitattributes
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# Automatically normalize line endings for all text-based files
|
||||
# http://git-scm.com/docs/gitattributes#_end_of_line_conversion
|
||||
* text=auto
|
||||
|
||||
# For the following file types, normalize line endings to LF on
|
||||
# checkin and prevent conversion to CRLF when they are checked out
|
||||
# (this is required in order to prevent newline related issues like,
|
||||
# for example, after the build script is run)
|
||||
.* text eol=lf
|
||||
*.css text eol=lf
|
||||
*.html text eol=lf
|
||||
*.jade text eol=lf
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.less text eol=lf
|
||||
*.scss text eol=lf
|
||||
*.md text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.xml text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
52
.gitignore
vendored
Normal file
52
.gitignore
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
# Debug log from npm
|
||||
npm-debug.log
|
||||
|
||||
# Error log from yarn
|
||||
yarn-error.log
|
||||
|
||||
# yarn lock - do work pls
|
||||
yarn.lock
|
||||
|
||||
# nodejs modules
|
||||
node_modules/
|
||||
|
||||
# edenjs stuff
|
||||
data/
|
||||
config.js
|
||||
edenappconfig.js
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
.remote-sync.json
|
||||
|
||||
# Log and Sentry
|
||||
*.log
|
||||
*.sentry
|
||||
|
||||
# Redis
|
||||
*.rdb
|
||||
|
||||
# sqlite files
|
||||
*.db
|
||||
*.sdb
|
||||
*.sqlite
|
||||
*.db3
|
||||
*.s3db
|
||||
*.sqlite3
|
||||
*.sl3
|
||||
*.db2
|
||||
*.s2db
|
||||
*.sqlite2
|
||||
*.sl2
|
||||
|
||||
# Other junk
|
||||
.*.swp
|
||||
._*
|
||||
.DS_Store
|
||||
.hg
|
||||
.npmrc
|
||||
.lock-wscript
|
||||
.svn
|
||||
.wafpickle-*
|
||||
config.gypi
|
||||
CVS
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"eslint.enable": true
|
||||
}
|
755
bundles/chatbot/daemons/chatbot.js
Normal file
755
bundles/chatbot/daemons/chatbot.js
Normal file
@ -0,0 +1,755 @@
|
||||
const Daemon = require('daemon');
|
||||
const config = require('config');
|
||||
const messageArgsParser = require('parsers/chatbot/messageparts');
|
||||
const { EventEmitter } = require('events');
|
||||
const equal = require('deep-equal');
|
||||
|
||||
const User = model('user');
|
||||
const Chat = model('chat');
|
||||
|
||||
const chatHelper = helper('chat');
|
||||
|
||||
const setChatDefaults = require('../includes/chatdefaults.js');
|
||||
|
||||
const EMOJI_LIST = ['🇦', '🇧', '🇨', '🇩', '🇪', '🇫', '🇬', '🇭', '🇮', '🇯', '🇰', '🇱', '🇲', '🇳', '🇴', '🇵', '🇶', '🇷', '🇸', '🇹', '🇺', '🇻', '🇼', '🇽', '🇾', '🇿'];
|
||||
const CANCEL_EMOJI = '🚫';
|
||||
|
||||
async function carelessCall(fn) {
|
||||
try { await fn(); } catch (_) { /* whocare */ }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Chat Bot Daemon Class
|
||||
*
|
||||
* @cluster bot
|
||||
*/
|
||||
class ChatBot extends Daemon {
|
||||
/**
|
||||
* Construct Chat Bot Daemon Class
|
||||
*/
|
||||
constructor() {
|
||||
// Run super
|
||||
super();
|
||||
|
||||
this._commandRegistry = [];
|
||||
this._argRegistry = new Map();
|
||||
this._responseRegistry = new Map();
|
||||
|
||||
this._events = new EventEmitter();
|
||||
this._events.on('error', err => global.printError(err));
|
||||
|
||||
setChatDefaults(this);
|
||||
|
||||
// Run build
|
||||
this.building = this.build();
|
||||
|
||||
this.eden.endpoint('chatbot.setResponse', async (...args) => {
|
||||
return await this.setResponse(...args);
|
||||
}, false);
|
||||
|
||||
this.eden.endpoint('chatbot.setArg', async (...args) => {
|
||||
return await this.setArg(...args);
|
||||
}, false);
|
||||
|
||||
this.eden.endpoint('chatbot.addCommand', async (...args) => {
|
||||
return await this.addCommand(...args);
|
||||
}, false);
|
||||
|
||||
this.eden.endpoint('chatbot.setStatus', async (...args) => {
|
||||
return await this.setStatus(...args);
|
||||
}, false);
|
||||
|
||||
this.eden.endpoint('chatbot.respond', async (...args) => {
|
||||
return await this.respond(...args);
|
||||
}, false);
|
||||
|
||||
this.eden.endpoint('chatbot.isReady', () => {
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
this.eden.emit('chatbot.ready', false);
|
||||
}
|
||||
|
||||
async setStatus(name) {
|
||||
// i feel dirty
|
||||
chatHelper.member.set(this._botUser, { get() { return ''; }, set() {} }, 'playing', name);
|
||||
}
|
||||
|
||||
async _getResponse(responseName) {
|
||||
let registeredResponse = this._responseRegistry.get(responseName);
|
||||
|
||||
if (!registeredResponse) {
|
||||
registeredResponse = await new Promise(resolve => this._events.on(`addedResponse.${responseName}`, resolve));
|
||||
}
|
||||
|
||||
return registeredResponse;
|
||||
}
|
||||
|
||||
async setResponse(name, fn) {
|
||||
const response = async (...responseArgs) => {
|
||||
const getResponse = async a => this._getResponse(a);
|
||||
return await fn(getResponse, ...responseArgs);
|
||||
};
|
||||
|
||||
this._responseRegistry.set(name, response);
|
||||
this._events.emit(`addedResponse.${name}`, response);
|
||||
}
|
||||
|
||||
async setArg(typeName, opts) {
|
||||
const arg = {
|
||||
query : opts.query || (name => `Please enter \`${name}\``),
|
||||
|
||||
handle : opts.handle ? opts.handle : v => v,
|
||||
|
||||
getOptions : opts.getOptions || null,
|
||||
strict : opts.strict || false,
|
||||
strictCheck : opts.strictCheck || false,
|
||||
|
||||
schemas : opts.schemas || [],
|
||||
};
|
||||
|
||||
this._argRegistry.set(typeName, arg);
|
||||
this._events.emit(`addedArg.${typeName}`, arg);
|
||||
}
|
||||
|
||||
async addCommand(rawSchemas, fn = null, desc = null, emoji = null, ver = 1) {
|
||||
// If rawSchemas is singular wrap in an array
|
||||
if (!(rawSchemas instanceof Array)) rawSchemas = [rawSchemas];
|
||||
|
||||
// Be able to handle addCommand(schemas, desc, emoji?, ver?)
|
||||
if (typeof fn === 'string') {
|
||||
ver = emoji;
|
||||
emoji = desc;
|
||||
desc = fn;
|
||||
fn = null;
|
||||
}
|
||||
|
||||
const schemas = rawSchemas.map((rawSchema) => {
|
||||
let schema = [];
|
||||
|
||||
if (typeof rawSchema === 'string') {
|
||||
for (const schemaPart of rawSchema.split(' ')) {
|
||||
if (schemaPart[0] === '[' && schemaPart[schemaPart.length - 1] === ']') {
|
||||
const [partName, argType] = schemaPart.slice(1, -1).split(':');
|
||||
schema.push({ name : partName, argType });
|
||||
} else {
|
||||
schema.push({ type : 'text', text : schemaPart });
|
||||
}
|
||||
}
|
||||
} else if (rawSchema instanceof Array) {
|
||||
schema = rawSchema;
|
||||
}
|
||||
|
||||
return schema;
|
||||
});
|
||||
|
||||
// Wait for all args to be defined
|
||||
for (const schema of schemas) {
|
||||
for (const schemaPart of schema) {
|
||||
if (schemaPart.name === undefined || schemaPart.name === null) continue;
|
||||
|
||||
if (!this._argRegistry.get(schemaPart.argType)) {
|
||||
await new Promise(resolve => this._events.on(`addedArg.${schemaPart.argType}`, resolve));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._commandRegistry.push({
|
||||
schemas, fn, desc, emoji, ver,
|
||||
});
|
||||
}
|
||||
|
||||
async build() {
|
||||
this.eden.on('eden.chat.message', async (messageData) => {
|
||||
try { await this._onRawMesage(messageData); } catch (err) {
|
||||
global.printError(err);
|
||||
}
|
||||
}, true);
|
||||
|
||||
this._botUser = await User.findById(config.get('chatbot.userId'));
|
||||
}
|
||||
|
||||
async respond(chat, responseName, ...responseArgs) {
|
||||
await this._respond(chat, responseName, ...responseArgs);
|
||||
}
|
||||
|
||||
async dm(user, responseName, ...responseArgs) {
|
||||
const chat = await chatHelper.create(user, [user, this._botUser], { type : 'dm' });
|
||||
await this._respond(chat, responseName, ...responseArgs);
|
||||
}
|
||||
|
||||
async _respond(chat, responseName, ...responseArgs) {
|
||||
const registeredResponse = await this._getResponse(responseName);
|
||||
const response = await registeredResponse(...responseArgs);
|
||||
|
||||
return await chatHelper.message.send(this._botUser, chat, {
|
||||
message : response.message || '',
|
||||
react : (response.reactions || []).reduce((a, c) => { a[c] = { [this._botUser.get('_id')] : new Date() }; return a; }, {}),
|
||||
embeds : [{
|
||||
primary : true,
|
||||
buttons : response.buttons || [],
|
||||
fields : response.fields || [],
|
||||
image : response.image || null,
|
||||
color : response.color || [],
|
||||
thumbnail : response.thumbnail || null,
|
||||
url : response.url || null,
|
||||
title : response.title || null,
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
async _callInputArgHandles(message, inputArg, argMap) {
|
||||
const argDef = this._argRegistry.get(inputArg.commandArg.argType);
|
||||
|
||||
const matchingSchema = argDef.schemas.find(s => equal(this._argToSchema(inputArg.arg), s));
|
||||
if (!matchingSchema) return [null, await this.respond(message.chat, 'badType')];
|
||||
|
||||
if (argDef.handle !== null) {
|
||||
try {
|
||||
const handleRes = await argDef.handle(inputArg.arg, message.from, argMap);
|
||||
if (handleRes !== null && handleRes !== undefined) inputArg.arg = handleRes;
|
||||
} catch (err) {
|
||||
return [null, await this.respond(message.chat, 'handleError', err)];
|
||||
}
|
||||
}
|
||||
|
||||
if (argDef.strictCheck) {
|
||||
const options = await argDef.getOptions(message.from, argMap);
|
||||
if (!options.find(option => equal(option.val, inputArg.arg))) {
|
||||
return [null, await this.respond(message.chat, 'badType')];
|
||||
}
|
||||
}
|
||||
|
||||
return [inputArg, null];
|
||||
}
|
||||
|
||||
async _query(message, props) {
|
||||
// Automatically enable strict if strict checking enabled
|
||||
if (props.strictCheck) props.strict = true;
|
||||
|
||||
// If strict, handle having 1 or 0 options automatically
|
||||
if (props.strict && props.options !== null) {
|
||||
if (props.options.length === 1) {
|
||||
return [props.options[0].val, true, null]; // lol
|
||||
} if (props.options.length === 0) {
|
||||
return [null, null, await this._respond(message.chat, 'noValidArg')];
|
||||
}
|
||||
}
|
||||
|
||||
await this.eden.set(`chatbot.awaitingreply.${message.from.get('_id')}`, this.eden.cluster + this.eden.id, 1000 * 40);
|
||||
|
||||
const safeOptions = props.options ? props.options.slice(0, 19) : [];
|
||||
|
||||
const buttons = safeOptions.map((option, i) => {
|
||||
return {
|
||||
emoji : option.emoji || EMOJI_LIST[i],
|
||||
label : option.label,
|
||||
id : i,
|
||||
};
|
||||
});
|
||||
|
||||
const rawQueryMessage = await this._respond(message.chat, 'query', {
|
||||
message : props.message,
|
||||
fields : safeOptions.length >= 1 ? [{
|
||||
name : 'Options:',
|
||||
text : safeOptions.map((option, i) => {
|
||||
return `${option.emoji || EMOJI_LIST[i]} - **${option.label}** - ${option.desc}`;
|
||||
}).join('\n'),
|
||||
}] : [],
|
||||
buttons : [{ emoji : CANCEL_EMOJI, label : 'cancel', id : 'cancel' }, ...buttons],
|
||||
});
|
||||
|
||||
let [replyArg, replyButtonID, foundCommandData] = [null, null];
|
||||
|
||||
// Create promise and hoist the resolve and reject methods
|
||||
let responsePromiseResolve = null;
|
||||
let responsePromiseReject = null;
|
||||
const responsePromise = new Promise((resolve, reject) => {
|
||||
responsePromiseResolve = resolve;
|
||||
responsePromiseReject = reject;
|
||||
});
|
||||
|
||||
// Create timeout for this query
|
||||
setTimeout(() => {
|
||||
responsePromiseReject(new Error('timeout'));
|
||||
}, 1000 * 35);
|
||||
|
||||
// Create listener for button presses
|
||||
const buttonListener = ({ button, member }) => {
|
||||
if (member !== message.from.get('_id')) return;
|
||||
responsePromiseResolve([null, button.id, null]);
|
||||
};
|
||||
|
||||
// Create listener for replies
|
||||
const replyListener = (recievedReplyArgs, recievedReplyText) => {
|
||||
if (recievedReplyArgs.length === 0) {
|
||||
responsePromiseResolve([null, null, null]);
|
||||
return;
|
||||
}
|
||||
|
||||
const [registeredCommand, inputArgMap] = this._findRegisteredCommand(recievedReplyArgs);
|
||||
|
||||
if (recievedReplyArgs.length > 1 && registeredCommand !== null) {
|
||||
responsePromiseResolve([null, null, [recievedReplyArgs, registeredCommand, inputArgMap]]);
|
||||
} else if (props.allowText && recievedReplyArgs.length > 1 && recievedReplyArgs[0].type === 'text' && registeredCommand === null) {
|
||||
responsePromiseResolve([{ type : 'text', text : recievedReplyText }, null, null]);
|
||||
} else {
|
||||
responsePromiseResolve([recievedReplyArgs[0], null, null]);
|
||||
}
|
||||
};
|
||||
|
||||
// Register the listeners to events
|
||||
this._events.once(`reply.${message.from.get('_id')}`, replyListener);
|
||||
this.eden.on(`eden.chat.message.buttonPress.${rawQueryMessage.get('_id')}`, buttonListener, true);
|
||||
|
||||
// Macro to remove listeners and the query message
|
||||
const done = async () => {
|
||||
try {
|
||||
await this.eden.del(`chatbot.awaitingreply.${message.from.get('_id')}`);
|
||||
carelessCall(async () => await chatHelper.message.remove(rawQueryMessage));
|
||||
} catch (err) {
|
||||
global.printError(err);
|
||||
}
|
||||
|
||||
this._events.off(`reply.${message.from.get('_id')}`, replyListener);
|
||||
this.eden.off(`eden.chat.message.buttonPress.${rawQueryMessage.get('_id')}`, buttonListener);
|
||||
};
|
||||
|
||||
try {
|
||||
[replyArg, replyButtonID, foundCommandData] = await responsePromise;
|
||||
} catch (err) {
|
||||
await done();
|
||||
|
||||
if (err.message === 'timeout') {
|
||||
return [null, null, await this._respond(message.chat, 'queryTimeout')];
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
await done();
|
||||
|
||||
if (replyArg !== null) {
|
||||
if (replyArg.type === 'text' && replyArg.text === 'cancel') {
|
||||
return [null, null, await this._respond(message.chat, 'argCancelled')];
|
||||
}
|
||||
|
||||
if (safeOptions.find(o => equal(o.val, this._argToGeneric(replyArg)))) {
|
||||
return [replyArg, true, null];
|
||||
}
|
||||
|
||||
return [replyArg, false];
|
||||
} if (replyButtonID !== null) {
|
||||
if (replyButtonID === 'cancel') {
|
||||
return [null, null, await this._respond(message.chat, 'argCancelled')];
|
||||
}
|
||||
|
||||
return [safeOptions[replyButtonID].val, true, null];
|
||||
}
|
||||
|
||||
if (foundCommandData !== null) {
|
||||
const [args, registeredCommand, inputArgMap] = foundCommandData;
|
||||
this._handleCommandData(message, args, registeredCommand, inputArgMap, null);
|
||||
return [null, null, null];
|
||||
}
|
||||
|
||||
return [null, null, await this._respond(message.chat, 'argMissing')];
|
||||
}
|
||||
|
||||
async _queryForInputArg(message, missingArg, argMap, oldResponses = [], iters = 0) {
|
||||
const argDef = this._argRegistry.get(missingArg.argType);
|
||||
|
||||
const options = argDef.getOptions ? await argDef.getOptions(message.from, argMap) : null;
|
||||
|
||||
const [res, exact, queryResponse] = await this._query(message, {
|
||||
message : await argDef.query(missingArg.name),
|
||||
allowText : argDef.schemas.find(schema => schema.type === 'text'),
|
||||
strict : argDef.strict,
|
||||
options,
|
||||
});
|
||||
|
||||
oldResponses.forEach(async (response) => {
|
||||
if (response) carelessCall(async () => await chatHelper.message.remove(response));
|
||||
});
|
||||
|
||||
if (res !== null) {
|
||||
const fullArg = {
|
||||
arg : res,
|
||||
commandArg : missingArg,
|
||||
};
|
||||
|
||||
if (exact) return fullArg;
|
||||
|
||||
const [handledReply, handleResponse] = await this._callInputArgHandles(message, fullArg);
|
||||
|
||||
if (handledReply === null) {
|
||||
const responses = [queryResponse, handleResponse];
|
||||
return await this._queryForInputArg(message, missingArg, argMap, responses, iters + 1);
|
||||
}
|
||||
|
||||
return handledReply;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async _queryForMatchArg(message, options, oldResponses = [], iters = 0) {
|
||||
const [res, exact, queryResponse] = await this._query(message, {
|
||||
message : 'Choose a command',
|
||||
strict : true,
|
||||
options,
|
||||
});
|
||||
|
||||
oldResponses.forEach(async (response) => {
|
||||
if (response) carelessCall(async () => await chatHelper.message.remove(response));
|
||||
});
|
||||
|
||||
if (res === null) return null;
|
||||
|
||||
if (!exact) {
|
||||
const response = await this._respond(message.chat, 'cnf');
|
||||
return await this._queryForMatchArg(message, options, [response, queryResponse], iters + 1);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async _handleArgs(message, args) {
|
||||
const findRes = this._findRegisteredCommand(args);
|
||||
return await this._handleCommandData(message, args, ...findRes);
|
||||
}
|
||||
|
||||
async _processInputArg(message, map, argName, arg) {
|
||||
// Skip if entire input arg is null, not just the arg part, this is intentional
|
||||
if (arg === null) {
|
||||
map[argName] = null;
|
||||
} else if (arg.arg === null) {
|
||||
// Query to get the arg
|
||||
const queryRes = await this._queryForInputArg(message, arg.commandArg, map);
|
||||
// Return if the query was cancelled
|
||||
if (queryRes === null) throw new Error('cancelled');
|
||||
// Set arg in map to result
|
||||
map[argName] = queryRes.arg;
|
||||
} else {
|
||||
// Handle the provided arg
|
||||
const [handledInputArg, handleErrorResponse] = await this._callInputArgHandles(message, arg, map);
|
||||
|
||||
// If the arg was handled successfully
|
||||
if (handledInputArg !== null) {
|
||||
map[argName] = handledInputArg.arg;
|
||||
} else {
|
||||
// Query for a new arg instead
|
||||
const queryRes = await this._queryForInputArg(message, arg.commandArg, map);
|
||||
// Remove error message from handling
|
||||
carelessCall(async () => await chatHelper.message.remove(handleErrorResponse));
|
||||
// Return if the query was cancelled
|
||||
if (queryRes === null) throw new Error('cancelled');
|
||||
// Set arg in map to result
|
||||
map[argName] = queryRes.arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _handleCommandData(message, args, registeredCommand, inputArgMap, furtherMatches) {
|
||||
if (furtherMatches) {
|
||||
const options = furtherMatches.map(([furtherMatchCommand, furtherMatchArg]) => {
|
||||
return {
|
||||
label : furtherMatchArg.type === 'text' ? furtherMatchArg.text : furtherMatchArg.title,
|
||||
val : furtherMatchArg,
|
||||
desc : furtherMatchCommand.desc,
|
||||
emoji : furtherMatchCommand.emoji,
|
||||
};
|
||||
});
|
||||
|
||||
const furtherRes = await this._queryForMatchArg(message, options);
|
||||
if (furtherRes === null) throw new Error('dropped');
|
||||
|
||||
return await this._handleArgs(message, [...args, furtherRes]);
|
||||
}
|
||||
|
||||
if (registeredCommand !== null && inputArgMap !== null) {
|
||||
const processedInputArgMap = {};
|
||||
|
||||
for (const [inputArgName, inputArg] of Object.entries(inputArgMap)) {
|
||||
try {
|
||||
await this._processInputArg(message, processedInputArgMap, inputArgName, inputArg);
|
||||
} catch (err) {
|
||||
if (err.message === 'cancelled') throw new Error('dropped');
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Create easy public response macro
|
||||
const respondMacro = async (responseName, ...responseArgs) => {
|
||||
await this.respond(message.chat, responseName, ...responseArgs);
|
||||
};
|
||||
|
||||
// Create easy DM macro
|
||||
const dmMacro = async (responseName, ...responseArgs) => {
|
||||
await this.dm(message.from, responseName, ...responseArgs);
|
||||
if (message.chat.get('type') !== 'dm') await respondMacro('dmNote');
|
||||
};
|
||||
|
||||
// Create easy call macro
|
||||
const callMacro = async (...callArgs) => {
|
||||
return await this._handleArgs(message, callArgs);
|
||||
};
|
||||
|
||||
// Create easy call macro
|
||||
const queryMacro = async (...queryArgs) => {
|
||||
return await this._query(message, ...queryArgs);
|
||||
};
|
||||
|
||||
// Support legacy commands (oof)
|
||||
if (registeredCommand.ver === 1) {
|
||||
// Call the registered function
|
||||
return await registeredCommand.fn(respondMacro,
|
||||
new Proxy(processedInputArgMap, { get(k, v) { return (k[v] || null); } }),
|
||||
message.from,
|
||||
callMacro,
|
||||
queryMacro);
|
||||
}
|
||||
|
||||
return await registeredCommand.fn({
|
||||
public : respondMacro,
|
||||
dm : dmMacro,
|
||||
respond : respondMacro,
|
||||
args : new Proxy(processedInputArgMap, { get(k, v) { return (k[v] || null); } }),
|
||||
from : message.from,
|
||||
call : callMacro,
|
||||
query : queryMacro,
|
||||
isDM : message.chat.get('type') === 'dm',
|
||||
});
|
||||
}
|
||||
|
||||
// Respond with command not found
|
||||
await this.respond(message.chat, 'cnf');
|
||||
throw new Error('dropped');
|
||||
}
|
||||
|
||||
_commandMatchArgToGeneric({
|
||||
name, type, id, tag, text,
|
||||
}) {
|
||||
// Return if this is an input arg, not a match arg
|
||||
if (name !== null && name !== undefined) return null;
|
||||
if (type === 'tag') return { type, id, tag };
|
||||
if (type === 'text') return { type, text };
|
||||
return {}; // UNIMPLEMENTED
|
||||
}
|
||||
|
||||
// Create generic form of arg, will equal to match args
|
||||
_argToGeneric({
|
||||
type, id, tag, text,
|
||||
}) {
|
||||
if (type === 'tag') return { type, id, tag };
|
||||
if (type === 'text') return { type, text };
|
||||
return {}; // UNIMPLEMENTED
|
||||
}
|
||||
|
||||
// Create schema form of arg, will equal to input args/schemas
|
||||
_argToSchema({ type, tag }) {
|
||||
if (type === 'tag') return { type, tag };
|
||||
if (type === 'text') return { type };
|
||||
return {}; // UNIMPLEMENTED
|
||||
}
|
||||
|
||||
_findLongerRegisteredCommand(args) {
|
||||
const matching = [];
|
||||
|
||||
for (const registeredCommand of this._commandRegistry) {
|
||||
// Skip unlisted commands
|
||||
if (registeredCommand.desc === null) continue;
|
||||
|
||||
for (const schema of registeredCommand.schemas) {
|
||||
// Get position of the first input arg, defaulting to the end if not existing
|
||||
let firstCommandInputArgPosition = schema
|
||||
.findIndex(commandArg => commandArg.name !== null && commandArg.name !== undefined);
|
||||
if (firstCommandInputArgPosition === -1) firstCommandInputArgPosition = schema.length;
|
||||
|
||||
// Check if there are match args existing after the first input arg
|
||||
const matchAfterInput = !!schema
|
||||
.slice(firstCommandInputArgPosition + 1)
|
||||
.find(commandArg => commandArg.name === null || commandArg.name === undefined);
|
||||
|
||||
// Skip if match after inputs found
|
||||
if (matchAfterInput) continue;
|
||||
|
||||
// Shorten the command arguments to the first input arg
|
||||
const shorterCommandMatchArgs = schema
|
||||
.slice(0, firstCommandInputArgPosition - 1)
|
||||
.map(commandArg => this._commandMatchArgToGeneric(commandArg));
|
||||
|
||||
// Convert args to generic so they can be used to match
|
||||
const potentialMatchArgs = args
|
||||
.map(arg => this._argToGeneric(arg));
|
||||
|
||||
// Check if our potential args match the shortened command args
|
||||
if (equal(shorterCommandMatchArgs, potentialMatchArgs)) {
|
||||
// Get the part of the command cut off to produce the match
|
||||
const trailingCommandMatchArg = schema[firstCommandInputArgPosition - 1];
|
||||
|
||||
// Add to list of matching
|
||||
matching.push([registeredCommand, trailingCommandMatchArg]);
|
||||
|
||||
// Skip all other schemas for this command
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matching;
|
||||
}
|
||||
|
||||
_findRegisteredCommand(args) {
|
||||
for (const registeredCommand of this._commandRegistry) {
|
||||
// Skip if not a real command
|
||||
if (registeredCommand.fn === null) continue;
|
||||
|
||||
for (const schema of registeredCommand.schemas) {
|
||||
// List of match args for command (remove input args/nulls)
|
||||
const commandMatchArgs = schema
|
||||
.map(commandArg => this._commandMatchArgToGeneric(commandArg));
|
||||
|
||||
// Get provided args in positions the command's match args are in
|
||||
const potentialMatchArgs = schema
|
||||
.map((commandArg, i) => {
|
||||
if (commandArg.name !== null && commandArg.name !== undefined) return null;
|
||||
return args[i] ? this._argToGeneric(args[i]) : null;
|
||||
});
|
||||
|
||||
// Check if our match args match up to the command's match args
|
||||
if (equal(commandMatchArgs, potentialMatchArgs)) {
|
||||
// Iterate the required args and make a formatted input arg from the input
|
||||
const inputArgMap = schema
|
||||
.map((commandArg, i) => {
|
||||
if (commandArg.name === null || commandArg.name === undefined) return null;
|
||||
|
||||
// Check if there are multiple trailing args, and this is the last text arg
|
||||
if (args.length > (i + 2) && args[i] && args[i].type === 'text' && (i + 1) === schema.length) {
|
||||
// Check registered info for command to check if last arg can be command
|
||||
const canBeText = !!this._argRegistry.get(commandArg.argType).schemas
|
||||
.find(argSchema => argSchema.type === 'text');
|
||||
|
||||
// Check that all following tags are also text
|
||||
const restAreText = !args
|
||||
.slice(i + 1)
|
||||
.find(arg => arg.type !== 'text');
|
||||
|
||||
// Set the arg to be all remaining args if can be text and rest are text
|
||||
if (canBeText && restAreText) {
|
||||
args[i].text = args.slice(i).map(arg => arg.raw + arg.rawSep).join('');
|
||||
}
|
||||
}
|
||||
|
||||
return { commandArg, arg : args[i] || null };
|
||||
})
|
||||
.filter(arg => arg !== null)
|
||||
.reduce((map, arg) => {
|
||||
map[arg.commandArg.name] = arg;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Return the registered command, and the map of input args
|
||||
return [registeredCommand, inputArgMap];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return with longer matching commands if found
|
||||
const matching = this._findLongerRegisteredCommand(args);
|
||||
if (matching.length > 0) return [null, null, matching];
|
||||
|
||||
return [null, null, null];
|
||||
}
|
||||
|
||||
// go get em jimmy
|
||||
async _fightForMessage(rawMessage) {
|
||||
const myId = this.eden.cluster + this.eden.id;
|
||||
|
||||
const awaitingReplyData = await this.eden.get(`chatbot.awaitingreply.${rawMessage.from}`);
|
||||
|
||||
if (awaitingReplyData && awaitingReplyData === myId) {
|
||||
// This should be a reply, and its for us
|
||||
return 2;
|
||||
} if (awaitingReplyData && awaitingReplyData !== myId) {
|
||||
// This should be a reply, and its not for us
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unlockMessage = await this.eden.lock(`chatbot.message.${rawMessage.id}`);
|
||||
|
||||
const dist = await this.eden.get('chatbot.distribution.*') || {};
|
||||
|
||||
// if (!Object.values(dist).find(chats => chats.length < dist[myId].length)) {
|
||||
if (!Object.values(dist).find(count => count < dist[myId])) {
|
||||
// await this.eden.set(`chat.distribution.${myId}`, [...dist[myId], rawMessage.get('_id')]);
|
||||
// await this.eden.incr(`chat.distribution.${myId}`);
|
||||
await this.eden.set(`chatbot.distribution.${myId}`, (dist[myId] || 0) + 1);
|
||||
unlockMessage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
unlockMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
async _onRawMesage(rawMessage) {
|
||||
await this.building;
|
||||
|
||||
// Return if its empty
|
||||
if (rawMessage.raw.length === 0) return;
|
||||
|
||||
// Return if its from us
|
||||
if (rawMessage.from === this._botUser.get('_id')) return;
|
||||
|
||||
// Fight over the message
|
||||
const messageFightRes = await this._fightForMessage(rawMessage);
|
||||
|
||||
// Return if we did not win the fight
|
||||
if (messageFightRes === 0) return;
|
||||
|
||||
// TODO Add automatic invalidation
|
||||
const basicChatInfo = await this.eden.get(`chatbot.basicchatinfo.${rawMessage.chat}`, async () => {
|
||||
const chat = await Chat.findById(rawMessage.chat);
|
||||
return {
|
||||
isInChat : !!chat.get().members.find(c => c.id === this._botUser.get('_id')),
|
||||
isDM : chat.get('type') === 'private',
|
||||
};
|
||||
});
|
||||
|
||||
// if we're not in the chat somehow, ignore
|
||||
if (!basicChatInfo.isInChat) return;
|
||||
|
||||
// Use pegjs parser to parse message arguments
|
||||
const { args, leadingSep } = messageArgsParser.parse(rawMessage.raw);
|
||||
|
||||
// Detect if message is a command
|
||||
const isCommand = leadingSep.length <= 0 && config.get('chatbot.commandArgs').find(cmdArg => equal(cmdArg, this._argToGeneric(args[0])));
|
||||
|
||||
// If its not a DM or a command its not worth our time, return
|
||||
if (!isCommand && !basicChatInfo.isDM) return;
|
||||
|
||||
// trim the first arg if this is a command (ex: removing .gm8)
|
||||
if (isCommand) args.shift();
|
||||
|
||||
// Check if its a reply to us, or just a normal command
|
||||
if (messageFightRes === 2) {
|
||||
// Rebuild text from the remaining args
|
||||
const text = leadingSep + args.map(arg => arg.raw + arg.rawSep).join('');
|
||||
|
||||
this._events.emit(`reply.${rawMessage.from}`, args, text);
|
||||
} else {
|
||||
try {
|
||||
await this._handleArgs({
|
||||
chat : await Chat.findById(rawMessage.chat),
|
||||
from : await User.findById(rawMessage.from),
|
||||
}, args);
|
||||
} catch (err) {
|
||||
if (err.message === 'dropped') return;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChatBot;
|
80
bundles/chatbot/helpers/chatbot.js
Normal file
80
bundles/chatbot/helpers/chatbot.js
Normal file
@ -0,0 +1,80 @@
|
||||
const Helper = require('helper');
|
||||
|
||||
/**
|
||||
* extend chat bot helper
|
||||
*
|
||||
* @extends {helper}
|
||||
*/
|
||||
class ChatBotHelper extends Helper {
|
||||
async waitReady() {
|
||||
return await new Promise((resolve) => {
|
||||
const done = () => {
|
||||
resolve();
|
||||
this.eden.off('chatbot.ready', done);
|
||||
};
|
||||
|
||||
this.eden.once('chatbot.ready', done);
|
||||
this.eden.call('chatbot.isReady', false).then(done);
|
||||
});
|
||||
}
|
||||
|
||||
async setResponse(name, fn) {
|
||||
return await this.eden.call('chatbot.setResponse', name, fn, false);
|
||||
}
|
||||
|
||||
async setArg(typeName, opts) {
|
||||
return await this.eden.call('chatbot.setArg', typeName, opts, false);
|
||||
}
|
||||
|
||||
async addCommand(schemas, fn = null, description = null, emoji = null, ver = 1) {
|
||||
return await this.eden.call('chatbot.addCommand', schemas, fn, description, emoji, ver, false);
|
||||
}
|
||||
|
||||
async setStatus(name) {
|
||||
return await this.eden.call('chatbot.setStatus', name, false);
|
||||
}
|
||||
|
||||
async respond(chat, responseName, ...responseArgs) {
|
||||
return await this.eden.call('chatbot.respond', chat, responseName, ...responseArgs, false);
|
||||
}
|
||||
|
||||
async loadTagArg(tagArg) {
|
||||
const m = await model(tagArg.tag).findById(tagArg.id);
|
||||
|
||||
return {
|
||||
title : tagArg.title,
|
||||
model : m,
|
||||
};
|
||||
}
|
||||
|
||||
unloadTagArg(loadedTag) {
|
||||
return {
|
||||
title : loadedTag.title,
|
||||
tag : loadedTag.model.constructor.name.toLowerCase(),
|
||||
id : loadedTag.model.get('_id').toString(),
|
||||
};
|
||||
}
|
||||
|
||||
tagArgToText(tagArg) {
|
||||
return `<${tagArg.tag}:${tagArg.title}|${tagArg.id}>`;
|
||||
}
|
||||
|
||||
argToText(arg) {
|
||||
if (arg.type === 'text') {
|
||||
return arg.text;
|
||||
}
|
||||
|
||||
return this.tagArgToText(arg);
|
||||
}
|
||||
|
||||
loadedTagArgToText(loadedTag) {
|
||||
return this.tagArgToText(this.unloadTagArg(loadedTag));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* export built chat bot helper
|
||||
*
|
||||
* @type {ChatBotHelper}
|
||||
*/
|
||||
module.exports = new ChatBotHelper();
|
4
bundles/chatbot/includes/chatdefaults.js
Normal file
4
bundles/chatbot/includes/chatdefaults.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = function setChatDefaults() {
|
||||
// This is just a placeholder, so you can overwrite it
|
||||
|
||||
};
|
52
bundles/chatbot/peg/messageparts.pegjs
Normal file
52
bundles/chatbot/peg/messageparts.pegjs
Normal file
@ -0,0 +1,52 @@
|
||||
Value
|
||||
= leadingSep:[ \t\n\r]* args:(
|
||||
arg:Arg sep:[ \t\n\r]*
|
||||
{ return [arg, sep.join('')]; }
|
||||
)* lastArg:Arg?
|
||||
{
|
||||
return {
|
||||
args: (lastArg !== null ? [...args, [lastArg, '']] : args).map(([arg, sep]) => {
|
||||
return Object.assign({}, arg, {
|
||||
rawSep: sep,
|
||||
});
|
||||
}),
|
||||
leadingSep: leadingSep.join(''),
|
||||
}
|
||||
}
|
||||
|
||||
Arg
|
||||
= '<' tagChars:TagNameCharacter+ ':' titleChars:TagTitleCharacter+ '|' idChars:TagIdCharacter+ '>' {
|
||||
return {
|
||||
type: 'tag',
|
||||
id: idChars.join(''),
|
||||
tag: tagChars.join(''),
|
||||
title: titleChars.join(''),
|
||||
raw: text(),
|
||||
};
|
||||
}
|
||||
/ textArg:TextArg { return { type: 'text', text: textArg, raw: text(), }; }
|
||||
|
||||
TagNameCharacter
|
||||
= !([ \t\n\r] / ':' / '\\') char:. { return char; }
|
||||
/ "\\" sequence:(':' / "\\") { return sequence; }
|
||||
|
||||
TagTitleCharacter
|
||||
= !([\t\n\r] / '|' / '\\') char:. { return char; }
|
||||
/ "\\" sequence:('|' / "\\") { return sequence; }
|
||||
|
||||
TagIdCharacter
|
||||
= !([ \t\n\r] / '>' / '\\') char:. { return char; }
|
||||
/ "\\" sequence:('"' / ">") { return sequence; }
|
||||
|
||||
TextArg
|
||||
= '"' chars:DoubleStringCharacter+ '"' !([^ \t\n\r]) { return chars.join(''); }
|
||||
/ chars:TextCharacter+ { return chars.join(''); }
|
||||
|
||||
DoubleStringCharacter
|
||||
= !('"' / "\\") char:. { return char; }
|
||||
/ "\\" sequence:('"' / "\\") { return sequence; }
|
||||
|
||||
TextCharacter
|
||||
= !([ \t\n\r] / "\\") char:. { return char; }
|
||||
/ "\\" char:. { return char; }
|
||||
/ "\\" { return "\\"; }
|
3
edenconfig.js
Normal file
3
edenconfig.js
Normal file
@ -0,0 +1,3 @@
|
||||
const config = {};
|
||||
|
||||
module.exports = config;
|
781
package-lock.json
generated
Normal file
781
package-lock.json
generated
Normal file
@ -0,0 +1,781 @@
|
||||
{
|
||||
"name": "@edenup/chatbot",
|
||||
"version": "1.0.8",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@edenjs/eslint-config-eden": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@edenjs/eslint-config-eden/-/eslint-config-eden-2.0.14.tgz",
|
||||
"integrity": "sha512-NkKUXO0U118uzsmPrBkPbBAKl4zhLjgyq3qv2AUjaS+Vbz2pa8o4/bi8yqhx16ZDJgfWoSc6ko9FWsXrwDM26g==",
|
||||
"dev": true
|
||||
},
|
||||
"@edenjs/peg": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@edenjs/peg/-/peg-1.0.2.tgz",
|
||||
"integrity": "sha512-uUNcZ3dJCbuFDlq9cQXD0+zkCs6/seW2BFiW9XHYsokDfKDpP38S8/aWkevTF6hULzdNgfMIgtz/f/8A7uUOtA==",
|
||||
"requires": {
|
||||
"gulp-pegjs": "^0.1.0",
|
||||
"gulp-rename": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"ansi-gray": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
|
||||
"integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
|
||||
"requires": {
|
||||
"ansi-wrap": "0.1.0"
|
||||
}
|
||||
},
|
||||
"ansi-wrap": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
|
||||
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768="
|
||||
},
|
||||
"aria-query": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
|
||||
"integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ast-types-flow": "0.0.7",
|
||||
"commander": "^2.11.0"
|
||||
}
|
||||
},
|
||||
"array-differ": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
|
||||
"integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE="
|
||||
},
|
||||
"array-includes": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
|
||||
"integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"array-uniq": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
|
||||
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
|
||||
},
|
||||
"ast-types-flow": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
||||
"integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
|
||||
"dev": true
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
|
||||
"integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ast-types-flow": "0.0.7"
|
||||
}
|
||||
},
|
||||
"beeper": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz",
|
||||
"integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak="
|
||||
},
|
||||
"clone": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
|
||||
},
|
||||
"clone-stats": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
|
||||
"integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE="
|
||||
},
|
||||
"color-support": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
|
||||
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"damerau-levenshtein": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
|
||||
"integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=",
|
||||
"dev": true
|
||||
},
|
||||
"dateformat": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
|
||||
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI="
|
||||
},
|
||||
"deep-equal": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
|
||||
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
|
||||
},
|
||||
"define-properties": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
},
|
||||
"duplexer2": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
|
||||
"integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
|
||||
"requires": {
|
||||
"readable-stream": "~1.1.9"
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
|
||||
"dev": true
|
||||
},
|
||||
"es-abstract": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
|
||||
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.0",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"is-callable": "^1.1.4",
|
||||
"is-regex": "^1.0.4",
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
},
|
||||
"es-to-primitive": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
|
||||
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"eslint-config-airbnb": {
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-17.1.0.tgz",
|
||||
"integrity": "sha512-R9jw28hFfEQnpPau01NO5K/JWMGLi6aymiF6RsnMURjTk+MqZKllCqGK/0tOvHkPi/NWSSOU2Ced/GX++YxLnw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-config-airbnb-base": "^13.1.0",
|
||||
"object.assign": "^4.1.0",
|
||||
"object.entries": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"eslint-config-airbnb-base": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz",
|
||||
"integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-restricted-globals": "^0.1.1",
|
||||
"object.assign": "^4.1.0",
|
||||
"object.entries": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-jsx-a11y": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.1.tgz",
|
||||
"integrity": "sha512-cjN2ObWrRz0TTw7vEcGQrx+YltMvZoOEx4hWU8eEERDnBIU00OTq7Vr+jA7DFKxiwLNv4tTh5Pq2GUNEa8b6+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aria-query": "^3.0.0",
|
||||
"array-includes": "^3.0.3",
|
||||
"ast-types-flow": "^0.0.7",
|
||||
"axobject-query": "^2.0.2",
|
||||
"damerau-levenshtein": "^1.0.4",
|
||||
"emoji-regex": "^7.0.2",
|
||||
"has": "^1.0.3",
|
||||
"jsx-ast-utils": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react": {
|
||||
"version": "7.12.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz",
|
||||
"integrity": "sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-includes": "^3.0.3",
|
||||
"doctrine": "^2.1.0",
|
||||
"has": "^1.0.3",
|
||||
"jsx-ast-utils": "^2.0.1",
|
||||
"object.fromentries": "^2.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"resolve": "^1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"doctrine": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-restricted-globals": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz",
|
||||
"integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=",
|
||||
"dev": true
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
||||
"dev": true
|
||||
},
|
||||
"fancy-log": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
|
||||
"integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
|
||||
"requires": {
|
||||
"ansi-gray": "^0.1.1",
|
||||
"color-support": "^1.1.3",
|
||||
"parse-node-version": "^1.0.0",
|
||||
"time-stamp": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"glogg": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz",
|
||||
"integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==",
|
||||
"requires": {
|
||||
"sparkles": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"gulp-pegjs": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/gulp-pegjs/-/gulp-pegjs-0.1.0.tgz",
|
||||
"integrity": "sha1-gwFY7q6OcwFx1E3N6xyiDH83FOo=",
|
||||
"requires": {
|
||||
"gulp-util": "^3.0.6",
|
||||
"object-assign": "^4.0.1",
|
||||
"pegjs": "^0.10.0",
|
||||
"through2": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"gulp-rename": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz",
|
||||
"integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg=="
|
||||
},
|
||||
"gulp-util": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
|
||||
"integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=",
|
||||
"requires": {
|
||||
"array-differ": "^1.0.0",
|
||||
"array-uniq": "^1.0.2",
|
||||
"beeper": "^1.0.0",
|
||||
"chalk": "^1.0.0",
|
||||
"dateformat": "^2.0.0",
|
||||
"fancy-log": "^1.1.0",
|
||||
"gulplog": "^1.0.0",
|
||||
"has-gulplog": "^0.1.0",
|
||||
"lodash._reescape": "^3.0.0",
|
||||
"lodash._reevaluate": "^3.0.0",
|
||||
"lodash._reinterpolate": "^3.0.0",
|
||||
"lodash.template": "^3.0.0",
|
||||
"minimist": "^1.1.0",
|
||||
"multipipe": "^0.1.2",
|
||||
"object-assign": "^3.0.0",
|
||||
"replace-ext": "0.0.1",
|
||||
"through2": "^2.0.0",
|
||||
"vinyl": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
|
||||
"integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I="
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
}
|
||||
}
|
||||
},
|
||||
"gulplog": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
|
||||
"integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
|
||||
"requires": {
|
||||
"glogg": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"has-gulplog": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz",
|
||||
"integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=",
|
||||
"requires": {
|
||||
"sparkles": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
|
||||
"dev": true
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
|
||||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
|
||||
"dev": true
|
||||
},
|
||||
"is-date-object": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
||||
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
|
||||
"dev": true
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
|
||||
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"is-symbol": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
|
||||
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"jsx-ast-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
|
||||
"integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-includes": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"lodash._basecopy": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
|
||||
"integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY="
|
||||
},
|
||||
"lodash._basetostring": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
|
||||
"integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U="
|
||||
},
|
||||
"lodash._basevalues": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
|
||||
"integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc="
|
||||
},
|
||||
"lodash._getnative": {
|
||||
"version": "3.9.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
|
||||
"integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
|
||||
},
|
||||
"lodash._isiterateecall": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
|
||||
"integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw="
|
||||
},
|
||||
"lodash._reescape": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
|
||||
"integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo="
|
||||
},
|
||||
"lodash._reevaluate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
|
||||
"integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0="
|
||||
},
|
||||
"lodash._reinterpolate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
||||
},
|
||||
"lodash._root": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
|
||||
"integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI="
|
||||
},
|
||||
"lodash.escape": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
|
||||
"integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
|
||||
"requires": {
|
||||
"lodash._root": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.isarguments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||
"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
|
||||
},
|
||||
"lodash.isarray": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
|
||||
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
|
||||
},
|
||||
"lodash.keys": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
|
||||
"integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
|
||||
"requires": {
|
||||
"lodash._getnative": "^3.0.0",
|
||||
"lodash.isarguments": "^3.0.0",
|
||||
"lodash.isarray": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.restparam": {
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
|
||||
"integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU="
|
||||
},
|
||||
"lodash.template": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
|
||||
"integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=",
|
||||
"requires": {
|
||||
"lodash._basecopy": "^3.0.0",
|
||||
"lodash._basetostring": "^3.0.0",
|
||||
"lodash._basevalues": "^3.0.0",
|
||||
"lodash._isiterateecall": "^3.0.0",
|
||||
"lodash._reinterpolate": "^3.0.0",
|
||||
"lodash.escape": "^3.0.0",
|
||||
"lodash.keys": "^3.0.0",
|
||||
"lodash.restparam": "^3.0.0",
|
||||
"lodash.templatesettings": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.templatesettings": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
|
||||
"integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
|
||||
"requires": {
|
||||
"lodash._reinterpolate": "^3.0.0",
|
||||
"lodash.escape": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"multipipe": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
|
||||
"integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
|
||||
"requires": {
|
||||
"duplexer2": "0.0.2"
|
||||
}
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz",
|
||||
"integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==",
|
||||
"dev": true
|
||||
},
|
||||
"object.assign": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
|
||||
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"function-bind": "^1.1.1",
|
||||
"has-symbols": "^1.0.0",
|
||||
"object-keys": "^1.0.11"
|
||||
}
|
||||
},
|
||||
"object.entries": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
|
||||
"integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.12.0",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"object.fromentries": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
|
||||
"integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.11.0",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"parse-node-version": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"pegjs": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz",
|
||||
"integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.8.4",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz",
|
||||
"integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"replace-ext": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
|
||||
"integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
|
||||
"integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"sparkles": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
|
||||
"integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw=="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
|
||||
"requires": {
|
||||
"readable-stream": "~2.3.6",
|
||||
"xtend": "~4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"time-stamp": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
|
||||
"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"vinyl": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
|
||||
"integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
|
||||
"requires": {
|
||||
"clone": "^1.0.0",
|
||||
"clone-stats": "^0.0.1",
|
||||
"replace-ext": "0.0.1"
|
||||
}
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
|
||||
}
|
||||
}
|
||||
}
|
20
package.json
Normal file
20
package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "wizbos-chatbot",
|
||||
"description": "nothing yet",
|
||||
"version": "1.0.8",
|
||||
"dependencies": {
|
||||
"@edenjs/peg": "^1.0.2",
|
||||
"deep-equal": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^6.0.1",
|
||||
"@edenjs/eslint-config-eden": "^2.0.14",
|
||||
"eslint-config-airbnb": "^17.1.1",
|
||||
"eslint-plugin-import": "^2.18.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-react": "^7.14.2"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user