#!/usr/bin/env python3 # -*- coding: utf-8 -*- import requests import json import getpass # Needed for secure password input in 2FA prompt # --- Global Configuration --- API_ENDPOINT = "https://api.domrobot.com/jsonrpc/" SESSION_ID = None def api_call(method, params={}): """ Executes an API call (Post-Login) and returns the JSON response. Uses the global SESSION_ID in the Cookie header for authentication. """ global SESSION_ID # Ensure the session ID is included in the Cookie header headers = { "Content-Type": "application/json", "Cookie": f"domrobot={SESSION_ID}" if SESSION_ID else "" } payload = { "jsonrpc": "2.0", "method": method, "params": params, "id": 1 } try: response = requests.post(API_ENDPOINT, headers=headers, data=json.dumps(payload), timeout=10) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"\n[ERROR] API call failed for {method}: {e}") return None def login(user, password): """ Logs into the INWX API and stores the session ID. Includes a check for required Two-Factor Authentication (2FA). """ global SESSION_ID print("--- Attempting standard login...") headers = {"Content-Type": "application/json"} payload = { "jsonrpc": "2.0", "method": "account.login", "params": {"user": user, "pass": password}, "id": 1 } try: response = requests.post(API_ENDPOINT, headers=headers, data=json.dumps(payload), timeout=10) response.raise_for_status() result_json = response.json() # 1. Standard Login Successful if result_json.get('code') == 1000: if 'domrobot' in response.cookies: SESSION_ID = response.cookies['domrobot'] print("[SUCCESS] Login successful! Session ID stored.") return True else: print("[ERROR] Login failed: 'code 1000' received, but no session cookie.") # 2. 2FA Required (Error Message Check) elif result_json.get('msg') and "two-factor-auth" in result_json.get('msg').lower(): print("[NOTICE] Two-Factor Authentication (2FA) is required.") return login_2fa(user, password) # Proceed to 2FA login flow # 3. Other Login Error else: print(f"[ERROR] Login failed: {result_json.get('msg', 'Unknown error.')}") except requests.exceptions.RequestException as e: print(f"\n[ERROR] API request failed during standard login: {e}") return False def login_2fa(user, password): """Performs the login using TOTP (account.login2fa).""" global SESSION_ID # Prompt user securely for the TOTP code topt_code = input("Enter your TOTP/2FA code: ").strip() headers = {"Content-Type": "application/json"} payload = { "jsonrpc": "2.0", "method": "account.login2fa", "params": { "user": user, "pass": password, "topt": topt_code }, "id": 1 } try: response = requests.post(API_ENDPOINT, headers=headers, data=json.dumps(payload), timeout=10) response.raise_for_status() result_json = response.json() if result_json.get('code') == 1000: if 'domrobot' in response.cookies: SESSION_ID = response.cookies['domrobot'] print("[SUCCESS] 2FA Login successful! Session ID stored.") return True else: print("[ERROR] 2FA Login failed: No session cookie received.") else: print(f"[ERROR] 2FA Login failed: {result_json.get('msg', 'Incorrect code or unknown error.')}") except requests.exceptions.RequestException as e: print(f"\n[ERROR] API request failed during 2FA login: {e}") return False def logout(): """Logs out of the INWX API and clears the global session ID.""" global SESSION_ID if not SESSION_ID: return print("\n--- Logging out...") api_call("account.logout", {}) SESSION_ID = None print("[SUCCESS] Logout successful.")