codecombat/scripts/fixCloseIoOpps.js

128 lines
4 KiB
JavaScript
Raw Permalink Normal View History

// Fix Close.io opportunity owners
'use strict';
if (process.argv.length !== 8) {
log("Usage: node <script> <Close.io general API key> <Close.io mail API key1> <Close.io mail API key2> <Close.io mail API key3> <Close.io EU mail API key>");
process.exit();
}
const scriptStartTime = new Date();
const closeIoApiKey = process.argv[2];
const closeIoMailApiKeys = [process.argv[3], process.argv[4], process.argv[5], process.argv[6], process.argv[7]];
const async = require('async');
const request = require('request');
// ** Main program
getUsers((err, ownerId, userApiKeyMap) => {
if (err) {
console.error(err);
return;
}
getOpps(ownerId, (err, opps) => {
if (err) {
console.error(err);
return;
}
log(`${opps.length} opps owned by ${userApiKeyMap[ownerId].data.first_name}`);
const tasks = [];
for (const opp of opps) {
tasks.push(createUpdateOppFn(ownerId, userApiKeyMap, opp));
}
async.parallel(tasks, (err, results) => {
if (err) console.error(err);
log("Script runtime: " + (new Date() - scriptStartTime));
});
});
});
function getUsers(done) {
let ownerId = null;
const userApiKeyMap = {};
let createGetUserFn = (apiKey) => {
return (done) => {
const url = `https://${apiKey}:X@app.close.io/api/v1/me/`;
request.get(url, (error, response, body) => {
if (error) return done();
const results = JSON.parse(body);
userApiKeyMap[results.id] = {key: apiKey, data: results};
if (apiKey === closeIoApiKey) {
ownerId = results.id;
}
return done();
});
};
}
const tasks = [createGetUserFn(closeIoApiKey)];
for (const apiKey of closeIoMailApiKeys) {
tasks.push(createGetUserFn(apiKey));
}
async.parallel(tasks, (err, results) => {
if (err) return done(err);
return done(null, ownerId, userApiKeyMap);
});
}
function getOpps(ownerId, done) {
const url = `https://${closeIoApiKey}:X@app.close.io/api/v1/opportunity/?user_id=${ownerId}`;
request.get(url, (err, response, body) => {
if (err) return done(err);
const results = JSON.parse(body);
return done(null, results.data);
});
}
function createUpdateOppFn(ownerId, userApiKeyMap, opp) {
return (done) => {
findOwner(ownerId, userApiKeyMap, opp, (err, userId) => {
if (err) return done(err);
// console.log(`DEBUG: ${opp.lead_id} owner ${userApiKeyMap[userId].data.first_name}`);
return updateOpp(opp, userId, userApiKeyMap, done);
});
};
}
function findOwner(ownerId, userApiKeyMap, opp, done) {
const url = `https://${closeIoApiKey}:X@app.close.io/api/v1/activity/?lead_id=${opp.lead_id}`;
request.get(url, (err, response, body) => {
if (err) return done(err);
const results = JSON.parse(body);
if (results.has_more) {
console.log(`ERROR: ${lead.id} has more activities than ${results.data.length} returned!`);
}
for (const activity of results.data) {
if (activity._type === 'Email' && userApiKeyMap[activity.user_id] && activity.user_id !== ownerId) {
return done(null, activity.user_id);
}
}
return done(`ERROR: No owner found for ${opp.lead_id}`);
});
}
function updateOpp(opp, userId, userApiKeyMap, done) {
const putData = {
user_id: userId,
user_name: `${userApiKeyMap[userId].data.first_name} ${userApiKeyMap[userId].data.last_name}`
};
console.log(`DEBUG: updating ${opp.lead_id} ${opp.id} to ${putData.user_name}`);
const options = {
uri: `https://${closeIoApiKey}:X@app.close.io/api/v1/opportunity/${opp.id}/`,
body: JSON.stringify(putData)
};
request.put(options, (err, response, body) => {
if (err) return done(err);
const result = JSON.parse(body);
if (result.errors || result['field-errors']) {
console.log(`PUT error for ${opp.lead_id} ${opp.id}`);
return done(result.errors || result['field-errors']);
}
return done();
});
}
// ** Utilities
function log(str) {
console.log(new Date().toISOString() + " " + str);
}