/ scripts / strip-sms-optout.mjs
strip-sms-optout.mjs
 1  /**
 2   * Strip opt-out spintax from SMS templates for countries where it's not legally required.
 3   * Required (keep opt-out): US, CA, KR
 4   * Not required (remove opt-out): everything else
 5   */
 6  import { readFileSync, writeFileSync } from 'node:fs';
 7  import { resolve, dirname } from 'node:path';
 8  import { fileURLToPath } from 'node:url';
 9  
10  const __dirname = dirname(fileURLToPath(import.meta.url));
11  const root = resolve(__dirname, '..');
12  
13  const requirements = JSON.parse(
14    readFileSync(resolve(root, 'data/compliance/requirements.json'), 'utf8')
15  );
16  
17  // Countries where opt-out IS required in body
18  const REQUIRED = new Set(
19    Object.entries(requirements)
20      .filter(([k, v]) => !k.startsWith('_') && v?.sms?.requiresOptOutInBody === true)
21      .map(([k]) => k)
22  );
23  
24  console.log('Opt-out REQUIRED (keep):', [...REQUIRED].join(', '));
25  
26  // All SMS template files
27  const SMS_FILES = [
28    { country: 'AU', file: 'data/templates/AU/sms.json' },
29    { country: 'NZ', file: 'data/templates/NZ/sms.json' },
30    { country: 'GB', file: 'data/templates/GB/sms.json' },
31    { country: 'IE', file: 'data/templates/IE/sms.json' },
32    { country: 'CA', file: 'data/templates/CA/sms.json' },
33    { country: 'US', file: 'data/templates/US/sms.json' },
34    { country: 'IN', file: 'data/templates/IN/sms.json' },
35    { country: 'IN', file: 'data/templates/IN/hi/sms.json' },
36    { country: 'JP', file: 'data/templates/JP/ja/sms.json' },
37    { country: 'KR', file: 'data/templates/KR/ko/sms.json' },
38    { country: 'DE', file: 'data/templates/DE/de/sms.json' },
39    { country: 'FR', file: 'data/templates/FR/fr/sms.json' },
40    { country: 'IT', file: 'data/templates/IT/it/sms.json' },
41    { country: 'MX', file: 'data/templates/MX/es/sms.json' },
42    { country: 'NL', file: 'data/templates/NL/nl/sms.json' },
43    { country: 'SE', file: 'data/templates/SE/sv/sms.json' },
44    { country: 'DK', file: 'data/templates/DK/da/sms.json' },
45    { country: 'PL', file: 'data/templates/PL/pl/sms.json' },
46    { country: 'ID', file: 'data/templates/ID/id/sms.json' },
47    { country: 'ZA', file: 'data/templates/ZA/sms.json' },
48  ];
49  
50  // Matches trailing opt-out spintax: a space + {options containing STOP or stop}
51  // The opt-out block is always the last {...} group in the body_spintax
52  const OPT_OUT_RE = /\s+\{[^{}]*(?:STOP|stop|停止|거부)[^{}]*\}$/u;
53  
54  let changed = 0;
55  let skipped = 0;
56  
57  for (const { country, file } of SMS_FILES) {
58    const filePath = resolve(root, file);
59  
60    if (REQUIRED.has(country)) {
61      console.log(`[${country}] SKIP — opt-out required`);
62      skipped++;
63      continue;
64    }
65  
66    const data = JSON.parse(readFileSync(filePath, 'utf8'));
67    let modified = false;
68  
69    for (const tmpl of data.templates) {
70      const orig = tmpl.body_spintax;
71      const stripped = orig.replace(OPT_OUT_RE, '').trimEnd();
72      if (stripped !== orig) {
73        tmpl.body_spintax = stripped;
74        modified = true;
75        console.log(`  [${country}] ${tmpl.id}: removed opt-out`);
76      } else {
77        console.log(`  [${country}] ${tmpl.id}: no opt-out found`);
78      }
79    }
80  
81    if (modified) {
82      writeFileSync(filePath, `${JSON.stringify(data, null, ' ')}\n`, 'utf8');
83      changed++;
84    }
85  }
86  
87  console.log(`\nDone. ${changed} files modified, ${skipped} skipped (opt-out required).`);