2016-05-03 18:52:53 -04:00
// Follow up on Close.io leads
'use strict' ;
2016-07-23 13:30:05 -04:00
if ( process . argv . length !== 7 ) {
log ( "Usage: node <script> <Close.io general API key> <Close.io mail API key1> <Close.io mail API key2> <Close.io mail API key3>" ) ;
2016-05-03 18:52:53 -04:00
process . exit ( ) ;
}
// TODO: Assumes 1:1 contact:email relationship (Close.io supports multiple emails for a single contact)
// TODO: Duplicate lead lookups when checking per-email (e.g. existing tasks)
// TODO: 2nd follow up email activity does not handle paged activity results
// TODO: sendMail copied from updateCloseIoLeads.js
// TODO: template values copied from updateCloseIoLeads.js
2016-05-10 17:40:41 -04:00
// TODO: status change is not related to specific lead contacts
2016-07-22 20:23:38 -04:00
// TODO: update status after adding a call task
2016-05-03 18:52:53 -04:00
const createTeacherEmailTemplatesAuto1 = [ 'tmpl_i5bQ2dOlMdZTvZil21bhTx44JYoojPbFkciJ0F560mn' , 'tmpl_CEZ9PuE1y4PRvlYiKB5kRbZAQcTIucxDvSeqvtQW57G' ] ;
2016-08-24 17:46:15 -04:00
const demoRequestEmailTemplatesAuto1 = [
'tmpl_s7BZiydyCHOMMeXAcqRZzqn0fOtk0yOFlXSZ412MSGm' , // (Auto1) Demo Request Long
'tmpl_cGb6m4ssDvqjvYd8UaG6cacvtSXkZY3vj9b9lSmdQrf' , // (Auto1) Demo Request Short
'tmpl_2hV6OdOXtsObLQK9qlRdpf0C9QKbER06T17ksGYOoUE' , // (Auto1) Demo Request With Questions
'tmpl_Q0tweZ5H4xs2E489KwdYj3HET9PpzkQ7jgDQb9hOMTR' , // (Auto1) Demo Request Without Questions
] ;
2016-07-22 19:59:55 -04:00
const createTeacherInternationalEmailTemplateAuto1 = 'tmpl_8vsXwcr6dWefMnAEfPEcdHaxqSfUKUY8UKq6WfReGqG' ;
const demoRequestInternationalEmailTemplateAuto1 = 'tmpl_nnH1p3II7G7NJYiPOIHphuj4XUaDptrZk1mGQb2d9Xa' ;
2016-05-03 18:52:53 -04:00
const createTeacherEmailTemplatesAuto2 = [ 'tmpl_pGPtKa07ioISupdSc1MAzNC57K40XoA4k0PI1igi8Ec' , 'tmpl_AYAcviU8NQGLbMGKSp3EmcBLha0gQw4cHSOR55Fmoha' ] ;
2016-08-24 17:46:15 -04:00
const demoRequestEmailTemplatesAuto2 = [
'tmpl_dmnK7IVpkyYfPYAl1rChhm9lClH5lJ9pQAZoPr7cvLt' , // (Auto2) Demo Request Long
'tmpl_HJ5zebh1SqC1QydDto05VPUMu4F7i5M35Llq7bzgfTw' , // (Auto2) Demo Request Short
'tmpl_oMH8Gqsh3dPl17FsBrz8dIF14sfTiySASDkmzyRlpWg' , // (Auto2) Demo Request With Questions
'tmpl_JuuQsQhWNpDMYmN9rwD5Kk7oBELVZI4fMmJNUQC7A8j' , // (Auto2) Demo Request Without Questions
] ;
2016-07-22 19:59:55 -04:00
const createTeacherInternationalEmailTemplatesAuto2 = [ 'tmpl_a6Syzzy6ri9MErfXQySM5UfaF5iNIv1VCArYowAEICT' , 'tmpl_jOqWLgT0G19Eqs7qZaAeNwtiull7UrSX4ZuvkYRM2gC' ] ;
const demoRequestInternationalEmailTemplatesAuto2 = [ 'tmpl_wz4SnDZMjNmAhp3MIuZaSMmjJTy5IW75Rcy3MYGb6Ti' , 'tmpl_5oJ0YQMZFqNi3DgW7hplD6JS2zHqkB4Gt7Fj1u19Nks' ] ;
2016-05-03 18:52:53 -04:00
const scriptStartTime = new Date ( ) ;
const closeIoApiKey = process . argv [ 2 ] ;
2016-07-12 09:32:50 -04:00
const closeIoMailApiKeys = [ process . argv [ 3 ] , process . argv [ 4 ] , process . argv [ 5 ] , process . argv [ 6 ] ] ; // Automatic mails sent as API owners
2016-05-03 18:52:53 -04:00
const async = require ( 'async' ) ;
const request = require ( 'request' ) ;
const earliestDate = new Date ( ) ;
earliestDate . setUTCDate ( earliestDate . getUTCDate ( ) - 10 ) ;
// ** Main program
async . series ( [
2016-05-10 17:40:41 -04:00
sendSecondFollowupMails ,
addCallTasks
// TODO: Cancel call tasks
2016-05-03 18:52:53 -04:00
] ,
( err , results ) => {
if ( err ) console . error ( err ) ;
log ( "Script runtime: " + ( new Date ( ) - scriptStartTime ) ) ;
2016-07-22 20:23:38 -04:00
} ) ;
2016-05-03 18:52:53 -04:00
// ** Utilities
2016-07-22 19:59:55 -04:00
function getRandomEmailTemplateAuto2 ( template ) {
if ( createTeacherEmailTemplatesAuto1 . indexOf ( template ) >= 0 ) {
return getRandomEmailTemplate ( createTeacherEmailTemplatesAuto2 ) ;
}
if ( demoRequestEmailTemplatesAuto1 . indexOf ( template ) >= 0 ) {
return getRandomEmailTemplate ( demoRequestEmailTemplatesAuto2 ) ;
}
if ( createTeacherInternationalEmailTemplateAuto1 == template ) {
return getRandomEmailTemplate ( createTeacherInternationalEmailTemplatesAuto2 ) ;
}
if ( demoRequestInternationalEmailTemplateAuto1 === template ) {
return getRandomEmailTemplate ( demoRequestInternationalEmailTemplatesAuto2 ) ;
}
return null ;
}
2016-05-03 18:52:53 -04:00
function getRandomEmailTemplate ( templates ) {
2016-07-22 19:59:55 -04:00
if ( templates . length < 0 ) return null ;
2016-05-03 18:52:53 -04:00
return templates [ Math . floor ( Math . random ( ) * templates . length ) ] ;
}
function isSameEmailTemplateType ( template1 , template2 ) {
if ( createTeacherEmailTemplatesAuto1 . indexOf ( template1 ) >= 0 && createTeacherEmailTemplatesAuto1 . indexOf ( template2 ) >= 0 ) {
return true ;
}
if ( demoRequestEmailTemplatesAuto1 . indexOf ( template1 ) >= 0 && demoRequestEmailTemplatesAuto1 . indexOf ( template2 ) >= 0 ) {
return true ;
}
return false ;
}
2016-07-22 19:59:55 -04:00
function isTemplateAuto1 ( template ) {
if ( createTeacherEmailTemplatesAuto1 . indexOf ( template ) >= 0 ) return true ;
if ( demoRequestEmailTemplatesAuto1 . indexOf ( template ) >= 0 ) return true ;
if ( createTeacherInternationalEmailTemplateAuto1 == template ) return true ;
if ( demoRequestInternationalEmailTemplateAuto1 === template ) return true ;
return false ;
2016-05-03 18:52:53 -04:00
}
2016-07-22 20:23:38 -04:00
function isTemplateAuto2 ( template ) {
if ( createTeacherEmailTemplatesAuto2 . indexOf ( template ) >= 0 ) return true ;
if ( demoRequestEmailTemplatesAuto2 . indexOf ( template ) >= 0 ) return true ;
if ( createTeacherInternationalEmailTemplatesAuto2 . indexOf ( template ) >= 0 ) return true ;
if ( demoRequestInternationalEmailTemplatesAuto2 . indexOf ( template ) >= 0 ) return true ;
return false ;
2016-05-10 17:40:41 -04:00
}
2016-05-03 18:52:53 -04:00
function log ( str ) {
console . log ( new Date ( ) . toISOString ( ) + " " + str ) ;
}
// ** Close.io methods
function sendMail ( toEmail , leadId , contactId , template , emailApiKey , delayMinutes , done ) {
// console.log('DEBUG: sendMail', toEmail, leadId, contactId, template, emailApiKey, delayMinutes);
// Check for previously sent email
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/activity/email/?lead_id= ${ leadId } ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) return done ( error ) ;
try {
const data = JSON . parse ( body ) ;
for ( const emailData of data . data ) {
if ( ! isSameEmailTemplateType ( emailData . template _id , template ) ) continue ;
for ( const email of emailData . to ) {
if ( email . toLowerCase ( ) === toEmail . toLowerCase ( ) ) {
console . log ( "ERROR: sending duplicate email:" , toEmail , leadId , contactId , template , emailData . contact _id ) ;
return done ( ) ;
}
}
}
}
catch ( err ) {
console . log ( err ) ;
console . log ( body ) ;
return done ( ) ;
}
// Send mail
const dateScheduled = new Date ( ) ;
dateScheduled . setUTCMinutes ( dateScheduled . getUTCMinutes ( ) + delayMinutes ) ;
const postData = {
to : [ toEmail ] ,
contact _id : contactId ,
lead _id : leadId ,
template _id : template ,
status : 'scheduled' ,
date _scheduled : dateScheduled
} ;
const options = {
uri : ` https:// ${ emailApiKey } :X@app.close.io/api/v1/activity/email/ ` ,
body : JSON . stringify ( postData )
} ;
request . post ( options , ( error , response , body ) => {
if ( error ) return done ( error ) ;
const result = JSON . parse ( body ) ;
if ( result . errors || result [ 'field-errors' ] ) {
const errorMessage = ` Send email POST error for ${ toEmail } ${ leadId } ${ contactId } ` ;
console . error ( errorMessage ) ;
console . error ( body ) ;
// console.error(postData);
return done ( errorMessage ) ;
}
return done ( ) ;
} ) ;
} ) ;
}
function updateLeadStatus ( lead , status , done ) {
2016-07-22 19:59:55 -04:00
// console.log(`DEBUG: updateLeadStatus ${lead.id} ${status}`);
2016-05-03 18:52:53 -04:00
const putData = { status : status } ;
const options = {
uri : ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/lead/ ${ lead . id } / ` ,
body : JSON . stringify ( putData )
} ;
request . put ( options , ( error , response , body ) => {
if ( error ) return done ( error ) ;
try {
const result = JSON . parse ( body ) ;
if ( result . errors || result [ 'field-errors' ] ) {
console . log ( ` Update existing lead status PUT error for ${ lead . id } ` ) ;
console . log ( body ) ;
return done ( result . errors || result [ 'field-errors' ] ) ;
}
return done ( ) ;
}
catch ( err ) {
console . log ( body ) ;
return done ( err ) ;
}
} ) ;
}
function createSendFollowupMailFn ( userApiKeyMap , latestDate , lead , email ) {
// Find first auto mail
// Find activity since first auto mail
// Send send auto mail of same template type (create or demo) from same user who sent first email
// Update status to Auto Attempt 2 or New US Schools Auto Attempt 2
return ( done ) => {
// console.log("DEBUG: sendFollowupMail", lead.id);
// Skip leads with tasks
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/task/?lead_id= ${ lead . id } ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) {
console . log ( error ) ;
return done ( ) ;
}
try {
const results = JSON . parse ( body ) ;
if ( results . total _results > 0 ) {
// console.log(`${lead.id} has ${results.total_results} tasks`);
return done ( ) ;
}
}
catch ( err ) {
return done ( err ) ;
}
// Find all lead activities
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/activity/?lead_id= ${ lead . id } ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) {
console . log ( error ) ;
return done ( ) ;
}
try {
const results = JSON . parse ( body ) ;
if ( results . has _more ) {
console . log ( ` ERROR: ${ lead . id } has more activities than returned! ` ) ;
return done ( ) ;
}
// Find first auto mail
let firstMailActivity ;
for ( const activity of results . data ) {
if ( activity . _type === 'Email' && activity . to [ 0 ] === email ) {
2016-07-22 19:59:55 -04:00
if ( isTemplateAuto1 ( activity . template _id ) ) {
if ( firstMailActivity ) {
console . log ( ` ERROR: ${ lead . id } sent multiple auto1 emails!? ` ) ;
2016-05-03 18:52:53 -04:00
return done ( ) ;
}
firstMailActivity = activity ;
}
}
}
if ( ! firstMailActivity ) {
console . log ( ` ERROR: No first auto mail sent for ${ lead . id } ` ) ;
return done ( ) ;
}
if ( new Date ( firstMailActivity . date _created ) > latestDate ) {
// console.log(`First auto mail too recent ${firstMailActivity.date_created} ${lead.id}`);
return done ( ) ;
}
// Find activity since first auto mail, that's not email to a different contact's email
let recentActivity ;
for ( const activity of results . data ) {
if ( activity . id === firstMailActivity . id ) continue ;
if ( new Date ( firstMailActivity . date _created ) > new Date ( activity . date _created ) ) continue ;
2016-08-30 12:21:48 -04:00
if ( activity . _type === 'Email' && activity . to [ 0 ] . toLowerCase ( ) !== email ) continue ;
2016-05-03 18:52:53 -04:00
recentActivity = activity ;
break ;
}
if ( ! recentActivity ) {
2016-07-22 19:59:55 -04:00
let template = getRandomEmailTemplateAuto2 ( firstMailActivity . template _id ) ;
2016-05-03 18:52:53 -04:00
if ( ! template ) {
2016-07-22 19:59:55 -04:00
console . log ( ` ERROR: no auto2 template selected for ${ lead . id } ${ firstMailActivity . template _id } ` ) ;
2016-05-03 18:52:53 -04:00
return done ( ) ;
}
// console.log(`TODO: ${firstMailActivity.to[0]} ${lead.id} ${firstMailActivity.contact_id} ${template} ${userApiKeyMap[firstMailActivity.user_id]}`);
sendMail ( firstMailActivity . to [ 0 ] , lead . id , firstMailActivity . contact _id , template , userApiKeyMap [ firstMailActivity . user _id ] , 0 , ( err ) => {
if ( err ) return done ( err ) ;
// TODO: some sort of callback problem that stops the series here
2016-07-22 19:59:55 -04:00
// TODO: manage this status mapping better
2016-05-03 18:52:53 -04:00
if ( lead . status _label === "Auto Attempt 1" ) {
return updateLeadStatus ( lead , "Auto Attempt 2" , done ) ;
}
else if ( lead . status _label === "New US Schools Auto Attempt 1" ) {
return updateLeadStatus ( lead , "New US Schools Auto Attempt 2" , done ) ;
}
2016-07-22 19:59:55 -04:00
else if ( lead . status _label === "Inbound AU Auto Attempt 1" ) {
return updateLeadStatus ( lead , "Inbound AU Auto Attempt 2" , done ) ;
}
else if ( lead . status _label === "Inbound Canada Auto Attempt 1" ) {
return updateLeadStatus ( lead , "Inbound Canada Auto Attempt 2" , done ) ;
}
else if ( lead . status _label === "Inbound NZ Auto Attempt 1" ) {
return updateLeadStatus ( lead , "Inbound NZ Auto Attempt 2" , done ) ;
}
else if ( lead . status _label === "Inbound UK Auto Attempt 1" ) {
return updateLeadStatus ( lead , "Inbound UK Auto Attempt 2" , done ) ;
}
2016-05-03 18:52:53 -04:00
else {
console . log ( ` ERROR: unknown lead status ${ lead . id } ${ lead . status _label } ` )
return done ( ) ;
}
} ) ;
}
else {
// console.log(`Found recent activity after auto1 mail for ${lead.id}`);
2016-08-30 12:21:48 -04:00
// console.log(firstMailActivity.template_id, recentActivity);
2016-05-03 18:52:53 -04:00
return done ( ) ;
}
}
catch ( err ) {
console . log ( err ) ;
console . log ( body ) ;
return done ( ) ;
}
} ) ;
} ) ;
} ;
}
function sendSecondFollowupMails ( done ) {
// Find all leads with auto 1 status, created since earliestDate
// console.log("DEBUG: sendSecondFollowupMails");
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 ] = apiKey ;
return done ( ) ;
} ) ;
} ;
}
const tasks = [ ] ;
for ( const apiKey of closeIoMailApiKeys ) {
tasks . push ( createGetUserFn ( apiKey ) ) ;
}
async . parallel ( tasks , ( err , results ) => {
if ( err ) console . log ( err ) ;
const latestDate = new Date ( ) ;
latestDate . setUTCDate ( latestDate . getUTCDate ( ) - 3 ) ;
2016-07-22 19:59:55 -04:00
// TODO: manage this status list better
const query = ` date_created > ${ earliestDate . toISOString ( ) . substring ( 0 , 19 ) } (lead_status:"Auto Attempt 1" or lead_status:"New US Schools Auto Attempt 1" or lead_status:"Inbound Canada Auto Attempt 1" or lead_status:"Inbound AU Auto Attempt 1" or lead_status:"Inbound NZ Auto Attempt 1" or lead_status:"Inbound UK Auto Attempt 1") ` ;
2016-05-03 18:52:53 -04:00
const limit = 100 ;
const nextPage = ( skip ) => {
let has _more = false ;
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/lead/?_skip= ${ skip } &_limit= ${ limit } &query= ${ encodeURIComponent ( query ) } / ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) return done ( error ) ;
try {
const results = JSON . parse ( body ) ;
2016-05-10 17:40:41 -04:00
if ( skip === 0 ) {
console . log ( ` sendSecondFollowupMails total num leads ${ results . total _results } has_more= ${ results . has _more } ` ) ;
}
2016-05-03 18:52:53 -04:00
has _more = results . has _more ;
const tasks = [ ] ;
for ( const lead of results . data ) {
2016-07-22 19:59:55 -04:00
// console.log(`DEBUG: ${lead.id}\t${lead.status_label}\t${lead.name}`);
// if (lead.id !== 'lead_8YZlEVQ4w3lETSlF43RQHK7cJQaBQ4tpbbxUUNA2uGC') continue;
2016-05-03 18:52:53 -04:00
const existingContacts = lead . contacts || [ ] ;
for ( const contact of existingContacts ) {
if ( contact . emails && contact . emails . length > 0 ) {
tasks . push ( createSendFollowupMailFn ( userApiKeyMap , latestDate , lead , contact . emails [ 0 ] . email . toLowerCase ( ) ) ) ;
}
else {
2016-07-22 19:59:55 -04:00
console . log ( ` ERROR: lead ${ lead . id } contact ${ contact . id } has no email ` ) ;
2016-05-03 18:52:53 -04:00
}
}
}
async . series ( tasks , ( err , results ) => {
if ( err ) return done ( err ) ;
if ( has _more ) {
return nextPage ( skip + limit ) ;
}
return done ( err ) ;
} ) ;
}
catch ( err ) {
return done ( err ) ;
}
} ) ;
} ;
nextPage ( 0 ) ;
} ) ;
}
2016-05-10 17:40:41 -04:00
function createAddCallTaskFn ( userApiKeyMap , latestDate , lead , email ) {
// Check for activity since second auto mail and status update
// Add call task
2016-07-22 20:23:38 -04:00
const auto1Statuses = [ "Auto Attempt 1" , "New US Schools Auto Attempt 1" , "Inbound Canada Auto Attempt 1" , "Inbound AU Auto Attempt 1" , "Inbound NZ Auto Attempt 1" , "Inbound UK Auto Attempt 1" ] ;
const auto2Statuses = [ "Auto Attempt 2" , "New US Schools Auto Attempt 2" , "Inbound Canada Auto Attempt 2" , "Inbound AU Auto Attempt 2" , "Inbound NZ Auto Attempt 2" , "Inbound UK Auto Attempt 2" ] ;
2016-05-10 17:40:41 -04:00
return ( done ) => {
// console.log("DEBUG: addCallTask", lead.id);
// Skip leads with tasks
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/task/?lead_id= ${ lead . id } ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) {
console . log ( error ) ;
return done ( ) ;
}
try {
const results = JSON . parse ( body ) ;
if ( results . total _results > 0 ) {
// console.log(`DEBUG: ${lead.id} has ${results.total_results} tasks`);
return done ( ) ;
}
}
catch ( err ) {
return done ( err ) ;
}
// Find all lead activities
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/activity/?lead_id= ${ lead . id } ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) {
console . log ( error ) ;
return done ( ) ;
}
try {
const results = JSON . parse ( body ) ;
if ( results . has _more ) {
console . log ( ` ERROR: ${ lead . id } has more activities than returned! ` ) ;
return done ( ) ;
}
// Find second auto mail and status change
let secondMailActivity ;
let statusUpdateActivity ;
for ( const activity of results . data ) {
if ( activity . _type === 'Email' && activity . to [ 0 ] === email ) {
2016-07-22 20:23:38 -04:00
if ( isTemplateAuto2 ( activity . template _id ) ) {
if ( secondMailActivity ) {
console . log ( ` ERROR: ${ lead . id } sent multiple auto2 emails!? ` ) ;
return done ( ) ;
2016-05-10 17:40:41 -04:00
}
secondMailActivity = activity ;
}
}
else if ( activity . _type === 'LeadStatusChange' && auto1Statuses . indexOf ( activity . old _status _label ) >= 0
&& auto2Statuses . indexOf ( activity . new _status _label ) >= 0 ) {
statusUpdateActivity = activity ;
}
}
if ( ! secondMailActivity ) {
// console.log(`DEBUG: No auto2 mail sent for ${lead.id} ${email}`);
return done ( ) ;
}
if ( ! statusUpdateActivity ) {
console . log ( ` ERROR: No status update for ${ lead . id } ${ email } ` ) ;
return done ( ) ;
}
if ( new Date ( secondMailActivity . date _created ) > latestDate ) {
// console.log(`DEBUG: Second auto mail too recent ${secondMailActivity.date_created} ${lead.id}`);
return done ( ) ;
}
// Find activity since second auto mail and status update
// Skip email to a different contact's email
// Skip note about different contact
let recentActivity ;
for ( const activity of results . data ) {
if ( activity . id === secondMailActivity . id ) continue ;
if ( activity . id === statusUpdateActivity . id ) continue ;
if ( new Date ( secondMailActivity . date _created ) > new Date ( activity . date _created ) ) continue ;
if ( new Date ( statusUpdateActivity . date _created ) > new Date ( activity . date _created ) ) continue ;
if ( activity . _type === 'Note' && activity . note
&& activity . note . indexOf ( 'demo_email' ) >= 0 && activity . note . indexOf ( email ) < 0 ) {
// console.log(`DEBUG: Skipping ${lead.id} ${email} auto import note for different contact`);
// console.log(activity.note);
continue ;
}
recentActivity = activity ;
break ;
}
// Create call task
if ( ! recentActivity ) {
console . log ( ` DEBUG: adding call task for ${ lead . id } ${ email } ` ) ;
const postData = {
_type : "lead" ,
lead _id : lead . id ,
assigned _to : secondMailActivity . user _id ,
text : ` Call ${ email } ` ,
is _complete : false
} ;
const options = {
uri : ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/task/ ` ,
body : JSON . stringify ( postData )
} ;
request . post ( options , ( error , response , body ) => {
if ( error ) return done ( error ) ;
const result = JSON . parse ( body ) ;
if ( result . errors || result [ 'field-errors' ] ) {
const errorMessage = ` Create call task POST error for ${ email } ${ lead . id } ` ;
console . error ( errorMessage ) ;
// console.error(body);
// console.error(postData);
return done ( errorMessage ) ;
}
return done ( ) ;
} ) ;
}
else {
// console.log(`DEBUG: Found recent activity after auto2 mail for ${lead.id} ${email}`);
// console.log(recentActivity);
return done ( ) ;
}
}
catch ( err ) {
console . log ( err ) ;
2016-07-22 20:23:38 -04:00
// console.log(body);
2016-05-10 17:40:41 -04:00
return done ( ) ;
}
} ) ;
} ) ;
} ;
}
function addCallTasks ( done ) {
// Find all leads with auto 2 status, created since earliestDate
// TODO: Very similar function to sendSecondFollowupMails
// console.log("DEBUG: addCallTasks");
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 ] = apiKey ;
return done ( ) ;
} ) ;
} ;
}
const tasks = [ ] ;
for ( const apiKey of closeIoMailApiKeys ) {
tasks . push ( createGetUserFn ( apiKey ) ) ;
}
async . parallel ( tasks , ( err , results ) => {
if ( err ) console . log ( err ) ;
const latestDate = new Date ( ) ;
latestDate . setUTCDate ( latestDate . getUTCDate ( ) - 3 ) ;
2016-07-22 20:23:38 -04:00
const query = ` date_created > ${ earliestDate . toISOString ( ) . substring ( 0 , 19 ) } (lead_status:"Auto Attempt 2" or lead_status:"New US Schools Auto Attempt 2" or lead_status:"Inbound Canada Auto Attempt 2" or lead_status:"Inbound AU Auto Attempt 2" or lead_status:"Inbound NZ Auto Attempt 2" or lead_status:"Inbound UK Auto Attempt 2") ` ;
2016-05-10 17:40:41 -04:00
const limit = 100 ;
const nextPage = ( skip ) => {
let has _more = false ;
const url = ` https:// ${ closeIoApiKey } :X@app.close.io/api/v1/lead/?_skip= ${ skip } &_limit= ${ limit } &query= ${ encodeURIComponent ( query ) } / ` ;
request . get ( url , ( error , response , body ) => {
if ( error ) return done ( error ) ;
try {
const results = JSON . parse ( body ) ;
if ( skip === 0 ) {
console . log ( ` addCallTasks total num leads ${ results . total _results } has_more= ${ results . has _more } ` ) ;
}
has _more = results . has _more ;
const tasks = [ ] ;
for ( const lead of results . data ) {
// console.log(`${lead.id}\t${lead.status_label}\t${lead.name}`);
// if (lead.id !== 'lead_foo') continue;
const existingContacts = lead . contacts || [ ] ;
for ( const contact of existingContacts ) {
if ( contact . emails && contact . emails . length > 0 ) {
if ( contact . phones && contact . phones . length > 0 ) {
tasks . push ( createAddCallTaskFn ( userApiKeyMap , latestDate , lead , contact . emails [ 0 ] . email . toLowerCase ( ) ) ) ;
}
}
else {
2016-07-22 20:23:38 -04:00
console . log ( ` ERROR: lead ${ lead . id } contact ${ contact . id } has no email ` ) ;
2016-05-10 17:40:41 -04:00
}
}
2016-07-22 20:23:38 -04:00
// if (tasks.length > 1) break;
2016-05-10 17:40:41 -04:00
}
async . series ( tasks , ( err , results ) => {
if ( err ) return done ( err ) ;
if ( has _more ) {
return nextPage ( skip + limit ) ;
}
return done ( err ) ;
} ) ;
}
catch ( err ) {
return done ( err ) ;
}
} ) ;
} ;
nextPage ( 0 ) ;
} ) ;
}