Skip to content

Commit

Permalink
Merge pull request #50 Version 1.1.0
Browse files Browse the repository at this point in the history
Version 1.1.0
  • Loading branch information
robsonbittencourt authored May 27, 2017
2 parents 6686674 + f7bee02 commit b506bc4
Show file tree
Hide file tree
Showing 35 changed files with 607 additions and 205 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sudo: required
language: node_js

node_js:
- 7.1.0
- 7.7.2

services:
- docker
Expand All @@ -25,7 +25,7 @@ deploy:

after_deploy:
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then
docker login -e="$DOCKER_EMAIL" -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" ;
docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" ;

export VERSION=$(node -p -e "JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version")

Expand Down
29 changes: 29 additions & 0 deletions locales/en-US/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"hello": "Hello,",
"thanks": "Thanks,",
"ops": "Ops! ",
"didNotUnderstand": "Sorry, I didn't understand. (Expected responses: ",

"firstUse": {
"message1": "My name is {{botName}} and from now on I will help you with some tasks using the Slack.",
"message2": "Before I need you to do some settings. How was you who started me I will define you as my system administrator. So you can access the settings in the future.",
"message3": "Initially I do not know perform tasks. But there are gears that when coupled to me add me skills.",
"message4": "At this time all the gears are active. You can deactivate them using the command ",
"message5": "Some gears have settings. To let them use the command ",
"message6": "Below is a list of gears available:"
},

"gears": {
"description": "gear {{gearDescription}}",
"deactivate": "deactivate gear-name",
"configure": "configure gear-name"
},

"feature": {
"disabled": "Sorry, this feature is disabled.",
"onlyChannel": "Sorry, this feature can only be performed on a channel.",
"onlyPrivate": "Sorry, this feature can only be performed directly with me in private."
}
}


27 changes: 27 additions & 0 deletions locales/pt-BR/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"hello": "Olá,",
"thanks": "Obrigado,",
"ops": "Ops! ",
"didNotUnderstand": "Desculpe, eu não entendi. (Respostas esperadas: ",

"firstUse": {
"message1": "Meu nome é {{botName}} e a partir de agora eu vou lhe ajudar com algumas tarefas utilizando o Slack.",
"message2": "Antes eu preciso que você faça algumas configurações. Como foi você que me iniciou vou defini-lo como meu administrador. Então você pode acessar as configurações no futuro.",
"message3": "Inicialmente eu não sei fazer muitas coisas. Mas existem engrenagens que quando acopladas à mim me adicionam habilidades.",
"message4": "Neste momento todas as engrenagens estão ativas. Você pode desativá-las utilizando o comando ",
"message5": "Algumas engrenagens possuem configurações. Para fazê-las use o comando ",
"message6": "Abaixo segue uma lista com as engrenagens disponíveis:"
},

"gears": {
"description": "gear {{gearDescription}}",
"deactivate": "desativar nome-da-engrenagem",
"configure": "configurar nome-da-engrenagem"
},

"feature": {
"disabled": "Desculpe, essa funcionalidade está desabilitada.",
"onlyChannel": "Desculpe, esta funcionalidade só pode ser utilizada em um canal.",
"onlyPrivate": "Desculpe. esta funcionalidade só pode ser utilizada diretamente comigo no privado."
}
}
6 changes: 6 additions & 0 deletions migrations/002-language.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Up
ALTER TABLE config ADD language TEXT;
UPDATE config SET language = 'en-US';

-- Down
ALTER TABLE config DROP language TEXT;
24 changes: 13 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hubot.js",
"version": "1.0.0",
"version": "1.1.0",
"description": "A small robot written in Javascript (He does not like coffeescript)",
"main": "index.js",
"bin": {
Expand Down Expand Up @@ -30,21 +30,23 @@
"dependencies": {
"slackbots": "^0.5.3",
"string": "^3.3.3",
"winston": "^2.3.0",
"q": "^1.4.1",
"sqlite": "^2.2.3",
"pm2": "^2.1.6",
"winston": "^2.3.1",
"q": "^2.0.3",
"sqlite": "^2.8.0",
"pm2": "^2.4.6",
"dialog": "^0.2.0",
"yargs": "^6.4.0",
"gear-help": "^2.0.0",
"gear-jenkins": "^2.0.0"
"yargs": "^8.0.1",
"i18next": "^7.1.0",
"i18next-sync-fs-backend": "^0.1.0",
"gear-help": "^2.1.0",
"gear-jenkins": "^2.1.0"
},
"devDependencies": {
"chai": "^3.5.0",
"coveralls": "^2.11.15",
"eslint": "^3.11.1",
"coveralls": "^2.13.1",
"eslint": "^3.19.0",
"eslint-config-hubot-js": "^1.0.4",
"istanbul": "^0.4.5",
"mocha": "^3.2.0"
"mocha": "^3.4.1"
}
}
53 changes: 40 additions & 13 deletions src/assembler.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
'use strict';

const fs = require('fs');
const path = require('path');

const db = require('./lib/db');
const log = require('./lib/log');
const speech = require('./speech');
const i18n = require('./lib/i18n');

const gearNamePrefix = 'gear-';

module.exports = class Assembler {

constructor() {
constructor(gearsPath, isInternal) {
this.gears = [];
this.gearsPath = gearsPath;
this.isInternal = isInternal;
}

build() {
Expand All @@ -20,20 +24,24 @@ module.exports = class Assembler {
}

loadGears(self) {
fs.readdir(global.__nodeModules, (error, list) => {
const gearsNames = list.filter(e => e.startsWith(gearNamePrefix));
const list = fs.readdirSync(this.gearsPath);

gearsNames.forEach((gearName) => {
const gearDescription = gearName.replace('gear-', '');
const gearsNames = list.filter(e => e.startsWith(gearNamePrefix));

self.gears.push({ name: gearName, description: gearDescription });
});
gearsNames.forEach((gearName) => {
const gearDescription = gearName.replace('gear-', '');

self.gears.forEach((gear, index) => self.loadGear(self.gears, gear, index));
self.gears.push({ name: gearName, description: gearDescription });
});

self.gears.forEach((gear, index) => self.loadGear(self.gears, gear, index));
}

loadGear(gears, gear, index) {
if (gear) {
gear.isInternal = this.isInternal;
}

logStartAssembling();
logAddingGear(gears, gear, index);
this.tryToLoad('gearStatus', gear, this.loadGearStatus);
Expand All @@ -42,6 +50,7 @@ module.exports = class Assembler {
this.tryToLoad('categories', gear, this.loadCategories);
this.tryToLoad('handlers', gear, this.loadHandlers);
this.tryToLoad('configHandler', gear, this.loadConfigHandler);
this.tryToLoad('locales', gear, this.loadLocales);
}

tryToLoad(type, gear, assemble) {
Expand Down Expand Up @@ -94,26 +103,44 @@ module.exports = class Assembler {
gear.configHandler = require(self.configsHandlersPath(gear));
}

loadLocales(gear, self) {
fs.readdir(self.localesPath(gear), (error, list) => {
if (error) return;

gear.locales = [];

list.forEach((dir) => {
const localeFile = require(path.join(self.localesPath(gear), dir, 'translation.json'));
i18n.addResourceBundle(dir, gear.description, localeFile);

gear.locales.push(dir.toLowerCase());
});
});
}

configsPath(gear) {
return `${global.__nodeModules}${gear.name}/config/config.json`;
return `${this.gearsPath}${gear.name}/config/config.json`;
}

tasksPath(gear) {
return `${global.__nodeModules}${gear.name}/config/tasks.json`;
return `${this.gearsPath}${gear.name}/config/tasks.json`;
}

categoriesPath(gear) {
return `${global.__nodeModules}${gear.name}/config/categories.json`;
return `${this.gearsPath}${gear.name}/config/categories.json`;
}

handlersPath(gear, handler) {
return `${global.__nodeModules}${gear.name}/src/handlers/${handler}`;
return `${this.gearsPath}${gear.name}/src/handlers/${handler}`;
}

configsHandlersPath(gear) {
return `${global.__nodeModules}${gear.name}/src/configHandler/configHandler`;
return `${this.gearsPath}${gear.name}/src/configHandler/configHandler`;
}

localesPath(gear) {
return `${this.gearsPath}${gear.name}/locales`;
}
};

function logStartAssembling() {
Expand Down
20 changes: 19 additions & 1 deletion src/core.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
'use strict';

const util = require('util');
const path = require('path');

const Bot = require('slackbots');

const db = require('./lib/db');
const Hubot = require('./hubot');
const log = require('./lib/log');
const i18n = require('./lib/i18n');
const firstRun = require('./first-run');
const Assembler = require('./assembler');
const normalizer = require('./lib/normalizer');
const messageHandler = require('./message-handler/message-handler');

let botName;
Expand Down Expand Up @@ -37,13 +40,23 @@ Core.prototype.run = function run() {

Core.prototype.onStart = function onStart() {
botUser = this.getUserByName(botName);

this.hubot = new Hubot(this);
this.hubot.gears = new Assembler().build();

const internalGearPath = path.join(__dirname, 'internal-gears/');
this.hubot.gears = new Assembler(internalGearPath, true).build();

const gears = new Assembler(global.__nodeModules, false).build();
this.hubot.gears = this.hubot.gears.concat(gears);

this.firstRunChecker();
this.setLanguage();
};

Core.prototype.onMessage = function onMessage(message) {
if (isChatMessage(message) && !isFromHubot(message)) {
message.text = normalizer.normalize(message.text);

if (isFirstInteraction(this, message)) {
isFirstRun = false;
firstRun.firstRun(this, message);
Expand All @@ -61,6 +74,11 @@ Core.prototype.firstRunChecker = function firstRunChecker() {
});
};

Core.prototype.setLanguage = function setLanguage() {
db.getDb().get('SELECT * FROM config')
.then(config => i18n.changeLanguage(config.language));
};

Core.prototype.getUserByName = function getUserByName(name) {
return this.users.find(user => user.name === name);
};
Expand Down
42 changes: 13 additions & 29 deletions src/first-run.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,33 @@ function firstRun(core, message) {
const hubot = core.hubot;
const messageDelay = 3000;

hubot.speak(message, message1(hubot, core, message), messageDelay)
.then(() => hubot.speak(message, message2(hubot), messageDelay))
.then(() => hubot.speak(message, message3(hubot), messageDelay))
.then(() => hubot.speak(message, message4(hubot), messageDelay))
.then(() => hubot.speak(message, message5(hubot), messageDelay))
.then(() => hubot.speak(message, message6(hubot), messageDelay))
.then(() => hubot.speak(message, postGearsNames(hubot), messageDelay));
hubot.speak(message, message1(hubot, core, message), null, messageDelay)
.then(() => hubot.speak(message, 'firstUse.message2', null, messageDelay))
.then(() => hubot.speak(message, 'firstUse.message3', null, messageDelay))
.then(() => hubot.speak(message, message4(hubot), null, messageDelay))
.then(() => hubot.speak(message, message5(hubot), null, messageDelay))
.then(() => hubot.speak(message, 'firstUse.message6', null, messageDelay))
.then(() => hubot.speak(message, postGearsNames(hubot), null, messageDelay));
}

function message1(hubot, core, message) {
return hubot.speech().hello(core.getUserById(message.user)).append('My name is ').append(core.name)
.append(' and from now on I will help you with some tasks using the Slack.').end();
}

function message2(hubot) {
return hubot.speech().append('Before I need you to do some settings.')
.append(' How was you who started me I will define you as my system administrator.')
.append(' So you can access the settings in the future.').end();
}

function message3(hubot) {
return hubot.speech().append('Initially I do not know perform tasks.')
.append(' But there are gears that when coupled to me add me skills.').end();
return hubot.speech().hello(core.getUserById(message.user)).append('firstUse.message1', { botName: 'hubot' }).end();
}

function message4(hubot) {
return hubot.speech().append('At this time all the gears are active. You can deactivate them using the command ')
.bold('deactivate gear-name').period().end();
return hubot.speech().append('firstUse.message4').bold('gears.deactivate').period().end();
}

function message5(hubot) {
return hubot.speech().append('Some gears have settings. To let them use the command ')
.bold('configure gear-name').period().end();
}

function message6(hubot) {
return hubot.speech().append('Below is a list of gears available:').end();
return hubot.speech().append('firstUse.message5').bold('gears.configure').period().end();
}

function postGearsNames(hubot) {
const speech = hubot.speech();

hubot.gears.forEach(g => speech.item(g.description).line());
const gears = hubot.gears.filter(g => !g.isInternal);

gears.forEach(g => speech.item(g.description).line());

return speech.end();
}
Loading

0 comments on commit b506bc4

Please sign in to comment.