summaryrefslogtreecommitdiff
path: root/domain_manager.py
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2025-07-18 15:24:15 +0200
committerYuval Adam <_@yuv.al>2025-07-18 15:24:15 +0200
commit257ad34dd8baf2c2e4b3621d2477c9fd265b709e (patch)
tree0f683c9fed13fa6b85f86a67aa5e21385932e6eb /domain_manager.py
Initial stuff works
Diffstat (limited to 'domain_manager.py')
-rwxr-xr-xdomain_manager.py213
1 files changed, 213 insertions, 0 deletions
diff --git a/domain_manager.py b/domain_manager.py
new file mode 100755
index 0000000..808339c
--- /dev/null
+++ b/domain_manager.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python3
+
+import sys
+from typing import Dict, Any, Optional
+from config import Config
+from namecheap_api import NamecheapAPI
+from cloudflare_api import CloudflareAPI
+
+class DomainManager:
+ def __init__(self, config: Config, sandbox: bool = False):
+ self.config = config
+ self.sandbox = sandbox
+ self.namecheap = NamecheapAPI(config, sandbox=sandbox)
+ self.cloudflare = CloudflareAPI(config)
+
+ def register_and_setup_domain(self, domain: str,
+ registrant_info: Optional[Dict[str, str]] = None,
+ setup_workers: bool = True,
+ dry_run: bool = False) -> Dict[str, Any]:
+ """
+ Complete domain registration and setup workflow:
+ 1. Check domain availability
+ 2. Verify pricing and account balance
+ 3. Register domain (with user confirmation)
+ 4. Add domain to Cloudflare
+ 5. Update nameservers in Namecheap
+ 6. Set up basic DNS records
+ """
+ result = {
+ 'domain': domain,
+ 'steps_completed': [],
+ 'errors': []
+ }
+
+ try:
+ # Step 1: Check domain availability
+ print(f"Checking availability for {domain}...")
+ if not self.namecheap.check_domain_availability(domain):
+ result['errors'].append(f"Domain {domain} is not available")
+ return result
+
+ result['steps_completed'].append('availability_check')
+ print(f"✓ Domain {domain} is available")
+
+ # Step 2: Check pricing and balance
+ print("Checking pricing and account balance...")
+
+ try:
+ pricing = self.namecheap.get_domain_pricing(domain)
+ except Exception as e:
+ result['errors'].append(f"Failed to get domain pricing: {str(e)}")
+ return result
+
+ try:
+ balance = self.namecheap.get_account_balance()
+ except Exception as e:
+ result['errors'].append(f"Failed to get account balance: {str(e)}")
+ return result
+
+ if balance < pricing['register']:
+ result['errors'].append(
+ f"Insufficient balance. Required: ${pricing['register']:.2f}, "
+ f"Available: ${balance:.2f}"
+ )
+ return result
+
+ result['steps_completed'].append('pricing_check')
+ print(f"✓ Pricing: ${pricing['register']:.2f}, Balance: ${balance:.2f}")
+
+ # Step 3: User confirmation with multiple safeguards
+ print(f"\n" + "="*50)
+ print(f"DOMAIN REGISTRATION CONFIRMATION")
+ print(f"="*50)
+ print(f"Domain: {domain}")
+ print(f"Registration Price: ${pricing['register']:.2f}")
+ print(f"Account Balance: ${balance:.2f}")
+ print(f"Remaining Balance: ${balance - pricing['register']:.2f}")
+ print(f"="*50)
+
+ # Multiple confirmation steps to prevent accidents
+ print(f"\nWARNING: This will charge ${pricing['register']:.2f} to your account!")
+ first_confirm = input(f"Type 'REGISTER' to proceed with registration of {domain}: ").strip()
+ if first_confirm != 'REGISTER':
+ result['errors'].append("Registration cancelled by user")
+ return result
+
+ second_confirm = input(f"Are you absolutely sure you want to register {domain} for ${pricing['register']:.2f}? (yes/no): ").lower().strip()
+ if second_confirm != 'yes':
+ result['errors'].append("Registration cancelled by user")
+ return result
+
+ # Step 4: Register domain
+ if dry_run:
+ print(f"DRY RUN: Would register domain {domain} (skipping actual registration)")
+ result['steps_completed'].append('domain_registration_dry_run')
+ else:
+ print(f"Registering domain {domain}...")
+ if not self.namecheap.register_domain(domain, registrant_info=registrant_info):
+ result['errors'].append(f"Failed to register domain {domain}")
+ return result
+ result['steps_completed'].append('domain_registration')
+
+ print(f"✓ Domain {domain} registered successfully")
+
+ # Step 5: Add domain to Cloudflare
+ print(f"Adding {domain} to Cloudflare...")
+ zone_info = self.cloudflare.add_zone(domain)
+ zone_id = zone_info['id']
+
+ result['steps_completed'].append('cloudflare_zone_creation')
+ result['zone_id'] = zone_id
+ print(f"✓ Domain added to Cloudflare (Zone ID: {zone_id})")
+
+ # Step 6: Get Cloudflare nameservers
+ print("Getting Cloudflare nameservers...")
+ nameservers = self.cloudflare.get_zone_nameservers(zone_id)
+
+ result['nameservers'] = nameservers
+ print(f"✓ Cloudflare nameservers: {', '.join(nameservers)}")
+
+ # Step 7: Update nameservers in Namecheap
+ print(f"Updating nameservers in Namecheap...")
+ if not self.namecheap.set_dns_servers(domain, nameservers):
+ result['errors'].append("Failed to update nameservers in Namecheap")
+ return result
+
+ result['steps_completed'].append('nameserver_update')
+ print(f"✓ Nameservers updated in Namecheap")
+
+ # Step 8: Set up basic DNS records
+ print("Setting up basic DNS records...")
+ dns_records = self.cloudflare.setup_basic_dns_records(zone_id, domain)
+
+ result['dns_records'] = dns_records
+ result['steps_completed'].append('basic_dns_setup')
+ print(f"✓ Basic DNS records created")
+
+ # Step 9: Set up worker subdomain if requested
+ if setup_workers:
+ print("Setting up worker subdomain...")
+ worker_record = self.cloudflare.create_worker_subdomain(zone_id, f"app.{domain}")
+ result['worker_record'] = worker_record
+ result['steps_completed'].append('worker_subdomain_setup')
+ print(f"✓ Worker subdomain app.{domain} created")
+
+ result['success'] = True
+ print(f"\n🎉 Domain {domain} setup completed successfully!")
+ print(f"Zone ID: {zone_id}")
+ print(f"Nameservers: {', '.join(nameservers)}")
+
+ return result
+
+ except Exception as e:
+ result['errors'].append(f"Unexpected error: {str(e)}")
+ return result
+
+ def setup_google_analytics_dns(self, domain: str) -> Dict[str, Any]:
+ """Set up DNS records for Google Analytics"""
+ try:
+ zone_info = self.cloudflare.get_zone_info(domain)
+ if not zone_info:
+ return {'error': f'Domain {domain} not found in Cloudflare'}
+
+ records = self.cloudflare.setup_google_analytics_dns(zone_info['id'], domain)
+ return {'success': True, 'records': records}
+
+ except Exception as e:
+ return {'error': str(e)}
+
+def main():
+ if len(sys.argv) < 2:
+ print("Usage: python domain_manager.py <domain> [--dry-run] [--sandbox]")
+ sys.exit(1)
+
+ domain = sys.argv[1]
+ dry_run = '--dry-run' in sys.argv
+ sandbox = '--sandbox' in sys.argv
+
+ # Load configuration
+ config = Config.from_env()
+
+
+ # Validate required configuration
+ if not all([
+ config.namecheap_api_key,
+ config.namecheap_api_user,
+ config.namecheap_username,
+ config.namecheap_client_ip,
+ config.cloudflare_api_token
+ ]):
+ print("Error: Missing required API credentials. Please check your .env file.")
+ sys.exit(1)
+
+ # Initialize domain manager
+ manager = DomainManager(config, sandbox=sandbox)
+
+ # Register and setup domain
+ if sandbox:
+ print("Running in SANDBOX mode - using Namecheap sandbox environment")
+ if dry_run:
+ print("Running in DRY RUN mode - no actual registration will occur")
+ result = manager.register_and_setup_domain(domain, dry_run=dry_run)
+
+ if result.get('success'):
+ print(f"\nSuccess! Domain {domain} is ready for use.")
+ else:
+ print(f"\nErrors occurred:")
+ for error in result.get('errors', []):
+ print(f" - {error}")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main() \ No newline at end of file