From 85e5f4901e184174215eeda279e6b5c7295b0b2e Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 17 Dec 2016 12:03:19 -0500 Subject: [PATCH 01/33] remove useless import statement --- lib/py/convo_classifier.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/py/convo_classifier.py b/lib/py/convo_classifier.py index 09955cac..cf1e6636 100644 --- a/lib/py/convo_classifier.py +++ b/lib/py/convo_classifier.py @@ -6,7 +6,6 @@ from copy import deepcopy from os import path from os.path import basename -from spacy.en import English # the ioid of this script for JSON payload 'from' ioid = basename(__file__) # 'hello.py' From d3dc278b9895917e7a8e425530e290d22e8fae0b Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 17 Dec 2016 12:48:08 -0500 Subject: [PATCH 02/33] change db user to save the more generic envelope instead of profile --- db/migrations/20161007155536-create-user.js | 2 +- db/models/user.js | 2 +- scripts/chatlog.js | 13 ++++++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/db/migrations/20161007155536-create-user.js b/db/migrations/20161007155536-create-user.js index 8a495dc8..1968e956 100644 --- a/db/migrations/20161007155536-create-user.js +++ b/db/migrations/20161007155536-create-user.js @@ -19,7 +19,7 @@ module.exports = { username: { type: Sequelize.STRING }, - profile: { + envelope: { type: Sequelize.TEXT }, createdAt: { diff --git a/db/models/user.js b/db/models/user.js index bce72121..68008bee 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -4,7 +4,7 @@ module.exports = function(sequelize, DataTypes) { adapter: DataTypes.STRING, userid: DataTypes.STRING, username: DataTypes.STRING, - profile: DataTypes.TEXT + envelope: DataTypes.TEXT }, { classMethods: { associate: function(models) { diff --git a/scripts/chatlog.js b/scripts/chatlog.js index a21f78dd..5d01092a 100644 --- a/scripts/chatlog.js +++ b/scripts/chatlog.js @@ -8,25 +8,24 @@ module.exports = (robot) => { robot.hear(/.*/, (res) => {}) robot.receiveMiddleware((context, next, done) => { - var source = context.response.envelope + var envelope = context.response.envelope var adapter = process.env.ADAPTER - var userid = _.toString(_.get(source, 'user.id')) - var username = _.get(source, 'user.username') || _.get(source, 'user.name') - var profile = _.get(source, 'user') + var userid = _.toString(_.get(envelope, 'user.id')) + var username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') inlogs = [{ 'adapter': adapter, 'userid': userid, 'username': username, - 'room': _.get(source, 'room'), + 'room': _.get(envelope, 'room'), 'incoming': true, 'method': 'receive', - 'message': _.get(source, 'message.text') || _.join(_.keys(_.get(source, 'message.message')), ', ') + 'message': _.get(envelope, 'message.text') || _.join(_.keys(_.get(envelope, 'message.message')), ', ') }] User.findOrCreate({ where: {adapter: adapter, userid: userid}, - defaults: {username: username, profile: JSON.stringify(profile)}}) + defaults: {username: username, envelope: JSON.stringify(envelope)}}) .spread((user, created) => {}) _.each(inlogs, (inlog) => { Chatlog.create(inlog) }) From 9e7d54478f86a049b9cdeb415b3c98f7e7724c97 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 17 Dec 2016 13:01:19 -0500 Subject: [PATCH 03/33] implement send using envelope, first step towards emulate receive --- scripts/emulate-receive.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 scripts/emulate-receive.js diff --git a/scripts/emulate-receive.js b/scripts/emulate-receive.js new file mode 100644 index 00000000..995a80c1 --- /dev/null +++ b/scripts/emulate-receive.js @@ -0,0 +1,21 @@ +// dependencies +// Interface script for convo engine +const _ = require('lomath') +const path = require('path') +const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) + +/* istanbul ignore next */ +module.exports = (robot) => { + /* istanbul ignore next */ + robot.respond(/.*/, (res) => { + var adapter = process.env.ADAPTER + var userid = _.toString(_.get(res.envelope, 'user.id')) + User.find({ + where: { adapter: adapter, userid: userid } + }) + .then((user) => { + var envelope = JSON.parse(user.envelope) + robot.send(envelope, 'Emulate message ') + }) + }) +} From b7e5cb6dc78da2682d3ed40827be88ff3a3f6f69 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 17 Dec 2016 13:46:54 -0500 Subject: [PATCH 04/33] get basic receive emulation working --- scripts/emulate-receive.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/emulate-receive.js b/scripts/emulate-receive.js index 995a80c1..27796ad7 100644 --- a/scripts/emulate-receive.js +++ b/scripts/emulate-receive.js @@ -3,11 +3,13 @@ const _ = require('lomath') const path = require('path') const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) +const { TextMessage } = require('hubot') /* istanbul ignore next */ module.exports = (robot) => { /* istanbul ignore next */ - robot.respond(/.*/, (res) => { + robot.respond(/emulate.*/, (res) => { + var adapter = process.env.ADAPTER var userid = _.toString(_.get(res.envelope, 'user.id')) User.find({ @@ -15,7 +17,10 @@ module.exports = (robot) => { }) .then((user) => { var envelope = JSON.parse(user.envelope) - robot.send(envelope, 'Emulate message ') + robot.send(envelope, 'Emulate message') + + message = new TextMessage(envelope.user, `${robot.name} ping`, '0') + robot.receive(message) }) }) } From 4e5210573ea485d423e7d632ae8dd59a0998961f Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 17 Dec 2016 15:00:01 -0500 Subject: [PATCH 05/33] add a wrapper msg-emulator for generic self-talking or thinking --- scripts/emulate-receive.js | 16 ++-------------- src/msg-emulator.js | 27 +++++++++++++++++++++++++++ src/start-io.js | 6 +++--- 3 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 src/msg-emulator.js diff --git a/scripts/emulate-receive.js b/scripts/emulate-receive.js index 27796ad7..bb9139d2 100644 --- a/scripts/emulate-receive.js +++ b/scripts/emulate-receive.js @@ -2,25 +2,13 @@ // Interface script for convo engine const _ = require('lomath') const path = require('path') -const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) -const { TextMessage } = require('hubot') +const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) /* istanbul ignore next */ module.exports = (robot) => { /* istanbul ignore next */ robot.respond(/emulate.*/, (res) => { - - var adapter = process.env.ADAPTER var userid = _.toString(_.get(res.envelope, 'user.id')) - User.find({ - where: { adapter: adapter, userid: userid } - }) - .then((user) => { - var envelope = JSON.parse(user.envelope) - robot.send(envelope, 'Emulate message') - - message = new TextMessage(envelope.user, `${robot.name} ping`, '0') - robot.receive(message) - }) + msgEmulator.receive(userid, 'ping') }) } diff --git a/src/msg-emulator.js b/src/msg-emulator.js new file mode 100644 index 00000000..c4a156e5 --- /dev/null +++ b/src/msg-emulator.js @@ -0,0 +1,27 @@ +const _ = require('lomath') +const path = require('path') +const randomBytes = require('randombytes') +const { TextMessage } = require('hubot') +const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) + +// emulate a user sending a message to bot +// call as: +// const msgEmulator = require('msg-emulator') +// msgEmulator.receive(userid, 'ping') +function receive(userid, text) { + var adapter = process.env.ADAPTER + var emulMsgID = `${userid}-${new Date().toISOString()}` + User.find({ + where: { adapter: adapter, userid: userid } + }) + .then((user) => { + var envelope = JSON.parse(user.envelope) + var message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) + global.robot.receive(message) + // global.robot.send(envelope, 'Direct message') + }) +} + +module.exports = { + receive: receive +} diff --git a/src/start-io.js b/src/start-io.js index 360d3389..96e89c55 100644 --- a/src/start-io.js +++ b/src/start-io.js @@ -5,8 +5,8 @@ const path = require('path') const polyIO = require('poly-socketio') const log = require(path.join(__dirname, 'log')) const { setEnv, activeAdapters } = require(path.join(__dirname, 'env')) -const { nlpServer } = require('cgkb') -const nlpServerCount = 1 +// const { nlpServer } = require('cgkb') +const nlpServerCount = 0 /* istanbul ignore next */ const bashSrc = (process.platform == 'darwin') ? '~/.bash_profile' : '~/.bashrc' @@ -55,7 +55,7 @@ function ioClient() { // import js locally jsIOClient.join() - nlpServer({ port: process.env.IOPORT }) // start nlp server + // nlpServer({ port: process.env.IOPORT }) // start nlp server _.each(ioClientCmds, (cmds, lang) => { // spawn ioclients for other lang From 1bc60974620aab34d1349c241ca4e74c8ccb186c Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 17 Dec 2016 15:38:42 -0500 Subject: [PATCH 06/33] print chatlog to debug --- scripts/chatlog.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/chatlog.js b/scripts/chatlog.js index 5d01092a..82ca8286 100644 --- a/scripts/chatlog.js +++ b/scripts/chatlog.js @@ -28,7 +28,10 @@ module.exports = (robot) => { defaults: {username: username, envelope: JSON.stringify(envelope)}}) .spread((user, created) => {}) - _.each(inlogs, (inlog) => { Chatlog.create(inlog) }) + _.each(inlogs, (inlog) => { + Chatlog.create(inlog) + global.log.debug(`[In log]: ${inlog.message}`) + }) return next() }) @@ -46,7 +49,10 @@ module.exports = (robot) => { 'method': context.method, 'message': text })) - _.each(outlogs, (outlog) => { Chatlog.create(outlog) }) + _.each(outlogs, (outlog) => { + Chatlog.create(outlog) + global.log.debug(`[Out log]: ${outlog.message}`) + }) return next() }) } From e333c6b738a5e18deee14cfcddbbea278964a7f0 Mon Sep 17 00:00:00 2001 From: kengz Date: Tue, 20 Dec 2016 08:49:05 -0500 Subject: [PATCH 07/33] add cronjob model, simple script to parse and create. testing --- .../20161219230220-create-cronjob.js | 36 ++++++++++++++++ db/models/cronjob.js | 16 +++++++ package.json | 1 + scripts/cronjob.js | 42 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 db/migrations/20161219230220-create-cronjob.js create mode 100644 db/models/cronjob.js create mode 100644 scripts/cronjob.js diff --git a/db/migrations/20161219230220-create-cronjob.js b/db/migrations/20161219230220-create-cronjob.js new file mode 100644 index 00000000..adc2ce59 --- /dev/null +++ b/db/migrations/20161219230220-create-cronjob.js @@ -0,0 +1,36 @@ +'use strict'; +module.exports = { + up: function(queryInterface, Sequelize) { + return queryInterface.createTable('Cronjobs', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + adapter: { + type: Sequelize.STRING + }, + userid: { + type: Sequelize.STRING + }, + pattern: { + type: Sequelize.STRING + }, + command: { + type: Sequelize.TEXT + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: function(queryInterface, Sequelize) { + return queryInterface.dropTable('Cronjobs'); + } +}; \ No newline at end of file diff --git a/db/models/cronjob.js b/db/models/cronjob.js new file mode 100644 index 00000000..56363713 --- /dev/null +++ b/db/models/cronjob.js @@ -0,0 +1,16 @@ +'use strict'; +module.exports = function(sequelize, DataTypes) { + var Cronjob = sequelize.define('Cronjob', { + adapter: DataTypes.STRING, + userid: DataTypes.STRING, + pattern: DataTypes.STRING, + command: DataTypes.TEXT + }, { + classMethods: { + associate: function(models) { + // associations can be defined here + } + } + }); + return Cronjob; +}; \ No newline at end of file diff --git a/package.json b/package.json index 27c3d048..07f99a58 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "cgkb": "^1.0.9", "co": "^4.6.0", "config": "^1.21.0", + "cron": "^1.2.1", "date.js": "^0.3.1", "express": "^4.13.4", "forever": "^0.15.2", diff --git a/scripts/cronjob.js b/scripts/cronjob.js new file mode 100644 index 00000000..255b11cf --- /dev/null +++ b/scripts/cronjob.js @@ -0,0 +1,42 @@ +// dependencies +const _ = require('lomath') +const { CronJob } = require('cron') +const date = require('date.js') +const path = require('path') +const { Cronjob, User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) +const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) + +// Create the real job from model job +function createJob(job) { + var time = new Date(job.pattern) + var pattern = _.isNaN(time.getTime()) ? job.pattern : time + new CronJob({ + cronTime: pattern, + onTick: _.partial(msgEmulator.receive, job.userid, job.command), + start: true, + }) +} + +Cronjob.all().then((jobs) => { + _.each(jobs, createJob) + // need to delete overdue + // need to also create on add below +}) + +/* istanbul ignore next */ +module.exports = (robot) => { + robot.respond(/cron.*/i, (res) => { + var adapter = process.env.ADAPTER + var userid = _.toString(_.get(res.envelope, 'user.id')) + var text = res.match[0] + var parsedDate = date(text).toString() + var job = { + 'adapter': adapter, + 'userid': userid, + 'pattern': parsedDate, + 'command': 'ping' + } + Cronjob.create(job) + createJob(job) // create on add + }) +} From 7a769083fa24f6a30a968e619969028ac763e4cf Mon Sep 17 00:00:00 2001 From: kengz Date: Tue, 20 Dec 2016 23:51:59 -0500 Subject: [PATCH 08/33] consolidate info into init.js --- scripts/_init.js | 28 +++++++++++++++ scripts/cronjob.js | 2 ++ scripts/info.js | 37 -------------------- test/scripts/test-_init.coffee | 28 +++++++++++++-- test/scripts/test-info.coffee | 64 ---------------------------------- 5 files changed, 56 insertions(+), 103 deletions(-) delete mode 100644 scripts/info.js delete mode 100644 test/scripts/test-info.coffee diff --git a/scripts/_init.js b/scripts/_init.js index beac959a..15a955ee 100644 --- a/scripts/_init.js +++ b/scripts/_init.js @@ -3,11 +3,13 @@ global.Promise = require('bluebird') global.co = require('co') global._ = require('lomath') +const fs = require('fs') const path = require('path') const polyIO = require('poly-socketio') global.ROOTPATH = path.join(__dirname, '..') const log = require(path.join(__dirname, '..', 'src', 'log')) +const brainDumpPath = path.join(__dirname, '..', 'brain.json') polyIO.client({ port: process.env.IOPORT }) // export for bot @@ -37,4 +39,30 @@ module.exports = (robot) => { res.send('Manually starting initialization, emitting "ready".') robot.emit('ready') }) + + // ensure bot name + robot.respond(/bot info/i, (res) => { + var envelope = res.envelope + var info = _.join([ + `robot.name: ${robot.name}`, + `process.env.NODE_ENV: ${process.env.NODE_ENV}`, + `adapter: ${process.env.ADAPTER}`, + `user.id: ${envelope.user.id}`, + `user.name: ${_.get(envelope, 'user.username') || _.get(envelope, 'user.name')}`, + `room: ${envelope.room}`, + `server time: ${new Date()}`, + ], '\n') + res.send(info) + }) + + // write the runtime brain to output + robot.respond(/write brain/i, (res) => { + try { + fs.writeFile(brainDumpPath, JSON.stringify(robot.brain.data)) + res.send(`Brain written to output.`) + } catch (e) { + /* istanbul ignore next */ + res.send(`No permission to write brain to output.`) + } + }) } diff --git a/scripts/cronjob.js b/scripts/cronjob.js index 255b11cf..3d1c9ac5 100644 --- a/scripts/cronjob.js +++ b/scripts/cronjob.js @@ -9,6 +9,7 @@ const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) // Create the real job from model job function createJob(job) { var time = new Date(job.pattern) + // when next phase complete, can just use date(job.pattern) var pattern = _.isNaN(time.getTime()) ? job.pattern : time new CronJob({ cronTime: pattern, @@ -21,6 +22,7 @@ Cronjob.all().then((jobs) => { _.each(jobs, createJob) // need to delete overdue // need to also create on add below + // also need to consider the best way to parse command }) /* istanbul ignore next */ diff --git a/scripts/info.js b/scripts/info.js deleted file mode 100644 index 595e555b..00000000 --- a/scripts/info.js +++ /dev/null @@ -1,37 +0,0 @@ -// dependencies -// Module to ping the robot and get basic info -const fs = require('fs') -const _ = require('lomath') -const path = require('path') - -const brainDumpPath = path.join(__dirname, '..', 'brain.json') - -// quick test scripts -module.exports = (robot) => { - // ensure bot name - robot.respond(/who\s*are\s*you/i, (res) => { - res.send(robot.name) - }) - - // check res object for dev and debug - robot.respond(/my\s*id/i, (res) => { - res.send(JSON.stringify(_.omit(res, 'robot'), null, 2)) - }) - - // check the current NODE_ENV mode: development or production - robot.respond(/node\s*env/i, (res) => { - res.send(`${process.env['BOTNAME']} with adapter ${process.env['ADAPTER']} is deployed in ${process.env.NODE_ENV} mode.`) - }) - - // write the runtime brain to output - robot.respond(/write brain/i, (res) => { - try { - fs.writeFile(brainDumpPath, JSON.stringify(robot.brain.data)) - res.send(`Brain written to output.`) - } catch (e) { - /* istanbul ignore next */ - res.send(`No permission to write brain to output.`) - } - }) - -} diff --git a/test/scripts/test-_init.coffee b/test/scripts/test-_init.coffee index 0f7732aa..cf72e1f5 100644 --- a/test/scripts/test-_init.coffee +++ b/test/scripts/test-_init.coffee @@ -1,4 +1,4 @@ -# helper = new Helper('../scripts/_init.js') +helper = new Helper('../scripts/_init.js') # test ping script describe 'scripts/_init.js', -> @@ -33,4 +33,28 @@ describe 'scripts/_init.js', -> it 'robot.emit(ready)', -> # re-invoke the initialization sinon.assert.calledOnce @spyRun - \ No newline at end of file + + # Test + context 'user: bot info', -> + beforeEach -> + co => + @room = helper.createRoom(httpd: false, name: global.DEFAULT_ROOM) + yield @room.user.say 'alice', '@hubot bot info' + + # response + it 'hubot: ', -> + @room.messages.should.not.be.empty + + # Test + context 'user: write brain', -> + beforeEach -> + co => + @room = helper.createRoom(httpd: false, name: global.DEFAULT_ROOM) + yield @room.user.say 'alice', '@hubot write brain' + + # response + it 'hubot: Brain written to output.', -> + @room.messages.should.eql [ + ['alice', '@hubot write brain'] + ['hubot', 'Brain written to output.'] + ] diff --git a/test/scripts/test-info.coffee b/test/scripts/test-info.coffee deleted file mode 100644 index ca81ba36..00000000 --- a/test/scripts/test-info.coffee +++ /dev/null @@ -1,64 +0,0 @@ -helper = new Helper('../scripts/info.js') - -# test info script -describe 'scripts/info.js', -> - beforeEach -> - # creating room with 'httpd: false' will auto tear-down - @room = helper.createRoom(httpd: false, name: global.DEFAULT_ROOM) - - - # Test - context 'user: whoareyou', -> - beforeEach -> - co => - yield @room.user.say 'alice', '@hubot whoareyou' - - # response - it 'hubot: PONG', -> - @room.messages.should.eql [ - ['alice', '@hubot whoareyou'] - ['hubot', 'hubot'] - ] - - - # Test - context 'user: myid', -> - beforeEach -> - co => - yield @room.user.say 'alice', '@hubot myid' - - # response - it 'hubot: ', -> - @room.messages.should.eql [ - # returns the stringified JSON - [ 'alice', '@hubot myid' ] - [ 'hubot', '{\n "message": {\n "user": {\n "id": "alice",\n "room": "bot-test",\n "name": "alice"\n },\n "text": "@hubot myid",\n "done": false,\n "room": "bot-test"\n },\n "match": [\n "@hubot myid"\n ],\n "envelope": {\n "room": "bot-test",\n "user": {\n "id": "alice",\n "room": "bot-test",\n "name": "alice"\n },\n "message": {\n "user": {\n "id": "alice",\n "room": "bot-test",\n "name": "alice"\n },\n "text": "@hubot myid",\n "done": false,\n "room": "bot-test"\n }\n }\n}' ] - ] - - - # Test - context 'user: nodeenv', -> - beforeEach -> - co => - yield @room.user.say 'alice', '@hubot nodeenv' - - # response - it 'hubot: (in Mocha test)', -> - @room.messages.should.eql [ - ['alice', '@hubot nodeenv'] - ['hubot', 'aivadev with adapter Shell is deployed in test mode.'] - ] - - - # Test - context 'user: write brain', -> - beforeEach -> - co => - yield @room.user.say 'alice', '@hubot write brain' - - # response - it 'hubot: Brain written to output.', -> - @room.messages.should.eql [ - ['alice', '@hubot write brain'] - ['hubot', 'Brain written to output.'] - ] From c30fb1fa71e35693946a7c0fbfd14bd2520c52f8 Mon Sep 17 00:00:00 2001 From: kengz Date: Tue, 20 Dec 2016 23:59:09 -0500 Subject: [PATCH 09/33] change all "var" to "let" per latest js styleguide --- lib/client.js | 6 +++--- scripts/_init.js | 4 ++-- scripts/cgkb-demo.js | 2 +- scripts/chatlog.js | 16 ++++++++-------- scripts/convo.js | 4 ++-- scripts/cronjob.js | 14 +++++++------- scripts/emulate-receive.js | 2 +- scripts/hello-io.js | 2 +- src/aiva.js | 4 ++-- src/db.js | 4 ++-- src/env.js | 18 +++++++++--------- src/formatter/slack_att.js | 16 ++++++++-------- src/hasher.js | 4 ++-- src/msg-emulator.js | 8 ++++---- src/start-io.js | 6 +++--- test/_init-test.js | 2 +- test/asset.js | 2 +- test/common.js | 2 +- 18 files changed, 58 insertions(+), 58 deletions(-) diff --git a/lib/client.js b/lib/client.js index 5a06fd57..c881e495 100644 --- a/lib/client.js +++ b/lib/client.js @@ -6,7 +6,7 @@ const socketIOClient = require('socket.io-client') const SRCPATH = path.join(__dirname, '..', 'src') const log = require(path.join(SRCPATH, 'log')) -var lib_js, client +let lib_js, client const ioid = 'js' // the id of this script for io client registration // log.info(lib_js.ai.nlp.POS.getPOS({input: "remind me to do laundry"})) @@ -36,10 +36,10 @@ function correctReply(reply, msg) { */ /* istanbul ignore next */ function handle(msg) { - var to = msg.to, + let to = msg.to, intent = msg.intent; if (to && intent) { - var reply; + let reply; // try JSON or JSON.input as input try { reply = _.get(lib_js[to], intent)(msg) diff --git a/scripts/_init.js b/scripts/_init.js index 15a955ee..4287a1e7 100644 --- a/scripts/_init.js +++ b/scripts/_init.js @@ -42,8 +42,8 @@ module.exports = (robot) => { // ensure bot name robot.respond(/bot info/i, (res) => { - var envelope = res.envelope - var info = _.join([ + let envelope = res.envelope + let info = _.join([ `robot.name: ${robot.name}`, `process.env.NODE_ENV: ${process.env.NODE_ENV}`, `adapter: ${process.env.ADAPTER}`, diff --git a/scripts/cgkb-demo.js b/scripts/cgkb-demo.js index 7d61d03a..e6702fc3 100644 --- a/scripts/cgkb-demo.js +++ b/scripts/cgkb-demo.js @@ -21,7 +21,7 @@ module.exports = (robot) => { }) robot.respond(/.*/, (res) => { - var text = res.match[0] + let text = res.match[0] text = _.trim(_.replace(text, robot.name, '')) if (_.includes(text, 'nlp') || _.includes(text, 'clear kb')) { return diff --git a/scripts/chatlog.js b/scripts/chatlog.js index 82ca8286..ee74bf2d 100644 --- a/scripts/chatlog.js +++ b/scripts/chatlog.js @@ -8,12 +8,12 @@ module.exports = (robot) => { robot.hear(/.*/, (res) => {}) robot.receiveMiddleware((context, next, done) => { - var envelope = context.response.envelope - var adapter = process.env.ADAPTER - var userid = _.toString(_.get(envelope, 'user.id')) - var username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') + let envelope = context.response.envelope + let adapter = process.env.ADAPTER + let userid = _.toString(_.get(envelope, 'user.id')) + let username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') - inlogs = [{ + let inlogs = [{ 'adapter': adapter, 'userid': userid, 'username': username, @@ -37,10 +37,10 @@ module.exports = (robot) => { }) robot.responseMiddleware((context, next, done) => { - var target = context.response.envelope + let target = context.response.envelope // global.log.info(JSON.stringify(target, null, 2)) - replies = context.strings - outlogs = _.map(replies, (text) => ({ + let replies = context.strings + let outlogs = _.map(replies, (text) => ({ 'adapter': process.env.ADAPTER, 'userid': _.get(target, 'user.id'), 'username': _.get(target, 'user.username') || _.get(target, 'user.name'), diff --git a/scripts/convo.js b/scripts/convo.js index c83c24fb..fe276b10 100644 --- a/scripts/convo.js +++ b/scripts/convo.js @@ -8,14 +8,14 @@ module.exports = (robot) => { if (process.env.CI) { return } - var str = res.match[0].replace(`${robot.name} `, '') + let str = res.match[0].replace(`${robot.name} `, '') global.client.pass({ input: str, to: 'convo_classifier.py', intent: 'classify' }) .then((reply) => { - convo = reply.output + let convo = reply.output global.log.info(`Convo Score ${convo.score}, Topic: ${convo.topic}`) if (convo.topic === 'exception') { // TODO can add some counter by user to activate diff --git a/scripts/cronjob.js b/scripts/cronjob.js index 3d1c9ac5..4648954c 100644 --- a/scripts/cronjob.js +++ b/scripts/cronjob.js @@ -8,9 +8,9 @@ const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) // Create the real job from model job function createJob(job) { - var time = new Date(job.pattern) + let time = new Date(job.pattern) // when next phase complete, can just use date(job.pattern) - var pattern = _.isNaN(time.getTime()) ? job.pattern : time + let pattern = _.isNaN(time.getTime()) ? job.pattern : time new CronJob({ cronTime: pattern, onTick: _.partial(msgEmulator.receive, job.userid, job.command), @@ -28,11 +28,11 @@ Cronjob.all().then((jobs) => { /* istanbul ignore next */ module.exports = (robot) => { robot.respond(/cron.*/i, (res) => { - var adapter = process.env.ADAPTER - var userid = _.toString(_.get(res.envelope, 'user.id')) - var text = res.match[0] - var parsedDate = date(text).toString() - var job = { + let adapter = process.env.ADAPTER + let userid = _.toString(_.get(res.envelope, 'user.id')) + let text = res.match[0] + let parsedDate = date(text).toString() + let job = { 'adapter': adapter, 'userid': userid, 'pattern': parsedDate, diff --git a/scripts/emulate-receive.js b/scripts/emulate-receive.js index bb9139d2..7b2d1d45 100644 --- a/scripts/emulate-receive.js +++ b/scripts/emulate-receive.js @@ -8,7 +8,7 @@ const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) module.exports = (robot) => { /* istanbul ignore next */ robot.respond(/emulate.*/, (res) => { - var userid = _.toString(_.get(res.envelope, 'user.id')) + let userid = _.toString(_.get(res.envelope, 'user.id')) msgEmulator.receive(userid, 'ping') }) } diff --git a/scripts/hello-io.js b/scripts/hello-io.js index 17fb7a7b..486685d9 100644 --- a/scripts/hello-io.js +++ b/scripts/hello-io.js @@ -10,7 +10,7 @@ module.exports = (robot) => { // call the hello.py methods robot.respond(/hello-io\s*(.+)/i, (res) => { - var lang = res.match[1] + let lang = res.match[1] // use the global client to pass to the hello.py client // this returns a promise diff --git a/src/aiva.js b/src/aiva.js index 796c099f..26f42afc 100644 --- a/src/aiva.js +++ b/src/aiva.js @@ -8,12 +8,12 @@ const startIO = require(path.join(__dirname, 'start-io')) const log = require(path.join(__dirname, 'log')) const { setEnv, spawnEnv, activeAdapters } = require(path.join(__dirname, 'env')) const { authDb, migrateDb } = require(path.join(__dirname, 'db')) -var children = [] // child processes for spawn +let children = [] // child processes for spawn // finally, spawn a hubot in child.process using env /* istanbul ignore next */ function spawnProcess(env) { - var hb = spawn('./bin/hubot', ['-a', _.toLower(env['ADAPTER']), '--name', env['BOTNAME']], { stdio: 'inherit', env: env }) + let hb = spawn('./bin/hubot', ['-a', _.toLower(env['ADAPTER']), '--name', env['BOTNAME']], { stdio: 'inherit', env: env }) children.push(hb) log.info(`Deploying bot ${env['BOTNAME']} with adapter ${env['ADAPTER']}`) return env diff --git a/src/db.js b/src/db.js index af5cd616..193658cb 100644 --- a/src/db.js +++ b/src/db.js @@ -24,8 +24,8 @@ function createDb() { dbConfig.username, dbConfig.password, dbConfig) - var nodeEnvs = ['test', 'development', 'production'] - var createDbQueries = _.map(nodeEnvs, (nodeEnv) => { + let nodeEnvs = ['test', 'development', 'production'] + let createDbQueries = _.map(nodeEnvs, (nodeEnv) => { return "CREATE DATABASE " + _.get(dbEnvConfig, `${nodeEnv}.database`) + ";" }) diff --git a/src/env.js b/src/env.js index 067a49a4..c62c597d 100644 --- a/src/env.js +++ b/src/env.js @@ -9,9 +9,9 @@ Promise.promisifyAll(portscanner) const log = require(path.join(__dirname, 'log')) global.config = config -var globalKeys = _.difference(_.keys(config), ['ADAPTERS', 'ACTIVATE_IO_CLIENTS']) -var globalConfig = _.pick(config, globalKeys) -var activeAdapters = _.pickBy(config.get('ADAPTERS'), 'ACTIVATE') +let globalKeys = _.difference(_.keys(config), ['ADAPTERS', 'ACTIVATE_IO_CLIENTS']) +let globalConfig = _.pick(config, globalKeys) +let activeAdapters = _.pickBy(config.get('ADAPTERS'), 'ACTIVATE') // helper to set process.env (or copy) from config function configToEnv(config, env = process.env) { @@ -41,7 +41,7 @@ function setEnv() { // clone a new env copy for an adapter, return in Promise for chaining /* istanbul ignore next */ function cloneEnv(adapter) { - var env = _.clone(process.env) + let env = _.clone(process.env) env['ADAPTER'] = adapter adapterConfig = config.get(`ADAPTERS.${adapter}`) log.debug(`adapterConfig ${JSON.stringify(adapterConfig, null, 2)}`) @@ -52,7 +52,7 @@ function cloneEnv(adapter) { // set the PORT of env if specified in adapterConfig /* istanbul ignore next */ function setPort(env) { - var basePort = config.get(`PORTS.${env['ADAPTER']}`) + let basePort = config.get(`PORTS.${env['ADAPTER']}`) return portscanner.findAPortNotInUseAsync(basePort, basePort + 50, '127.0.0.1') .then((port) => { env['PORT'] = port @@ -65,18 +65,18 @@ function setPort(env) { // Spawn a ngrok automatically to handle the webhook /* istanbul ignore next */ function setWebhook(env) { - var webhookKey = env['WEBHOOK_KEY'] + let webhookKey = env['WEBHOOK_KEY'] if (!webhookKey) { log.debug(`No WEBHOOK set for adapter ${env['ADAPTER']}`) return env } else { - var webhook = env[webhookKey] - var subdomain + let webhook = env[webhookKey] + let subdomain if (webhook && webhook.match(/\/\/(\w+)\.ngrok/)) { subdomain = webhook.match(/\/\/(\w+)\.ngrok/)[1] } - var ngrokOpts = _.pickBy({ + let ngrokOpts = _.pickBy({ proto: 'http', // http|tcp|tls addr: env['PORT'], // port or network address subdomain: subdomain, diff --git a/src/formatter/slack_att.js b/src/formatter/slack_att.js index 7c7c5cbc..986605a3 100644 --- a/src/formatter/slack_att.js +++ b/src/formatter/slack_att.js @@ -32,7 +32,7 @@ function getColor(str) { // sample simple attachment // keys can be missing -var Att = { +let Att = { // color can be "good", "warning", "danger", hex #439FE0 color: "good", pretext: "This is a pretext", @@ -88,8 +88,8 @@ function genAttach(Att) { // filter out undefined values Att = _.pickBy(Att) // the 3 keys for each field - var fieldKeys = ["title", "value", "short"] - var fields = _.map(Att.fieldMat, (fieldArr) => { + let fieldKeys = ["title", "value", "short"] + let fields = _.map(Att.fieldMat, (fieldArr) => { // for default: short = true fieldArr.push(true) return _.zipObject(fieldKeys, fieldArr) @@ -140,7 +140,7 @@ function cleanFieldMat(fieldMat) { */ /* istanbul ignore next */ function gkgParser(gkgRes) { - var items = (gkgRes.itemListElement || []) + let items = (gkgRes.itemListElement || []) return _.map(items, _gkgParser) } /** @@ -148,7 +148,7 @@ function gkgParser(gkgRes) { */ /* istanbul ignore next */ function _gkgParser(item) { - var att = { + let att = { color: "purple", pretext: _.get(item, "result.description"), title: _.get(item, "result.name"), @@ -174,7 +174,7 @@ function _gkgParser(item) { */ /* istanbul ignore next */ function gsearchParser(gsearchRes) { - var items = (gsearchRes.links || []) + let items = (gsearchRes.links || []) return _.compact(_.map(items, _gsearchParser)) } /** @@ -183,7 +183,7 @@ function gsearchParser(gsearchRes) { /* istanbul ignore next */ function _gsearchParser(item) { if (!_.get(item, "href")) { return null } - var att = { + let att = { color: "indigo", title: _.get(item, "title"), title_link: _.get(item, "href"), @@ -197,7 +197,7 @@ function _gsearchParser(item) { } -var slackAtt = { +let slackAtt = { gen: gen, gkgParser: gkgParser, gsearchParser: gsearchParser diff --git a/src/hasher.js b/src/hasher.js index e60c0a0e..a64ed30d 100644 --- a/src/hasher.js +++ b/src/hasher.js @@ -3,7 +3,7 @@ const _ = require('lomath') const randomBytes = require('randombytes') // The hashMap for this global hash -var hashMap = {} +let hashMap = {} // !for future multiple replies: don't delete on 'handle', but do a periodic scan and prune keys with older hash timestamp /** @@ -40,7 +40,7 @@ function handle(msg) { const hashStr = _.isString(msg) ? msg : msg.hash if (hashStr) { global.log.debug('hash string exists for global-client') - var cb = hashMap[hashStr] + let cb = hashMap[hashStr] if (cb) { global.log.debug('hasher.handle invoking cb for global-client') _.omit(hashMap, hashStr) diff --git a/src/msg-emulator.js b/src/msg-emulator.js index c4a156e5..7b594490 100644 --- a/src/msg-emulator.js +++ b/src/msg-emulator.js @@ -9,14 +9,14 @@ const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) // const msgEmulator = require('msg-emulator') // msgEmulator.receive(userid, 'ping') function receive(userid, text) { - var adapter = process.env.ADAPTER - var emulMsgID = `${userid}-${new Date().toISOString()}` + let adapter = process.env.ADAPTER + let emulMsgID = `${userid}-${new Date().toISOString()}` User.find({ where: { adapter: adapter, userid: userid } }) .then((user) => { - var envelope = JSON.parse(user.envelope) - var message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) + let envelope = JSON.parse(user.envelope) + let message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) global.robot.receive(message) // global.robot.send(envelope, 'Direct message') }) diff --git a/src/start-io.js b/src/start-io.js index 96e89c55..451f6820 100644 --- a/src/start-io.js +++ b/src/start-io.js @@ -18,7 +18,7 @@ const LIBPATH = path.join(__dirname, '..', 'lib') const jsIOClient = require(path.join(LIBPATH, 'client')) // import other languages via child_process -var ioClientCmds = _.pickBy({ +let ioClientCmds = _.pickBy({ ruby: { // install_dependency: "gem install socket.io-client-simple activesupport", client: path.join(LIBPATH, 'client.rb') @@ -43,7 +43,7 @@ const CLIENT_COUNT = 1 + _.size(ioClientCmds) + adapterCount + nlpServerCount /* istanbul ignore next */ function ioClient() { // the child processes,kill all on death - var children = [] + let children = [] /* istanbul ignore next */ process.on('exit', () => { @@ -60,7 +60,7 @@ function ioClient() { _.each(ioClientCmds, (cmds, lang) => { // spawn ioclients for other lang global.log.info(`Starting socketIO client for ${lang} at ${process.env.IOPORT}`) - var cp = spawn('/bin/sh', ['-c', ` + let cp = spawn('/bin/sh', ['-c', ` ${srcCmd} ${lang} ${cmds['client']} `], { stdio: [process.stdin, process.stdout, 'pipe'] }) diff --git a/test/_init-test.js b/test/_init-test.js index 9316ac89..0d35e0b9 100644 --- a/test/_init-test.js +++ b/test/_init-test.js @@ -9,7 +9,7 @@ before(() => { global.log.info(`Running in ${process.env.NODE_ENV} mode`) global.log.info(`Create rooms, init brain for tests`) - var helper = new Helper(path.join(__dirname, '..', 'scripts')) // emulate full hubot init + let helper = new Helper(path.join(__dirname, '..', 'scripts')) // emulate full hubot init // emulate full hubot initialization, set to global.room for use global.room = helper.createRoom({ name: global.DEFAULT_ROOM }) diff --git a/test/asset.js b/test/asset.js index 1410ddce..3bd5759c 100644 --- a/test/asset.js +++ b/test/asset.js @@ -1,7 +1,7 @@ // Assets for the tests const _ = require('lomath') -var A = { +let A = { // lib/test_todo todoGenProp: { name: 'task1', diff --git a/test/common.js b/test/common.js index ede9630f..74008d85 100644 --- a/test/common.js +++ b/test/common.js @@ -25,7 +25,7 @@ global.say = (room, name, key) => { // Promise.delay, with adjusted time factors. for use with yield global.delayer = (factor) => { factor = factor || 1 - var timeout = 100 * factor + let timeout = 100 * factor timeout = _.min([timeout, 16000]) // timeout is capped at 16s return Promise.delay(timeout) } From 373f7a1fdeed4c878848b5dd2b259517d6e38df3 Mon Sep 17 00:00:00 2001 From: kengz Date: Fri, 23 Dec 2016 22:52:57 -0500 Subject: [PATCH 10/33] merge chatlog into convo --- scripts/chatlog.js | 58 ---------------------------------------------- scripts/convo.js | 57 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 58 deletions(-) delete mode 100644 scripts/chatlog.js diff --git a/scripts/chatlog.js b/scripts/chatlog.js deleted file mode 100644 index ee74bf2d..00000000 --- a/scripts/chatlog.js +++ /dev/null @@ -1,58 +0,0 @@ -// dependencies -const _ = require('lomath') -const path = require('path') -const { Chatlog, User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) - -/* istanbul ignore next */ -module.exports = (robot) => { - robot.hear(/.*/, (res) => {}) - - robot.receiveMiddleware((context, next, done) => { - let envelope = context.response.envelope - let adapter = process.env.ADAPTER - let userid = _.toString(_.get(envelope, 'user.id')) - let username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') - - let inlogs = [{ - 'adapter': adapter, - 'userid': userid, - 'username': username, - 'room': _.get(envelope, 'room'), - 'incoming': true, - 'method': 'receive', - 'message': _.get(envelope, 'message.text') || _.join(_.keys(_.get(envelope, 'message.message')), ', ') - }] - - User.findOrCreate({ - where: {adapter: adapter, userid: userid}, - defaults: {username: username, envelope: JSON.stringify(envelope)}}) - .spread((user, created) => {}) - - _.each(inlogs, (inlog) => { - Chatlog.create(inlog) - global.log.debug(`[In log]: ${inlog.message}`) - }) - - return next() - }) - - robot.responseMiddleware((context, next, done) => { - let target = context.response.envelope - // global.log.info(JSON.stringify(target, null, 2)) - let replies = context.strings - let outlogs = _.map(replies, (text) => ({ - 'adapter': process.env.ADAPTER, - 'userid': _.get(target, 'user.id'), - 'username': _.get(target, 'user.username') || _.get(target, 'user.name'), - 'room': _.get(target, 'room'), - 'incoming': false, - 'method': context.method, - 'message': text - })) - _.each(outlogs, (outlog) => { - Chatlog.create(outlog) - global.log.debug(`[Out log]: ${outlog.message}`) - }) - return next() - }) -} diff --git a/scripts/convo.js b/scripts/convo.js index fe276b10..0b634a27 100644 --- a/scripts/convo.js +++ b/scripts/convo.js @@ -1,8 +1,12 @@ // dependencies // Interface script for convo engine +const _ = require('lomath') +const path = require('path') +const { Chatlog, User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) /* istanbul ignore next */ module.exports = (robot) => { + /* istanbul ignore next */ robot.respond(/.*/, (res) => { if (process.env.CI) { @@ -24,4 +28,57 @@ module.exports = (robot) => { res.send(convo.response) }).catch(console.log) }) + + // catch all chatlogs + robot.hear(/.*/, (res) => {}) + + robot.receiveMiddleware((context, next, done) => { + let envelope = context.response.envelope + let adapter = process.env.ADAPTER + let userid = _.toString(_.get(envelope, 'user.id')) + let username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') + + let inlogs = [{ + 'adapter': adapter, + 'userid': userid, + 'username': username, + 'room': _.get(envelope, 'room'), + 'incoming': true, + 'method': 'receive', + 'message': _.get(envelope, 'message.text') || _.join(_.keys(_.get(envelope, 'message.message')), ', ') + }] + + User.findOrCreate({ + where: { adapter: adapter, userid: userid }, + defaults: { username: username, envelope: JSON.stringify(envelope) } + }) + .spread((user, created) => {}) + + _.each(inlogs, (inlog) => { + Chatlog.create(inlog) + global.log.debug(`[In log]: ${inlog.message}`) + }) + + return next() + }) + + robot.responseMiddleware((context, next, done) => { + let target = context.response.envelope + // global.log.info(JSON.stringify(target, null, 2)) + let replies = context.strings + let outlogs = _.map(replies, (text) => ({ + 'adapter': process.env.ADAPTER, + 'userid': _.get(target, 'user.id'), + 'username': _.get(target, 'user.username') || _.get(target, 'user.name'), + 'room': _.get(target, 'room'), + 'incoming': false, + 'method': context.method, + 'message': text + })) + _.each(outlogs, (outlog) => { + Chatlog.create(outlog) + global.log.debug(`[Out log]: ${outlog.message}`) + }) + return next() + }) } From 4c8e77de18a727fb7ad7e3a19e3d00f25c22db6a Mon Sep 17 00:00:00 2001 From: kengz Date: Fri, 23 Dec 2016 23:00:31 -0500 Subject: [PATCH 11/33] remove emulate-receive since cron already uses it --- scripts/cronjob.js | 2 +- scripts/emulate-receive.js | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) delete mode 100644 scripts/emulate-receive.js diff --git a/scripts/cronjob.js b/scripts/cronjob.js index 4648954c..303aaa48 100644 --- a/scripts/cronjob.js +++ b/scripts/cronjob.js @@ -22,7 +22,7 @@ Cronjob.all().then((jobs) => { _.each(jobs, createJob) // need to delete overdue // need to also create on add below - // also need to consider the best way to parse command + // also need to consider the best way to parse command. do 'remind' vs 'emulate' }) /* istanbul ignore next */ diff --git a/scripts/emulate-receive.js b/scripts/emulate-receive.js deleted file mode 100644 index 7b2d1d45..00000000 --- a/scripts/emulate-receive.js +++ /dev/null @@ -1,14 +0,0 @@ -// dependencies -// Interface script for convo engine -const _ = require('lomath') -const path = require('path') -const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) - -/* istanbul ignore next */ -module.exports = (robot) => { - /* istanbul ignore next */ - robot.respond(/emulate.*/, (res) => { - let userid = _.toString(_.get(res.envelope, 'user.id')) - msgEmulator.receive(userid, 'ping') - }) -} From eef66149c46b56865e1d6a0fefbc54e71fd1d6fa Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 00:52:57 -0500 Subject: [PATCH 12/33] add eslint, auto style fixes --- .eslintrc.json | 18 ++ .../20161003021116-create-chatlog.js | 23 +-- db/migrations/20161007155536-create-user.js | 31 ++-- .../20161219230220-create-cronjob.js | 31 ++-- db/models/chatlog.js | 21 +-- db/models/cronjob.js | 21 +-- db/models/index.js | 42 +++-- db/models/user.js | 21 +-- lib/client.js | 19 +- lib/js/hello.js | 8 +- package.json | 6 + scripts/_init.js | 14 +- scripts/convo.js | 63 ++++--- scripts/cronjob.js | 24 +-- scripts/hello-io.js | 10 +- src/aiva.js | 12 +- src/db.js | 26 +-- src/env.js | 40 ++--- src/formatter/slack_att.js | 100 +++++------ src/hasher.js | 14 +- src/log.js | 13 +- src/msg-emulator.js | 14 +- src/start-io.js | 32 ++-- test/_init-test.js | 22 ++- test/asset.js | 169 +++++++++--------- test/common.js | 10 +- 26 files changed, 406 insertions(+), 398 deletions(-) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..89efc7bb --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": "airbnb", + "plugins": [ + "react", + "jsx-a11y", + "import" + ], + "env": { + "node": true, + "es6": true, + "mocha": true + }, + "rules": { + "semi": ["error", "never"], + "import/no-unresolved": 0, + "import/no-extraneous-dependencies": 0 + } +} diff --git a/db/migrations/20161003021116-create-chatlog.js b/db/migrations/20161003021116-create-chatlog.js index c71093cb..190e4198 100644 --- a/db/migrations/20161003021116-create-chatlog.js +++ b/db/migrations/20161003021116-create-chatlog.js @@ -1,24 +1,25 @@ -'use strict'; + + // to create: sequelize migration:create --name create-chatlog // to run: sequelize db:migrate // to revert: sequelize db:migrate:undo:all module.exports = { - up: function(queryInterface, Sequelize) { + up(queryInterface, Sequelize) { return queryInterface.createTable('Chatlogs', { id: { allowNull: false, autoIncrement: true, primaryKey: true, - type: Sequelize.INTEGER + type: Sequelize.INTEGER, }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, }, updatedAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, }, adapter: Sequelize.STRING, userid: Sequelize.STRING, @@ -26,10 +27,10 @@ module.exports = { room: Sequelize.STRING, incoming: Sequelize.BOOLEAN, method: Sequelize.STRING, - message: Sequelize.STRING - }); + message: Sequelize.STRING, + }) + }, + down(queryInterface, Sequelize) { + return queryInterface.dropTable('Chatlogs') }, - down: function(queryInterface, Sequelize) { - return queryInterface.dropTable('Chatlogs'); - } -}; +} diff --git a/db/migrations/20161007155536-create-user.js b/db/migrations/20161007155536-create-user.js index 1968e956..f5411c70 100644 --- a/db/migrations/20161007155536-create-user.js +++ b/db/migrations/20161007155536-create-user.js @@ -1,38 +1,39 @@ -'use strict'; + + module.exports = { - up: function(queryInterface, Sequelize) { + up(queryInterface, Sequelize) { return queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, - type: Sequelize.INTEGER + type: Sequelize.INTEGER, }, adapter: { allowNull: false, - type: Sequelize.STRING + type: Sequelize.STRING, }, userid: { allowNull: false, - type: Sequelize.STRING + type: Sequelize.STRING, }, username: { - type: Sequelize.STRING + type: Sequelize.STRING, }, envelope: { - type: Sequelize.TEXT + type: Sequelize.TEXT, }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, }, updatedAt: { allowNull: false, - type: Sequelize.DATE - } - }); + type: Sequelize.DATE, + }, + }) + }, + down(queryInterface, Sequelize) { + return queryInterface.dropTable('Users') }, - down: function(queryInterface, Sequelize) { - return queryInterface.dropTable('Users'); - } -}; \ No newline at end of file +} diff --git a/db/migrations/20161219230220-create-cronjob.js b/db/migrations/20161219230220-create-cronjob.js index adc2ce59..7fc818ea 100644 --- a/db/migrations/20161219230220-create-cronjob.js +++ b/db/migrations/20161219230220-create-cronjob.js @@ -1,36 +1,37 @@ -'use strict'; + + module.exports = { - up: function(queryInterface, Sequelize) { + up(queryInterface, Sequelize) { return queryInterface.createTable('Cronjobs', { id: { allowNull: false, autoIncrement: true, primaryKey: true, - type: Sequelize.INTEGER + type: Sequelize.INTEGER, }, adapter: { - type: Sequelize.STRING + type: Sequelize.STRING, }, userid: { - type: Sequelize.STRING + type: Sequelize.STRING, }, pattern: { - type: Sequelize.STRING + type: Sequelize.STRING, }, command: { - type: Sequelize.TEXT + type: Sequelize.TEXT, }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, }, updatedAt: { allowNull: false, - type: Sequelize.DATE - } - }); + type: Sequelize.DATE, + }, + }) + }, + down(queryInterface, Sequelize) { + return queryInterface.dropTable('Cronjobs') }, - down: function(queryInterface, Sequelize) { - return queryInterface.dropTable('Cronjobs'); - } -}; \ No newline at end of file +} diff --git a/db/models/chatlog.js b/db/models/chatlog.js index 0ea4e40f..8a3bdcba 100644 --- a/db/models/chatlog.js +++ b/db/models/chatlog.js @@ -1,23 +1,24 @@ -'use strict'; + + // create with: // sequelize model:create --name Chatlog --attributes "adapter:string" -module.exports = function(sequelize, DataTypes) { - var Chatlog = sequelize.define('Chatlog', { +module.exports = function (sequelize, DataTypes) { + const Chatlog = sequelize.define('Chatlog', { adapter: DataTypes.STRING, userid: DataTypes.STRING, username: DataTypes.STRING, room: DataTypes.STRING, incoming: DataTypes.BOOLEAN, method: DataTypes.STRING, - message: DataTypes.TEXT + message: DataTypes.TEXT, }, { classMethods: { - associate: function(models) { + associate(models) { // associations can be defined here // Chatlog.belongsTo(models.User) - } - } - }); - return Chatlog; -}; \ No newline at end of file + }, + }, + }) + return Chatlog +} diff --git a/db/models/cronjob.js b/db/models/cronjob.js index 56363713..74511993 100644 --- a/db/models/cronjob.js +++ b/db/models/cronjob.js @@ -1,16 +1,17 @@ -'use strict'; -module.exports = function(sequelize, DataTypes) { - var Cronjob = sequelize.define('Cronjob', { + + +module.exports = function (sequelize, DataTypes) { + const Cronjob = sequelize.define('Cronjob', { adapter: DataTypes.STRING, userid: DataTypes.STRING, pattern: DataTypes.STRING, - command: DataTypes.TEXT + command: DataTypes.TEXT, }, { classMethods: { - associate: function(models) { + associate(models) { // associations can be defined here - } - } - }); - return Cronjob; -}; \ No newline at end of file + }, + }, + }) + return Cronjob +} diff --git a/db/models/index.js b/db/models/index.js index 23574ed3..692e54ea 100644 --- a/db/models/index.js +++ b/db/models/index.js @@ -1,37 +1,35 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); -const Sequelize = require('sequelize'); -const basename = path.basename(module.filename); -const env = process.env.NODE_ENV || 'development'; -const config = require(path.join(__dirname, '..', '..', 'config', 'db.json'))[env]; -var db = {}; -var sequelize + +const fs = require('fs') +const path = require('path') +const Sequelize = require('sequelize') +const basename = path.basename(module.filename) +const env = process.env.NODE_ENV || 'development' +const config = require(path.join(__dirname, '..', '..', 'config', 'db.json'))[env] +const db = {} +let sequelize if (config.use_env_variable) { - sequelize = new Sequelize(process.env[config.use_env_variable]); + sequelize = new Sequelize(process.env[config.use_env_variable]) } else { - sequelize = new Sequelize(config.database, config.username, config.password, config); + sequelize = new Sequelize(config.database, config.username, config.password, config) } fs .readdirSync(__dirname) - .filter((file) => { - return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); - }) + .filter(file => (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')) .forEach((file) => { - var model = sequelize['import'](path.join(__dirname, file)); - db[model.name] = model; - }); + const model = sequelize.import(path.join(__dirname, file)) + db[model.name] = model + }) Object.keys(db).forEach((modelName) => { if (db[modelName].associate) { - db[modelName].associate(db); + db[modelName].associate(db) } -}); +}) -db.sequelize = sequelize; -db.Sequelize = Sequelize; +db.sequelize = sequelize +db.Sequelize = Sequelize -module.exports = db; +module.exports = db diff --git a/db/models/user.js b/db/models/user.js index 68008bee..76a79343 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -1,16 +1,17 @@ -'use strict'; -module.exports = function(sequelize, DataTypes) { - var User = sequelize.define('User', { + + +module.exports = function (sequelize, DataTypes) { + const User = sequelize.define('User', { adapter: DataTypes.STRING, userid: DataTypes.STRING, username: DataTypes.STRING, - envelope: DataTypes.TEXT + envelope: DataTypes.TEXT, }, { classMethods: { - associate: function(models) { + associate(models) { // associations can be defined here - } - } - }); - return User; -}; \ No newline at end of file + }, + }, + }) + return User +} diff --git a/lib/client.js b/lib/client.js index c881e495..a9edcd80 100644 --- a/lib/client.js +++ b/lib/client.js @@ -6,7 +6,8 @@ const socketIOClient = require('socket.io-client') const SRCPATH = path.join(__dirname, '..', 'src') const log = require(path.join(SRCPATH, 'log')) -let lib_js, client +let lib_js, + client const ioid = 'js' // the id of this script for io client registration // log.info(lib_js.ai.nlp.POS.getPOS({input: "remind me to do laundry"})) @@ -15,12 +16,12 @@ const ioid = 'js' // the id of this script for io client registration /* istanbul ignore next */ function correctReply(reply, msg) { if (!_.isPlainObject(reply)) { - reply = { "output": reply } + reply = { output: reply } } // autofill if not already exist - reply["to"] = reply["to"] || msg["from"] - reply["from"] = reply["from"] || ioid - reply["hash"] = reply["hash"] || msg["hash"] + reply.to = reply.to || msg.from + reply.from = reply.from || ioid + reply.hash = reply.hash || msg.hash return reply } @@ -37,9 +38,9 @@ function correctReply(reply, msg) { /* istanbul ignore next */ function handle(msg) { let to = msg.to, - intent = msg.intent; + intent = msg.intent if (to && intent) { - let reply; + let reply // try JSON or JSON.input as input try { reply = _.get(lib_js[to], intent)(msg) @@ -63,7 +64,7 @@ function handle(msg) { function join() { // import all in lib/js/, called only when the modules are needed lib_js = requireDir(path.join(__dirname, 'js')) - log.debug(`import js lib from client.js`) + log.debug('import js lib from client.js') const IOPORT = process.env.IOPORT || 6466 log.info(`Starting socketIO client for js at ${IOPORT}`) client = socketIOClient(`http://localhost:${IOPORT}`) @@ -73,7 +74,7 @@ function join() { } module.exports = { - join: join + join, } /* istanbul ignore next */ diff --git a/lib/js/hello.js b/lib/js/hello.js index e9fbf9fd..178bbf3f 100644 --- a/lib/js/hello.js +++ b/lib/js/hello.js @@ -7,14 +7,14 @@ function foo(input) { function sayHi(msg) { reply = { - output: foo(msg['input']), - to: msg['from'], + output: foo(msg.input), + to: msg.from, from: ioid, - hash: msg['hash'] + hash: msg.hash, } return reply } module.exports = { - sayHi: sayHi + sayHi, } diff --git a/package.json b/package.json index 07f99a58..31f6395f 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "shell": "NODE_ENV=development bin/hubot", "setup": "bin/setup", + "lint": "eslint db/ lib/ scripts/ src/ test/ --fix", "test": "bin/test", "_test": "./node_modules/.bin/istanbul cover -x 'db/**' ./node_modules/mocha/bin/_mocha", "posttest": "rm -rf .hubot_history brain.json npm-debug.log*", @@ -69,6 +70,11 @@ "chai-as-promised": "^6.0.0", "codeclimate-test-reporter": "^0.4.0", "coffee-script": "^1.10.0", + "eslint": "^3.12.2", + "eslint-config-airbnb": "^13.0.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^2.2.3", + "eslint-plugin-react": "^6.8.0", "hubot-test-helper": "^1.4.4", "istanbul": "^0.4.2", "mocha": "^3.0.2", diff --git a/scripts/_init.js b/scripts/_init.js index 4287a1e7..f04843fd 100644 --- a/scripts/_init.js +++ b/scripts/_init.js @@ -18,13 +18,13 @@ module.exports = (robot) => { global.robot = robot // wake up, init - co(function*() { + co(function* () { /* istanbul ignore next */ if (robot.adapter.constructor.name === 'Shell') { // set for Shell local dev robot.brain.data.users = global.users } - yield Promise.delay(10); // wait to connect, get users + yield Promise.delay(10) // wait to connect, get users // emit 'ready' event to kick off initialization robot.emit('ready') }).catch(global.log.error) @@ -42,8 +42,8 @@ module.exports = (robot) => { // ensure bot name robot.respond(/bot info/i, (res) => { - let envelope = res.envelope - let info = _.join([ + const envelope = res.envelope + const info = _.join([ `robot.name: ${robot.name}`, `process.env.NODE_ENV: ${process.env.NODE_ENV}`, `adapter: ${process.env.ADAPTER}`, @@ -51,7 +51,7 @@ module.exports = (robot) => { `user.name: ${_.get(envelope, 'user.username') || _.get(envelope, 'user.name')}`, `room: ${envelope.room}`, `server time: ${new Date()}`, - ], '\n') + ], '\n') res.send(info) }) @@ -59,10 +59,10 @@ module.exports = (robot) => { robot.respond(/write brain/i, (res) => { try { fs.writeFile(brainDumpPath, JSON.stringify(robot.brain.data)) - res.send(`Brain written to output.`) + res.send('Brain written to output.') } catch (e) { /* istanbul ignore next */ - res.send(`No permission to write brain to output.`) + res.send('No permission to write brain to output.') } }) } diff --git a/scripts/convo.js b/scripts/convo.js index 0b634a27..2d7a7682 100644 --- a/scripts/convo.js +++ b/scripts/convo.js @@ -6,20 +6,19 @@ const { Chatlog, User } = require(path.join(__dirname, '..', 'db', 'models', 'in /* istanbul ignore next */ module.exports = (robot) => { - /* istanbul ignore next */ robot.respond(/.*/, (res) => { if (process.env.CI) { return } - let str = res.match[0].replace(`${robot.name} `, '') + const str = res.match[0].replace(`${robot.name} `, '') global.client.pass({ - input: str, - to: 'convo_classifier.py', - intent: 'classify' - }) + input: str, + to: 'convo_classifier.py', + intent: 'classify', + }) .then((reply) => { - let convo = reply.output + const convo = reply.output global.log.info(`Convo Score ${convo.score}, Topic: ${convo.topic}`) if (convo.topic === 'exception') { // TODO can add some counter by user to activate @@ -33,25 +32,25 @@ module.exports = (robot) => { robot.hear(/.*/, (res) => {}) robot.receiveMiddleware((context, next, done) => { - let envelope = context.response.envelope - let adapter = process.env.ADAPTER - let userid = _.toString(_.get(envelope, 'user.id')) - let username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') + const envelope = context.response.envelope + const adapter = process.env.ADAPTER + const userid = _.toString(_.get(envelope, 'user.id')) + const username = _.get(envelope, 'user.username') || _.get(envelope, 'user.name') - let inlogs = [{ - 'adapter': adapter, - 'userid': userid, - 'username': username, - 'room': _.get(envelope, 'room'), - 'incoming': true, - 'method': 'receive', - 'message': _.get(envelope, 'message.text') || _.join(_.keys(_.get(envelope, 'message.message')), ', ') + const inlogs = [{ + adapter, + userid, + username, + room: _.get(envelope, 'room'), + incoming: true, + method: 'receive', + message: _.get(envelope, 'message.text') || _.join(_.keys(_.get(envelope, 'message.message')), ', '), }] User.findOrCreate({ - where: { adapter: adapter, userid: userid }, - defaults: { username: username, envelope: JSON.stringify(envelope) } - }) + where: { adapter, userid }, + defaults: { username, envelope: JSON.stringify(envelope) }, + }) .spread((user, created) => {}) _.each(inlogs, (inlog) => { @@ -63,17 +62,17 @@ module.exports = (robot) => { }) robot.responseMiddleware((context, next, done) => { - let target = context.response.envelope + const target = context.response.envelope // global.log.info(JSON.stringify(target, null, 2)) - let replies = context.strings - let outlogs = _.map(replies, (text) => ({ - 'adapter': process.env.ADAPTER, - 'userid': _.get(target, 'user.id'), - 'username': _.get(target, 'user.username') || _.get(target, 'user.name'), - 'room': _.get(target, 'room'), - 'incoming': false, - 'method': context.method, - 'message': text + const replies = context.strings + const outlogs = _.map(replies, text => ({ + adapter: process.env.ADAPTER, + userid: _.get(target, 'user.id'), + username: _.get(target, 'user.username') || _.get(target, 'user.name'), + room: _.get(target, 'room'), + incoming: false, + method: context.method, + message: text, })) _.each(outlogs, (outlog) => { Chatlog.create(outlog) diff --git a/scripts/cronjob.js b/scripts/cronjob.js index 303aaa48..b1f13115 100644 --- a/scripts/cronjob.js +++ b/scripts/cronjob.js @@ -1,16 +1,16 @@ // dependencies const _ = require('lomath') -const { CronJob } = require('cron') const date = require('date.js') const path = require('path') +const { CronJob } = require('cron') const { Cronjob, User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) // Create the real job from model job function createJob(job) { - let time = new Date(job.pattern) + const time = new Date(job.pattern) // when next phase complete, can just use date(job.pattern) - let pattern = _.isNaN(time.getTime()) ? job.pattern : time + const pattern = _.isNaN(time.getTime()) ? job.pattern : time new CronJob({ cronTime: pattern, onTick: _.partial(msgEmulator.receive, job.userid, job.command), @@ -28,15 +28,15 @@ Cronjob.all().then((jobs) => { /* istanbul ignore next */ module.exports = (robot) => { robot.respond(/cron.*/i, (res) => { - let adapter = process.env.ADAPTER - let userid = _.toString(_.get(res.envelope, 'user.id')) - let text = res.match[0] - let parsedDate = date(text).toString() - let job = { - 'adapter': adapter, - 'userid': userid, - 'pattern': parsedDate, - 'command': 'ping' + const adapter = process.env.ADAPTER + const userid = _.toString(_.get(res.envelope, 'user.id')) + const text = res.match[0] + const parsedDate = date(text).toString() + const job = { + adapter, + userid, + pattern: parsedDate, + command: 'ping', } Cronjob.create(job) createJob(job) // create on add diff --git a/scripts/hello-io.js b/scripts/hello-io.js index 486685d9..b98bad04 100644 --- a/scripts/hello-io.js +++ b/scripts/hello-io.js @@ -10,16 +10,16 @@ module.exports = (robot) => { // call the hello.py methods robot.respond(/hello-io\s*(.+)/i, (res) => { - let lang = res.match[1] + const lang = res.match[1] // use the global client to pass to the hello.py client // this returns a promise global.client.pass({ // must specify at least the following keys - input: 'Hello from user.', - to: `hello.${lang}`, - intent: 'sayHi' - }) + input: 'Hello from user.', + to: `hello.${lang}`, + intent: 'sayHi', + }) // this goes through hello.py -> client.js // respond to user when client.js resolves the promise .then((reply) => { diff --git a/src/aiva.js b/src/aiva.js index 26f42afc..8b0fc5c5 100644 --- a/src/aiva.js +++ b/src/aiva.js @@ -8,14 +8,14 @@ const startIO = require(path.join(__dirname, 'start-io')) const log = require(path.join(__dirname, 'log')) const { setEnv, spawnEnv, activeAdapters } = require(path.join(__dirname, 'env')) const { authDb, migrateDb } = require(path.join(__dirname, 'db')) -let children = [] // child processes for spawn +const children = [] // child processes for spawn // finally, spawn a hubot in child.process using env /* istanbul ignore next */ function spawnProcess(env) { - let hb = spawn('./bin/hubot', ['-a', _.toLower(env['ADAPTER']), '--name', env['BOTNAME']], { stdio: 'inherit', env: env }) + const hb = spawn('./bin/hubot', ['-a', _.toLower(env.ADAPTER), '--name', env.BOTNAME], { stdio: 'inherit', env }) children.push(hb) - log.info(`Deploying bot ${env['BOTNAME']} with adapter ${env['ADAPTER']}`) + log.info(`Deploying bot ${env.BOTNAME} with adapter ${env.ADAPTER}`) return env } @@ -29,13 +29,13 @@ function spawnHubot(adapter) { /* istanbul ignore next */ function startProcess() { return new Promise((resolve, reject) => { - log.info(`Starting aiva process`) + log.info('Starting aiva process') setEnv() // so that hubot is killed when forever exits. process.on('exit', () => { children.forEach((child) => { child.kill() }) - log.info("Shutting down") + log.info('Shutting down') }) startIO() // start socketIO @@ -60,5 +60,5 @@ process.on('SIGTERM', cleanExit) // catch kill // export the setEnv for convenient usage in dev module.exports = { - start: start + start, } diff --git a/src/db.js b/src/db.js index 193658cb..fbfb6547 100644 --- a/src/db.js +++ b/src/db.js @@ -24,18 +24,14 @@ function createDb() { dbConfig.username, dbConfig.password, dbConfig) - let nodeEnvs = ['test', 'development', 'production'] - let createDbQueries = _.map(nodeEnvs, (nodeEnv) => { - return "CREATE DATABASE " + _.get(dbEnvConfig, `${nodeEnv}.database`) + ";" - }) + const nodeEnvs = ['test', 'development', 'production'] + const createDbQueries = _.map(nodeEnvs, nodeEnv => `CREATE DATABASE ${_.get(dbEnvConfig, `${nodeEnv}.database`)};`) return Promise.any( - _.map(createDbQueries, (createDbQuery) => { - return sysSeq.query(createDbQuery) - })).then(() => { - sysSeq.close() - log.info(`Created the aiva databases`) - }).catch(e => { log.error(JSON.stringify(e, null, 2)) }) + _.map(createDbQueries, createDbQuery => sysSeq.query(createDbQuery))).then(() => { + sysSeq.close() + log.info('Created the aiva databases') + }).catch((e) => { log.error(JSON.stringify(e, null, 2)) }) } /* istanbul ignore next */ @@ -44,11 +40,7 @@ function authDb() { .authenticate() .then((e) => { log.info('Authenticated database successfully') - }).catch((e) => { - return createDb() - }).finally(() => { - return sequelize.close() - }) + }).catch(e => createDb()).finally(() => sequelize.close()) } /* istanbul ignore next */ @@ -66,8 +58,8 @@ function migrateDb() { } module.exports = { - authDb: authDb, - migrateDb: migrateDb + authDb, + migrateDb, } /* istanbul ignore next */ diff --git a/src/env.js b/src/env.js index c62c597d..0c952f06 100644 --- a/src/env.js +++ b/src/env.js @@ -9,9 +9,9 @@ Promise.promisifyAll(portscanner) const log = require(path.join(__dirname, 'log')) global.config = config -let globalKeys = _.difference(_.keys(config), ['ADAPTERS', 'ACTIVATE_IO_CLIENTS']) -let globalConfig = _.pick(config, globalKeys) -let activeAdapters = _.pickBy(config.get('ADAPTERS'), 'ACTIVATE') +const globalKeys = _.difference(_.keys(config), ['ADAPTERS', 'ACTIVATE_IO_CLIENTS']) +const globalConfig = _.pick(config, globalKeys) +const activeAdapters = _.pickBy(config.get('ADAPTERS'), 'ACTIVATE') // helper to set process.env (or copy) from config function configToEnv(config, env = process.env) { @@ -41,8 +41,8 @@ function setEnv() { // clone a new env copy for an adapter, return in Promise for chaining /* istanbul ignore next */ function cloneEnv(adapter) { - let env = _.clone(process.env) - env['ADAPTER'] = adapter + const env = _.clone(process.env) + env.ADAPTER = adapter adapterConfig = config.get(`ADAPTERS.${adapter}`) log.debug(`adapterConfig ${JSON.stringify(adapterConfig, null, 2)}`) configToEnv(adapterConfig, env) @@ -52,11 +52,11 @@ function cloneEnv(adapter) { // set the PORT of env if specified in adapterConfig /* istanbul ignore next */ function setPort(env) { - let basePort = config.get(`PORTS.${env['ADAPTER']}`) + const basePort = config.get(`PORTS.${env.ADAPTER}`) return portscanner.findAPortNotInUseAsync(basePort, basePort + 50, '127.0.0.1') .then((port) => { - env['PORT'] = port - log.debug(`Set ${env['ADAPTER']} PORT: ${port}`) + env.PORT = port + log.debug(`Set ${env.ADAPTER} PORT: ${port}`) return env }) } @@ -65,29 +65,29 @@ function setPort(env) { // Spawn a ngrok automatically to handle the webhook /* istanbul ignore next */ function setWebhook(env) { - let webhookKey = env['WEBHOOK_KEY'] + const webhookKey = env.WEBHOOK_KEY if (!webhookKey) { - log.debug(`No WEBHOOK set for adapter ${env['ADAPTER']}`) + log.debug(`No WEBHOOK set for adapter ${env.ADAPTER}`) return env } else { - let webhook = env[webhookKey] + const webhook = env[webhookKey] let subdomain if (webhook && webhook.match(/\/\/(\w+)\.ngrok/)) { subdomain = webhook.match(/\/\/(\w+)\.ngrok/)[1] } - let ngrokOpts = _.pickBy({ - proto: 'http', // http|tcp|tls - addr: env['PORT'], // port or network address - subdomain: subdomain, - authtoken: env['NGROK_AUTH'] + const ngrokOpts = _.pickBy({ + proto: 'http', // http|tcp|tls + addr: env.PORT, // port or network address + subdomain, + authtoken: env.NGROK_AUTH, }) log.debug(`ngrok options: ${JSON.stringify(ngrokOpts, null, 2)}`) return ngrok.connectAsync(ngrokOpts) .then((url) => { env[webhookKey] = url // update - log.debug(`Set ${env['ADAPTER']} webhook url: ${url}:${env['PORT']}`) + log.debug(`Set ${env.ADAPTER} webhook url: ${url}:${env.PORT}`) return env }) .catch((e) => { @@ -106,7 +106,7 @@ function spawnEnv(adapter) { } module.exports = { - setEnv: setEnv, - spawnEnv: spawnEnv, - activeAdapters: activeAdapters + setEnv, + spawnEnv, + activeAdapters, } diff --git a/src/formatter/slack_att.js b/src/formatter/slack_att.js index 986605a3..ba225ce5 100644 --- a/src/formatter/slack_att.js +++ b/src/formatter/slack_att.js @@ -21,7 +21,7 @@ const palette = { yellow: 'warning', orange: '#ffa726', brown: '#795548', - grey: '#546e7a' + grey: '#546e7a', } // quick function to get color from palette @@ -32,20 +32,20 @@ function getColor(str) { // sample simple attachment // keys can be missing -let Att = { +const Att = { // color can be "good", "warning", "danger", hex #439FE0 - color: "good", - pretext: "This is a pretext", - title: "This is a title", - title_link: "https://api.slack.com/docs/attachments", + color: 'good', + pretext: 'This is a pretext', + title: 'This is a title', + title_link: 'https://api.slack.com/docs/attachments', text: "This is the main text in a message attachment, and can contain standard message markup (see details below). The content will automatically collapse if it contains 700+ characters or 5+ linebreaks, and will display a 'Show more...' link to expand the content.", fieldMat: [ // the "short" key defaults to true - ["Priority", "high"], - ["Status", "pending"] + ['Priority', 'high'], + ['Status', 'pending'], ], - image_url: "https://slack.global.ssl.fastly.net/ae57/img/slack_api_logo.png", - thumb_url: "https://slack.global.ssl.fastly.net/ae57/img/slack_api_logo.png" + image_url: 'https://slack.global.ssl.fastly.net/ae57/img/slack_api_logo.png', + thumb_url: 'https://slack.global.ssl.fastly.net/ae57/img/slack_api_logo.png', } // console.log(gen({ message: { room: 'kengz' } }, Att)) @@ -72,7 +72,7 @@ function gen(res, atts, parser) { } return { channel: res.message.room, - attachments: _.map(atts, genAttach) + attachments: _.map(atts, genAttach), } } @@ -84,11 +84,11 @@ function gen(res, atts, parser) { /* istanbul ignore next */ function genAttach(Att) { // cleanup the fieldmat - Att["fieldMat"] = cleanFieldMat(Att["fieldMat"]) + Att.fieldMat = cleanFieldMat(Att.fieldMat) // filter out undefined values Att = _.pickBy(Att) // the 3 keys for each field - let fieldKeys = ["title", "value", "short"] + const fieldKeys = ['title', 'value', 'short'] let fields = _.map(Att.fieldMat, (fieldArr) => { // for default: short = true fieldArr.push(true) @@ -98,15 +98,15 @@ function genAttach(Att) { fields = _.isEmpty(fields) ? null : fields // filter out null values return _.pickBy({ - "fallback": _.join(_.compact([Att.pretext, Att.title, Att.title_link]), ' - '), - "color": getColor(Att.color), - "pretext": Att.pretext, - "title": Att.title, - "title_link": Att.title_link, - "text": Att.text, - "fields": fields, - "image_url": Att.image_url, - "thumb_url": Att.thumb_url + fallback: _.join(_.compact([Att.pretext, Att.title, Att.title_link]), ' - '), + color: getColor(Att.color), + pretext: Att.pretext, + title: Att.title, + title_link: Att.title_link, + text: Att.text, + fields, + image_url: Att.image_url, + thumb_url: Att.thumb_url, }) } @@ -117,16 +117,14 @@ function genAttach(Att) { */ /* istanbul ignore next */ function cleanFieldMat(fieldMat) { - cleanMap = _.map(fieldMat, (row) => { - return row[1] ? row : null - }) + cleanMap = _.map(fieldMat, row => row[1] ? row : null) return _.compact(cleanMap) } -////////////////////////////////////////////// +// //////////////////////////////////////////// // The parsers into Slack attachment format // -////////////////////////////////////////////// +// //////////////////////////////////////////// /** @@ -136,11 +134,11 @@ function cleanFieldMat(fieldMat) { * @example * gen(res, gkgseachRes, slackAtt.gkgParser) * // => gkgsearchRes as array of Slack attachments - * + * */ /* istanbul ignore next */ function gkgParser(gkgRes) { - let items = (gkgRes.itemListElement || []) + const items = (gkgRes.itemListElement || []) return _.map(items, _gkgParser) } /** @@ -148,17 +146,17 @@ function gkgParser(gkgRes) { */ /* istanbul ignore next */ function _gkgParser(item) { - let att = { - color: "purple", - pretext: _.get(item, "result.description"), - title: _.get(item, "result.name"), - title_link: _.get(item, "result.detailedDescription.url"), - text: _.get(item, "result.detailedDescription.articleBody"), + const att = { + color: 'purple', + pretext: _.get(item, 'result.description'), + title: _.get(item, 'result.name'), + title_link: _.get(item, 'result.detailedDescription.url'), + text: _.get(item, 'result.detailedDescription.articleBody'), fieldMat: [ // the "short" key defaults to true - ["Type", _.join(_.get(item, "result.@type"), ", "), false] + ['Type', _.join(_.get(item, 'result.@type'), ', '), false], ], - thumb_url: _.get(item, "result.image.contentUrl") + thumb_url: _.get(item, 'result.image.contentUrl'), } return att } @@ -170,11 +168,11 @@ function _gkgParser(item) { * @example * gen(res, gseachRes, slackAtt.gsearchParser) * // => gsearchRes as array of Slack attachments - * + * */ /* istanbul ignore next */ function gsearchParser(gsearchRes) { - let items = (gsearchRes.links || []) + const items = (gsearchRes.links || []) return _.compact(_.map(items, _gsearchParser)) } /** @@ -182,25 +180,25 @@ function gsearchParser(gsearchRes) { */ /* istanbul ignore next */ function _gsearchParser(item) { - if (!_.get(item, "href")) { return null } - let att = { - color: "indigo", - title: _.get(item, "title"), - title_link: _.get(item, "href"), - text: _.get(item, "description"), + if (!_.get(item, 'href')) { return null } + const att = { + color: 'indigo', + title: _.get(item, 'title'), + title_link: _.get(item, 'href'), + text: _.get(item, 'description'), fieldMat: [ // the "short" key defaults to true - ["url", _.get(item, "link"), false] - ] + ['url', _.get(item, 'link'), false], + ], } return att } -let slackAtt = { - gen: gen, - gkgParser: gkgParser, - gsearchParser: gsearchParser +const slackAtt = { + gen, + gkgParser, + gsearchParser, } module.exports = slackAtt diff --git a/src/hasher.js b/src/hasher.js index a64ed30d..ef15cfce 100644 --- a/src/hasher.js +++ b/src/hasher.js @@ -3,7 +3,7 @@ const _ = require('lomath') const randomBytes = require('randombytes') // The hashMap for this global hash -let hashMap = {} +const hashMap = {} // !for future multiple replies: don't delete on 'handle', but do a periodic scan and prune keys with older hash timestamp /** @@ -17,10 +17,10 @@ function gen(id, cb) { /* istanbul ignore next */ id = id || 'unidentified' /* istanbul ignore next */ - const hashStr = id + '_' + randomBytes(16).toString('hex') + const hashStr = `${id}_${randomBytes(16).toString('hex')}` /* istanbul ignore next */ if (cb) { - global.log.debug(`Added a callback to hasher for global-client`) + global.log.debug('Added a callback to hasher for global-client') // if exists, add the callback function to map hashMap[hashStr] = cb } @@ -40,7 +40,7 @@ function handle(msg) { const hashStr = _.isString(msg) ? msg : msg.hash if (hashStr) { global.log.debug('hash string exists for global-client') - let cb = hashMap[hashStr] + const cb = hashMap[hashStr] if (cb) { global.log.debug('hasher.handle invoking cb for global-client') _.omit(hashMap, hashStr) @@ -50,7 +50,7 @@ function handle(msg) { } module.exports = { - hashMap: hashMap, - gen: gen, - handle: handle + hashMap, + gen, + handle, } diff --git a/src/log.js b/src/log.js index c47b4d68..7f3fd8f6 100644 --- a/src/log.js +++ b/src/log.js @@ -1,15 +1,14 @@ const winston = require('winston') /* istanbul ignore next */ -logLevel = process.env['npm_config_debug'] ? 'debug' : 'info' -const log = global.log || new(winston.Logger)({ +logLevel = process.env.npm_config_debug ? 'debug' : 'info' +const log = global.log || new (winston.Logger)({ level: logLevel, - transports: [new(winston.transports.Console)({ - formatter: (options) => { + transports: [new (winston.transports.Console)({ + formatter: options => /* istanbul ignore next */ - return `[${new Date}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}` - } - })] + `[${new Date()}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}`, + })], }) global.log = log diff --git a/src/msg-emulator.js b/src/msg-emulator.js index 7b594490..c77af9f0 100644 --- a/src/msg-emulator.js +++ b/src/msg-emulator.js @@ -9,19 +9,19 @@ const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) // const msgEmulator = require('msg-emulator') // msgEmulator.receive(userid, 'ping') function receive(userid, text) { - let adapter = process.env.ADAPTER - let emulMsgID = `${userid}-${new Date().toISOString()}` + const adapter = process.env.ADAPTER + const emulMsgID = `${userid}-${new Date().toISOString()}` User.find({ - where: { adapter: adapter, userid: userid } - }) + where: { adapter, userid }, + }) .then((user) => { - let envelope = JSON.parse(user.envelope) - let message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) + const envelope = JSON.parse(user.envelope) + const message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) global.robot.receive(message) // global.robot.send(envelope, 'Direct message') }) } module.exports = { - receive: receive + receive, } diff --git a/src/start-io.js b/src/start-io.js index 451f6820..dc159015 100644 --- a/src/start-io.js +++ b/src/start-io.js @@ -18,19 +18,17 @@ const LIBPATH = path.join(__dirname, '..', 'lib') const jsIOClient = require(path.join(LIBPATH, 'client')) // import other languages via child_process -let ioClientCmds = _.pickBy({ - ruby: { +const ioClientCmds = _.pickBy({ + ruby: { // install_dependency: "gem install socket.io-client-simple activesupport", - client: path.join(LIBPATH, 'client.rb') - }, - python: { + client: path.join(LIBPATH, 'client.rb'), + }, + python: { // install_dependency: "python -m pip install socketIO-client", - client: path.join(LIBPATH, 'client.py') - } + client: path.join(LIBPATH, 'client.py'), }, - (args, cmd) => { - return global.config.get("ACTIVATE_IO_CLIENTS").get(cmd) - }) +}, + (args, cmd) => global.config.get('ACTIVATE_IO_CLIENTS').get(cmd)) /* istanbul ignore next */ const adapterCount = (process.env.NODE_ENV === 'test') ? 1 : _.size(activeAdapters) @@ -43,7 +41,7 @@ const CLIENT_COUNT = 1 + _.size(ioClientCmds) + adapterCount + nlpServerCount /* istanbul ignore next */ function ioClient() { // the child processes,kill all on death - let children = [] + const children = [] /* istanbul ignore next */ process.on('exit', () => { @@ -60,9 +58,9 @@ function ioClient() { _.each(ioClientCmds, (cmds, lang) => { // spawn ioclients for other lang global.log.info(`Starting socketIO client for ${lang} at ${process.env.IOPORT}`) - let cp = spawn('/bin/sh', ['-c', ` + const cp = spawn('/bin/sh', ['-c', ` ${srcCmd} - ${lang} ${cmds['client']} + ${lang} ${cmds.client} `], { stdio: [process.stdin, process.stdout, 'pipe'] }) children.push(cp) @@ -81,10 +79,10 @@ function ioClient() { /* istanbul ignore next */ function ioStart() { polyIO.server({ - port: process.env.IOPORT, - clientCount: CLIENT_COUNT, - debug: process.env['npm_config_debug'] - }) + port: process.env.IOPORT, + clientCount: CLIENT_COUNT, + debug: process.env.npm_config_debug, + }) .then(ioClient) return global.ioPromise } diff --git a/test/_init-test.js b/test/_init-test.js index 0d35e0b9..b7d6510c 100644 --- a/test/_init-test.js +++ b/test/_init-test.js @@ -3,25 +3,23 @@ const _ = require('lomath') const path = require('path') const aiva = require(path.join(__dirname, 'common')) -before(() => { - return co(function*() { - yield aiva.start() +before(() => co(function* () { + yield aiva.start() - global.log.info(`Running in ${process.env.NODE_ENV} mode`) - global.log.info(`Create rooms, init brain for tests`) - let helper = new Helper(path.join(__dirname, '..', 'scripts')) // emulate full hubot init + global.log.info(`Running in ${process.env.NODE_ENV} mode`) + global.log.info('Create rooms, init brain for tests') + const helper = new Helper(path.join(__dirname, '..', 'scripts')) // emulate full hubot init // emulate full hubot initialization, set to global.room for use - global.room = helper.createRoom({ name: global.DEFAULT_ROOM }) + global.room = helper.createRoom({ name: global.DEFAULT_ROOM }) // set the brain to test/asset.js's - _.set(this.room.robot, 'brain.data.users', users) - yield global.ioPromise - }) -}) + _.set(this.room.robot, 'brain.data.users', users) + yield global.ioPromise +})) after(() => { - global.log.info(`Destroying rooms, resetting test db`) + global.log.info('Destroying rooms, resetting test db') global.room.destroy() // cleanup test db }) diff --git a/test/asset.js b/test/asset.js index 3bd5759c..1b1ed931 100644 --- a/test/asset.js +++ b/test/asset.js @@ -1,7 +1,7 @@ // Assets for the tests const _ = require('lomath') -let A = { +const A = { // lib/test_todo todoGenProp: { name: 'task1', @@ -10,7 +10,7 @@ let A = { status: 'doing', tag: null, notes: null, - due: null + due: null, }, todoLegalizeProp_nonself: { name: 'task1', @@ -21,7 +21,7 @@ let A = { status: 'doing', tag: null, notes: null, - due: null + due: null, }, todoLegalizeProp_self: { name: 'task1', @@ -32,109 +32,104 @@ let A = { status: 'doing', tag: null, notes: null, - due: null + due: null, }, // lib/test_user - whois_alice: [[{"name":"alice","id":"ID0000001","email_address":"alice@email.com"}]], - wrapRes_alice: { envelope: { user: { id: 'ID0000001' } } } + whois_alice: [[{ name: 'alice', id: 'ID0000001', email_address: 'alice@email.com' }]], + wrapRes_alice: { envelope: { user: { id: 'ID0000001' } } }, } // users at robot.brain.data.users global.users = { - "ID0000001": { - "id": "ID0000001", - "name": "alice", - "email_address": "alice@email.com", - "slack": { - "id": "ID0000001", - "team_id": "TD0000001", - "name": "alice", - "deleted": false, - "presence": "away" - } + ID0000001: { + id: 'ID0000001', + name: 'alice', + email_address: 'alice@email.com', + slack: { + id: 'ID0000001', + team_id: 'TD0000001', + name: 'alice', + deleted: false, + presence: 'away', + }, + }, + ID0000002: { + id: 'ID0000002', + name: 'bob', + email_address: 'bob@email.com', + slack: { + id: 'ID0000002', + team_id: 'TD0000002', + name: 'bob', + deleted: false, + presence: 'away', + }, }, - "ID0000002": { - "id": "ID0000002", - "name": "bob", - "email_address": "bob@email.com", - "slack": { - "id": "ID0000002", - "team_id": "TD0000002", - "name": "bob", - "deleted": false, - "presence": "away" - } + USLACKBOT: { + id: 'USLACKBOT', + name: 'slackbot', + real_name: 'slackbot', + email_address: null, + slack: { + id: 'USLACKBOT', + team_id: 'T07S1438V', + name: 'slackbot', + deleted: false, + status: null, + color: '757575', + real_name: 'slackbot', + tz: null, + tz_label: 'Pacific Standard Time', + tz_offset: -28800, + is_admin: false, + is_owner: false, + is_primary_owner: false, + is_restricted: false, + is_ultra_restricted: false, + is_bot: false, + presence: 'active', + }, }, - "USLACKBOT": { - "id": "USLACKBOT", - "name": "slackbot", - "real_name": "slackbot", - "email_address": null, - "slack": { - "id": "USLACKBOT", - "team_id": "T07S1438V", - "name": "slackbot", - "deleted": false, - "status": null, - "color": "757575", - "real_name": "slackbot", - "tz": null, - "tz_label": "Pacific Standard Time", - "tz_offset": -28800, - "is_admin": false, - "is_owner": false, - "is_primary_owner": false, - "is_restricted": false, - "is_ultra_restricted": false, - "is_bot": false, - "presence": "active" - } - } } // hubot response object global.res = { - "message": { - "user": { - "id": "ID0000001", - "name": "alice", - "room": "Shell" + message: { + user: { + id: 'ID0000001', + name: 'alice', + room: 'Shell', }, - "text": "hubot myid", - "id": "messageId", - "done": false, - "room": "Shell" + text: 'hubot myid', + id: 'messageId', + done: false, + room: 'Shell', }, - "match": [ - "hubot myid" + match: [ + 'hubot myid', ], - "envelope": { - "room": "Shell", - "user": { - "id": "ID0000001", - "name": "alice", - "room": "Shell" + envelope: { + room: 'Shell', + user: { + id: 'ID0000001', + name: 'alice', + room: 'Shell', }, - "message": { - "user": { - "id": "ID0000001", - "name": "alice", - "room": "Shell" + message: { + user: { + id: 'ID0000001', + name: 'alice', + room: 'Shell', }, - "text": "hubot myid", - "id": "messageId", - "done": false, - "room": "Shell" - } - } + text: 'hubot myid', + id: 'messageId', + done: false, + room: 'Shell', + }, + }, } - - - - - -module.exports = A; +module.exports = A diff --git a/test/common.js b/test/common.js index 74008d85..e72319f5 100644 --- a/test/common.js +++ b/test/common.js @@ -8,12 +8,12 @@ const log = require(path.join(SRCPATH, 'log')) const { setEnv } = require(path.join(SRCPATH, 'env')) const { migrateDb } = require(path.join(SRCPATH, 'db')) global.chai = require('chai') // chai assertation library -chai.use(require("chai-as-promised")) +chai.use(require('chai-as-promised')) global.should = chai.should() global.sinon = require('sinon') // sinon spy/stub library global.Helper = require('hubot-test-helper') global.Promise.config({ warnings: false }) -global.DEFAULT_ROOM = "bot-test" // set for test +global.DEFAULT_ROOM = 'bot-test' // set for test global.A = require(path.join(__dirname, 'asset')) // global asset // set the hubot say handlers for unit tests: send reply to room @@ -36,14 +36,14 @@ function startProcess() { // set the port to test process.env.NODE_ENV = 'test' process.env.ADAPTER = 'Shell' - log.info(`Starting aiva test process`) + log.info('Starting aiva test process') setEnv() process.env.PORT = 9090 process.env.IOPORT = 7676 log.info(`Test is using PORT: ${process.env.PORT}; IOPORT: ${process.env.IOPORT}`) } catch (e) { log.error(JSON.stringify(e, null, 2)) - log.error("No config and not in CI, please provide your config file.") + log.error('No config and not in CI, please provide your config file.') reject() process.exit(1) } @@ -61,5 +61,5 @@ function start() { } module.exports = { - start: start + start, } From cecb370380002480eccb6929dd854cd6c5e62259 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 10:41:39 -0500 Subject: [PATCH 13/33] style correction in db/ --- db/migrations/20161003021116-create-chatlog.js | 2 +- db/migrations/20161007155536-create-user.js | 2 +- db/migrations/20161219230220-create-cronjob.js | 2 +- db/models/chatlog.js | 6 +++--- db/models/cronjob.js | 6 +++--- db/models/user.js | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/db/migrations/20161003021116-create-chatlog.js b/db/migrations/20161003021116-create-chatlog.js index 190e4198..5fd267c0 100644 --- a/db/migrations/20161003021116-create-chatlog.js +++ b/db/migrations/20161003021116-create-chatlog.js @@ -30,7 +30,7 @@ module.exports = { message: Sequelize.STRING, }) }, - down(queryInterface, Sequelize) { + down(queryInterface) { return queryInterface.dropTable('Chatlogs') }, } diff --git a/db/migrations/20161007155536-create-user.js b/db/migrations/20161007155536-create-user.js index f5411c70..4a6adba3 100644 --- a/db/migrations/20161007155536-create-user.js +++ b/db/migrations/20161007155536-create-user.js @@ -33,7 +33,7 @@ module.exports = { }, }) }, - down(queryInterface, Sequelize) { + down(queryInterface) { return queryInterface.dropTable('Users') }, } diff --git a/db/migrations/20161219230220-create-cronjob.js b/db/migrations/20161219230220-create-cronjob.js index 7fc818ea..c14ebcb7 100644 --- a/db/migrations/20161219230220-create-cronjob.js +++ b/db/migrations/20161219230220-create-cronjob.js @@ -31,7 +31,7 @@ module.exports = { }, }) }, - down(queryInterface, Sequelize) { + down(queryInterface) { return queryInterface.dropTable('Cronjobs') }, } diff --git a/db/models/chatlog.js b/db/models/chatlog.js index 8a3bdcba..6e065e78 100644 --- a/db/models/chatlog.js +++ b/db/models/chatlog.js @@ -3,7 +3,7 @@ // create with: // sequelize model:create --name Chatlog --attributes "adapter:string" -module.exports = function (sequelize, DataTypes) { +module.exports = function fn(sequelize, DataTypes) { const Chatlog = sequelize.define('Chatlog', { adapter: DataTypes.STRING, userid: DataTypes.STRING, @@ -14,10 +14,10 @@ module.exports = function (sequelize, DataTypes) { message: DataTypes.TEXT, }, { classMethods: { - associate(models) { + // associate(models) { // associations can be defined here // Chatlog.belongsTo(models.User) - }, + // }, }, }) return Chatlog diff --git a/db/models/cronjob.js b/db/models/cronjob.js index 74511993..62dbbfcc 100644 --- a/db/models/cronjob.js +++ b/db/models/cronjob.js @@ -1,6 +1,6 @@ -module.exports = function (sequelize, DataTypes) { +module.exports = function fn(sequelize, DataTypes) { const Cronjob = sequelize.define('Cronjob', { adapter: DataTypes.STRING, userid: DataTypes.STRING, @@ -8,9 +8,9 @@ module.exports = function (sequelize, DataTypes) { command: DataTypes.TEXT, }, { classMethods: { - associate(models) { + // associate(models) { // associations can be defined here - }, + // }, }, }) return Cronjob diff --git a/db/models/user.js b/db/models/user.js index 76a79343..f378e202 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -1,6 +1,6 @@ -module.exports = function (sequelize, DataTypes) { +module.exports = function fn(sequelize, DataTypes) { const User = sequelize.define('User', { adapter: DataTypes.STRING, userid: DataTypes.STRING, @@ -8,9 +8,9 @@ module.exports = function (sequelize, DataTypes) { envelope: DataTypes.TEXT, }, { classMethods: { - associate(models) { + // associate(models) { // associations can be defined here - }, + // }, }, }) return User From 0fdc216ef3bfece6b9c3dfe331276db67a065d18 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 11:22:46 -0500 Subject: [PATCH 14/33] styleguide fix for src --- src/aiva.js | 13 ++- src/db.js | 10 +-- src/env.js | 65 +++++++-------- src/formatter/slack_att.js | 159 ++++++++++++++++++++----------------- src/hasher.js | 33 +++++--- src/log.js | 2 +- src/msg-emulator.js | 17 ++-- src/start-io.js | 41 ++++++---- 8 files changed, 184 insertions(+), 156 deletions(-) diff --git a/src/aiva.js b/src/aiva.js index 8b0fc5c5..6dc2a7e7 100644 --- a/src/aiva.js +++ b/src/aiva.js @@ -1,13 +1,12 @@ const Promise = require('bluebird') -const { spawn, exec } = require('child_process') +const { spawn } = require('child_process') const _ = require('lomath') const ngrok = require('ngrok') -const path = require('path') +const { authDb, migrateDb } = require('./db') +const { setEnv, spawnEnv, activeAdapters } = require('./env') +const log = require('./log') +const startIO = require('./start-io') -const startIO = require(path.join(__dirname, 'start-io')) -const log = require(path.join(__dirname, 'log')) -const { setEnv, spawnEnv, activeAdapters } = require(path.join(__dirname, 'env')) -const { authDb, migrateDb } = require(path.join(__dirname, 'db')) const children = [] // child processes for spawn // finally, spawn a hubot in child.process using env @@ -28,7 +27,7 @@ function spawnHubot(adapter) { /* istanbul ignore next */ function startProcess() { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { log.info('Starting aiva process') setEnv() diff --git a/src/db.js b/src/db.js index fbfb6547..0d0ed725 100644 --- a/src/db.js +++ b/src/db.js @@ -1,10 +1,10 @@ const Promise = require('bluebird') const { exec } = require('child_process') const _ = require('lomath') -const path = require('path') const Sequelize = require('sequelize') -const log = require(path.join(__dirname, 'log')) -const dbEnvConfig = require(path.join(__dirname, '..', 'config', 'db.json')) +const log = require('./log') +const dbEnvConfig = require('../config/db.json') + Promise.config({ warnings: false }) /* istanbul ignore next */ @@ -38,9 +38,9 @@ function createDb() { function authDb() { return sequelize .authenticate() - .then((e) => { + .then(() => { log.info('Authenticated database successfully') - }).catch(e => createDb()).finally(() => sequelize.close()) + }).catch(() => createDb()).finally(() => sequelize.close()) } /* istanbul ignore next */ diff --git a/src/env.js b/src/env.js index 0c952f06..3a2a3d32 100644 --- a/src/env.js +++ b/src/env.js @@ -2,11 +2,11 @@ const Promise = require('bluebird') const config = require('config') const _ = require('lomath') const ngrok = require('ngrok') -Promise.promisifyAll(ngrok) -const path = require('path') const portscanner = require('portscanner') +const log = require('./log') + +Promise.promisifyAll(ngrok) Promise.promisifyAll(portscanner) -const log = require(path.join(__dirname, 'log')) global.config = config const globalKeys = _.difference(_.keys(config), ['ADAPTERS', 'ACTIVATE_IO_CLIENTS']) @@ -14,12 +14,14 @@ const globalConfig = _.pick(config, globalKeys) const activeAdapters = _.pickBy(config.get('ADAPTERS'), 'ACTIVATE') // helper to set process.env (or copy) from config -function configToEnv(config, env = process.env) { - _.forOwn(config, (v, k) => { +function configToEnv(conf, env = process.env) { + _.forOwn(conf, (v, k) => { if (_.isPlainObject(v)) { configToEnv(v, env) } else { - env[k] = v + _.assign(env, { + [k]: v, + }) } }) } @@ -43,7 +45,7 @@ function setEnv() { function cloneEnv(adapter) { const env = _.clone(process.env) env.ADAPTER = adapter - adapterConfig = config.get(`ADAPTERS.${adapter}`) + const adapterConfig = config.get(`ADAPTERS.${adapter}`) log.debug(`adapterConfig ${JSON.stringify(adapterConfig, null, 2)}`) configToEnv(adapterConfig, env) return Promise.resolve(env) @@ -55,7 +57,7 @@ function setPort(env) { const basePort = config.get(`PORTS.${env.ADAPTER}`) return portscanner.findAPortNotInUseAsync(basePort, basePort + 50, '127.0.0.1') .then((port) => { - env.PORT = port + _.assign(env, { PORT: port }) log.debug(`Set ${env.ADAPTER} PORT: ${port}`) return env }) @@ -69,32 +71,33 @@ function setWebhook(env) { if (!webhookKey) { log.debug(`No WEBHOOK set for adapter ${env.ADAPTER}`) return env - } else { - const webhook = env[webhookKey] - let subdomain - if (webhook && webhook.match(/\/\/(\w+)\.ngrok/)) { - subdomain = webhook.match(/\/\/(\w+)\.ngrok/)[1] - } + } + const webhook = env[webhookKey] + let subdomain + if (webhook && webhook.match(/\/\/(\w+)\.ngrok/)) { + subdomain = webhook.match(/\/\/(\w+)\.ngrok/)[1] + } - const ngrokOpts = _.pickBy({ - proto: 'http', // http|tcp|tls - addr: env.PORT, // port or network address - subdomain, - authtoken: env.NGROK_AUTH, - }) - log.debug(`ngrok options: ${JSON.stringify(ngrokOpts, null, 2)}`) + const ngrokOpts = _.pickBy({ + proto: 'http', // http|tcp|tls + addr: env.PORT, // port or network address + subdomain, + authtoken: env.NGROK_AUTH, + }) + log.debug(`ngrok options: ${JSON.stringify(ngrokOpts, null, 2)}`) - return ngrok.connectAsync(ngrokOpts) - .then((url) => { - env[webhookKey] = url // update - log.debug(`Set ${env.ADAPTER} webhook url: ${url}:${env.PORT}`) - return env - }) - .catch((e) => { - log.error(`${JSON.stringify(e, null, 2)}`) - return env + return ngrok.connectAsync(ngrokOpts) + .then((url) => { + _.assign(env, { + [webhookKey]: url, }) - } + log.debug(`Set ${env.ADAPTER} webhook url: ${url}:${env.PORT}`) + return env + }) + .catch((e) => { + log.error(`${JSON.stringify(e, null, 2)}`) + return env + }) } // spawn env and set all the adapter-specific env vars for adapter diff --git a/src/formatter/slack_att.js b/src/formatter/slack_att.js index ba225ce5..b143b704 100644 --- a/src/formatter/slack_att.js +++ b/src/formatter/slack_att.js @@ -1,6 +1,4 @@ // Module to generate Slack attachments for robot.adapter.customMessage - -// dependencies const _ = require('lomath') @@ -26,13 +24,14 @@ const palette = { // quick function to get color from palette /* istanbul ignore next */ + function getColor(str) { return _.get(palette, str.toLowerCase()) } // sample simple attachment // keys can be missing -const Att = { +const sampleAtt = { // color can be "good", "warning", "danger", hex #439FE0 color: 'good', pretext: 'This is a pretext', @@ -48,77 +47,87 @@ const Att = { thumb_url: 'https://slack.global.ssl.fastly.net/ae57/img/slack_api_logo.png', } -// console.log(gen({ message: { room: 'kengz' } }, Att)) - +// console.log(gen({ message: { room: 'kengz' } }, att)) /** - * Generates the JSON message object for Slack's robot.adapter.customMessage, on taking robot's res and multiple simple objs. - * @param {*} res robot's response object. - * @param {JSON|Array|*} Att Simplified attachment object(s) or an array of them, or any result to be parsed - * @param {Function} Parser (batch) that will be applied to atts, if specified. - * @return {JSON} The message object for Slack's robot.adapter.customMessage - * @example - * gen(res, gkgseachRes, slackAtt.gkgParser) - * // => gkgsearchRes as array of Slack attachments + * Helper method to clean the deeper fieldMat: remove rows where row[1] is falsy. + * @param {Array} fieldMat The fieldMat of slack attachment + * @return {Array} The cleaned matrix. */ /* istanbul ignore next */ -function gen(res, atts, parser) { - if (parser) { - // apply parser directly if specified - atts = parser(atts) - } else { - // no parser, ensure atts is an array of attachment JSONs - if (!_.isArray(atts)) { atts = [atts] } - } - return { - channel: res.message.room, - attachments: _.map(atts, genAttach), - } + +function cleanFieldMat(fieldMat) { + const cleanMap = _.map(fieldMat, row => (row[1] ? row : null)) + return _.compact(cleanMap) } /** * Generates the JSON attachment payload for Slack's robot.adapter.customMessage from a simplified JSON attachment object. Refer to https://api.slack.com/docs/attachments for details. - * @param {JSON} Att A simplified attachment object + * @param {JSON} att A simplified attachment object * @return {JSON} The attachment object. */ /* istanbul ignore next */ -function genAttach(Att) { + +function genAttach(rawAtt) { + let att = rawAtt + // cleanup the fieldmat - Att.fieldMat = cleanFieldMat(Att.fieldMat) + att.fieldMat = cleanFieldMat(att.fieldMat) + // filter out undefined values - Att = _.pickBy(Att) + att = _.pickBy(att) + // the 3 keys for each field const fieldKeys = ['title', 'value', 'short'] - let fields = _.map(Att.fieldMat, (fieldArr) => { - // for default: short = true + let fields = _.map(att.fieldMat, (fieldArr) => { fieldArr.push(true) return _.zipObject(fieldKeys, fieldArr) }) + // make null if is empty fields = _.isEmpty(fields) ? null : fields + // filter out null values return _.pickBy({ - fallback: _.join(_.compact([Att.pretext, Att.title, Att.title_link]), ' - '), - color: getColor(Att.color), - pretext: Att.pretext, - title: Att.title, - title_link: Att.title_link, - text: Att.text, + fallback: _.join(_.compact([att.pretext, att.title, att.title_link]), ' - '), + color: getColor(att.color), + pretext: att.pretext, + title: att.title, + title_link: att.title_link, + text: att.text, fields, - image_url: Att.image_url, - thumb_url: Att.thumb_url, + image_url: att.image_url, + thumb_url: att.thumb_url, }) } /** - * Helper method to clean the deeper fieldMat: remove rows where row[1] is falsy. - * @param {Array} fieldMat The fieldMat of slack attachment - * @return {Array} The cleaned matrix. + * Generates the JSON message object for Slack's robot.adapter.customMessage, + * on taking robot's res and multiple simple objs. + * @param {*} res robot's response object. + * @param {JSON|Array|*} att Simplified attachment object(s) + * or an array of them, or any result to be parsed + * @param {Function} Parser (batch) that will be applied to atts, if specified. + * @return {JSON} The message object for Slack's robot.adapter.customMessage + * @example + * gen(res, gkgseachRes, slackAtt.gkgParser) + * // => gkgsearchRes as array of Slack attachments */ /* istanbul ignore next */ -function cleanFieldMat(fieldMat) { - cleanMap = _.map(fieldMat, row => row[1] ? row : null) - return _.compact(cleanMap) + +function gen(res, atts, parser) { + let parsedAtts = atts + if (parser) { + // apply parser directly if specified + parsedAtts = parser(parsedAtts) + } else if (!_.isArray(parsedAtts)) { + // no parser, ensure parsedAtts is an array of attachment JSONs + parsedAtts = [parsedAtts] + } + return { + channel: res.message.room, + attachments: _.map(parsedAtts, genAttach), + } } @@ -126,26 +135,12 @@ function cleanFieldMat(fieldMat) { // The parsers into Slack attachment format // // //////////////////////////////////////////// - -/** - * Parser for google knowledge graph into slack attachments - * @param {JSON} gkgRes Result from google.kgsearch() - * @return {Array} Of Slack attachments - * @example - * gen(res, gkgseachRes, slackAtt.gkgParser) - * // => gkgsearchRes as array of Slack attachments - * - */ -/* istanbul ignore next */ -function gkgParser(gkgRes) { - const items = (gkgRes.itemListElement || []) - return _.map(items, _gkgParser) -} /** * Unit parser for google knowledge graph result to slack attachment */ /* istanbul ignore next */ -function _gkgParser(item) { + +function subGkgParser(item) { const att = { color: 'purple', pretext: _.get(item, 'result.description'), @@ -163,24 +158,29 @@ function _gkgParser(item) { /** * Parser for google knowledge graph into slack attachments - * @param {JSON} gsearchRes Result from google.gsearch() + * @param {JSON} gkgRes Result from google.kgsearch() * @return {Array} Of Slack attachments * @example - * gen(res, gseachRes, slackAtt.gsearchParser) - * // => gsearchRes as array of Slack attachments + * gen(res, gkgseachRes, slackAtt.gkgParser) + * // => gkgsearchRes as array of Slack attachments * */ /* istanbul ignore next */ -function gsearchParser(gsearchRes) { - const items = (gsearchRes.links || []) - return _.compact(_.map(items, _gsearchParser)) + +function gkgParser(gkgRes) { + const items = (gkgRes.itemListElement || []) + return _.map(items, subGkgParser) } + /** * Unit parser for google knowledge graph result to slack attachment */ /* istanbul ignore next */ -function _gsearchParser(item) { - if (!_.get(item, 'href')) { return null } + +function subGsearchParser(item) { + if (!_.get(item, 'href')) { + return null + } const att = { color: 'indigo', title: _.get(item, 'title'), @@ -194,11 +194,26 @@ function _gsearchParser(item) { return att } +/** + * Parser for google knowledge graph into slack attachments + * @param {JSON} gsearchRes Result from google.gsearch() + * @return {Array} Of Slack attachments + * @example + * gen(res, gseachRes, slackAtt.gsearchParser) + * // => gsearchRes as array of Slack attachments + * + */ +/* istanbul ignore next */ -const slackAtt = { +function gsearchParser(gsearchRes) { + const items = (gsearchRes.links || []) + return _.compact(_.map(items, subGsearchParser)) +} + + +module.exports = { + sampleAtt, gen, gkgParser, gsearchParser, } - -module.exports = slackAtt diff --git a/src/hasher.js b/src/hasher.js index ef15cfce..bb18acb7 100644 --- a/src/hasher.js +++ b/src/hasher.js @@ -1,42 +1,49 @@ -// Module for socket communication: use hash string and hashMap of callback functions for correct identification and execution. Is set as global. +// Module for socket communication: +// use hash string and hashMap of callback functions +// for correct identification and execution. +// Is set as global. const _ = require('lomath') const randomBytes = require('randombytes') // The hashMap for this global hash const hashMap = {} -// !for future multiple replies: don't delete on 'handle', but do a periodic scan and prune keys with older hash timestamp + // !for future multiple replies: don't delete on 'handle', + // but do a periodic scan and prune keys with older hash timestamp /** * Generates a hash string as current _.uniqueId(_.now()), format: __ - * Used when client passes msg to target script. This generates and registers in the hashMap the hash string, and also the optional callback function to handle replies. + * Used when client passes msg to target script. + * This generates and registers in the hashMap the hash string, + * and also the optional callback function to handle replies. * @param {string} id Script name from basename(__file__) * @param {Function} cb Callback function to store in this map, invoked by this hash string. * @return {string} the hash string */ -function gen(id, cb) { - /* istanbul ignore next */ - id = id || 'unidentified' + +function gen(id = 'unidentified', cb) { /* istanbul ignore next */ const hashStr = `${id}_${randomBytes(16).toString('hex')}` - /* istanbul ignore next */ + /* istanbul ignore next */ if (cb) { global.log.debug('Added a callback to hasher for global-client') - // if exists, add the callback function to map + // if exists, add the callback function to map hashMap[hashStr] = cb } return hashStr } /** - * Handler for socket client; use the msg's hash to find a callback function from hashMap, and execute cb(msg) if found. - * Note the payload msg received must contain the same hash, thus it's your job to include the same when replying. + * Handler for socket client; use the msg's hash to find + * a callback function from hashMap, and execute cb(msg) if found. + * Note the payload msg received must contain the same hash, + * thus it's your job to include the same when replying. * @param {JSON} msg The socket client JSON payload. */ /* istanbul ignore next */ -function handle(msg) { + +function handle(msg = {}) { // skip if it's an outgoing request (sending input to people to wait for output reply to handle) if (msg.input && !msg.output) { return } - msg = msg || {} const hashStr = _.isString(msg) ? msg : msg.hash if (hashStr) { global.log.debug('hash string exists for global-client') @@ -44,7 +51,7 @@ function handle(msg) { if (cb) { global.log.debug('hasher.handle invoking cb for global-client') _.omit(hashMap, hashStr) - return cb(msg) + cb(msg) } } } diff --git a/src/log.js b/src/log.js index 7f3fd8f6..a96bcf36 100644 --- a/src/log.js +++ b/src/log.js @@ -1,7 +1,7 @@ const winston = require('winston') /* istanbul ignore next */ -logLevel = process.env.npm_config_debug ? 'debug' : 'info' +const logLevel = process.env.npm_config_debug ? 'debug' : 'info' const log = global.log || new (winston.Logger)({ level: logLevel, transports: [new (winston.transports.Console)({ diff --git a/src/msg-emulator.js b/src/msg-emulator.js index c77af9f0..4de77bfa 100644 --- a/src/msg-emulator.js +++ b/src/msg-emulator.js @@ -1,8 +1,5 @@ -const _ = require('lomath') -const path = require('path') -const randomBytes = require('randombytes') const { TextMessage } = require('hubot') -const { User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) +const { User } = require('../db/models/index') // emulate a user sending a message to bot // call as: @@ -14,12 +11,12 @@ function receive(userid, text) { User.find({ where: { adapter, userid }, }) - .then((user) => { - const envelope = JSON.parse(user.envelope) - const message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) - global.robot.receive(message) - // global.robot.send(envelope, 'Direct message') - }) + .then((user) => { + const envelope = JSON.parse(user.envelope) + const message = new TextMessage(envelope, `${global.robot.name} ${text}`, emulMsgID) + global.robot.receive(message) + // global.robot.send(envelope, 'Direct message') + }) } module.exports = { diff --git a/src/start-io.js b/src/start-io.js index dc159015..9ceb4192 100644 --- a/src/start-io.js +++ b/src/start-io.js @@ -1,34 +1,36 @@ // The socket.io server and polyglot clients. Called by scripts/_init.js +// const { nlpServer } = require('cgkb') const { spawn } = require('child_process') const _ = require('lomath') const path = require('path') const polyIO = require('poly-socketio') -const log = require(path.join(__dirname, 'log')) -const { setEnv, activeAdapters } = require(path.join(__dirname, 'env')) -// const { nlpServer } = require('cgkb') +const { setEnv, activeAdapters } = require('./env') +const log = require('./log') +const jsIOClient = require('../lib/client') + const nlpServerCount = 0 +const LIBPATH = path.join(__dirname, '..', 'lib') /* istanbul ignore next */ -const bashSrc = (process.platform == 'darwin') ? '~/.bash_profile' : '~/.bashrc' +const bashSrc = (process.platform === 'darwin') ? '~/.bash_profile' : '~/.bashrc' + /* istanbul ignore next */ const srcCmd = process.env.CI ? '' : `. ${bashSrc}` + /* istanbul ignore next */ if (process.env.IOPORT === undefined) { setEnv() } -const LIBPATH = path.join(__dirname, '..', 'lib') -const jsIOClient = require(path.join(LIBPATH, 'client')) // import other languages via child_process const ioClientCmds = _.pickBy({ ruby: { - // install_dependency: "gem install socket.io-client-simple activesupport", + // install_dependency: "gem install socket.io-client-simple activesupport", client: path.join(LIBPATH, 'client.rb'), }, python: { - // install_dependency: "python -m pip install socketIO-client", + // install_dependency: "python -m pip install socketIO-client", client: path.join(LIBPATH, 'client.py'), }, -}, - (args, cmd) => global.config.get('ACTIVATE_IO_CLIENTS').get(cmd)) +}, (args, cmd) => global.config.get('ACTIVATE_IO_CLIENTS').get(cmd)) /* istanbul ignore next */ const adapterCount = (process.env.NODE_ENV === 'test') ? 1 : _.size(activeAdapters) @@ -36,9 +38,13 @@ const CLIENT_COUNT = 1 + _.size(ioClientCmds) + adapterCount + nlpServerCount /** * Helper: called from within ioServer after its setup. - * Start all polyglot ioClient processes using spawn. Kill them on error to prevent runaway processes, i.e. run all the io_import. processes. The io_import. im turn runs all the io clients of that language. + * Start all polyglot ioClient processes using spawn. + * Kill them on error to prevent runaway processes, + * i.e. run all the io_import. processes. + * The io_import. im turn runs all the io clients of that language. */ /* istanbul ignore next */ + function ioClient() { // the child processes,kill all on death const children = [] @@ -48,16 +54,16 @@ function ioClient() { children.forEach((child) => { child.kill() }) - global.log.info('Exit: killed ioClient.js children') + log.info('Exit: killed ioClient.js children') }) // import js locally jsIOClient.join() - // nlpServer({ port: process.env.IOPORT }) // start nlp server + // nlpServer({ port: process.env.IOPORT }) // start nlp server _.each(ioClientCmds, (cmds, lang) => { // spawn ioclients for other lang - global.log.info(`Starting socketIO client for ${lang} at ${process.env.IOPORT}`) + log.info(`Starting socketIO client for ${lang} at ${process.env.IOPORT}`) const cp = spawn('/bin/sh', ['-c', ` ${srcCmd} ${lang} ${cmds.client} @@ -66,7 +72,7 @@ function ioClient() { /* istanbul ignore next */ cp.stderr.on('data', (data) => { - global.log.error(`${data.toString('utf8')}`) + log.error(`${data.toString('utf8')}`) cp.kill('SIGTERM') // kill if err to prevent runover process }) }) @@ -77,13 +83,14 @@ function ioClient() { * Calls server and client methods above. */ /* istanbul ignore next */ + function ioStart() { polyIO.server({ port: process.env.IOPORT, clientCount: CLIENT_COUNT, debug: process.env.npm_config_debug, }) - .then(ioClient) + .then(ioClient) return global.ioPromise } @@ -91,7 +98,7 @@ function ioStart() { const cleanExit = () => { process.exit() } process.on('SIGINT', cleanExit) // catch ctrl-c process.on('SIGTERM', cleanExit) // catch kill -process.on('uncaughtException', global.log.error) +process.on('uncaughtException', log.error) // export for use by hubot module.exports = ioStart From 1d9ec18f30924a3062c7fd59af9b324ea17d57aa Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 11:25:58 -0500 Subject: [PATCH 15/33] styleguide fix for db/ --- db/migrations/20161003021116-create-chatlog.js | 2 -- db/migrations/20161007155536-create-user.js | 2 -- db/migrations/20161219230220-create-cronjob.js | 2 -- db/models/chatlog.js | 6 ++---- db/models/cronjob.js | 4 +--- db/models/index.js | 6 +++--- db/models/user.js | 4 +--- 7 files changed, 7 insertions(+), 19 deletions(-) diff --git a/db/migrations/20161003021116-create-chatlog.js b/db/migrations/20161003021116-create-chatlog.js index 5fd267c0..cbff4cef 100644 --- a/db/migrations/20161003021116-create-chatlog.js +++ b/db/migrations/20161003021116-create-chatlog.js @@ -1,5 +1,3 @@ - - // to create: sequelize migration:create --name create-chatlog // to run: sequelize db:migrate // to revert: sequelize db:migrate:undo:all diff --git a/db/migrations/20161007155536-create-user.js b/db/migrations/20161007155536-create-user.js index 4a6adba3..5ad3db16 100644 --- a/db/migrations/20161007155536-create-user.js +++ b/db/migrations/20161007155536-create-user.js @@ -1,5 +1,3 @@ - - module.exports = { up(queryInterface, Sequelize) { return queryInterface.createTable('Users', { diff --git a/db/migrations/20161219230220-create-cronjob.js b/db/migrations/20161219230220-create-cronjob.js index c14ebcb7..1b8bc7b7 100644 --- a/db/migrations/20161219230220-create-cronjob.js +++ b/db/migrations/20161219230220-create-cronjob.js @@ -1,5 +1,3 @@ - - module.exports = { up(queryInterface, Sequelize) { return queryInterface.createTable('Cronjobs', { diff --git a/db/models/chatlog.js b/db/models/chatlog.js index 6e065e78..1d621122 100644 --- a/db/models/chatlog.js +++ b/db/models/chatlog.js @@ -1,5 +1,3 @@ - - // create with: // sequelize model:create --name Chatlog --attributes "adapter:string" @@ -15,8 +13,8 @@ module.exports = function fn(sequelize, DataTypes) { }, { classMethods: { // associate(models) { - // associations can be defined here - // Chatlog.belongsTo(models.User) + // associations can be defined here + // Chatlog.belongsTo(models.User) // }, }, }) diff --git a/db/models/cronjob.js b/db/models/cronjob.js index 62dbbfcc..efab3669 100644 --- a/db/models/cronjob.js +++ b/db/models/cronjob.js @@ -1,5 +1,3 @@ - - module.exports = function fn(sequelize, DataTypes) { const Cronjob = sequelize.define('Cronjob', { adapter: DataTypes.STRING, @@ -9,7 +7,7 @@ module.exports = function fn(sequelize, DataTypes) { }, { classMethods: { // associate(models) { - // associations can be defined here + // associations can be defined here // }, }, }) diff --git a/db/models/index.js b/db/models/index.js index 692e54ea..20dfa88d 100644 --- a/db/models/index.js +++ b/db/models/index.js @@ -1,11 +1,11 @@ - - const fs = require('fs') const path = require('path') const Sequelize = require('sequelize') +const fullConfig = require('../../config/db.json') + const basename = path.basename(module.filename) const env = process.env.NODE_ENV || 'development' -const config = require(path.join(__dirname, '..', '..', 'config', 'db.json'))[env] +const config = fullConfig[env] const db = {} let sequelize diff --git a/db/models/user.js b/db/models/user.js index f378e202..7a072155 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -1,5 +1,3 @@ - - module.exports = function fn(sequelize, DataTypes) { const User = sequelize.define('User', { adapter: DataTypes.STRING, @@ -9,7 +7,7 @@ module.exports = function fn(sequelize, DataTypes) { }, { classMethods: { // associate(models) { - // associations can be defined here + // associations can be defined here // }, }, }) From 7e4f0103fa3ec0b4d6d382f79ca6d99b44aa19cf Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 11:41:36 -0500 Subject: [PATCH 16/33] styleguide fix for scripts/ --- scripts/_init.js | 18 ++++++++++-------- scripts/cgkb-demo.js | 12 +++++------- scripts/convo.js | 31 ++++++++++++++----------------- scripts/cronjob.js | 13 +++++++------ scripts/hello-io.js | 3 +-- 5 files changed, 37 insertions(+), 40 deletions(-) diff --git a/scripts/_init.js b/scripts/_init.js index f04843fd..4c4ca5b3 100644 --- a/scripts/_init.js +++ b/scripts/_init.js @@ -1,14 +1,16 @@ // dependencies -// Module that runs after bot is constructed, before all other scripts are loaded; emit 'ready' to kickstart things such as auto-serialization -global.Promise = require('bluebird') -global.co = require('co') -global._ = require('lomath') +// Module that runs after bot is constructed, +// before all other scripts are loaded; +// emit 'ready' to kickstart things such as auto-serialization +const Promise = require('bluebird') +const co = require('co') const fs = require('fs') +const _ = require('lomath') const path = require('path') const polyIO = require('poly-socketio') +const log = require('../src/log') global.ROOTPATH = path.join(__dirname, '..') -const log = require(path.join(__dirname, '..', 'src', 'log')) const brainDumpPath = path.join(__dirname, '..', 'brain.json') polyIO.client({ port: process.env.IOPORT }) @@ -18,16 +20,16 @@ module.exports = (robot) => { global.robot = robot // wake up, init - co(function* () { + co(function* wake() { /* istanbul ignore next */ if (robot.adapter.constructor.name === 'Shell') { // set for Shell local dev - robot.brain.data.users = global.users + _.assign(robot.brain.data, { users: global.users }) } yield Promise.delay(10) // wait to connect, get users // emit 'ready' event to kick off initialization robot.emit('ready') - }).catch(global.log.error) + }).catch(log.error) // initializations robot.on('ready', () => { diff --git a/scripts/cgkb-demo.js b/scripts/cgkb-demo.js index e6702fc3..571a9d9e 100644 --- a/scripts/cgkb-demo.js +++ b/scripts/cgkb-demo.js @@ -1,7 +1,5 @@ // dependencies -const co = require('co') const _ = require('lomath') -const path = require('path') const cgkb = require('cgkb') /* istanbul ignore next */ @@ -18,6 +16,7 @@ module.exports = (robot) => { robot.respond(/nlp\s*demo\s*2$/i, (res) => { cgkb.add('Book me a flight from New York to London for Sunday') + res.send('Your wish is my command') }) robot.respond(/.*/, (res) => { @@ -25,12 +24,11 @@ module.exports = (robot) => { text = _.trim(_.replace(text, robot.name, '')) if (_.includes(text, 'nlp') || _.includes(text, 'clear kb')) { return - } else { - cgkb.add(text) - .then(() => { - global.log.info('Knowledge saved to brain') - }) } + cgkb.add(text) + .then(() => { + global.log.info('Knowledge saved to brain') + }) if (_.includes(text, 'flight')) { res.send('Your wish is my command') } diff --git a/scripts/convo.js b/scripts/convo.js index 2d7a7682..80c6c7d3 100644 --- a/scripts/convo.js +++ b/scripts/convo.js @@ -1,8 +1,6 @@ -// dependencies // Interface script for convo engine const _ = require('lomath') -const path = require('path') -const { Chatlog, User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) +const { Chatlog, User } = require('../db/models/index') /* istanbul ignore next */ module.exports = (robot) => { @@ -17,21 +15,20 @@ module.exports = (robot) => { to: 'convo_classifier.py', intent: 'classify', }) - .then((reply) => { - const convo = reply.output - global.log.info(`Convo Score ${convo.score}, Topic: ${convo.topic}`) - if (convo.topic === 'exception') { - // TODO can add some counter by user to activate - return - } - res.send(convo.response) - }).catch(console.log) + .then((reply) => { + const convo = reply.output + global.log.info(`Convo Score ${convo.score}, Topic: ${convo.topic}`) + if (convo.topic === 'exception') { + return + } + res.send(convo.response) + }).catch(global.log.error) }) // catch all chatlogs - robot.hear(/.*/, (res) => {}) + robot.hear(/.*/, () => {}) - robot.receiveMiddleware((context, next, done) => { + robot.receiveMiddleware((context, next) => { const envelope = context.response.envelope const adapter = process.env.ADAPTER const userid = _.toString(_.get(envelope, 'user.id')) @@ -51,7 +48,6 @@ module.exports = (robot) => { where: { adapter, userid }, defaults: { username, envelope: JSON.stringify(envelope) }, }) - .spread((user, created) => {}) _.each(inlogs, (inlog) => { Chatlog.create(inlog) @@ -61,9 +57,10 @@ module.exports = (robot) => { return next() }) - robot.responseMiddleware((context, next, done) => { + robot.responseMiddleware((context, next) => { const target = context.response.envelope - // global.log.info(JSON.stringify(target, null, 2)) + + // global.log.info(JSON.stringify(target, null, 2)) const replies = context.strings const outlogs = _.map(replies, text => ({ adapter: process.env.ADAPTER, diff --git a/scripts/cronjob.js b/scripts/cronjob.js index b1f13115..6efa1ce5 100644 --- a/scripts/cronjob.js +++ b/scripts/cronjob.js @@ -1,17 +1,17 @@ // dependencies -const _ = require('lomath') -const date = require('date.js') -const path = require('path') const { CronJob } = require('cron') -const { Cronjob, User } = require(path.join(__dirname, '..', 'db', 'models', 'index')) -const msgEmulator = require(path.join(__dirname, '..', 'src', 'msg-emulator')) +const date = require('date.js') +const _ = require('lomath') +const { Cronjob } = require('../db/models/index') +const msgEmulator = require('../src/msg-emulator') // Create the real job from model job function createJob(job) { const time = new Date(job.pattern) + // when next phase complete, can just use date(job.pattern) const pattern = _.isNaN(time.getTime()) ? job.pattern : time - new CronJob({ + return new CronJob({ cronTime: pattern, onTick: _.partial(msgEmulator.receive, job.userid, job.command), start: true, @@ -20,6 +20,7 @@ function createJob(job) { Cronjob.all().then((jobs) => { _.each(jobs, createJob) + // need to delete overdue // need to also create on add below // also need to consider the best way to parse command. do 'remind' vs 'emulate' diff --git a/scripts/hello-io.js b/scripts/hello-io.js index b98bad04..f5414116 100644 --- a/scripts/hello-io.js +++ b/scripts/hello-io.js @@ -1,4 +1,3 @@ -// dependencies // Sample interface script for lib//hello. // Bot will call this function with the robot argument @@ -24,6 +23,6 @@ module.exports = (robot) => { // respond to user when client.js resolves the promise .then((reply) => { res.send(reply.output) - }).catch(console.log) + }).catch(global.log.error) }) } From ad8c422019bde2f90cf78c2dfc2abc7c9e2283b3 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 12:33:33 -0500 Subject: [PATCH 17/33] fix middleware done arg breakage --- scripts/convo.js | 9 +++++---- scripts/hello-io.js | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/convo.js b/scripts/convo.js index 80c6c7d3..5bcb4313 100644 --- a/scripts/convo.js +++ b/scripts/convo.js @@ -1,3 +1,4 @@ +// dependencies // Interface script for convo engine const _ = require('lomath') const { Chatlog, User } = require('../db/models/index') @@ -28,7 +29,7 @@ module.exports = (robot) => { // catch all chatlogs robot.hear(/.*/, () => {}) - robot.receiveMiddleware((context, next) => { + robot.receiveMiddleware((context, next, done) => { const envelope = context.response.envelope const adapter = process.env.ADAPTER const userid = _.toString(_.get(envelope, 'user.id')) @@ -54,10 +55,10 @@ module.exports = (robot) => { global.log.debug(`[In log]: ${inlog.message}`) }) - return next() + return next(done) }) - robot.responseMiddleware((context, next) => { + robot.responseMiddleware((context, next, done) => { const target = context.response.envelope // global.log.info(JSON.stringify(target, null, 2)) @@ -75,6 +76,6 @@ module.exports = (robot) => { Chatlog.create(outlog) global.log.debug(`[Out log]: ${outlog.message}`) }) - return next() + return next(done) }) } diff --git a/scripts/hello-io.js b/scripts/hello-io.js index f5414116..8efc7a4c 100644 --- a/scripts/hello-io.js +++ b/scripts/hello-io.js @@ -1,3 +1,4 @@ +// dependencies // Sample interface script for lib//hello. // Bot will call this function with the robot argument From 33549d7d58b5ad9e6926417326165315513828c6 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 12:43:22 -0500 Subject: [PATCH 18/33] styleguide fix for test --- lib/client.js | 33 +++++++++++----------- lib/js/hello.js | 5 ++-- test/_init-test.js | 12 ++++---- test/asset.js | 1 - test/common.js | 46 +++++++++++++++++-------------- test/scripts/test-hello-io.coffee | 2 +- 6 files changed, 54 insertions(+), 45 deletions(-) diff --git a/lib/client.js b/lib/client.js index a9edcd80..1f82b8c6 100644 --- a/lib/client.js +++ b/lib/client.js @@ -3,26 +3,26 @@ const _ = require('lomath') const path = require('path') const requireDir = require('require-dir') const socketIOClient = require('socket.io-client') -const SRCPATH = path.join(__dirname, '..', 'src') -const log = require(path.join(SRCPATH, 'log')) +const log = require('../src/log') -let lib_js, - client +let libJs +let client const ioid = 'js' // the id of this script for io client registration -// log.info(lib_js.ai.nlp.POS.getPOS({input: "remind me to do laundry"})) +// log.info(libJs.ai.nlp.POS.getPOS({input: "remind me to do laundry"})) // correct the reply JSON /* istanbul ignore next */ function correctReply(reply, msg) { - if (!_.isPlainObject(reply)) { - reply = { output: reply } + let cReply = reply + if (!_.isPlainObject(cReply)) { + cReply = { output: cReply } } // autofill if not already exist - reply.to = reply.to || msg.from - reply.from = reply.from || ioid - reply.hash = reply.hash || msg.hash - return reply + cReply.to = cReply.to || msg.from + cReply.from = cReply.from || ioid + cReply.hash = cReply.hash || msg.hash + return cReply } // 1. Register the socket.io client @@ -37,16 +37,17 @@ function correctReply(reply, msg) { */ /* istanbul ignore next */ function handle(msg) { - let to = msg.to, - intent = msg.intent + const to = msg.to + const intent = msg.intent if (to && intent) { let reply + // try JSON or JSON.input as input try { - reply = _.get(lib_js[to], intent)(msg) + reply = _.get(libJs[to], intent)(msg) } catch (err) { try { - reply = _.get(lib_js[to], intent)(msg.input) + reply = _.get(libJs[to], intent)(msg.input) } catch (deepErr) { log.debug('js handle fails.', deepErr) } @@ -63,7 +64,7 @@ function handle(msg) { /* istanbul ignore next */ function join() { // import all in lib/js/, called only when the modules are needed - lib_js = requireDir(path.join(__dirname, 'js')) + libJs = requireDir(path.join(__dirname, 'js')) log.debug('import js lib from client.js') const IOPORT = process.env.IOPORT || 6466 log.info(`Starting socketIO client for js at ${IOPORT}`) diff --git a/lib/js/hello.js b/lib/js/hello.js index 178bbf3f..9944fa72 100644 --- a/lib/js/hello.js +++ b/lib/js/hello.js @@ -1,12 +1,13 @@ const path = require('path') + const ioid = path.basename(__filename) function foo(input) { - return 'Hello from Nodejs.' + return `Hello from Nodejs, ${input}` } function sayHi(msg) { - reply = { + const reply = { output: foo(msg.input), to: msg.from, from: ioid, diff --git a/test/_init-test.js b/test/_init-test.js index b7d6510c..9beb179f 100644 --- a/test/_init-test.js +++ b/test/_init-test.js @@ -1,20 +1,22 @@ // First mocha test to run: sets up before all tests +const co = require('co') +const Helper = require('hubot-test-helper') const _ = require('lomath') const path = require('path') -const aiva = require(path.join(__dirname, 'common')) +const aiva = require('./common') -before(() => co(function* () { +before(() => co(function* init() { yield aiva.start() global.log.info(`Running in ${process.env.NODE_ENV} mode`) global.log.info('Create rooms, init brain for tests') const helper = new Helper(path.join(__dirname, '..', 'scripts')) // emulate full hubot init - // emulate full hubot initialization, set to global.room for use + // emulate full hubot initialization, set to global.room for use global.room = helper.createRoom({ name: global.DEFAULT_ROOM }) - // set the brain to test/asset.js's - _.set(this.room.robot, 'brain.data.users', users) + // set the brain to test/asset.js's + _.set(this.room.robot, 'brain.data.users', global.users) yield global.ioPromise })) diff --git a/test/asset.js b/test/asset.js index 1b1ed931..ecb533da 100644 --- a/test/asset.js +++ b/test/asset.js @@ -1,5 +1,4 @@ // Assets for the tests -const _ = require('lomath') const A = { // lib/test_todo diff --git a/test/common.js b/test/common.js index e72319f5..43e81aff 100644 --- a/test/common.js +++ b/test/common.js @@ -1,30 +1,37 @@ // common setups for tests, run before tests -global.Promise = require('bluebird') -global.co = require('co') -const path = require('path') -const SRCPATH = path.join(__dirname, '..', 'src') -const startIO = require(path.join(SRCPATH, 'start-io')) -const log = require(path.join(SRCPATH, 'log')) -const { setEnv } = require(path.join(SRCPATH, 'env')) -const { migrateDb } = require(path.join(SRCPATH, 'db')) -global.chai = require('chai') // chai assertation library -chai.use(require('chai-as-promised')) +const Promise = require('bluebird') +const chai = require('chai') // chai assertation library +const chaiAsPromised = require('chai-as-promised') +const co = require('co') +const Helper = require('hubot-test-helper') +const _ = require('lomath') +const sinon = require('sinon') // sinon spy/stub library + +const A = require('./asset') // global asset +const { migrateDb } = require('../src/db') +const { setEnv } = require('../src/env') +const log = require('../src/log') +const startIO = require('../src/start-io') + +chai.use(chaiAsPromised) +global.chai = chai +global.co = co +global.Promise = Promise global.should = chai.should() -global.sinon = require('sinon') // sinon spy/stub library -global.Helper = require('hubot-test-helper') -global.Promise.config({ warnings: false }) +global.sinon = sinon +global.Helper = Helper +global.A = A global.DEFAULT_ROOM = 'bot-test' // set for test -global.A = require(path.join(__dirname, 'asset')) // global asset +global.Promise.config({ warnings: false }) // set the hubot say handlers for unit tests: send reply to room -global.say = (room, name, key) => { - key = key || 'output' - return _.flow(_.partial(_.get, _, key), _.bind(room.user.say, room, name)) +global.say = (room, name, key = 'output') => { + const msg = _.flow(_.partial(_.get, _, key), _.bind(room.user.say, room, name)) + return msg } // Promise.delay, with adjusted time factors. for use with yield -global.delayer = (factor) => { - factor = factor || 1 +global.delayer = (factor = 1) => { let timeout = 100 * factor timeout = _.min([timeout, 16000]) // timeout is capped at 16s return Promise.delay(timeout) @@ -48,7 +55,6 @@ function startProcess() { process.exit(1) } - const ROOTPATH = path.join(__dirname, '..') startIO() // start socketIO resolve() }) diff --git a/test/scripts/test-hello-io.coffee b/test/scripts/test-hello-io.coffee index f6eb5e6b..94439f63 100644 --- a/test/scripts/test-hello-io.coffee +++ b/test/scripts/test-hello-io.coffee @@ -45,6 +45,6 @@ describe 'scripts/hello-io.js', -> it 'hubot: Hello from Nodejs.', -> @room.messages.should.eql [ ['alice', '@hubot hello-io js'] - ['hubot', 'Hello from Nodejs.'] + ['hubot', 'Hello from Nodejs, Hello from user.'] ] From f93d5c5a3623d96610ff58411fc9ba7d12664577 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 13:23:46 -0500 Subject: [PATCH 19/33] styleguide fix for index --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index 616bce1d..e8f2d229 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,4 @@ -const path = require('path') -const aiva = require(path.join(__dirname, 'src', 'aiva')) +const aiva = require('../src/aiva') if (require.main === module) { aiva.start() From 5b70ecd0a5396b734727ea3a0f89109adcc7eb8b Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:01:02 -0500 Subject: [PATCH 20/33] fix pathng in index --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index e8f2d229..100cc2b6 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -const aiva = require('../src/aiva') +const aiva = require('./src/aiva') if (require.main === module) { aiva.start() From 9e774eebc70b1aafff1d4cc864f60a085b4124fc Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:01:12 -0500 Subject: [PATCH 21/33] fix py styles for codacy --- lib/client.py | 6 +++--- lib/py/hello.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/client.py b/lib/client.py index 5b7d499e..6834bcd6 100644 --- a/lib/client.py +++ b/lib/client.py @@ -73,7 +73,7 @@ def getAt(module, dotpath): def correctReply(reply, msg): '''correct the reply JSON''' - if type(reply) is not dict: + if not isinstance(reply, dict): reply = {"output": reply} # autofill if not already exist reply["to"] = reply.get("to") or msg.get("from") @@ -111,10 +111,10 @@ def handle(msg): # try JSON or JSON.input as input try: reply = getAt(getAt(lib_py, to), intent)(msg) - except: + except Exception: try: reply = getAt(getAt(lib_py, to), intent)(msg.get("input")) - except: + except Exception: e = sys.exc_info()[0] print('py handle fails.', e) finally: diff --git a/lib/py/hello.py b/lib/py/hello.py index 7637c788..e0ced0c5 100644 --- a/lib/py/hello.py +++ b/lib/py/hello.py @@ -6,8 +6,8 @@ ########################################## -def foo(input): - match = input.find('Hello') > -1 +def foo(incoming): + match = incoming.find('Hello') > -1 return 'Hello from Python.' if match else 'Who are you?' From 7cccc81f67c5974f21a871423c83eb4bc2e3a47d Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:01:22 -0500 Subject: [PATCH 22/33] fix test co --- test/lib/test-client.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/test-client.coffee b/test/lib/test-client.coffee index cc09041a..6121568e 100644 --- a/test/lib/test-client.coffee +++ b/test/lib/test-client.coffee @@ -10,7 +10,7 @@ describe 'src/global-client.js', -> # creating room with 'httpd: false' will auto tear-down @room = helper.createRoom(httpd: false, name: global.DEFAULT_ROOM) # delay to wait for all clients to join - co => + co -> yield delayer() describe 'global.client.clientPass', -> From 935c7cde4680f4ae9994ae821bd0e5618e80535d Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:11:09 -0500 Subject: [PATCH 23/33] fix io naming convention for py and rb --- lib/py/hello.py | 2 +- lib/rb/Hello.rb | 6 +++--- scripts/hello-io.js | 3 ++- test/lib/test-client.coffee | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/py/hello.py b/lib/py/hello.py index e0ced0c5..b7de101f 100644 --- a/lib/py/hello.py +++ b/lib/py/hello.py @@ -12,7 +12,7 @@ def foo(incoming): # module method. Feel free to add more -def sayHi(msg): +def say_hi(msg): # the reply JSON payload. reply = { 'output': foo(msg.get('input')), diff --git a/lib/rb/Hello.rb b/lib/rb/Hello.rb index 4dedf014..8478c277 100644 --- a/lib/rb/Hello.rb +++ b/lib/rb/Hello.rb @@ -2,11 +2,11 @@ module Hello class << self - # the id of this script for JSON payload 'from' - @@ioid = File.basename(__FILE__) + # the id of this script for JSON payload 'from' + @ioid = File.basename(__FILE__) # module method definition - def sayHi(msg) + def say_hi(msg) reply = { 'output' => 'Hello from Ruby.', 'to' => msg['from'], diff --git a/scripts/hello-io.js b/scripts/hello-io.js index 8efc7a4c..14face2c 100644 --- a/scripts/hello-io.js +++ b/scripts/hello-io.js @@ -11,6 +11,7 @@ module.exports = (robot) => { // call the hello.py methods robot.respond(/hello-io\s*(.+)/i, (res) => { const lang = res.match[1] + const fnName = lang === 'js' ? 'sayHi' : 'say_hi' // use the global client to pass to the hello.py client // this returns a promise @@ -18,7 +19,7 @@ module.exports = (robot) => { // must specify at least the following keys input: 'Hello from user.', to: `hello.${lang}`, - intent: 'sayHi', + intent: fnName, }) // this goes through hello.py -> client.js // respond to user when client.js resolves the promise diff --git a/test/lib/test-client.coffee b/test/lib/test-client.coffee index 6121568e..61a4b21b 100644 --- a/test/lib/test-client.coffee +++ b/test/lib/test-client.coffee @@ -4,7 +4,7 @@ describe 'src/global-client.js', -> msgDirect = input: 'Hello from user.', to: 'hello.py', - intent: 'sayHi' + intent: 'say_hi' beforeEach -> # creating room with 'httpd: false' will auto tear-down From c459bf2f8eff78442859387db3f5add095d1b3d6 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:20:06 -0500 Subject: [PATCH 24/33] correct str len issues --- scripts/convo.js | 4 +++- src/aiva.js | 6 +++++- src/db.js | 8 ++++++-- src/formatter/slack_att.js | 2 +- src/log.js | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/scripts/convo.js b/scripts/convo.js index 5bcb4313..68313022 100644 --- a/scripts/convo.js +++ b/scripts/convo.js @@ -42,7 +42,9 @@ module.exports = (robot) => { room: _.get(envelope, 'room'), incoming: true, method: 'receive', - message: _.get(envelope, 'message.text') || _.join(_.keys(_.get(envelope, 'message.message')), ', '), + message: ( + _.get(envelope, 'message.text') || + _.join(_.keys(_.get(envelope, 'message.message')), ', ')), }] User.findOrCreate({ diff --git a/src/aiva.js b/src/aiva.js index 6dc2a7e7..de1fa969 100644 --- a/src/aiva.js +++ b/src/aiva.js @@ -12,7 +12,11 @@ const children = [] // child processes for spawn // finally, spawn a hubot in child.process using env /* istanbul ignore next */ function spawnProcess(env) { - const hb = spawn('./bin/hubot', ['-a', _.toLower(env.ADAPTER), '--name', env.BOTNAME], { stdio: 'inherit', env }) + const hb = spawn( + './bin/hubot', + ['-a', _.toLower(env.ADAPTER), '--name', env.BOTNAME], + { stdio: 'inherit', env }, + ) children.push(hb) log.info(`Deploying bot ${env.BOTNAME} with adapter ${env.ADAPTER}`) return env diff --git a/src/db.js b/src/db.js index 0d0ed725..243a4a80 100644 --- a/src/db.js +++ b/src/db.js @@ -25,7 +25,10 @@ function createDb() { dbConfig.password, dbConfig) const nodeEnvs = ['test', 'development', 'production'] - const createDbQueries = _.map(nodeEnvs, nodeEnv => `CREATE DATABASE ${_.get(dbEnvConfig, `${nodeEnv}.database`)};`) + const createDbQueries = _.map( + nodeEnvs, + nodeEnv => `CREATE DATABASE ${_.get(dbEnvConfig, `${nodeEnv}.database`)};`, + ) return Promise.any( _.map(createDbQueries, createDbQuery => sysSeq.query(createDbQuery))).then(() => { @@ -46,7 +49,8 @@ function authDb() { /* istanbul ignore next */ function migrateDb() { return new Promise((resolve, reject) => { - exec(`./node_modules/.bin/sequelize db:migrate --env ${process.env.NODE_ENV}`, (err, stdout, stderr) => { + const cmdStr = `./node_modules/.bin/sequelize db:migrate --env ${process.env.NODE_ENV}` + exec(cmdStr, (err, stdout, stderr) => { if (err) { log.error(stderr.toString()) reject(err) diff --git a/src/formatter/slack_att.js b/src/formatter/slack_att.js index b143b704..c66d6816 100644 --- a/src/formatter/slack_att.js +++ b/src/formatter/slack_att.js @@ -37,7 +37,7 @@ const sampleAtt = { pretext: 'This is a pretext', title: 'This is a title', title_link: 'https://api.slack.com/docs/attachments', - text: "This is the main text in a message attachment, and can contain standard message markup (see details below). The content will automatically collapse if it contains 700+ characters or 5+ linebreaks, and will display a 'Show more...' link to expand the content.", + text: 'This is the main text in a message attachment', fieldMat: [ // the "short" key defaults to true ['Priority', 'high'], diff --git a/src/log.js b/src/log.js index a96bcf36..a16f8a71 100644 --- a/src/log.js +++ b/src/log.js @@ -7,7 +7,7 @@ const log = global.log || new (winston.Logger)({ transports: [new (winston.transports.Console)({ formatter: options => /* istanbul ignore next */ - `[${new Date()}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}`, + `[${new Date()}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}`, })], }) global.log = log From 8e29106a9da4ed59dbe475b5f7a86b8a86f4aa6a Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:25:04 -0500 Subject: [PATCH 25/33] fix winston format str len --- src/log.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/log.js b/src/log.js index a16f8a71..c93e4ba6 100644 --- a/src/log.js +++ b/src/log.js @@ -5,9 +5,11 @@ const logLevel = process.env.npm_config_debug ? 'debug' : 'info' const log = global.log || new (winston.Logger)({ level: logLevel, transports: [new (winston.transports.Console)({ - formatter: options => - /* istanbul ignore next */ - `[${new Date()}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}`, + /* istanbul ignore next */ + formatter: (options) => { + const formatStr = `[${new Date()}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}` + return formatStr + }, })], }) global.log = log From a0282a65a8c4758d2cbdd14e308c776962ade580 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:29:52 -0500 Subject: [PATCH 26/33] break up log str to shorter chunks --- src/log.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/log.js b/src/log.js index c93e4ba6..c127967f 100644 --- a/src/log.js +++ b/src/log.js @@ -7,7 +7,9 @@ const log = global.log || new (winston.Logger)({ transports: [new (winston.transports.Console)({ /* istanbul ignore next */ formatter: (options) => { - const formatStr = `[${new Date()}] ${winston.config.colorize(options.level, options.level.toUpperCase())} ${options.message || ''}` + const levelStr = winston.config.colorize(options.level, options.level.toUpperCase()) + const msgStr = options.message || '' + const formatStr = `[${new Date()}] ${levelStr} ${msgStr}` return formatStr }, })], From eeec0bf4781f1e979102ab3600a95133fa63fdb8 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:31:19 -0500 Subject: [PATCH 27/33] fix db str --- src/db.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/db.js b/src/db.js index 243a4a80..ead83515 100644 --- a/src/db.js +++ b/src/db.js @@ -27,8 +27,7 @@ function createDb() { const nodeEnvs = ['test', 'development', 'production'] const createDbQueries = _.map( nodeEnvs, - nodeEnv => `CREATE DATABASE ${_.get(dbEnvConfig, `${nodeEnv}.database`)};`, - ) + nodeEnv => `CREATE DATABASE ${_.get(dbEnvConfig, `${nodeEnv}.database`)};`) return Promise.any( _.map(createDbQueries, createDbQuery => sysSeq.query(createDbQuery))).then(() => { From 133a51d3347726dea46fea237063e530092bd285 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:32:33 -0500 Subject: [PATCH 28/33] fix syntax err in aiva.js --- src/aiva.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/aiva.js b/src/aiva.js index de1fa969..5cda91a3 100644 --- a/src/aiva.js +++ b/src/aiva.js @@ -15,8 +15,7 @@ function spawnProcess(env) { const hb = spawn( './bin/hubot', ['-a', _.toLower(env.ADAPTER), '--name', env.BOTNAME], - { stdio: 'inherit', env }, - ) + { stdio: 'inherit', env }) children.push(hb) log.info(`Deploying bot ${env.BOTNAME} with adapter ${env.ADAPTER}`) return env From 65d4ef4502c3e1ae22ab0927549c77b09ab3b808 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:32:52 -0500 Subject: [PATCH 29/33] switch cc to codacy --- circle.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 32cc33db..1ca795e2 100644 --- a/circle.yml +++ b/circle.yml @@ -27,7 +27,7 @@ test: override: - npm test post: - - cat ./coverage/lcov.info | ./node_modules/codeclimate-test-reporter/bin/codeclimate.js + - cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage general: branches: diff --git a/package.json b/package.json index 31f6395f..1fb59432 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "devDependencies": { "chai": "^3.5.0", "chai-as-promised": "^6.0.0", - "codeclimate-test-reporter": "^0.4.0", + "codacy-coverage": "^2.0.0", "coffee-script": "^1.10.0", "eslint": "^3.12.2", "eslint-config-airbnb": "^13.0.0", From f2631af738f2dc3dd6967b621e1889941166b2bf Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:37:24 -0500 Subject: [PATCH 30/33] remove useless cc repo token for circle yml --- circle.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/circle.yml b/circle.yml index 1ca795e2..a3423c96 100644 --- a/circle.yml +++ b/circle.yml @@ -3,8 +3,6 @@ machine: version: 3.5.1 node: version: 6 - environment: - CODECLIMATE_REPO_TOKEN: df0a1e703d4e417fb88724c9e1f7c4b49f53c9c17494d59cd182aa6cc2daccf8 services: - mysql - neo4j From 8cdaa614693a9b83601946fd7f45b271abe73a35 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 14:42:41 -0500 Subject: [PATCH 31/33] add codacy badges, bump version to v4.2.0 --- README.md | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe00b4b0..35786390 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# AIVA [![GitHub version](https://badge.fury.io/gh/kengz%2Faiva.svg)](http://badge.fury.io/gh/kengz%2Faiva) [![CircleCI](https://circleci.com/gh/kengz/poly-socketio.svg?style=shield)](https://circleci.com/gh/kengz/poly-socketio) [![Code Climate](https://codeclimate.com/github/kengz/aiva/badges/gpa.svg)](https://codeclimate.com/github/kengz/aiva) [![Test Coverage](https://codeclimate.com/github/kengz/aiva/badges/coverage.svg)](https://codeclimate.com/github/kengz/aiva/coverage) [![Dependency Status](https://gemnasium.com/kengz/aiva.svg)](https://gemnasium.com/kengz/aiva) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/hyperium/hyper/master/LICENSE) [![GitHub forks](https://img.shields.io/github/forks/kengz/aiva.svg?style=social&label=Fork)](https://github.com/kengz/aiva) [![GitHub stars](https://img.shields.io/github/stars/kengz/aiva.svg?style=social&label=Star)](https://github.com/kengz/aiva) +# AIVA [![GitHub version](https://badge.fury.io/gh/kengz%2Faiva.svg)](http://badge.fury.io/gh/kengz%2Faiva) [![CircleCI](https://circleci.com/gh/kengz/poly-socketio.svg?style=shield)](https://circleci.com/gh/kengz/poly-socketio) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/53459c1d07154b5e8d95d9f9922e5e7a)](https://www.codacy.com/app/kengzwl/aiva?utm_source=github.com&utm_medium=referral&utm_content=kengz/aiva&utm_campaign=Badge_Grade) [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/53459c1d07154b5e8d95d9f9922e5e7a)](https://www.codacy.com/app/kengzwl/aiva?utm_source=github.com&utm_medium=referral&utm_content=kengz/aiva&utm_campaign=Badge_Coverage) [![Dependency Status](https://gemnasium.com/kengz/aiva.svg)](https://gemnasium.com/kengz/aiva) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/hyperium/hyper/master/LICENSE) [![GitHub forks](https://img.shields.io/github/forks/kengz/aiva.svg?style=social&label=Fork)](https://github.com/kengz/aiva) [![GitHub stars](https://img.shields.io/github/stars/kengz/aiva.svg?style=social&label=Star)](https://github.com/kengz/aiva) **AIVA** (A.I. Virtual Assistant): General-purpose virtual assistant for developers. [http://kengz.me/aiva/](http://kengz.me/aiva/) diff --git a/package.json b/package.json index 1fb59432..0cb0e169 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aiva", - "version": "4.1.2", + "version": "4.2.0", "description": "General-purpose virtual assistant for developers.", "private": true, "main": "index.js", @@ -57,7 +57,7 @@ "mysql": "^2.12.0", "mysql2": "^1.1.2", "ngrok": "^2.2.3", - "poly-socketio": "^1.1.1", + "poly-socketio": "^1.1.4", "portscanner": "^2.1.1", "randombytes": "^2.0.3", "require-dir": "^0.3.0", From e1f76568ddf43dcf9f8bf372a677e3a40156f090 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 15:02:10 -0500 Subject: [PATCH 32/33] restore cgkb --- src/start-io.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/start-io.js b/src/start-io.js index 9ceb4192..a8d52052 100644 --- a/src/start-io.js +++ b/src/start-io.js @@ -1,5 +1,5 @@ // The socket.io server and polyglot clients. Called by scripts/_init.js -// const { nlpServer } = require('cgkb') +const { nlpServer } = require('cgkb') const { spawn } = require('child_process') const _ = require('lomath') const path = require('path') @@ -8,7 +8,7 @@ const { setEnv, activeAdapters } = require('./env') const log = require('./log') const jsIOClient = require('../lib/client') -const nlpServerCount = 0 +const nlpServerCount = nlpServer ? 1 : 0 const LIBPATH = path.join(__dirname, '..', 'lib') /* istanbul ignore next */ @@ -59,7 +59,7 @@ function ioClient() { // import js locally jsIOClient.join() - // nlpServer({ port: process.env.IOPORT }) // start nlp server + nlpServer({ port: process.env.IOPORT }) // start nlp server _.each(ioClientCmds, (cmds, lang) => { // spawn ioclients for other lang From 7e9a1e4e3a1001ca3d0d21162a899021e47bbac7 Mon Sep 17 00:00:00 2001 From: kengz Date: Sat, 24 Dec 2016 15:04:03 -0500 Subject: [PATCH 33/33] remove codeclimate.yml --- .codeclimate.yml | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 .codeclimate.yml diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index e21023c5..00000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,35 +0,0 @@ -engines: - duplication: - enabled: true - config: - languages: - - javascript - - python - - ruby - fixme: - enabled: true - eslint: - enabled: true - checks: - no-process-exit: - enabled: false - csslint: - enabled: true - radon: - enabled: true - config: - threshold: "C" - pep8: - enabled: true - rubocop: - enabled: true - -ratings: - paths: - - "**.js" - - "**.jsx" - - "**.py" - - "**.rb" - -exclude_paths: -- test/ \ No newline at end of file