From 2722d501be584f332b53cdb5ad4e6e75a233b642 Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Fri, 22 Jul 2016 16:59:55 -0700 Subject: [PATCH 1/9] Add followup emails for CA/UK/AU/NZ --- scripts/followupCloseIoLeads.js | 92 ++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/scripts/followupCloseIoLeads.js b/scripts/followupCloseIoLeads.js index 31008e286..e81474e51 100644 --- a/scripts/followupCloseIoLeads.js +++ b/scripts/followupCloseIoLeads.js @@ -15,8 +15,12 @@ if (process.argv.length !== 8) { const createTeacherEmailTemplatesAuto1 = ['tmpl_i5bQ2dOlMdZTvZil21bhTx44JYoojPbFkciJ0F560mn', 'tmpl_CEZ9PuE1y4PRvlYiKB5kRbZAQcTIucxDvSeqvtQW57G']; const demoRequestEmailTemplatesAuto1 = ['tmpl_s7BZiydyCHOMMeXAcqRZzqn0fOtk0yOFlXSZ412MSGm', 'tmpl_cGb6m4ssDvqjvYd8UaG6cacvtSXkZY3vj9b9lSmdQrf']; +const createTeacherInternationalEmailTemplateAuto1 = 'tmpl_8vsXwcr6dWefMnAEfPEcdHaxqSfUKUY8UKq6WfReGqG'; +const demoRequestInternationalEmailTemplateAuto1 = 'tmpl_nnH1p3II7G7NJYiPOIHphuj4XUaDptrZk1mGQb2d9Xa'; const createTeacherEmailTemplatesAuto2 = ['tmpl_pGPtKa07ioISupdSc1MAzNC57K40XoA4k0PI1igi8Ec', 'tmpl_AYAcviU8NQGLbMGKSp3EmcBLha0gQw4cHSOR55Fmoha']; const demoRequestEmailTemplatesAuto2 = ['tmpl_HJ5zebh1SqC1QydDto05VPUMu4F7i5M35Llq7bzgfTw', 'tmpl_dmnK7IVpkyYfPYAl1rChhm9lClH5lJ9pQAZoPr7cvLt']; +const createTeacherInternationalEmailTemplatesAuto2 = ['tmpl_a6Syzzy6ri9MErfXQySM5UfaF5iNIv1VCArYowAEICT', 'tmpl_jOqWLgT0G19Eqs7qZaAeNwtiull7UrSX4ZuvkYRM2gC']; +const demoRequestInternationalEmailTemplatesAuto2 = ['tmpl_wz4SnDZMjNmAhp3MIuZaSMmjJTy5IW75Rcy3MYGb6Ti', 'tmpl_5oJ0YQMZFqNi3DgW7hplD6JS2zHqkB4Gt7Fj1u19Nks']; const scriptStartTime = new Date(); const closeIoApiKey = process.argv[2]; @@ -44,8 +48,24 @@ async.series([ // ** Utilities +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; +} + function getRandomEmailTemplate(templates) { - if (templates.length < 0) return ''; + if (templates.length < 0) return null; return templates[Math.floor(Math.random() * templates.length)]; } @@ -59,12 +79,12 @@ function isSameEmailTemplateType(template1, template2) { return false; } -function isDemoRequestTemplateAuto1(template) { - return demoRequestEmailTemplatesAuto1.indexOf(template) >= 0; -} - -function isCreateTeacherTemplateAuto1(template) { - return createTeacherEmailTemplatesAuto1.indexOf(template) >= 0; +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; } function isDemoRequestTemplateAuto2(template) { @@ -137,7 +157,7 @@ function sendMail(toEmail, leadId, contactId, template, emailApiKey, delayMinute } function updateLeadStatus(lead, status, done) { - // console.log("DEBUG: updateLeadStatus", lead.id, status); + // console.log(`DEBUG: updateLeadStatus ${lead.id} ${status}`); const putData = {status: status}; const options = { uri: `https://${closeIoApiKey}:X@app.close.io/api/v1/lead/${lead.id}/`, @@ -202,25 +222,14 @@ function createSendFollowupMailFn(userApiKeyMap, latestDate, lead, email) { } // Find first auto mail - let sentFirstCreateTeacherEmail = false; - let sentFirstDemoRequestEmail = false; let firstMailActivity; for (const activity of results.data) { if (activity._type === 'Email' && activity.to[0] === email) { - if (isCreateTeacherTemplateAuto1(activity.template_id)) { - if (sentFirstCreateTeacherEmail || sentFirstDemoRequestEmail) { - console.log(`ERROR: ${lead.id} sent multiple auto1 emails!? ${sentFirstCreateTeacherEmail} ${sentFirstDemoRequestEmail}`); + if (isTemplateAuto1(activity.template_id)) { + if (firstMailActivity) { + console.log(`ERROR: ${lead.id} sent multiple auto1 emails!?`); return done(); } - sentFirstCreateTeacherEmail = true; - firstMailActivity = activity; - } - else if (isDemoRequestTemplateAuto1(activity.template_id)) { - if (sentFirstCreateTeacherEmail || sentFirstDemoRequestEmail) { - console.log(`ERROR: ${lead.id} sent multiple auto1 emails!? ${sentFirstCreateTeacherEmail} ${sentFirstDemoRequestEmail}`); - return done(); - } - sentFirstDemoRequestEmail = true; firstMailActivity = activity; } } @@ -235,11 +244,6 @@ function createSendFollowupMailFn(userApiKeyMap, latestDate, lead, email) { return done(); } - if (sentFirstCreateTeacherEmail && sentFirstDemoRequestEmail) { - console.log(`ERROR: ${lead.id} sent multiple auto1 emails!? ${sentFirstCreateTeacherEmail} ${sentFirstDemoRequestEmail}`); - 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) { @@ -251,17 +255,9 @@ function createSendFollowupMailFn(userApiKeyMap, latestDate, lead, email) { } if (!recentActivity) { - let template; - if (sentFirstCreateTeacherEmail) { - // console.log(`Create teacher auto 1 sent: ${lead.id} ${firstMailUserId} ${userApiKeyMap[firstMailUserId]}`); - template = getRandomEmailTemplate(createTeacherEmailTemplatesAuto2); - } - else if (sentFirstDemoRequestEmail) { - // console.log(`Demo request auto 1 sent: ${lead.id} ${firstMailUserId} ${userApiKeyMap[firstMailUserId]}`); - template = getRandomEmailTemplate(demoRequestEmailTemplatesAuto2); - } + let template = getRandomEmailTemplateAuto2(firstMailActivity.template_id); if (!template) { - console.log(`ERROR: no template selected ${lead.id}`); + console.log(`ERROR: no auto2 template selected for ${lead.id} ${firstMailActivity.template_id}`); return done(); } // console.log(`TODO: ${firstMailActivity.to[0]} ${lead.id} ${firstMailActivity.contact_id} ${template} ${userApiKeyMap[firstMailActivity.user_id]}`); @@ -271,12 +267,25 @@ function createSendFollowupMailFn(userApiKeyMap, latestDate, lead, email) { // TODO: some sort of callback problem that stops the series here + // TODO: manage this status mapping better 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); } + 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); + } else { console.log(`ERROR: unknown lead status ${lead.id} ${lead.status_label}`) return done(); @@ -322,7 +331,8 @@ function sendSecondFollowupMails(done) { if (err) console.log(err); const latestDate = new Date(); latestDate.setUTCDate(latestDate.getUTCDate() - 3); - const query = `date_created > ${earliestDate.toISOString().substring(0, 19)} (lead_status:"Auto Attempt 1" or lead_status:"New US Schools Auto Attempt 1")"`; + // 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")`; const limit = 100; const nextPage = (skip) => { let has_more = false; @@ -337,15 +347,15 @@ function sendSecondFollowupMails(done) { 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_KYuI2HVOiUdJANvkOe1uLJBuuQVaaGSRveklhTWbHv2') continue; + // console.log(`DEBUG: ${lead.id}\t${lead.status_label}\t${lead.name}`); + // if (lead.id !== 'lead_8YZlEVQ4w3lETSlF43RQHK7cJQaBQ4tpbbxUUNA2uGC') continue; 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 { - console.log(`ERROR: lead ${lead.id} contact has non-1 emails`); + console.log(`ERROR: lead ${lead.id} contact ${contact.id} has no email`); } } } From 12f46a6f310684b58002420ae62c0ce4f37f950f Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Fri, 22 Jul 2016 17:23:38 -0700 Subject: [PATCH 2/9] Add followup call tasks for CA/UK/AU/NZ --- scripts/followupCloseIoLeads.js | 54 +++++++++++---------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/scripts/followupCloseIoLeads.js b/scripts/followupCloseIoLeads.js index e81474e51..84d6efd6c 100644 --- a/scripts/followupCloseIoLeads.js +++ b/scripts/followupCloseIoLeads.js @@ -12,6 +12,7 @@ if (process.argv.length !== 8) { // TODO: sendMail copied from updateCloseIoLeads.js // TODO: template values copied from updateCloseIoLeads.js // TODO: status change is not related to specific lead contacts +// TODO: update status after adding a call task const createTeacherEmailTemplatesAuto1 = ['tmpl_i5bQ2dOlMdZTvZil21bhTx44JYoojPbFkciJ0F560mn', 'tmpl_CEZ9PuE1y4PRvlYiKB5kRbZAQcTIucxDvSeqvtQW57G']; const demoRequestEmailTemplatesAuto1 = ['tmpl_s7BZiydyCHOMMeXAcqRZzqn0fOtk0yOFlXSZ412MSGm', 'tmpl_cGb6m4ssDvqjvYd8UaG6cacvtSXkZY3vj9b9lSmdQrf']; @@ -43,8 +44,7 @@ async.series([ (err, results) => { if (err) console.error(err); log("Script runtime: " + (new Date() - scriptStartTime)); -} -); +}); // ** Utilities @@ -87,12 +87,12 @@ function isTemplateAuto1(template) { return false; } -function isDemoRequestTemplateAuto2(template) { - return demoRequestEmailTemplatesAuto2.indexOf(template) >= 0; -} - -function isCreateTeacherTemplateAuto2(template) { - return createTeacherEmailTemplatesAuto2.indexOf(template) >= 0; +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; } function log(str) { @@ -380,8 +380,8 @@ function createAddCallTaskFn(userApiKeyMap, latestDate, lead, email) { // Check for activity since second auto mail and status update // Add call task // TODO: Very similar function to createSendFollowupMailFn - const auto1Statuses = ["Auto Attempt 1", "New US Schools Auto Attempt 1"]; - const auto2Statuses = ["Auto Attempt 2", "New US Schools Auto Attempt 2"]; + 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"]; return (done) => { // console.log("DEBUG: addCallTask", lead.id); @@ -418,27 +418,15 @@ function createAddCallTaskFn(userApiKeyMap, latestDate, lead, email) { } // Find second auto mail and status change - let sentSecondCreateTeacherEmail = false; - let sentSecondDemoRequestEmail = false; let secondMailActivity; let statusUpdateActivity; - let contactReplyMail; for (const activity of results.data) { if (activity._type === 'Email' && activity.to[0] === email) { - if (isCreateTeacherTemplateAuto2(activity.template_id)) { - if (sentSecondCreateTeacherEmail || sentSecondDemoRequestEmail) { - console.log(`ERROR: ${lead.id} ${email} sent multiple auto2 emails!? ${sentSecondCreateTeacherEmail} ${sentSecondDemoRequestEmail}`); - return done(); + if (isTemplateAuto2(activity.template_id)) { + if (secondMailActivity) { + console.log(`ERROR: ${lead.id} sent multiple auto2 emails!?`); + return done(); } - sentSecondCreateTeacherEmail = true; - secondMailActivity = activity; - } - else if (isDemoRequestTemplateAuto2(activity.template_id)) { - if (sentSecondCreateTeacherEmail || sentSecondDemoRequestEmail) { - console.log(`ERROR: ${lead.id} ${email} sent multiple auto2 emails!? ${sentSecondCreateTeacherEmail} ${sentSecondDemoRequestEmail}`); - return done(); - } - sentSecondDemoRequestEmail = true; secondMailActivity = activity; } } @@ -461,12 +449,6 @@ function createAddCallTaskFn(userApiKeyMap, latestDate, lead, email) { return done(); } - if (sentSecondCreateTeacherEmail && sentSecondDemoRequestEmail) { - console.log(`ERROR: ${lead.id} ${email} sent multiple auto2 emails!? ${sentSecondCreateTeacherEmail} ${sentSecondDemoRequestEmail}`); - return done(); - } - // console.log(secondMailActivity); - // Find activity since second auto mail and status update // Skip email to a different contact's email // Skip note about different contact @@ -521,7 +503,7 @@ function createAddCallTaskFn(userApiKeyMap, latestDate, lead, email) { } catch (err) { console.log(err); - console.log(body); + // console.log(body); return done(); } }); @@ -553,7 +535,7 @@ function addCallTasks(done) { if (err) console.log(err); const latestDate = new Date(); latestDate.setUTCDate(latestDate.getUTCDate() - 3); - const query = `date_created > ${earliestDate.toISOString().substring(0, 19)} (lead_status:"Auto Attempt 2" or lead_status:"New US Schools Auto Attempt 2")"`; + 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")`; const limit = 100; const nextPage = (skip) => { let has_more = false; @@ -578,10 +560,10 @@ function addCallTasks(done) { } } else { - console.log(`ERROR: lead ${lead.id} contact has non-1 emails`); + console.log(`ERROR: lead ${lead.id} contact ${contact.id} has no email`); } } - // if (tasks.length > 10) break; + // if (tasks.length > 1) break; } async.series(tasks, (err, results) => { if (err) return done(err); From ea61499a1061b504f10b93d1f753f628ed7b41f2 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Fri, 22 Jul 2016 17:59:32 -0700 Subject: [PATCH 3/9] Add Done button hotkey --- app/views/play/level/tome/SpellView.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/play/level/tome/SpellView.coffee b/app/views/play/level/tome/SpellView.coffee index f288a12d1..8a950d77b 100644 --- a/app/views/play/level/tome/SpellView.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -131,7 +131,10 @@ module.exports = class SpellView extends CocoView name: 'run-code-real-time' bindKey: {win: 'Ctrl-Shift-Enter', mac: 'Command-Shift-Enter|Ctrl-Shift-Enter'} exec: => - if @options.level.get('replayable') and (timeUntilResubmit = @session.timeUntilResubmit()) > 0 + doneButton = @$('.done-button:visible') + if doneButton.length + doneButton.trigger 'click' + else if @options.level.get('replayable') and (timeUntilResubmit = @session.timeUntilResubmit()) > 0 Backbone.Mediator.publish 'tome:manual-cast-denied', timeUntilResubmit: timeUntilResubmit else Backbone.Mediator.publish 'tome:manual-cast', {realTime: true} From e4867e3700545a5b5a0d6e23161b8d65691426d6 Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Sat, 23 Jul 2016 10:30:05 -0700 Subject: [PATCH 4/9] Fix close.io opportunities script License inquiries initially assigned to wrong owner, and this fixes them up. --- scripts/fixCloseIoOpps.js | 127 ++++++++++++++++++++++++++++++++ scripts/followupCloseIoLeads.js | 6 +- 2 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 scripts/fixCloseIoOpps.js diff --git a/scripts/fixCloseIoOpps.js b/scripts/fixCloseIoOpps.js new file mode 100644 index 000000000..599e68d21 --- /dev/null +++ b/scripts/fixCloseIoOpps.js @@ -0,0 +1,127 @@ +// Fix Close.io opportunity owners + +'use strict'; +if (process.argv.length !== 8) { + log("Usage: node