prince1604 commited on
Commit
da8ed9b
·
1 Parent(s): 1937b23

Rename async endpoints to match user req

Browse files
Files changed (2) hide show
  1. api.py +3 -3
  2. static/index.html +151 -132
api.py CHANGED
@@ -203,7 +203,7 @@ def get_system_status(domain: Optional[str] = None):
203
  stats = SystemMonitor.get_system_stats(target_url=domain)
204
  return stats
205
 
206
- @app.post("/api/scan/start")
207
  def start_scan(payload: StartReq, bg: BackgroundTasks):
208
  job_id = str(uuid4())
209
  JOBS[job_id] = {
@@ -220,7 +220,7 @@ def start_scan(payload: StartReq, bg: BackgroundTasks):
220
  bg.add_task(run_scan_job, job_id, payload.domain, payload.limit)
221
  return {"job_id": job_id}
222
 
223
- @app.get("/api/scan/progress/{job_id}")
224
  def scan_progress(job_id: str):
225
  job = JOBS.get(job_id)
226
  if not job:
@@ -256,7 +256,7 @@ def scan_progress(job_id: str):
256
  "error": job.get("error"),
257
  }
258
 
259
- @app.get("/api/scan/result/{job_id}")
260
  def scan_result(job_id: str):
261
  job = JOBS.get(job_id)
262
  if not job:
 
203
  stats = SystemMonitor.get_system_stats(target_url=domain)
204
  return stats
205
 
206
+ @app.post("/api/scanstart")
207
  def start_scan(payload: StartReq, bg: BackgroundTasks):
208
  job_id = str(uuid4())
209
  JOBS[job_id] = {
 
220
  bg.add_task(run_scan_job, job_id, payload.domain, payload.limit)
221
  return {"job_id": job_id}
222
 
223
+ @app.get("/api/progress/{job_id}")
224
  def scan_progress(job_id: str):
225
  job = JOBS.get(job_id)
226
  if not job:
 
256
  "error": job.get("error"),
257
  }
258
 
259
+ @app.get("/api/result/{job_id}")
260
  def scan_result(job_id: str):
261
  job = JOBS.get(job_id)
262
  if not job:
static/index.html CHANGED
@@ -1,5 +1,6 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -16,8 +17,13 @@
16
  --error: #ef4444;
17
  }
18
 
19
- * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', system-ui, sans-serif; }
20
-
 
 
 
 
 
21
  body {
22
  background-color: var(--bg);
23
  color: var(--text);
@@ -52,7 +58,7 @@
52
  border-radius: 1rem;
53
  padding: 2rem;
54
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
55
- border: 1px solid rgba(255,255,255,0.05);
56
  margin-bottom: 1.5rem;
57
  }
58
 
@@ -140,7 +146,7 @@
140
  }
141
 
142
  .stat-box {
143
- background: rgba(255,255,255,0.03);
144
  padding: 1rem;
145
  border-radius: 0.5rem;
146
  text-align: center;
@@ -182,157 +188,170 @@
182
  color: #a5b4fc;
183
  font-size: 0.85rem;
184
  }
185
-
186
- .json-key { color: #9cdcfe; }
187
- .json-string { color: #ce9178; }
188
- .json-number { color: #b5cea8; }
189
- .json-boolean { color: #569cd6; }
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  </style>
192
  </head>
 
193
  <body>
194
 
195
- <div class="container">
196
- <header>
197
- <h1>SEO Scaler</h1>
198
- <p style="color: var(--text-muted);">Antigravity Async Scanner Interface</p>
199
- </header>
200
-
201
- <div class="card">
202
- <div class="input-group">
203
- <input type="text" id="domainInput" placeholder="Enter Domain (e.g. https://example.com)" value="https://example.com">
204
- <input type="number" id="limitInput" placeholder="Limit" value="25" style="max-width: 100px;">
205
- <button id="scanBtn" onclick="startScan()">Start Scan</button>
 
 
206
  </div>
207
- </div>
208
 
209
- <!-- Progress Card -->
210
- <div id="progress-section" class="card">
211
- <div class="progress-labels">
212
- <span id="status-badge">Initializing...</span>
213
- <span id="percent-badge">0%</span>
214
- </div>
215
- <div class="progress-bar-bg">
216
- <div id="progress-fill" class="progress-bar"></div>
217
- </div>
218
-
219
- <div class="stats-grid">
220
- <div class="stat-box">
221
- <div id="pages-stat" class="stat-value">0</div>
222
- <div class="stat-label">Pages Scanned</div>
223
  </div>
224
- <div class="stat-box">
225
- <div id="images-stat" class="stat-value">0</div>
226
- <div class="stat-label">Images Found</div>
 
 
 
 
 
 
 
 
 
 
 
227
  </div>
228
- <div class="stat-box">
229
- <div id="time-stat" class="stat-value">0s</div>
230
- <div class="stat-label">Elapsed Time</div>
231
  </div>
232
  </div>
233
 
234
- <div id="log-msg" class="status-msg">
235
- Waiting to start...
 
 
236
  </div>
237
  </div>
238
 
239
- <!-- Result Card -->
240
- <div id="result-section" class="card">
241
- <h3 style="margin-bottom: 1rem;">Scan Results</h3>
242
- <pre id="json-output"></pre>
243
- </div>
244
- </div>
245
-
246
- <script>
247
- let jobId = null;
248
- let pollInterval = null;
249
-
250
- async function startScan() {
251
- const domain = document.getElementById('domainInput').value;
252
- const limit = parseInt(document.getElementById('limitInput').value);
253
-
254
- if (!domain) return alert("Please enter a domain");
255
-
256
- // UI Reset
257
- document.getElementById('scanBtn').disabled = true;
258
- document.getElementById('progress-section').style.display = 'block';
259
- document.getElementById('result-section').style.display = 'none';
260
-
261
- try {
262
- // 1. Start Job
263
- const res = await fetch('/api/scan/start', {
264
- method: 'POST',
265
- headers: { 'Content-Type': 'application/json' },
266
- body: JSON.stringify({ domain, limit })
267
- });
268
- const data = await res.json();
269
- jobId = data.job_id;
270
 
271
- // 2. Start Polling
272
- pollInterval = setInterval(pollProgress, 1000);
 
273
 
274
- } catch (e) {
275
- alert("Error starting scan: " + e);
276
- document.getElementById('scanBtn').disabled = false;
277
- }
278
- }
279
 
280
- async function pollProgress() {
281
- if (!jobId) return;
 
 
282
 
283
- try {
284
- const res = await fetch(`/api/scan/progress/${jobId}`);
285
- const data = await res.json();
 
 
 
 
 
 
 
 
 
286
 
287
- // Update UI
288
- document.getElementById('percent-badge').innerText = data.percent + '%';
289
- document.getElementById('progress-fill').style.width = data.percent + '%';
290
- document.getElementById('status-badge').innerText = data.status.toUpperCase();
291
-
292
- document.getElementById('pages-stat').innerText = data.pages_scanned;
293
- document.getElementById('images-stat').innerText = data.images_found;
294
- document.getElementById('time-stat').innerText = data.elapsed_seconds + 's';
295
- document.getElementById('log-msg').innerText = "> " + data.message;
296
-
297
- if (data.status === 'done' || data.status === 'error') {
298
- clearInterval(pollInterval);
299
  document.getElementById('scanBtn').disabled = false;
300
-
301
- if (data.status === 'done') {
302
- fetchResult();
303
- } else {
304
- document.getElementById('log-msg').innerHTML += '<br><strong style="color:var(--error)">ERROR: ' + data.error + '</strong>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  }
 
 
 
306
  }
 
 
 
 
 
 
 
 
 
307
 
308
- } catch (e) {
309
- console.error("Poll error", e);
310
- }
311
- }
312
-
313
- async function fetchResult() {
314
- const res = await fetch(`/api/scan/result/${jobId}`);
315
- const data = await res.json();
316
-
317
- document.getElementById('result-section').style.display = 'block';
318
- document.getElementById('json-output').innerText = JSON.stringify(data, null, 2);
319
- }
320
-
321
- // Auto-fill from query params
322
- window.onload = () => {
323
- const urlParams = new URLSearchParams(window.location.search);
324
- const domain = urlParams.get('domain');
325
- const limit = urlParams.get('limit');
326
-
327
- if (domain) {
328
- document.getElementById('domainInput').value = domain;
329
- if (limit) document.getElementById('limitInput').value = limit;
330
-
331
- // Auto start
332
- startScan();
333
- }
334
- }
335
- </script>
336
 
337
  </body>
338
- </html>
 
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
+
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
17
  --error: #ef4444;
18
  }
19
 
20
+ * {
21
+ margin: 0;
22
+ padding: 0;
23
+ box-sizing: border-box;
24
+ font-family: 'Inter', system-ui, sans-serif;
25
+ }
26
+
27
  body {
28
  background-color: var(--bg);
29
  color: var(--text);
 
58
  border-radius: 1rem;
59
  padding: 2rem;
60
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
61
+ border: 1px solid rgba(255, 255, 255, 0.05);
62
  margin-bottom: 1.5rem;
63
  }
64
 
 
146
  }
147
 
148
  .stat-box {
149
+ background: rgba(255, 255, 255, 0.03);
150
  padding: 1rem;
151
  border-radius: 0.5rem;
152
  text-align: center;
 
188
  color: #a5b4fc;
189
  font-size: 0.85rem;
190
  }
 
 
 
 
 
191
 
192
+ .json-key {
193
+ color: #9cdcfe;
194
+ }
195
+
196
+ .json-string {
197
+ color: #ce9178;
198
+ }
199
+
200
+ .json-number {
201
+ color: #b5cea8;
202
+ }
203
+
204
+ .json-boolean {
205
+ color: #569cd6;
206
+ }
207
  </style>
208
  </head>
209
+
210
  <body>
211
 
212
+ <div class="container">
213
+ <header>
214
+ <h1>SEO Scaler</h1>
215
+ <p style="color: var(--text-muted);">Antigravity Async Scanner Interface</p>
216
+ </header>
217
+
218
+ <div class="card">
219
+ <div class="input-group">
220
+ <input type="text" id="domainInput" placeholder="Enter Domain (e.g. https://example.com)"
221
+ value="https://example.com">
222
+ <input type="number" id="limitInput" placeholder="Limit" value="25" style="max-width: 100px;">
223
+ <button id="scanBtn" onclick="startScan()">Start Scan</button>
224
+ </div>
225
  </div>
 
226
 
227
+ <!-- Progress Card -->
228
+ <div id="progress-section" class="card">
229
+ <div class="progress-labels">
230
+ <span id="status-badge">Initializing...</span>
231
+ <span id="percent-badge">0%</span>
232
+ </div>
233
+ <div class="progress-bar-bg">
234
+ <div id="progress-fill" class="progress-bar"></div>
 
 
 
 
 
 
235
  </div>
236
+
237
+ <div class="stats-grid">
238
+ <div class="stat-box">
239
+ <div id="pages-stat" class="stat-value">0</div>
240
+ <div class="stat-label">Pages Scanned</div>
241
+ </div>
242
+ <div class="stat-box">
243
+ <div id="images-stat" class="stat-value">0</div>
244
+ <div class="stat-label">Images Found</div>
245
+ </div>
246
+ <div class="stat-box">
247
+ <div id="time-stat" class="stat-value">0s</div>
248
+ <div class="stat-label">Elapsed Time</div>
249
+ </div>
250
  </div>
251
+
252
+ <div id="log-msg" class="status-msg">
253
+ Waiting to start...
254
  </div>
255
  </div>
256
 
257
+ <!-- Result Card -->
258
+ <div id="result-section" class="card">
259
+ <h3 style="margin-bottom: 1rem;">Scan Results</h3>
260
+ <pre id="json-output"></pre>
261
  </div>
262
  </div>
263
 
264
+ <script>
265
+ let jobId = null;
266
+ let pollInterval = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
+ async function startScan() {
269
+ const domain = document.getElementById('domainInput').value;
270
+ const limit = parseInt(document.getElementById('limitInput').value);
271
 
272
+ if (!domain) return alert("Please enter a domain");
 
 
 
 
273
 
274
+ // UI Reset
275
+ document.getElementById('scanBtn').disabled = true;
276
+ document.getElementById('progress-section').style.display = 'block';
277
+ document.getElementById('result-section').style.display = 'none';
278
 
279
+ try {
280
+ // 1. Start Job
281
+ const res = await fetch('/api/scanstart', {
282
+ method: 'POST',
283
+ headers: { 'Content-Type': 'application/json' },
284
+ body: JSON.stringify({ domain, limit })
285
+ });
286
+ const data = await res.json();
287
+ jobId = data.job_id;
288
+
289
+ // 2. Start Polling
290
+ pollInterval = setInterval(pollProgress, 1000);
291
 
292
+ } catch (e) {
293
+ alert("Error starting scan: " + e);
 
 
 
 
 
 
 
 
 
 
294
  document.getElementById('scanBtn').disabled = false;
295
+ }
296
+ }
297
+
298
+ async function pollProgress() {
299
+ if (!jobId) return;
300
+
301
+ try {
302
+ const res = await fetch(`/api/progress/${jobId}`);
303
+ const data = await res.json();
304
+
305
+ // Update UI
306
+ document.getElementById('percent-badge').innerText = data.percent + '%';
307
+ document.getElementById('progress-fill').style.width = data.percent + '%';
308
+ document.getElementById('status-badge').innerText = data.status.toUpperCase();
309
+
310
+ document.getElementById('pages-stat').innerText = data.pages_scanned;
311
+ document.getElementById('images-stat').innerText = data.images_found;
312
+ document.getElementById('time-stat').innerText = data.elapsed_seconds + 's';
313
+ document.getElementById('log-msg').innerText = "> " + data.message;
314
+
315
+ if (data.status === 'done' || data.status === 'error') {
316
+ clearInterval(pollInterval);
317
+ document.getElementById('scanBtn').disabled = false;
318
+
319
+ if (data.status === 'done') {
320
+ fetchResult();
321
+ } else {
322
+ document.getElementById('log-msg').innerHTML += '<br><strong style="color:var(--error)">ERROR: ' + data.error + '</strong>';
323
+ }
324
  }
325
+
326
+ } catch (e) {
327
+ console.error("Poll error", e);
328
  }
329
+ }
330
+
331
+ async function fetchResult() {
332
+ const res = await fetch(`/api/result/${jobId}`);
333
+ const data = await res.json();
334
+
335
+ document.getElementById('result-section').style.display = 'block';
336
+ document.getElementById('json-output').innerText = JSON.stringify(data, null, 2);
337
+ }
338
 
339
+ // Auto-fill from query params
340
+ window.onload = () => {
341
+ const urlParams = new URLSearchParams(window.location.search);
342
+ const domain = urlParams.get('domain');
343
+ const limit = urlParams.get('limit');
344
+
345
+ if (domain) {
346
+ document.getElementById('domainInput').value = domain;
347
+ if (limit) document.getElementById('limitInput').value = limit;
348
+
349
+ // Auto start
350
+ startScan();
351
+ }
352
+ }
353
+ </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
354
 
355
  </body>
356
+
357
+ </html>