Merge pull request #3 from nerdymark/feature/scan-progress-and-auto-idle Add li...

File: backend/geoip_db.py
 def import_csv(db_path: str, csv_gz_path: str, progress_cb=None) -> int:
     return total_imported
+def random_cidr(db_path: str) -> dict:
+    """Pick a random block and return a /24 derived from its starting IP.
+
+    Returns {"cidr": "a.b.c.0/24", "label": "City / State / Country"}.
+    Raises FileNotFoundError if no blocks are imported.
+    """
+    import random
+    if not Path(db_path).exists():
+        raise FileNotFoundError("GeoIP database not imported")
+    conn = _get_conn(db_path)
+    try:
+        total = conn.execute("SELECT COUNT(*) FROM ip_blocks").fetchone()[0]
+        if total == 0:
+            raise FileNotFoundError("GeoIP database has no blocks")
+        # OFFSET N on a random index is faster than ORDER BY RANDOM() across millions of rows
+        offset = random.randrange(total)
+        row = conn.execute(
+            "SELECT ip_start, country, state, city FROM ip_blocks LIMIT 1 OFFSET ?",
+            (offset,),
+        ).fetchone()
+    finally:
+        conn.close()
+
+    octets = row["ip_start"].split(".")
+    cidr = f"{octets[0]}.{octets[1]}.{octets[2]}.0/24"
+    label = " / ".join(p for p in (row["city"], row["state"], row["country"]) if p)
+    return {"cidr": cidr, "label": label or "GeoIP random"}
+
+
 def list_countries(db_path: str) -> list[dict]:
     """List all countries with their block counts."""
     conn = _get_conn(db_path)
File: backend/routers/geoip.py
 def trigger_import():
     return {"message": "Import started"}
+@router.get("/random-cidr")
+def random_cidr():
+    """Pick a random /24 CIDR from the GeoIP blocks, for auto-idle scanning."""
+    from backend.geoip_db import random_cidr as _random_cidr
+
+    config = _get_config()
+    try:
+        return _random_cidr(config.geoip.database_path)
+    except FileNotFoundError as e:
+        raise HTTPException(404, str(e))
+
+
 @router.get("/countries", response_model=list[GeoipCountryResponse])
 def get_countries():
     """List all countries with block counts."""
File: frontend/src/api.ts
 import type {
   Subnet, Scan, Host, HostStats, FeedTarget, VncRandomHost,
   GeoipStatus, GeoipCountry, GeoipState, GeoipCity, GeoipBlocksResponse, BulkSubnetResponse,
+  GeoipRandomCidr,
 } from './types'
 const BASE = '/api'
 export const addGeoipSubnets = (cidrs: string[], label = '') =>
     method: 'POST',
     body: JSON.stringify({ cidrs, label }),
   })
+export const getGeoipRandomCidr = () => request<GeoipRandomCidr>('/geoip/random-cidr')
Read more...