#!/usr/bin/env python3 """ CZDS Zone File Sync Script ========================== Manually sync zone files from ICANN CZDS. Usage: # Sync all approved TLDs python scripts/sync_czds.py # Sync specific TLDs python scripts/sync_czds.py xyz org dev Environment: CZDS_USERNAME: ICANN CZDS username (email) CZDS_PASSWORD: ICANN CZDS password CZDS_DATA_DIR: Directory for zone file cache (default: /tmp/pounce_czds) """ import asyncio import os import sys from pathlib import Path # Add backend to path sys.path.insert(0, str(Path(__file__).parent.parent)) from dotenv import load_dotenv load_dotenv() async def main(): from app.database import AsyncSessionLocal, init_db from app.services.czds_client import CZDSClient, APPROVED_TLDS # Parse arguments tlds = sys.argv[1:] if len(sys.argv) > 1 else APPROVED_TLDS # Check credentials username = os.getenv("CZDS_USERNAME") password = os.getenv("CZDS_PASSWORD") if not username or not password: print("āŒ CZDS credentials not configured!") print() print("Set these environment variables:") print(" export CZDS_USERNAME='your-icann-email'") print(" export CZDS_PASSWORD='your-password'") print() print("Or add to .env file:") print(" CZDS_USERNAME=your-icann-email") print(" CZDS_PASSWORD=your-password") sys.exit(1) print("🌐 ICANN CZDS Zone File Sync") print("=" * 50) print(f"šŸ“§ Username: {username}") print(f"šŸ“‚ TLDs: {', '.join(tlds)}") print(f"šŸ’¾ Cache Dir: {os.getenv('CZDS_DATA_DIR', '/tmp/pounce_czds')}") print("=" * 50) print() # Initialize database print("šŸ“¦ Initializing database...") await init_db() # Create client and sync client = CZDSClient() print("\nšŸ” Authenticating with ICANN...") async with AsyncSessionLocal() as db: print("\nšŸ“„ Starting zone file downloads...") print(" (This may take a while for large zones)") print() results = await client.sync_all_zones(db, tlds) # Summary print("\n" + "=" * 50) print("šŸ“Š SYNC RESULTS") print("=" * 50) total_domains = 0 total_dropped = 0 total_new = 0 for r in results: status_icon = "āœ…" if r["status"] == "success" else "āŒ" print(f"\n{status_icon} .{r['tld']}") if r["status"] == "success": print(f" Domains: {r['current_count']:>12,}") print(f" Previous: {r['previous_count']:>12,}") print(f" Dropped: {r['dropped_count']:>12,}") print(f" New: {r['new_count']:>12,}") total_domains += r['current_count'] total_dropped += r['dropped_count'] total_new += r['new_count'] else: print(f" Error: {r.get('error', 'Unknown error')}") print("\n" + "-" * 50) print(f"šŸ“ˆ TOTALS") print(f" Total Domains: {total_domains:>12,}") print(f" Total Dropped: {total_dropped:>12,}") print(f" Total New: {total_new:>12,}") print() if total_dropped > 0: print(f"šŸŽÆ {total_dropped:,} dropped domains available in the database!") print(" View them at: https://pounce.ch/terminal/hunt -> Drops tab") if __name__ == "__main__": asyncio.run(main())