inwx-api-tool/inwx_config.py

135 lines
4.2 KiB
Python

#!/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.")