UNPKG

jive-sdk

Version:

Node.js SDK for Jive Software to assist with the development of add-ons

351 lines (309 loc) 12.2 kB
var jive = require("jive-sdk"); var url = require('url'); var util = require('util'); var sampleOauth = require('./routes/oauth/sampleOauth'); var q = require('q'); var basecamp_Helpers = require( "./routes/oauth/basecamp_helpers"); var metadataCollection = "basecampActivityMetadata"; var metadataStore = jive.service.persistence(); exports.getLastTimePulled = getLastTimePulled; exports.getMetadataByInstance = getMetadataByInstance; exports.pullActivity = pullActivity; exports.pullComments = pullComments; exports.updateLastTimePulled = updateLastTimePulled; exports.recordSyncFromJive = recordSyncFromJive; function pullActivity(extstreamInstance) { return getLastTimePulled(extstreamInstance, 'activity').then(function (lastTimePulled) { var accountID = extstreamInstance.config.accountID; var projectID = extstreamInstance.config.id; var ticketID = extstreamInstance.config.ticketID; var date = new Date(lastTimePulled); var since = date.toISOString(); // returns Zulu time (UTC) var query = "/projects/" + projectID + "/events.json?since=" + since; return basecamp_Helpers.queryBasecampV1( accountID, ticketID, sampleOauth, query).then( function (response) { var entity = response['entity'] ; return convertToActivities(entity, lastTimePulled, extstreamInstance); /* // only return created things, not commented on or other ... var createdEvents = []; entity.forEach(function(record) { if (record.action != "commented on") createdEvents.push( record ); } ); return createdEvents; */ }) ; }).catch(function (err) { jive.logger.error('Error querying basecamp', err); }); }; function pullComments(extstreamInstance) { return getLastTimePulled(extstreamInstance, 'comment').then(function (lastTimePulled) { var accountID = extstreamInstance.config.accountID; var projectID = extstreamInstance.config.id; var ticketID = extstreamInstance.config.ticketID; var date = new Date(lastTimePulled); var since = date.toISOString(); // returns Zulu time (UTC) var query = "/projects/" + projectID + "/events.json?since=" + since; return basecamp_Helpers.queryBasecampV1( accountID, ticketID, sampleOauth, query).then( function (response) { var entity = response['entity'] ; return convertToComments(entity, lastTimePulled, extstreamInstance) ; /* // only return created things, not commented on or other ... var comments = []; entity.forEach(function(record) { if (record.action == "commented on") comments.push( record ); } ); return comments; */ }) ; }).catch(function (err) { jive.logger.error('Error querying basecamp', err); }); } function convertToActivities(entity, lastTimePulled, instance) { var records = entity; var tempActivities = records.map(function (record) { if (record.action != "commented on") { // need to pass the project name down ... // note that we should really be getting the most current project name from Basecamp, like the other tiles record['projectName'] = instance.config['project']; var json = getActivityJSON(record); if (!isNaN(json['bcCreatedDate'])) { lastTimePulled = Math.max(lastTimePulled, json['bcCreatedDate']); } return json; } else return null; }); // now get rid of NULL entries in the array (these will be the comments ...) var numActivities = tempActivities.length; var activities = []; var activityCounter=0; if (numActivities > 0) { for (var i=(numActivities-1); i >= 0; i--) if (tempActivities[i] != null) activities[activityCounter++] = tempActivities[i]; } return updateLastTimePulled(instance, lastTimePulled, 'activity').thenResolve(activities); } function convertToComments(entity, lastTimePulled, instance) { var records = entity; var comments = []; var promise = q.resolve(null); records.forEach(function (record) { if (record['action'] == "commented on") { var bcCommentID; var nIdx1 = record['html_url'].lastIndexOf("_"); if (nIdx1 > 0) { bcCommentID = record['html_url'].substring(nIdx1+1); // make sure we have a number and not a string to allow the sync compare to work ... bcCommentID = Number(bcCommentID) ; } // need to pass the project name down ... // note that we should really be getting the most current project name from Basecamp, like the other tiles record['projectName'] = instance.config['project']; promise = promise.thenResolve( wasSynced(instance, bcCommentID).then(function (wasItSynced) { if (wasItSynced) { return; } var json = getCommentJSON(record); if (!isNaN(json['bcCreatedDate'])) { lastTimePulled = Math.max(lastTimePulled, json['bcCreatedDate']); } comments.push(json); })); } }); return promise.then(function() { return updateLastTimePulled(instance, lastTimePulled, 'comment').thenResolve(comments); }); } function getActivityJSON(record) { var url = record['html_url']; url = url.replace("basecamp.com", "www.basecamp.com") ; var summary = record['summary']; summary = summary.replace("<span>", " "); summary = summary.replace("</span>", " "); // extract the actual Activity ID, not the event ID from the data ... var nIdx1 = record['html_url'].lastIndexOf("/"); var externalID = ""; if (nIdx1 > 0) { var nIdx2 = record['html_url'].indexOf("-", nIdx1) ; if (nIdx2 > 0) externalID = record['html_url'].substring(nIdx1+1, nIdx2); } var createdDate = new Date(record['created_at']).getTime(); return { "bcCreatedDate" : createdDate, "activity" : { "action":{ "name":"posted", "description": record['projectName'] + " Activity" }, "actor":{ "name":record['creator']['name'], "email":"" }, "object":{ "type":"website", "url": url, "image":"http://37signals.com/svn/images/basecamp-logo-for-fluid.png", "title": summary + " @ '" + record['projectName'] + "'", "description":record['excerpt'] }, "externalID": '' + externalID } } }; function getCommentJSON(record) { var url = record['html_url']; url = url.replace("basecamp.com", "www.basecamp.com") ; var summary = record['summary']; summary = summary.replace("<span>", " "); summary = summary.replace("</span>", " "); // extract the actual Activity ID, not the event ID from the data ... var nIdx1 = record['html_url'].lastIndexOf("_"); var externalID = ""; var externalActivityID = "" if (nIdx1 > 0) { externalID = record['html_url'].substring(nIdx1+1); } nIdx1 = record['html_url'].lastIndexOf("/"); if (nIdx1 > 0) { var nIdx2 = record['html_url'].indexOf("-", nIdx1) ; if (nIdx2 > 0) externalActivityID = record['html_url'].substring(nIdx1+1, nIdx2); } var createdDate = new Date(record['created_at']).getTime(); var gName="" var fName="" var names = record['creator'] ['name'].split(" ") ; var email = ""; // need to get this another way in future versions ... if (names.length) { gName=names[0]; fName = names[names.length - 1] ; } return { "bcCreatedDate" : createdDate, "author" : { name: { "givenName" : gName , "familyName" : fName } , "email" : email }, "content" : {"type" : "text/html", "text" : "<p>" + record['excerpt'] +"</p>"}, "type" : "comment", "externalID": '' + externalID, "externalActivityID" : externalActivityID } /* return { "action":{ "name":"posted", "description": record['projectName'] + " Activity" }, "actor":{ "name":record['creator']['name'], "email":"" }, "object":{ "type":"website", "url": url, "image":"http://37signals.com/svn/images/basecamp-logo-for-fluid.png", "title": summary + " @ '" + record['projectName'] + "'", "description":record['excerpt'] }, } */ }; function getMetadataByInstance(instance) { return metadataStore.find(metadataCollection, {'instanceID': instance['id']}).then(function (results) { if (results.length <= 0) { return null; } return results[0]; }); } function getLastTimePulled(instance, type) { return getMetadataByInstance(instance).then(function (metadata) { var lastTimePulled = metadata && metadata.lastTimePulled && metadata.lastTimePulled[type]; if (!lastTimePulled) { // set to something way before we were born! lastTimePulled = new Date("2013-08-05T16:26:53.664Z").getTime(); return updateLastTimePulled(instance, lastTimePulled, type).thenResolve(lastTimePulled); } return lastTimePulled; }); } function updateLastTimePulled(instance, lastTimePulled, type) { return getMetadataByInstance(instance).then(function (metadata) { var changed = false; if (!metadata) { metadata = { "instanceID": instance['id'] }; } if (!metadata.lastTimePulled) { metadata.lastTimePulled = {}; } if (!metadata.lastTimePulled[type]) { metadata.lastTimePulled[type] = lastTimePulled; changed = true; } else { if (metadata.lastTimePulled[type] < lastTimePulled) { changed = true; metadata.lastTimePulled[type] = lastTimePulled; } } if (changed) { return metadataStore.save(metadataCollection, instance['id'], metadata); } return metadata; }); } function recordSyncFromJive(instance, bcCommentID) { return getMetadataByInstance(instance).then(function (metadata) { if (!metadata) { metadata = {"instanceID": instance['id'], "syncs": []}; } if (!metadata.syncs) { metadata.syncs = []; } var changed = false; if (metadata.syncs.indexOf(bcCommentID) < 0) { metadata.syncs.push(bcCommentID); changed = true; } if (changed) { console.log( "Jive comment sync id='" + bcCommentID + "'") ; return metadataStore.save(metadataCollection, instance['id'], metadata); } return metadata; }); } function wasSynced(instance, bcCommentID) { //console.log( "Check for Jive comment sync id='" + bcCommentID+ "'" + " typeof=" + typeof bcCommentID ) ; return getMetadataByInstance(instance).then(function (metadata) { /* console.log( "indexOf = ", metadata.syncs.indexOf(bcCommentID)) ; for (var i=0; i<metadata.syncs.length; i++) console.log( i + " : '" + metadata.syncs[i] + "' typeof=" + typeof metadata.syncs[i]); */ if (metadata && metadata.syncs && metadata.syncs.indexOf(bcCommentID) >= 0) { return true; } return false; }); }