Skip to content

Instantly share code, notes, and snippets.

@briandonahue
Created November 9, 2015 14:33
Show Gist options
  • Save briandonahue/b6c6e4af84ffb8426274 to your computer and use it in GitHub Desktop.
Save briandonahue/b6c6e4af84ffb8426274 to your computer and use it in GitHub Desktop.
var async = require('async');
var AWS = require('aws-sdk');
var gm = require('gm');
var request = require('superagent');
var dateFormat = require('dateformat');
var sdbDomain = 'timesync';
console.log("Function loaded...");
exports.handler = function(event, context){
console.log("Function begun...");
var s3 = new AWS.S3();
var simpleDB = new AWS.SimpleDB();
var fileKey = "data.json";
var data = {};
async.waterfall([
function createDomain(next){
simpleDB.createDomain({ DomainName: sdbDomain }, next);
},
function callApi(data, next){
console.log ("Call API");
request
.get("https://domain.teamwork.com/time_entries.json?fromdate=20151101")
.set("Content-Type", "application/json")
.set("Accept", "application/json")
.set("Authorization", "Basic BASE64ENCODED=")
.end(function (err, res){ next(err, res, data); });
},
function apiResponse(res, data, next){
console.log ("Handle API Response");
if (res.ok) {
var entries = res.body["time-entries"];
async.each(entries, function(item, callback){processTeamworkItem(item, simpleDB, callback);}, next);
}
else{
context.fail();
}
}
],
function (err){
console.log ("Final function");
if (err && err.errorResult !== "NoSuchKey") {
context.fail(JSON.stringify(err));
}
context.succeed();
}
);
};
function processTeamworkItem(twTime, simpleDB, callback){
console.log("entered sync");
var date = new Date(twTime.date);
var notes = twTime['project-name'] + ' - ' + twTime['todo-item-name'] + ' - ' + twTime.description;
async.waterfall([
function parseTimeEntry(next){
console.log("entered parseTimeEntry");
var timeData = {
teamworkId: twTime.id,
notes: notes,
hours: parseInt(twTime.hours) + (twTime.minutes/60),
project_id: 654321, // TODO: map to real project
task_id: 123456, // same task all the time is probably fine
spent_at: dateFormat(date, "ddd, d mmm yyyy"), // formatted for Harvest API
updatedDate: new Date(twTime['updated-date']),
itemName: 'entry_' + twTime.id,
};
next(null, timeData);
},
function fetchFromDb(timeData, next){
console.log("entered fetchFromDb");
simpleDB.getAttributes({DomainName: sdbDomain, ItemName: timeData.itemName }, function(err, res){ next(err, res, timeData); });
},
function parseDbResult(result, timeData, next){
console.log("entered parseDbResult");
var data = {};
if(result.Attributes){
result.Attributes.forEach(function (item) {
var val;
if(item.Name === 'updatedDate') {
val = new Date(item.Value);
if(val < timeData.updatedDate){
timeData.update = true;
}
}
else {
timeData[item.Name] = parseInt(item.Value);
}
});
if(timeData.update){
timeData.harvestPath = "/daily/update/" + timeData.harvestId;
}
else{
console.log("No need to update:\n" + JSON.stringify(timeData));
return next({ errorResult: "NoUpdateNeeded"});
}
}
else {
timeData.harvestPath = "/daily/add";
}
console.log("Sending to update");
return next(null, timeData);
},
function updateHarvest (timeData, next){
console.log("Sending to " + timeData.harvestPath + ":\n" + JSON.stringify(timeData));
request
.post("https://domain.harvestapp.com" + timeData.harvestPath)
.send({
notes: timeData.notes,
hours: timeData.hours,
spent_at: timeData.spent_at,
project_id: timeData.project_id,
task_id: timeData.task_id
})
.set("Content-Type", "application/json")
.set("Accept", "application/json")
.set("Authorization", "Basic BASE64ENCODED=")
.end(function (err, res){ next(err, res, timeData); });
},
function harvestResponse(res, timeData, next){
console.log("HARVEST RESPONDED");
var returned = JSON.parse(res.text);
console.log("harvest response:" + JSON.stringify(returned));
timeData.harvestId = returned.id;
simpleDB.putAttributes({
Attributes: [
{
Name: 'teamworkId',
Value: timeData.teamworkId.toString(),
Replace: true
},
{
Name: 'harvestId',
Value: timeData.harvestId.toString(),
Replace: true
},
{
Name: 'updatedDate',
Value: timeData.updatedDate.toString(),
Replace: true
}
],
DomainName: sdbDomain,
ItemName: timeData.itemName
}, function(err, data){next(err, data);});
},
function logResponse(data, next){
console.log('simpledb: ' + JSON.stringify(data));
next(null);
}
],
function(err){
if (!err || err.errorResult === "NoUpdateNeeded") {
return callback();
}
else{
console.log('EXIT ERROR: ' + JSON.stringify(err));
return callback(err);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment