diff --git a/app/beauty_main.py b/app/beauty_main.py index 1d82c1e..54d4aeb 100644 --- a/app/beauty_main.py +++ b/app/beauty_main.py @@ -188,6 +188,26 @@ async def validator_status(): # ── Pre-screen (shared) ─────────────────────────────────────────────────────── +@app.post("/api/validate/batch") +async def validate_batch(body: dict): + """HTTP-check only — no DeepSeek classification. Fast live/dead check for bulk selection.""" + domains_list = body.get("domains", []) + if not domains_list: + return JSONResponse({"error": "no domains provided"}, status_code=400) + if len(domains_list) > 500: + return JSONResponse({"error": "max 500 per batch"}, status_code=400) + from app.prescreener import prescreen_domains + results = await prescreen_domains(domains_list) + await save_prescreen_results(results) + counts: dict = {} + for r in results: + s = r.get("prescreen_status", "dead") + counts[s] = counts.get(s, 0) + 1 + return {"total": len(domains_list), "live": counts.get("live", 0), + "dead": counts.get("dead", 0), "parked": counts.get("parked", 0), + "redirect": counts.get("redirect", 0), "error": counts.get("error", 0)} + + @app.post("/api/prescreen/batch") async def prescreen_batch(body: dict): domains_list = body.get("domains", []) diff --git a/app/static/beauty/index.html b/app/static/beauty/index.html index 87eeb8c..3b88147 100644 --- a/app/static/beauty/index.html +++ b/app/static/beauty/index.html @@ -145,6 +145,12 @@ textarea{width:100%;resize:vertical;font-family:monospace;font-size:12px} Landing Page + + Alpha only + + + No SLD + 50 100 @@ -159,6 +165,10 @@ textarea{width:100%;resize:vertical;font-family:monospace;font-size:12px} + + Validate Selected + Validating… + Pre-screen Selected Screening… @@ -430,10 +440,10 @@ function app() { valSt: {running:false,processed:0,live:0,dead:0,error:0,parked:0,redirect:0,skipped:0,offset:0,rate:0}, valTld: '', valRescan: false, toasts: [], - prescreening: false, + prescreening: false, validating: false, exportQuality: '', exportCountry: '', f: {keyword:'', tld:'', prescreen_status:'live', niche:'beauty_cosmetics', - site_type:'ecommerce', country:'', limit:'100', page:1}, + site_type:'ecommerce', country:'', alpha_only:false, no_sld:false, limit:'100', page:1}, pf: {quality:'', country:'', limit:'100', page:1}, async init() { @@ -478,8 +488,10 @@ function app() { this.loading = true; try { const p = new URLSearchParams({page: this.f.page, limit: this.f.limit}); - if (this.f.keyword) p.set('keyword', this.f.keyword.trim()); - if (this.f.tld) p.set('tld', this.f.tld.trim()); + if (this.f.keyword) p.set('keyword', this.f.keyword.trim()); + if (this.f.tld) p.set('tld', this.f.tld.trim()); + if (this.f.alpha_only) p.set('alpha_only', 'true'); + if (this.f.no_sld) p.set('no_sld', 'true'); const d = await fetch('/api/domains?' + p).then(r=>r.json()); this.domainsTotal = d.total || 0; let rows = d.results || []; @@ -509,7 +521,7 @@ function app() { resetFilters() { this.f = {keyword:'', tld:'', prescreen_status:'live', niche:'beauty_cosmetics', - site_type:'ecommerce', country:'', limit:'100', page:1}; + site_type:'ecommerce', country:'', alpha_only:false, no_sld:false, limit:'100', page:1}; this.selected = []; this.loadDomains(); }, @@ -518,6 +530,28 @@ function app() { this.selected = e.target.checked ? this.domains.map(r=>r.domain) : []; }, + async validateSelected() { + if (!this.selected.length || this.validating) return; + this.validating = true; + this.notify(`Validating ${this.selected.length} domains…`, 'info'); + try { + const chunks = []; + for (let i=0; ir.json()); + for (const k of Object.keys(totals)) totals[k] += d[k]||0; + } + this.notify(`✅ ${totals.live} live · ☠ ${totals.dead} dead · 🅿 ${totals.parked} parked · ↗ ${totals.redirect} redirect`, 'success'); + this.selected = []; + await this.loadDomains(); + } catch(e) { this.notify('Validate failed: '+e.message, 'error'); } + finally { this.validating = false; } + }, + async prescreenSelected() { if (!this.selected.length || this.prescreening) return; this.prescreening = true;