Skip to content

Utilizing Autobot for plank time recording #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8a8476f
Initial setup for google api
alan-andrade Aug 17, 2016
8dafaa9
set up basic writing to sheet columns
abMatGit Aug 28, 2016
bc4076f
add credentials for google auth and our sheets
abMatGit Oct 16, 2016
ccd3aa1
update packages for libraries we're trying out (async!)
abMatGit Oct 16, 2016
3f5f9c0
add google spreadsheet resource
abMatGit Oct 16, 2016
62cc205
utilize google spreadsheet resource in autobot
abMatGit Oct 16, 2016
aa7d748
remove the quickstart.js tutorial
abMatGit Oct 16, 2016
0cf8983
patch up code logic to handle dynamic core types (this will fix tests)
abMatGit Oct 16, 2016
afdd038
replace token store to dynamo DB!
abMatGit Oct 24, 2016
8fa4927
mbp air changes
abMatGit Oct 24, 2016
dc44819
use all of slacks parameters instead of just using user text
abMatGit Oct 24, 2016
ced762f
include greeting logic and refactor parser into object
abMatGit Oct 24, 2016
c8d90f0
fix up test to use slacks input hash
abMatGit Oct 24, 2016
eb0f275
default to lowercase on all usernames
abMatGit Oct 24, 2016
a15389f
getting some chart stuff out there
abMatGit Nov 9, 2016
236b3e6
some small clean up
abMatGit Nov 23, 2016
58a06bd
formal cleanup of plankbot chart methods
abMatGit Nov 23, 2016
500a36d
add url shortening to chart method
abMatGit Nov 23, 2016
4229482
add documentation and reorganize methods
abMatGit Nov 23, 2016
4855394
add interpolating to plankbot !
abMatGit Dec 4, 2016
0c3ab09
restructure google resource to have its own chart and parser for data
abMatGit Dec 4, 2016
eba61af
clean up logic for parsing all users
abMatGit Dec 4, 2016
f51c339
add jira credentials to pre-setup script for tests
abMatGit Dec 4, 2016
cc62248
finishing touches
abMatGit Dec 4, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Credentials
*/*_credentials.js
configs/*.js
configs/*.json

# Logs
logs
Expand Down
Empty file modified circle.yml
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions configs/google_credentials.js.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports.spreadsheetId = 'you will never know';
Empty file modified configs/jira_credentials.js.example
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion configs/slack_token.js.example
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports.slackToken = 'blah';
module.exports.slackTokens = ['blah', 'blah2'];
15 changes: 15 additions & 0 deletions configs/user_mappings.js.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports.nameIndexMapper = {
mang: 1,
idiota: 2,
pendejo: 3,
womang: 4,
chola: 5
}

module.exports.nameLetterMapper = {
mang: "A",
idiota: "B",
pendejo: "C",
womang: "D",
chola: "E"
}
Empty file modified event.json
100644 → 100755
Empty file.
15 changes: 9 additions & 6 deletions handler.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use strict';

var qs = require('querystring');
var slackToken = require('./configs/slack_token').slackToken;
var slackTokens = require('./configs/slack_token').slackTokens;
var Autobot = require('./main/autobot');
var _= require('underscore');

module.exports.slack = function(event, context, callback) {
module.exports.slack = function(event, context, callback) {};

module.exports.updateSheet = function(event, context, callback) {

var statusCode, text;
var body = event.body;
Expand All @@ -23,12 +26,12 @@ module.exports.slack = function(event, context, callback) {
context.fail(err);
};

if (requestToken !== slackToken) {
if (_.contains(slackTokens, requestToken)) {
var autobot = new Autobot('slack', 'google');
autobot.receive(params).then(success, failure);
} else {
console.error("Request token (%s) does not match exptected", requestToken);
context.fail("Invalid request token");
callback("Invalid request token");
} else {
var autobot = new Autobot('slack');
autobot.receive(params.text).then(success, failure);
}
};
7 changes: 5 additions & 2 deletions main/autobot.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
var Handler = require('./autobot/handler');
var access = require('./lib/resource_accessor').access;
var Adapters = require('./autobot/adapters');
var googleCore = require('./autobot/core/core').google;
var defaultCore = require('./autobot/core/core').default;

class Autobot {
constructor(adapter) {
constructor(adapter, coreType) {
var adapterClass = access(Adapters, adapter);
this.adapter = new adapterClass();
if(coreType == 'google') { this.adapter = new adapterClass(googleCore); }
else { this.adapter = new adapterClass(defaultCore); }
}

receive(input) {
Expand Down
Empty file modified main/autobot/adapters.js
100644 → 100755
Empty file.
Empty file modified main/autobot/adapters/adapter.js
100644 → 100755
Empty file.
77 changes: 74 additions & 3 deletions main/autobot/adapters/cli.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,78 @@

var Adapter = require('../adapters/adapter');

class Parser {
constructor(input) {
this.input = input;
this.commandIndex = 0;
this.argsIndex = 1;
}

parse() {
if(this.input) {
var command = this.fetchCommand();

switch(command) {
case 'update':
return this.parseUpdate();
case 'chart':
return this.parseChart();
case 'interpolate':
return this.parseInterpolate();
default:
return this.parseDefault();
}
}
else {
return { command: '', args: {} }
}
}

fetchCommand() {
return this.input.trim().split(' ')[this.commandIndex];
}

parseUpdate() {
var regexUsers = /(@?)([a-zA-Z]*)(:?)(\ )*(\d+)/gi
var regexUser = /(@?)([a-zA-Z]*)(:?)(\ )*(\d+)/i

var matchedUsers = this.input.match(regexUsers);
var usernameGroup = 2;
var timeGroup = 5;
var parsedArgs = {};

for(var i = 0; i < matchedUsers.length; i++) {
var matchedUser = matchedUsers[i].match(regexUser);
var username = matchedUser[usernameGroup];
var plankTime = matchedUser[timeGroup];

parsedArgs[username] = plankTime;
};

return { command: 'update', args: parsedArgs };
}

parseChart() {
var regexUsers = /[a-zA-z]+/gi
var matchedUsers = this.input.match(regexUsers);

return { command: 'chart', args: matchedUsers };
}

parseInterpolate() {
var regexUsers = /([a-zA-z]+)/gi
var matchedUsers = this.input.match(regexUsers).slice(this.argsIndex);

return { command: 'interpolate', args: matchedUsers };
}

parseDefault() {
var command = this.fetchCommand();
var args = this.input.split(' ').slice(this.argsIndex);
return { command: command, args: args }
}
}

class Cli extends Adapter {

/* Right now this parsing is very dumb.
Expand All @@ -10,11 +82,10 @@ class Cli extends Adapter {
for more intelligent mapping.
*/
parse(input) {
var tokens = input.trim().split(' ');
return { command: tokens[0], args: tokens.slice(1) }
var parser = new Parser(input)
return parser.parse();
}


/*
TODO: Have an object whose responsibility it is to render
this data depending on what kind of data it is?
Expand Down
104 changes: 101 additions & 3 deletions main/autobot/adapters/slack.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,113 @@
'use strict';

var Adapter = require('../adapters/adapter');
class Parser {
constructor(input) {
if(input.text) {
this.input = input.text;
this.username = input.user_name;
} else {
this.input = input;
}
this.commandIndex = 1;
this.argsIndex = 2;
}

parse() {
if(this.fetchGreeting() != null) {
return this.fetchGreeting();
} else if(this.input) {
var command = this.fetchCommand();

switch(command) {
case 'update':
return this.parseUpdate();
case 'chart':
return this.parseChart();
case 'interpolate':
return this.parseInterpolate();
default:
return this.parseDefault();
}
} else {
return { command: '', args: {} }
}
}

fetchGreeting() {
var firstWord = this.input.trim().split(' ')[0];
var greetingsRegex = /^(greetings|hello|hi|hey|sup)/g

if(firstWord.match(greetingsRegex) != null) {
return { command: 'greetings', username: this.username, args: {} }
}

return null;
}

fetchCommand() {
return this.input.trim().split(' ')[this.commandIndex];
}

parseUpdate() {
var regexUsers = /(@?)([a-zA-Z]*)(:?)(\ )*(\d+)/gi
var regexUser = /(@?)([a-zA-Z]*)(:?)(\ )*(\d+)/i

var matchedUsers = this.input.match(regexUsers);
var usernameGroup = 2;
var timeGroup = 5;
var parsedArgs = {};

for(var i = 0; i < matchedUsers.length; i++) {
var matchedUser = matchedUsers[i].match(regexUser);
var username = matchedUser[usernameGroup];
var plankTime = matchedUser[timeGroup];

parsedArgs[username] = plankTime;
};

return { command: 'update', args: parsedArgs };
}

parseChart() {
var regexUsers = /[a-zA-z]+/gi
var matchedUsers = this.input.match(regexUsers).slice(this.argsIndex);

return { command: 'chart', args: matchedUsers };
}

parseInterpolate() {
var regexUsers = /([a-zA-z]+)/gi
var matchedUsers = this.input.match(regexUsers).slice(this.argsIndex);

return { command: 'interpolate', args: matchedUsers };
}

parseDefault() {
var command = this.fetchCommand();
var args = this.input.split(' ').slice(this.argsIndex);
return { command: command, args: args }
}
}

class Slack extends Adapter {
parse(input) {
var tokens = input.split(' ');
return { command: tokens[1], args: tokens.slice(2) }
var parser = new Parser(input);
return parser.parse();
}

render(data) {
return { text: JSON.stringify(data) };
//responseData = JSON.stringify(data);
//console.log(data);
if(data['totalUpdatedColumns']) {
if(data['totalUpdatedColumns'] == 2) {
return { text: 'Successfully updated 1 record!' }
} else {
return { text: 'Sucessfully updated ' + (data['totalUpdatedColumns'] - 1) + ' records!' };
}
} else {
return { text: data }
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion main/autobot/cli.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repl.start({
});

var Autobot = require('../autobot');
var dudeBot = new Autobot('slack');
var dudeBot = new Autobot('cli', 'google');

function evalAutobot(input, context, filename, callback) {
dudeBot.receive(input).then(callback);
Expand Down
73 changes: 69 additions & 4 deletions main/autobot/core/core.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
'use strict';

var jiraResource = require('../resources/jira');
var googleResource = require('../resources/google/google');
var access = require('../../lib/resource_accessor').access;

var doNothing = new Promise(function(resolve, reject) { resolve(); });

class Core {
constructor(commands, resource) {
this.resource = resource;
Expand All @@ -26,13 +29,32 @@ class Core {
var commandToken = inputTokens['command'];
var args = inputTokens['args'];

var cmd = access(this.commands, commandToken).bind(this);
if(commandToken == '') { return doNothing; }
else if(commandToken == 'greetings') {
var username = inputTokens['username'];
var cmd = access(this.commands, commandToken).bind(this);
return cmd(username);
} else {
var cmd = access(this.commands, commandToken).bind(this);
return cmd(args);
}
}

return cmd(args);
type() {
return access(this.commands, 'type').bind(this).call();
}
}

var commands = {
// Returns a random integer between min (included) and max (excluded)
// Using Math.round() will give you a non-uniform distribution!
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}

var defaultCommands = {
type: function() { return 'default'; },
/*
A simple echo call.

Expand Down Expand Up @@ -64,5 +86,48 @@ var commands = {
}
}

var googleCommands = {
type: function() { return 'google';},

greetings: function(username) {
var motivations = [
" Ready to give a good plank today?",
" Good stuff today! Let's keep it going!",
" You're pretty cool, but can you plank?",
" Let's see what you can do today!"
];
var emojis = [
" :sweat_drops:",
" :fuck_yes:",
" :punch:",
" :yoga:"
];

var motivationIndex = getRandomInt(0,4);
var emojiIndex = getRandomInt(0,4);
return new Promise(function(resolve, reject) {
var returnString = "Hey @" + username + "!" + motivations[motivationIndex] + emojis[emojiIndex];
resolve(returnString);
});
},

get: function(args) {
return this.resource.get(args);
},

chart: function(args) {
return this.resource.chart(args);
},

interpolate: function(args) {
return this.resource.interpolate(args);
},

update: function(args) {
return this.resource.update(args);
}
}

module.exports.Core = Core;
module.exports.default = new Core(commands, jiraResource);
module.exports.default = new Core(defaultCommands, jiraResource);
module.exports.google = new Core(googleCommands, googleResource);
Empty file modified main/autobot/handler.js
100644 → 100755
Empty file.
Loading