sproutkit-code 1.15.1 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +118 -43
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -121,6 +121,49 @@ var require_runtime = __commonJS({
|
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
+
// ../desktop/dist/main/lib/outreach-template.js
|
|
125
|
+
var require_outreach_template = __commonJS({
|
|
126
|
+
"../desktop/dist/main/lib/outreach-template.js"(exports2) {
|
|
127
|
+
"use strict";
|
|
128
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
129
|
+
exports2.PREVIOUS_DEFAULT_TEMPLATE = exports2.OUTREACH_TEMPLATE = void 0;
|
|
130
|
+
exports2.OUTREACH_TEMPLATE = `Hello,
|
|
131
|
+
|
|
132
|
+
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
133
|
+
|
|
134
|
+
{site_url}
|
|
135
|
+
|
|
136
|
+
It's built from your real reviews and photos.
|
|
137
|
+
|
|
138
|
+
I also recorded a short video walking you through it: {video}
|
|
139
|
+
|
|
140
|
+
And I've set up a virtual front desk for {name}. It answers your calls when you can't get to the phone, knows your services, prices and opening hours, and texts you a summary of every call. Try it the way a customer would \u2014 ask if you're open on Saturday, or what something costs:
|
|
141
|
+
|
|
142
|
+
{front_desk}
|
|
143
|
+
|
|
144
|
+
If you like the website, I can put it live on your own domain for a one-off fee of \xA3199, with no monthly charges. The front desk can be switched on for your number whenever you're ready.
|
|
145
|
+
|
|
146
|
+
Would you be open to a quick chat this week?
|
|
147
|
+
|
|
148
|
+
Best regards
|
|
149
|
+
|
|
150
|
+
If you'd rather not hear from me again, just reply and let me know.`;
|
|
151
|
+
exports2.PREVIOUS_DEFAULT_TEMPLATE = `Hello,
|
|
152
|
+
|
|
153
|
+
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
154
|
+
|
|
155
|
+
{site_url}
|
|
156
|
+
|
|
157
|
+
It's built from your real reviews and photos. If you like it, I can put it live on your own domain with your details for a one-off fee of \xA3199 \u2014 no monthly charges.
|
|
158
|
+
|
|
159
|
+
Would you be open to a quick chat this week?
|
|
160
|
+
|
|
161
|
+
Best regards
|
|
162
|
+
|
|
163
|
+
If you'd rather not hear from me again, just reply and let me know.`;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
124
167
|
// ../desktop/dist/main/db.js
|
|
125
168
|
var require_db = __commonJS({
|
|
126
169
|
"../desktop/dist/main/db.js"(exports2) {
|
|
@@ -131,6 +174,7 @@ var require_db = __commonJS({
|
|
|
131
174
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
132
175
|
exports2.databasePath = databasePath;
|
|
133
176
|
exports2.initDatabase = initDatabase2;
|
|
177
|
+
exports2.upgradeDefaultTemplate = upgradeDefaultTemplate;
|
|
134
178
|
exports2.getDb = getDb2;
|
|
135
179
|
var node_sqlite3_wasm_1 = require("node-sqlite3-wasm");
|
|
136
180
|
var path_1 = __importDefault(require("path"));
|
|
@@ -407,7 +451,7 @@ var require_db = __commonJS({
|
|
|
407
451
|
} catch {
|
|
408
452
|
}
|
|
409
453
|
}
|
|
410
|
-
for (const col of ["receptionist_id TEXT", "receptionist_url TEXT", "receptionist_price_pence INTEGER", "receptionist_line TEXT"]) {
|
|
454
|
+
for (const col of ["receptionist_id TEXT", "receptionist_url TEXT", "receptionist_price_pence INTEGER", "receptionist_line TEXT", "front_desk_chat INTEGER NOT NULL DEFAULT 0"]) {
|
|
411
455
|
try {
|
|
412
456
|
db2.exec(`ALTER TABLE leads ADD COLUMN ${col}`);
|
|
413
457
|
} catch {
|
|
@@ -426,6 +470,16 @@ var require_db = __commonJS({
|
|
|
426
470
|
}
|
|
427
471
|
}
|
|
428
472
|
}
|
|
473
|
+
function upgradeDefaultTemplate() {
|
|
474
|
+
try {
|
|
475
|
+
const t = require_outreach_template();
|
|
476
|
+
db2.run("UPDATE settings SET value = ? WHERE key = 'outreach_template' AND value = ?", [
|
|
477
|
+
t.OUTREACH_TEMPLATE,
|
|
478
|
+
t.PREVIOUS_DEFAULT_TEMPLATE
|
|
479
|
+
]);
|
|
480
|
+
} catch {
|
|
481
|
+
}
|
|
482
|
+
}
|
|
429
483
|
function getDb2() {
|
|
430
484
|
return db2;
|
|
431
485
|
}
|
|
@@ -31510,7 +31564,7 @@ var require_analytics_runtime = __commonJS({
|
|
|
31510
31564
|
"../desktop/dist/main/lib/analytics-runtime.js"(exports2) {
|
|
31511
31565
|
"use strict";
|
|
31512
31566
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
31513
|
-
exports2.TRACK_SNIPPET = exports2.API_STATS_JS = exports2.API_TRACK_JS = void 0;
|
|
31567
|
+
exports2.FRONT_DESK_SNIPPET = exports2.TRACK_SNIPPET = exports2.API_STATS_JS = exports2.API_TRACK_JS = void 0;
|
|
31514
31568
|
exports2.API_TRACK_JS = `import { list, put } from "@vercel/blob";
|
|
31515
31569
|
import { createHash, createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
31516
31570
|
|
|
@@ -31876,6 +31930,7 @@ export default async function handler(req, res) {
|
|
|
31876
31930
|
}, true);
|
|
31877
31931
|
})();
|
|
31878
31932
|
</script>`;
|
|
31933
|
+
exports2.FRONT_DESK_SNIPPET = `<script src="${process.env.SPROUTKIT_API_BASE_URL ?? "https://sproutkit.app"}/front-desk.js" defer></script>`;
|
|
31879
31934
|
}
|
|
31880
31935
|
});
|
|
31881
31936
|
|
|
@@ -81633,6 +81688,7 @@ var require_builder = __commonJS({
|
|
|
81633
81688
|
exports2.deployStandaloneBooking = deployStandaloneBooking2;
|
|
81634
81689
|
exports2.handoverSite = handoverSite2;
|
|
81635
81690
|
exports2.addEditorToSite = addEditorToSite2;
|
|
81691
|
+
exports2.redeployAsIs = redeployAsIs;
|
|
81636
81692
|
var sdk_1 = __importDefault(require_sdk());
|
|
81637
81693
|
var axios_1 = __importDefault(require_axios());
|
|
81638
81694
|
var crypto_1 = require("crypto");
|
|
@@ -82402,7 +82458,7 @@ ${prompt}` : prompt;
|
|
|
82402
82458
|
onProgress("Deploying to Vercel...");
|
|
82403
82459
|
const indexHtml = `<!DOCTYPE html>
|
|
82404
82460
|
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head>
|
|
82405
|
-
<body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}</body></html>`;
|
|
82461
|
+
<body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}${analytics_runtime_1.FRONT_DESK_SNIPPET}</body></html>`;
|
|
82406
82462
|
const mainJsx = `import { StrictMode } from 'react';
|
|
82407
82463
|
import { createRoot } from 'react-dom/client';
|
|
82408
82464
|
import App from './App.jsx';
|
|
@@ -82633,7 +82689,7 @@ export default defineConfig({ plugins: [react()] });`;
|
|
|
82633
82689
|
{ source: "/book/", destination: "/book/index.html" }
|
|
82634
82690
|
]
|
|
82635
82691
|
});
|
|
82636
|
-
const indexHtmlCms = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head><body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}</body></html>`;
|
|
82692
|
+
const indexHtmlCms = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head><body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}${analytics_runtime_1.FRONT_DESK_SNIPPET}</body></html>`;
|
|
82637
82693
|
const mainJsxCms = `import { StrictMode } from 'react';
|
|
82638
82694
|
import { createRoot } from 'react-dom/client';
|
|
82639
82695
|
import App from './App.jsx';
|
|
@@ -82712,7 +82768,7 @@ export default defineConfig({ plugins: [react()] });`;
|
|
|
82712
82768
|
snapshot[appJsxIndex] = { ...snapshot[appJsxIndex], data: modifiedApp };
|
|
82713
82769
|
saveSnapshot(lead.id, snapshot);
|
|
82714
82770
|
const files = snapshot.map((f) => ({ file: f.file, data: f.data, encoding: f.encoding }));
|
|
82715
|
-
const indexHtml = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head><body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}</body></html>`;
|
|
82771
|
+
const indexHtml = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head><body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}${analytics_runtime_1.FRONT_DESK_SNIPPET}</body></html>`;
|
|
82716
82772
|
const mainJsx = `import { StrictMode } from 'react';
|
|
82717
82773
|
import { createRoot } from 'react-dom/client';
|
|
82718
82774
|
import App from './App.jsx';
|
|
@@ -83015,7 +83071,7 @@ export default defineConfig({ plugins: [react()] });`;
|
|
|
83015
83071
|
deps["@vercel/blob"] = "^0.23.4";
|
|
83016
83072
|
deps.bcryptjs = "^2.4.3";
|
|
83017
83073
|
}
|
|
83018
|
-
const indexHtml = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head><body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}</body></html>`;
|
|
83074
|
+
const indexHtml = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${lead.name}</title></head><body style="margin:0">${bannerFor(lead)}<div id="root"></div><script type="module" src="/src/main.jsx"></script>${analytics_runtime_1.TRACK_SNIPPET}${analytics_runtime_1.FRONT_DESK_SNIPPET}</body></html>`;
|
|
83019
83075
|
files.push({ file: "index.html", data: indexHtml, encoding: "utf-8" }, {
|
|
83020
83076
|
file: "src/main.jsx",
|
|
83021
83077
|
data: `import { StrictMode } from 'react';
|
|
@@ -83206,6 +83262,22 @@ Your previous reply was unusable (${lastErr}). Follow the reply format exactly.`
|
|
|
83206
83262
|
}
|
|
83207
83263
|
throw new Error(`Couldn't connect this site to the editor (${lastErr}). Try again \u2014 nothing was changed.`);
|
|
83208
83264
|
}
|
|
83265
|
+
async function redeployAsIs(args) {
|
|
83266
|
+
const { lead } = args;
|
|
83267
|
+
if (lead.booking_url) {
|
|
83268
|
+
throw new Error("This site has online booking, which a redeploy would remove. Skipped to keep bookings working.");
|
|
83269
|
+
}
|
|
83270
|
+
const uid = (0, db_1.getDb)().get("SELECT site_uid FROM leads WHERE id = ?", [lead.id])?.site_uid ?? null;
|
|
83271
|
+
return redeployWithoutBanner({
|
|
83272
|
+
lead,
|
|
83273
|
+
vercelToken: args.vercelToken,
|
|
83274
|
+
blobToken: args.blobToken,
|
|
83275
|
+
hasCms: !!lead.admin_url,
|
|
83276
|
+
adminPassword: lead.admin_password ?? null,
|
|
83277
|
+
siteUid: uid,
|
|
83278
|
+
onProgress: args.onProgress
|
|
83279
|
+
});
|
|
83280
|
+
}
|
|
83209
83281
|
function hasBookLink(code) {
|
|
83210
83282
|
return /(href\s*=\s*["'`{]*\s*["'`]?\/book\/?["'`}]?)|(location(?:\.href)?\s*=\s*["'`]\/book["'`])/i.test(code);
|
|
83211
83283
|
}
|
|
@@ -84482,7 +84554,7 @@ var require_pitch_text = __commonJS({
|
|
|
84482
84554
|
exports2.prettyNumber = prettyNumber;
|
|
84483
84555
|
function withVideo(message, videoUrl) {
|
|
84484
84556
|
if (!videoUrl)
|
|
84485
|
-
return message
|
|
84557
|
+
return omit(message, /\{video\}/, /\bvideo\b/i);
|
|
84486
84558
|
if (message.includes("{video}"))
|
|
84487
84559
|
return message.replace(/\{video\}/g, videoUrl);
|
|
84488
84560
|
const line = `I also recorded a short video walking you through it: ${videoUrl}`;
|
|
@@ -84495,13 +84567,14 @@ ${line}`;
|
|
|
84495
84567
|
lines.splice(at + 1, 0, "", line);
|
|
84496
84568
|
return lines.join("\n");
|
|
84497
84569
|
}
|
|
84498
|
-
function withReceptionist(message, url, demoNumber, businessName) {
|
|
84570
|
+
function withReceptionist(message, url, demoNumber, businessName, chatOn) {
|
|
84499
84571
|
void demoNumber;
|
|
84572
|
+
message = message.replace(/\{front_desk\}/g, "{receptionist}");
|
|
84500
84573
|
if (!url)
|
|
84501
|
-
return message
|
|
84574
|
+
return omit(message, /\{receptionist\}/, /front desk|receptionist/i);
|
|
84502
84575
|
if (message.includes("{receptionist}"))
|
|
84503
84576
|
return message.replace(/\{receptionist\}/g, url);
|
|
84504
|
-
const line = `I've also set up
|
|
84577
|
+
const line = `I've also set up a virtual front desk for ${businessName ?? "you"}: it answers your calls when you can't${chatOn ? ", and questions on your website" : ""}, 24/7. You can try it here: ${url}`;
|
|
84505
84578
|
const lines = message.split("\n");
|
|
84506
84579
|
const at = lines.findIndex((l) => /https?:\/\//.test(l));
|
|
84507
84580
|
if (at < 0)
|
|
@@ -84525,6 +84598,23 @@ ${line}`;
|
|
|
84525
84598
|
return `(${d.slice(2, 5)}) ${d.slice(5, 8)}-${d.slice(8)}`;
|
|
84526
84599
|
return e164;
|
|
84527
84600
|
}
|
|
84601
|
+
function omit(message, placeholder, mention) {
|
|
84602
|
+
const blocks = message.split(/\n[ \t]*\n/);
|
|
84603
|
+
const drop = /* @__PURE__ */ new Set();
|
|
84604
|
+
blocks.forEach((b, i) => {
|
|
84605
|
+
if (!placeholder.test(b))
|
|
84606
|
+
return;
|
|
84607
|
+
const rest = b.replace(placeholder, "").trim();
|
|
84608
|
+
if (!rest || /:$/.test(rest)) {
|
|
84609
|
+
drop.add(i);
|
|
84610
|
+
if (!rest && i > 0 && /:\s*$/.test(blocks[i - 1]))
|
|
84611
|
+
drop.add(i - 1);
|
|
84612
|
+
} else {
|
|
84613
|
+
blocks[i] = b.split("\n").filter((line) => !placeholder.test(line)).join("\n");
|
|
84614
|
+
}
|
|
84615
|
+
});
|
|
84616
|
+
return blocks.filter((_, i) => !drop.has(i)).map((b) => b.split(/(?<=[.!?])\s+/).filter((sent) => !mention.test(sent)).join(" ") || "").filter((b) => b.trim()).join("\n\n");
|
|
84617
|
+
}
|
|
84528
84618
|
}
|
|
84529
84619
|
});
|
|
84530
84620
|
|
|
@@ -84715,6 +84805,7 @@ var require_receptionist = __commonJS({
|
|
|
84715
84805
|
exports2.listAll = listAll;
|
|
84716
84806
|
exports2.activateReceptionist = activateReceptionist;
|
|
84717
84807
|
exports2.forwardingSheet = forwardingSheet;
|
|
84808
|
+
exports2.setChat = setChat;
|
|
84718
84809
|
exports2.removeReceptionist = removeReceptionist;
|
|
84719
84810
|
var db_1 = require_db();
|
|
84720
84811
|
var agency_1 = require_agency();
|
|
@@ -84841,11 +84932,14 @@ ${source.slice(0, 6e4)}`
|
|
|
84841
84932
|
const { config, ownerEmail } = await buildConfig(leadId);
|
|
84842
84933
|
if (extra)
|
|
84843
84934
|
config.extra = extra;
|
|
84935
|
+
const site = (0, db_1.getDb)().get("SELECT site_url, domain_choice, domain_status FROM leads WHERE id = ?", [leadId]);
|
|
84936
|
+
const siteHosts = [site?.site_url, site?.domain_status === "bought" ? site.domain_choice : null].filter((h) => !!h);
|
|
84844
84937
|
const r = await api("POST", "/api/receptionists", {
|
|
84845
84938
|
leadRef: String(leadId),
|
|
84846
84939
|
config,
|
|
84847
84940
|
ownerEmail,
|
|
84848
|
-
prospectPhones: config.phone ? [config.phone] : []
|
|
84941
|
+
prospectPhones: config.phone ? [config.phone] : [],
|
|
84942
|
+
siteHosts
|
|
84849
84943
|
});
|
|
84850
84944
|
(0, db_1.getDb)().run("UPDATE leads SET receptionist_id = ?, receptionist_url = ?, receptionist_line = ?, receptionist_price_pence = COALESCE(receptionist_price_pence, 4900) WHERE id = ?", [r.receptionist.id, r.trialUrl, r.demoNumber, leadId]);
|
|
84851
84945
|
return { trialUrl: r.trialUrl, id: r.receptionist.id, demoNumber: r.demoNumber };
|
|
@@ -84878,6 +84972,10 @@ ${source.slice(0, 6e4)}`
|
|
|
84878
84972
|
}
|
|
84879
84973
|
return lines.join("\n");
|
|
84880
84974
|
}
|
|
84975
|
+
async function setChat(id, leadId, on) {
|
|
84976
|
+
await api("PATCH", `/api/receptionists/${id}`, { chatEnabled: on });
|
|
84977
|
+
(0, db_1.getDb)().run("UPDATE leads SET front_desk_chat = ? WHERE id = ?", [on ? 1 : 0, leadId]);
|
|
84978
|
+
}
|
|
84881
84979
|
async function removeReceptionist(id, leadId) {
|
|
84882
84980
|
await api("DELETE", `/api/receptionists/${id}`);
|
|
84883
84981
|
(0, db_1.getDb)().run("UPDATE leads SET receptionist_id = NULL, receptionist_url = NULL WHERE id = ?", [leadId]);
|
|
@@ -97710,6 +97808,7 @@ var require_chat_tools = __commonJS({
|
|
|
97710
97808
|
var lead_search_1 = require_lead_search();
|
|
97711
97809
|
var ai_search_1 = require_ai_search();
|
|
97712
97810
|
var pitch_text_1 = require_pitch_text();
|
|
97811
|
+
var outreach_template_1 = require_outreach_template();
|
|
97713
97812
|
var receptionist_1 = require_receptionist();
|
|
97714
97813
|
var places_1 = require_places();
|
|
97715
97814
|
var booking_detect_1 = require_booking_detect();
|
|
@@ -98215,19 +98314,7 @@ Want it live on your own domain?`;
|
|
|
98215
98314
|
}
|
|
98216
98315
|
function outreachTemplate(db2) {
|
|
98217
98316
|
const row = db2.get("SELECT value FROM settings WHERE key = ?", ["outreach_template"]);
|
|
98218
|
-
return row?.value ??
|
|
98219
|
-
|
|
98220
|
-
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
98221
|
-
|
|
98222
|
-
{site_url}
|
|
98223
|
-
|
|
98224
|
-
It's built from your real reviews and photos. If you like it, I can put it live on your own domain with your details for a one-off fee of \xA3199 \u2014 no monthly charges.
|
|
98225
|
-
|
|
98226
|
-
Would you be open to a quick chat this week?
|
|
98227
|
-
|
|
98228
|
-
Best regards
|
|
98229
|
-
|
|
98230
|
-
If you'd rather not hear from me again, just reply and let me know.`;
|
|
98317
|
+
return row?.value ?? outreach_template_1.OUTREACH_TEMPLATE;
|
|
98231
98318
|
}
|
|
98232
98319
|
function normaliseChannel(value) {
|
|
98233
98320
|
switch (String(value ?? "").toLowerCase()) {
|
|
@@ -98389,31 +98476,19 @@ If you'd rather not hear from me again, just reply and let me know.`;
|
|
|
98389
98476
|
const phone = (lead.phone ?? "").replace(/[^\d+]/g, "");
|
|
98390
98477
|
const e164 = phone.startsWith("+") ? phone : phone.startsWith("0") ? `+44${phone.slice(1)}` : phone;
|
|
98391
98478
|
const tplRow = db2.get("SELECT value FROM settings WHERE key = ?", ["outreach_template"]);
|
|
98392
|
-
const template = tplRow?.value ??
|
|
98393
|
-
|
|
98394
|
-
I came across {name} on Google and noticed you don't have a website yet, so I put together a free demo to show what one could look like:
|
|
98395
|
-
|
|
98396
|
-
{site_url}
|
|
98397
|
-
|
|
98398
|
-
It's built from your real reviews and photos. If you like it, I can put it live on your own domain with your details for a one-off fee of \xA3199 \u2014 no monthly charges.
|
|
98399
|
-
|
|
98400
|
-
Would you be open to a quick chat this week?
|
|
98401
|
-
|
|
98402
|
-
Best regards
|
|
98403
|
-
|
|
98404
|
-
If you'd rather not hear from me again, just reply and let me know.`;
|
|
98479
|
+
const template = tplRow?.value ?? outreach_template_1.OUTREACH_TEMPLATE;
|
|
98405
98480
|
const body = input.message ?? template.replace(/\{name\}/g, lead.name).replace(/\{site_url\}/g, lead.site_url ?? "");
|
|
98406
98481
|
const url = `https://wa.me/${e164.replace(/^\+/, "")}?text=${encodeURIComponent(body)}`;
|
|
98407
98482
|
return { url, message: body, phone: e164 };
|
|
98408
98483
|
}
|
|
98409
98484
|
case "prepare_outreach": {
|
|
98410
98485
|
const explicit = input.ids;
|
|
98411
|
-
const rows = explicit && explicit.length > 0 ? db2.all(`SELECT id, name, phone, email, address, city, site_url, lead_kind, booking_platform, booking_url, pitch_video_url, receptionist_url, receptionist_line FROM leads WHERE id IN (${explicit.map(() => "?").join(",")})`, explicit) : db2.all(
|
|
98486
|
+
const rows = explicit && explicit.length > 0 ? db2.all(`SELECT id, name, phone, email, address, city, site_url, lead_kind, booking_platform, booking_url, pitch_video_url, receptionist_url, receptionist_line, front_desk_chat FROM leads WHERE id IN (${explicit.map(() => "?").join(",")})`, explicit) : db2.all(
|
|
98412
98487
|
// Eligible = we have something to show them: either a demo site
|
|
98413
98488
|
// we built (site_url) OR a booking page we built (booking_url).
|
|
98414
98489
|
// Booking leads never get a site_url, so requiring it silently
|
|
98415
98490
|
// excluded every one-shot booking customer.
|
|
98416
|
-
"SELECT id, name, phone, email, address, city, site_url, lead_kind, booking_platform, booking_url, pitch_video_url, receptionist_url, receptionist_line FROM leads WHERE status IN ('site_built','discovered') AND ((site_url IS NOT NULL AND site_url != '') OR (booking_url IS NOT NULL AND booking_url != '')) ORDER BY score DESC NULLS LAST, id DESC",
|
|
98491
|
+
"SELECT id, name, phone, email, address, city, site_url, lead_kind, booking_platform, booking_url, pitch_video_url, receptionist_url, receptionist_line, front_desk_chat FROM leads WHERE status IN ('site_built','discovered') AND ((site_url IS NOT NULL AND site_url != '') OR (booking_url IS NOT NULL AND booking_url != '')) ORDER BY score DESC NULLS LAST, id DESC",
|
|
98417
98492
|
[]
|
|
98418
98493
|
);
|
|
98419
98494
|
const eligible = rows.filter((r) => r.site_url || r.booking_url);
|
|
@@ -98446,8 +98521,8 @@ If you'd rather not hear from me again, just reply and let me know.`;
|
|
|
98446
98521
|
}
|
|
98447
98522
|
let receptionistUrl = r.receptionist_url ?? null;
|
|
98448
98523
|
let receptionistLine = r.receptionist_line ?? null;
|
|
98449
|
-
if (!isBookingLead && !receptionistUrl && r.site_url && getDecryptedSetting("receptionist_auto")
|
|
98450
|
-
ctx.emitProgress?.({ channel: "outreach:progress", payload: { msg: `Setting up ${r.name}
|
|
98524
|
+
if (!isBookingLead && !receptionistUrl && r.site_url && getDecryptedSetting("receptionist_auto") !== "0") {
|
|
98525
|
+
ctx.emitProgress?.({ channel: "outreach:progress", payload: { msg: `Setting up Front Desk for ${r.name}\u2026` } });
|
|
98451
98526
|
try {
|
|
98452
98527
|
const t = await (0, receptionist_1.createTrial)(r.id);
|
|
98453
98528
|
receptionistUrl = t.trialUrl;
|
|
@@ -98456,7 +98531,7 @@ If you'd rather not hear from me again, just reply and let me know.`;
|
|
|
98456
98531
|
receptionistUrl = null;
|
|
98457
98532
|
}
|
|
98458
98533
|
}
|
|
98459
|
-
const message = (0, pitch_text_1.withVideo)((0, pitch_text_1.withReceptionist)((isBookingLead ? bookingTemplate : template).replace(/\{name\}/g, r.name).replace(/\{site_url\}/g, (isBookingLead ? r.booking_url : r.site_url) ?? r.site_url ?? "").replace(/\{booking_how\}/g, r.booking_platform || "WhatsApp/phone"), isBookingLead ? null : receptionistUrl, isBookingLead ? null : receptionistLine, r.name), isBookingLead ? null : videoUrl);
|
|
98534
|
+
const message = (0, pitch_text_1.withVideo)((0, pitch_text_1.withReceptionist)((isBookingLead ? bookingTemplate : template).replace(/\{name\}/g, r.name).replace(/\{site_url\}/g, (isBookingLead ? r.booking_url : r.site_url) ?? r.site_url ?? "").replace(/\{booking_how\}/g, r.booking_platform || "WhatsApp/phone"), isBookingLead ? null : receptionistUrl, isBookingLead ? null : receptionistLine, r.name, !!r.front_desk_chat), isBookingLead ? null : videoUrl);
|
|
98460
98535
|
const e164 = toE164(r.phone ?? "");
|
|
98461
98536
|
if (!r.email && smtp && (preferEmail || !e164)) {
|
|
98462
98537
|
ctx.emitProgress?.({
|
|
@@ -100467,7 +100542,7 @@ var require_package2 = __commonJS({
|
|
|
100467
100542
|
"package.json"(exports2, module2) {
|
|
100468
100543
|
module2.exports = {
|
|
100469
100544
|
name: "sproutkit-code",
|
|
100470
|
-
version: "1.
|
|
100545
|
+
version: "1.16.1",
|
|
100471
100546
|
description: "Sproutkit in your terminal \u2014 find leads, build sites, run outreach, all via chat.",
|
|
100472
100547
|
bin: {
|
|
100473
100548
|
sproutkit: "./dist/index.js"
|