<!DOCTYPE html>
<html lang="bn">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BD Number Format Checker + Old Robi Series Generator</title>
<style>
:root{--bg:#0b1222;--card:#111827;--muted:#94a3b8;--txt:#e5e7eb;--accent:#22c55e;--accent2:#3b82f6}
*{box-sizing:border-box}
body{margin:0;font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial;background:linear-gradient(180deg,#0b1222,#0f172a);color:var(--txt)}
.wrap{max-width:1100px;margin:24px auto;padding:16px}
.card{background:rgba(17,24,39,.85);border:1px solid rgba(148,163,184,.25);backdrop-filter:blur(6px);border-radius:18px;padding:20px;box-shadow:0 10px 30px rgba(0,0,0,.35)}
h1{font-size:26px;margin:0 0 6px}
h2{font-size:18px;margin:18px 0 10px;color:#d1d5db}
p, label, small{color:var(--muted)}
.grid{display:grid;gap:12px}
@media(min-width:960px){.grid.cols-2{grid-template-columns:1fr 1fr}}
@media(min-width:960px){.grid.cols-3{grid-template-columns:1.1fr .9fr .9fr}}
.row{display:flex;gap:10px;flex-wrap:wrap}
input, textarea, select{width:100%;padding:12px 14px;border-radius:12px;border:1px solid rgba(148,163,184,.25);background:#0b1020;color:var(--txt);outline:none}
input:focus, textarea:focus, select:focus{border-color:var(--accent2)}
textarea{min-height:160px;resize:vertical}
.btn{padding:11px 14px;border-radius:12px;border:1px solid rgba(148,163,184,.25);background:#0b1020;color:var(--txt);cursor:pointer;transition:.2s}
.btn:hover{transform:translateY(-1px)}
.btn.primary{background:linear-gradient(135deg,#22c55e,#16a34a);border:none;color:white}
.btn.ghost{background:#0b1020}
.btn.warn{background:linear-gradient(135deg,#ef4444,#dc2626);border:none;color:white}
.muted{color:var(--muted)}
.badge{display:inline-block;padding:6px 10px;border-radius:999px;background:#0b1020;border:1px solid rgba(148,163,184,.25);color:var(--muted);font-size:12px}
.panel{border:1px solid rgba(148,163,184,.25);border-radius:14px;padding:12px;background:#0b1020}
.listbox{min-height:220px}
.stats{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}
@media(min-width:720px){.stats{grid-template-columns:repeat(4,1fr)}}
.kpi{background:#0b1020;border:1px solid rgba(148,163,184,.25);border-radius:14px;padding:10px}
.kpi b{font-size:18px;color:#fff}
table{width:100%;border-collapse:collapse}
th, td{border-bottom:1px solid rgba(148,163,184,.18);padding:8px 6px;text-align:left;font-size:14px}
th{color:#cbd5e1}
.footer{margin-top:10px;color:var(--muted);font-size:12px}
</style>
</head>
<body>
<div class="wrap">
<div class="card">
<h1>Bangladesh Number Format Checker + Old Robi Series Generator</h1>
<p>এই টুলটি <b>ফরম্যাট চেক</b> ও <b>পুরনো সিরিজ থেকে ডেমো নম্বর জেনারেট</b> করার জন্য। এটি <b>ফেসবুকে আছে/নেই</b> এমন কোনো তথ্য <u>চেক করে না</u> এবং <u>করতে পারবে না</u>। প্রাইভেসি রুলস অনুযায়ী এটা অনুমোদিত নয়।</p>
<div class="grid cols-2">
<!-- LEFT: VALIDATOR -->
<div class="panel">
<h2>1) নম্বর ফরম্যাট চেক</h2>
<label for="numbers">নিচে নাম্বার দিন (এক লাইন = এক নাম্বার)। +88 / 88 / 0 — সবই অটো-নরমালাইজ হবে:</label>
<textarea id="numbers" placeholder="01893123456\n+8801893123456\n8801893123456\n01612345678"></textarea>
<div class="row" style="margin-top:10px">
<input type="file" id="csvFile" accept=".csv,.txt" />
<button class="btn ghost" id="loadCsv">CSV লোড</button>
<button class="btn primary" id="validate">Validate</button>
<button class="btn ghost" id="copyValid">Copy Valid</button>
<button class="btn ghost" id="exportValid">Export Valid CSV</button>
<button class="btn warn" id="clearAll">Clear</button>
</div>
<div class="stats" style="margin-top:12px">
<div class="kpi"><div class="muted">মোট ইনপুট</div><b id="k_total">0</b></div>
<div class="kpi"><div class="muted">ভ্যালিড</div><b id="k_valid">0</b></div>
<div class="kpi"><div class="muted">ইনভ্যালিড</div><b id="k_invalid">0</b></div>
<div class="kpi"><div class="muted">ডুপ্লিকেট বাদ</div><b id="k_dedup">0</b></div>
</div>
<h3 style="margin-top:14px;color:#d1d5db">ভ্যালিড নাম্বার (নরমালাইজড)</h3>
<textarea id="validOut" class="listbox" placeholder="ভ্যালিড নাম্বার এখানে..."></textarea>
<h3 style="margin-top:14px;color:#d1d5db">ইনভ্যালিড / কারণ</h3>
<div class="panel" style="max-height:200px;overflow:auto;background:#0b1026">
<table id="badTable">
<thead><tr><th>ইনপুট</th><th>কারণ</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
<!-- RIGHT: GENERATOR -->
<div class="panel">
<h2>2) Old Robi Series Generator (Demo)</h2>
<label>সিরিজ সিলেক্ট করুন (ডিফল্ট পুরনো সিরিজ):</label>
<select id="series" multiple size="7">
<option value="01819" selected>01819 (Robi – old)</option>
<option value="01820">01820 (Robi)</option>
<option value="01821">01821 (Robi)</option>
<option value="01822">01822 (Robi)</option>
<option value="01892" selected>01892 (Robi – old)</option>
<option value="01893" selected>01893 (Robi – old)</option>
<option value="016">016 (Airtel BD)</option>
</select>
<div class="grid cols-3" style="margin-top:10px">
<div>
<label for="g_count">কতটি?</label>
<input id="g_count" type="number" min="1" max="100000" value="500" />
</div>
<div>
<label for="g_len">মোট ডিজিট</label>
<input id="g_len" type="number" min="7" max="15" value="11" />
</div>
<div>
<label for="g_dash">ফরম্যাট</label>
<select id="g_dash">
<option value="none" selected>018931234567</option>
<option value="dash">01893-1234567</option>
<option value="space">01893 1234567</option>
</select>
</div>
</div>
<div class="row" style="margin-top:10px">
<button class="btn primary" id="gen">Generate</button>
<button class="btn ghost" id="copyGen">Copy</button>
<button class="btn ghost" id="exportGen">Export CSV</button>
<span class="badge" id="g_stats">Ready</span>
</div>
<textarea id="genOut" class="listbox" placeholder="জেনারেটেড নাম্বার এখানে..."></textarea>
<div class="footer">
নোট: এগুলো <b>শুধু ডেমো</b> নম্বর। এগুলো কারো সঙ্গে যোগাযোগ/ভেরিফিকেশন চেষ্টা করবেন না।
</div>
</div>
</div>
<div class="footer" style="margin-top:14px">
⚠️ ডিসক্লেমার: এই টুল কোনোভাবেই Facebook/কোনো সার্ভিসে নাম্বার মিলিয়ে দেখার চেষ্টা করে না। এমন চেষ্টা করা প্রাইভেসি ও টার্মস ভায়োলেশন।
</div>
</div>
</div>
<script>
// ------- Utils -------
const $ = id => document.getElementById(id);
const OPERATORS = {
'013':'Grameenphone','017':'Grameenphone',
'014':'Banglalink','019':'Banglalink',
'015':'Teletalk',
'016':'Airtel',
'018':'Robi'
};
function normalizeOne(input){
const raw = String(input).trim();
if(!raw) return null;
// keep digits only
let d = raw.replace(/\D/g,'');
// Remove leading country code 880 or +880
if(d.startsWith('880')) d = d.slice(3);
// Ensure leading 0 for local format
if(d.length === 10 && !d.startsWith('0')) d = '0' + d;
// Final checks
if(d.length !== 11) return {ok:false, value:raw, reason:'ডিজিট ১১ না'};
const op = d.slice(0,3);
if(!OPERATORS[op]) return {ok:false, value:raw, reason:'অকার্যকর প্রিফিক্স'};
return {ok:true, value:d, operator:OPERATORS[op]};
}
function parseLines(text){
return text.split(/\r?\n/).map(s=>s.trim()).filter(Boolean);
}
function downloadCSV(filename, rows){
const blob = new Blob([rows.join('\n')], {type:'text/csv;charset=utf-8;'});
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
// ------- Validator -------
$('loadCsv').addEventListener('click', ()=>{
const file = $('csvFile').files?.[0];
if(!file) return alert('CSV বা TXT ফাইল সিলেক্ট করুন');
const fr = new FileReader();
fr.onload = () => { $('numbers').value = String(fr.result||''); };
fr.readAsText(file);
});
$('validate').addEventListener('click', ()=>{
const lines = parseLines($('numbers').value);
const badBody = $('badTable').querySelector('tbody');
badBody.innerHTML = '';
const validSet = new Set();
const seen = new Set();
let invalid = 0;
let dedup = 0;
for(const line of lines){
if(seen.has(line)) { dedup++; continue; }
seen.add(line);
const res = normalizeOne(line);
if(!res || !res.ok){
invalid++;
const tr = document.createElement('tr');
const td1 = document.createElement('td'); td1.textContent = line;
const td2 = document.createElement('td'); td2.textContent = res? res.reason : 'খালি লাইন';
tr.append(td1, td2); badBody.appendChild(tr);
} else {
validSet.add(res.value);
}
}
$('k_total').textContent = lines.length.toLocaleString();
$('k_valid').textContent = validSet.size.toLocaleString();
$('k_invalid').textContent = invalid.toLocaleString();
$('k_dedup').textContent = dedup.toLocaleString();
$('validOut').value = Array.from(validSet).join('\n');
});
$('copyValid').addEventListener('click', async ()=>{
const val = $('validOut').value.trim();
if(!val) return;
try{ await navigator.clipboard.writeText(val); alert('Copied valid numbers'); }
catch{ alert('Copy failed'); }
});
$('exportValid').addEventListener('click', ()=>{
const val = $('validOut').value.trim();
if(!val) return;
const rows = ['number'];
for(const n of val.split(/\n+/)) rows.push(n);
downloadCSV(`valid_numbers_${Date.now()}.csv`, rows);
});
$('clearAll').addEventListener('click', ()=>{
$('numbers').value=''; $('validOut').value='';
$('k_total').textContent='0'; $('k_valid').textContent='0'; $('k_invalid').textContent='0'; $('k_dedup').textContent='0';
$('badTable').querySelector('tbody').innerHTML='';
});
// ------- Generator -------
function pad(num, size){ let s=String(num); while(s.length<size) s='0'+s; return s; }
function mulberry32(a){return function(){let t=a+=0x6D2B79F5; t=Math.imul(t^t>>>15,t|1); t^=t+Math.imul(t^t>>>7,t|61); return ((t^t>>>14)>>>0)/4294967296;}}
$('gen').addEventListener('click', ()=>{
const opts = Array.from($('series').selectedOptions).map(o=>o.value);
if(opts.length===0) return alert('কমপক্ষে একটি সিরিজ সিলেক্ট করুন');
const totalLen = Math.max(7, Math.min(15, parseInt($('g_len').value||'11',10)));
const count = Math.max(1, Math.min(100000, parseInt($('g_count').value||'1000',10)));
const fmt = $('g_dash').value;
const rng = mulberry32(Date.now() & 0xffffffff);
const out = [];
const perSeries = Math.ceil(count / opts.length);
for(const prefix of opts){
const p = prefix.replace(/\D/g,'');
const remain = totalLen - p.length;
if(remain <= 0) continue;
const maxComb = Math.pow(10, remain);
const needed = Math.min(perSeries, maxComb);
const set = new Set();
while(set.size < needed){
set.add(pad(Math.floor(rng()*maxComb), remain));
}
for(const tail of set){
let n = p + tail;
if(fmt==='dash') n = n.slice(0,p.length)+'-'+n.slice(p.length);
else if(fmt==='space') n = n.slice(0,p.length)+' '+n.slice(p.length);
out.push(n);
}
}
$('genOut').value = out.slice(0, count).join('\n');
$('g_stats').textContent = `Generated ${Math.min(count,out.length).toLocaleString()} numbers`;
});
$('copyGen').addEventListener('click', async ()=>{
const val = $('genOut').value.trim(); if(!val) return;
try{ await navigator.clipboard.writeText(val); alert('Copied'); } catch{ alert('Copy failed'); }
});
$('exportGen').addEventListener('click', ()=>{
const val = $('genOut').value.trim(); if(!val) return;
const rows = ['number']; for(const n of val.split(/\n+/)) rows.push(n.replace(/\s|-/g,''));
downloadCSV(`generated_${Date.now()}.csv`, rows);
});
</script>
</body>
</html>
Comments
Post a Comment