← back to Designer Wallcoverings
mailers/cc-api/build-koroseal-campaign.js
135 lines
'use strict';
/**
* build-hollywood-campaign.js — Designer Wallcoverings
* A DUPLICATE of build-pr-naturals-campaign.js (same validation + create path),
* pointed at ../hollywood-launch.html. Promotes this week's storewide New Arrivals.
*
* --dry-run (DEFAULT): prints payload + validation checklist. NO network.
* --confirm : creates the DRAFT campaign — STILL double-gated by
* CC_LIVE === '1' inside cc-client. Creating a DRAFT
* does NOT send; scheduling/sending is a separate gate.
*/
const fs = require('fs');
const path = require('path');
const cc = require('./cc-client');
const MAILER = path.join(__dirname, '..', 'koroseal-commercial-launch.html');
const argv = process.argv.slice(2);
const CONFIRM = argv.includes('--confirm');
const DRY_RUN = argv.includes('--dry-run') || !CONFIRM; // default dry-run
const CAMPAIGN = {
name: `Koroseal Commercial Wallcoverings — ${new Date().toISOString().slice(0, 10)}`,
subject: 'New: Koroseal Commercial Wallcoverings — contract-grade Type II vinyl',
preheader: 'Durable, scrubbable, Class A fire-rated wallcoverings for hospitality, healthcare & corporate interiors. Order swatches today.',
fromName: 'Designer Wallcoverings',
fromEmail: 'steve@designerwallcoverings.com',
replyTo: 'steve@designerwallcoverings.com',
physicalAddress: {
address_line1: '15442 Ventura Bl',
city: 'Sherman Oaks',
state_code: 'CA',
postal_code: '91403',
country_code: 'US',
},
};
const PLACEHOLDER_ADDRESS_MARKER = '15442 Ventura Boulevard #102';
function loadHtml() {
if (!fs.existsSync(MAILER)) throw new Error(`mailer not found: ${MAILER}`);
return fs.readFileSync(MAILER, 'utf8');
}
function extractImageSrcs(html) {
const srcs = []; const re = /<img\b[^>]*?\bsrc\s*=\s*(["'])(.*?)\1/gi; let m;
while ((m = re.exec(html)) !== null) srcs.push(m[2]);
return srcs;
}
const isAbsoluteHttps = (u) => /^https:\/\//i.test(u);
const unhostedLogoSrcs = (srcs) => srcs.filter((s) => /\/vendor-logos\//i.test(s));
function visibleWallpaperHits(html) {
const hits = [];
const noComments = html.replace(/<!--[\s\S]*?-->/g, '');
const altRe = /\balt\s*=\s*(["'])(.*?)\1/gi; let m;
while ((m = altRe.exec(noComments)) !== null) if (/\bwallpapers?\b/i.test(m[2])) hits.push(`alt: "${m[2]}"`);
const textOnly = noComments.replace(/<[^>]+>/g, ' ');
for (const t of (textOnly.match(/\bwallpapers?\b/gi) || [])) hits.push(`visible text: "${t}"`);
return hits;
}
function runChecklist(html) {
const results = []; const add = (name, pass, detail) => results.push({ name, pass, detail });
add('subject set', !!CAMPAIGN.subject && CAMPAIGN.subject.trim().length > 0, CAMPAIGN.subject);
add('from name + email set', !!CAMPAIGN.fromName && !!CAMPAIGN.fromEmail && CAMPAIGN.fromEmail.includes('@'), `${CAMPAIGN.fromName} <${CAMPAIGN.fromEmail}>`);
add('reply-to set', !!CAMPAIGN.replyTo && CAMPAIGN.replyTo.includes('@'), CAMPAIGN.replyTo);
const addr = CAMPAIGN.physicalAddress || {};
const addrComplete = !!(addr.address_line1 && addr.city && addr.state_code && addr.postal_code && addr.country_code);
const addrIsPlaceholder = (addr.address_line1 || '').includes(PLACEHOLDER_ADDRESS_MARKER);
add('physical address complete', addrComplete, JSON.stringify(addr));
add('physical address non-placeholder', addrComplete && !addrIsPlaceholder, addrIsPlaceholder ? 'matches placeholder marker' : 'confirmed non-placeholder');
add('html content non-empty', !!html && html.length > 200, `${html.length} bytes`);
const bannedHits = visibleWallpaperHits(html);
add('no banned word "Wallpaper" (visible copy + alt)', bannedHits.length === 0, bannedHits.length ? `found:\n - ${bannedHits.join('\n - ')}` : 'clean (alt + visible text)');
const srcs = extractImageSrcs(html);
const nonHttps = srcs.filter((s) => !isAbsoluteHttps(s));
add('all image src absolute https', nonHttps.length === 0, nonHttps.length ? `${nonHttps.length}/${srcs.length} not absolute-https` : `${srcs.length}/${srcs.length} absolute-https`);
const unhosted = unhostedLogoSrcs(srcs);
add('logos hosted at public https (not the un-hosted /vendor-logos/ path)', unhosted.length === 0, unhosted.length ? `${unhosted.length} on un-hosted path` : 'all logos on a confirmed-live host');
return results;
}
function buildPayload(html) {
return {
name: CAMPAIGN.name,
email_campaign_activities: [{
format_type: 5,
from_name: CAMPAIGN.fromName,
from_email: CAMPAIGN.fromEmail,
reply_to_email: CAMPAIGN.replyTo,
subject: CAMPAIGN.subject,
preheader: CAMPAIGN.preheader,
html_content: html,
physical_address_in_footer: CAMPAIGN.physicalAddress,
}],
};
}
async function main() {
const html = loadHtml();
console.log('='.repeat(72));
console.log('New Arrivals Weekly → Constant Contact v3 campaign builder');
console.log(`mode: ${CONFIRM ? '--confirm' : '--dry-run (default)'} CC_LIVE=${process.env.CC_LIVE === '1' ? '1' : '(unset)'}`);
console.log('='.repeat(72));
const payload = buildPayload(html);
const printable = JSON.parse(JSON.stringify(payload));
printable.email_campaign_activities[0].html_content = `<<${html.length} bytes of HTML — truncated>>\n` + html.slice(0, 300) + '\n…';
console.log('\n--- CREATE-CAMPAIGN PAYLOAD (html_content truncated) ---');
console.log(JSON.stringify(printable, null, 2));
console.log('\n--- VALIDATION CHECKLIST ---');
const results = runChecklist(html); let failed = 0;
for (const r of results) { const mark = r.pass ? 'PASS' : 'FAIL'; if (!r.pass) failed++; console.log(` [${mark}] ${r.name}`); if (r.detail) console.log(` ${r.detail}`); }
console.log(`\n ${results.length - failed}/${results.length} checks passed, ${failed} failed.`);
if (DRY_RUN) {
console.log('\nDRY-RUN: no network call made. (default)');
process.exitCode = failed > 0 ? 2 : 0;
return;
}
if (failed > 0) { console.log('\nREFUSING to create: validation has FAILs.'); process.exitCode = 2; return; }
console.log('\n--confirm + validation clean → creating DRAFT (NO-OPs unless CC_LIVE=1):');
const activityId = await cc.createCustomCodeCampaign({
name: CAMPAIGN.name, subject: CAMPAIGN.subject, preheader: CAMPAIGN.preheader,
fromEmail: CAMPAIGN.fromEmail, fromName: CAMPAIGN.fromName, replyTo: CAMPAIGN.replyTo,
htmlContent: html, physicalAddress: CAMPAIGN.physicalAddress, confirm: true,
});
console.log('result:', activityId);
}
main().catch((e) => { console.error('[build-new-arrivals] ERROR:', e.message); process.exitCode = 1; });