<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CP Digital SMS/RVM Engine</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; padding: 20px; color: #333; }
.container { max-width: 1000px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); overflow: hidden; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 30px; text-align: center; }
.header h1 { font-size: 2.5em; margin-bottom: 10px; font-weight: 700; }
.header p { font-size: 1.1em; opacity: 0.9; }
.domain-badge { display: inline-block; background: rgba(255, 255, 255, 0.2); padding: 8px 16px; border-radius: 20px; margin-top: 15px; font-size: 0.9em; backdrop-filter: blur(10px); }
.content { padding: 40px 30px; }
.section { margin-bottom: 35px; padding: 25px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #667eea; }
.section h2 { font-size: 1.3em; margin-bottom: 20px; color: #667eea; display: flex; align-items: center; gap: 10px; }
.section-number { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: #667eea; color: white; border-radius: 50%; font-weight: bold; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 8px; font-weight: 600; color: #333; }
input[type="text"], input[type="file"], textarea, select { width: 100%; padding: 12px 14px; border: 2px solid #e0e0e0; border-radius: 6px; font-size: 0.95em; font-family: inherit; transition: border-color 0.3s; }
input[type="text"]:focus, textarea:focus, select:focus { outline: none; border-color: #667eea; box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); }
textarea { resize: vertical; min-height: 100px; font-family: 'Monaco', 'Courier New', monospace; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.checkbox-group { display: flex; align-items: center; gap: 10px; padding: 15px; background: white; border-radius: 6px; border: 2px solid #e0e0e0; cursor: pointer; }
input[type="checkbox"] { width: 20px; height: 20px; cursor: pointer; accent-color: #667eea; }
.badge { display: inline-block; background: #10b981; color: white; padding: 4px 10px; border-radius: 12px; font-size: 0.75em; font-weight: 600; }
button { padding: 14px 24px; font-size: 1em; font-weight: 600; border: none; border-radius: 6px; cursor: pointer; transition: all 0.3s; }
.btn-send { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; width: 100%; }
.btn-send:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3); }
.counter { margin-top: 10px; padding: 10px 14px; background: white; border-left: 3px solid #667eea; border-radius: 4px; font-size: 0.9em; color: #667eea; font-weight: 500; }
.results-section { background: white; border: 2px solid #e0e0e0; border-radius: 8px; }
.results-header { background: #f8f9fa; padding: 15px 20px; border-bottom: 2px solid #e0e0e0; display: flex; justify-content: space-between; align-items: center; }
.copy-btn { background: #e0e0e0; color: #333; padding: 6px 12px; font-size: 0.8em; border-radius: 4px; }
.copy-btn:hover { background: #667eea; color: white; }
#resultsWindow { background: #1e1e1e; color: #00ff00; padding: 20px; font-family: 'Monaco', 'Courier New', monospace; font-size: 0.85em; line-height: 1.6; margin: 0; min-height: 150px; max-height: 400px; overflow-y: auto; white-space: pre-wrap; word-wrap: break-word; }
.info-box { background: #dbeafe; border-left: 4px solid #3b82f6; padding: 15px; border-radius: 4px; margin-bottom: 20px; font-size: 0.9em; color: #1e40af; }
.footer { background: #f8f9fa; padding: 20px 30px; text-align: center; font-size: 0.85em; color: #666; border-top: 1px solid #e0e0e0; }
@media (max-width: 768px) { .row { grid-template-columns: 1fr; } .header h1 { font-size: 1.8em; } }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📱 CP Digital SMS/RVM Engine</h1>
<p>Bulk SMS & Robotic Voice Message Sender</p>
<div class="domain-badge">Domain: <strong>cp-digital.online</strong></div>
</div>
<div class="content">
<div class="section">
<h2><span class="section-number">1</span> Load Phone Numbers</h2>
<div class="info-box">📌 Upload CSV or paste numbers (one per line)</div>
<div class="form-group">
<label for="csvFile">📁 Upload CSV File</label>
<input type="file" id="csvFile" accept=".csv" />
</div>
<div class="form-group">
<label for="numbersTextarea">Or paste numbers</label>
<textarea id="numbersTextarea" placeholder="+15550000001 +15550000002 +15550000003"></textarea>
<div class="counter">Total: <strong id="numbersCount">0</strong></div>
</div>
</div>
<div class="section">
<h2><span class="section-number">2</span> Configure Message</h2>
<div class="row">
<div class="form-group">
<label for="modeSelect">📢 Mode</label>
<select id="modeSelect">
<option value="sms">SMS (Text)</option>
<option value="rvm">RVM (Voice)</option>
</select>
</div>
<div class="form-group">
<label for="providerSelect">🔗 Provider</label>
<select id="providerSelect">
<option value="telnyx">Telnyx</option>
<option value="dropcowboy">DropCowboy</option>
<option value="both">Both</option>
</select>
</div>
</div>
<div class="form-group">
<label for="fromNumber">📞 From (optional)</label>
<input type="text" id="fromNumber" placeholder="+15551234567" />
</div>
<div class="form-group">
<label for="messageInput">✉️ Message</label>
<textarea id="messageInput" placeholder="Your message here"></textarea>
</div>
<div class="form-group">
<div class="checkbox-group">
<input type="checkbox" id="testMode" checked />
<label for="testMode" style="margin: 0; cursor: pointer;">🧪 Test Mode <span class="badge">SAFE</span></label>
</div>
</div>
</div>
<div class="section">
<button id="sendButton" class="btn-send">✈️ Send Messages</button>
</div>
<div class="section">
<h2><span class="section-number">3</span> Response</h2>
<div class="results-section">
<div class="results-header">
<h3>📊 JSON</h3>
<button class="copy-btn" id="copyBtn">📋 Copy</button>
</div>
<pre id="resultsWindow">{ "status": "idle" }</pre>
</div>
</div>
</div>
<div class="footer">
<p>CP Digital SMS/RVM Engine | Cloudflare Workers & Pages</p>
<p style="margin-top: 8px; opacity: 0.7;">Worker: cp-digital-sms-engine.tanmc301.workers.dev</p>
</div>
</div>
<script>
const WORKER_URL = 'https://cp-digital-sms-engine.tanmc301.workers.dev';
const el = {
csvFile: document.getElementById('csvFile'),
numbersTextarea: document.getElementById('numbersTextarea'),
numbersCount: document.getElementById('numbersCount'),
modeSelect: document.getElementById('modeSelect'),
providerSelect: document.getElementById('providerSelect'),
fromNumber: document.getElementById('fromNumber'),
messageInput: document.getElementById('messageInput'),
testMode: document.getElementById('testMode'),
sendButton: document.getElementById('sendButton'),
resultsWindow: document.getElementById('resultsWindow'),
copyBtn: document.getElementById('copyBtn')
};
let numbers = [];
function updateCount() { el.numbersCount.textContent = numbers.length; }
function parseNumbers(text) { return text.split(/\r?\n/).map(l => l.trim()).filter(l => l.length > 0); }
el.numbersTextarea.addEventListener('input', () => { numbers = parseNumbers(el.numbersTextarea.value); updateCount(); });
el.csvFile.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = () => {
const lines = reader.result.split(/\r?\n/).map(l => l.trim()).filter(Boolean);
let parsed = [];
const firstLine = lines[0].split(',');
const idx = firstLine.findIndex(c => c.toLowerCase() === 'number');
if (idx >= 0) {
for (let i = 1; i < lines.length; i++) {
const cols = lines[i].split(',');
if (cols[idx]) parsed.push(cols[idx].trim());
}
} else {
parsed = lines;
}
numbers = parsed;
el.numbersTextarea.value = parsed.join('\n');
updateCount();
};
reader.readAsText(file);
});
el.copyBtn.addEventListener('click', () => {
navigator.clipboard.writeText(el.resultsWindow.textContent);
el.copyBtn.textContent = '✓ Copied!';
setTimeout(() => el.copyBtn.textContent = '📋 Copy', 2000);
});
el.sendButton.addEventListener('click', async () => {
if (numbers.length === 0) { alert('No numbers loaded'); return; }
if (!el.messageInput.value.trim()) { alert('Message required'); return; }
el.sendButton.disabled = true;
el.resultsWindow.textContent = 'Sending...';
const payload = {
mode: el.modeSelect.value,
provider: el.providerSelect.value,
from: el.fromNumber.value.trim() || undefined,
numbers: numbers,
message: el.messageInput.value,
test: el.testMode.checked
};
try {
const res = await fetch(WORKER_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const data = await res.json();
el.resultsWindow.textContent = JSON.stringify({ status: res.status, response: data }, null, 2);
} catch (err) {
el.resultsWindow.textContent = JSON.stringify({ error: err.message }, null, 2);
} finally {
el.sendButton.disabled = false;
}
});
</script>
</body>
</html>