inital commit
This commit is contained in:
parent
db47c876b5
commit
7733773d21
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Python Bytecode-Dateien
|
||||
__pycache__/
|
||||
|
||||
59
inwx_cli.py
Normal file
59
inwx_cli.py
Normal file
@ -0,0 +1,59 @@
|
||||
import os
|
||||
from inwx_config import login, logout # Importiere Login/Logout aus der Konfigurationsdatei
|
||||
from inwx_dns_functions import get_dns_info, add_record, update_record, delete_record # Importiere DNS-Funktionen
|
||||
|
||||
def main_menu():
|
||||
"""Hauptmenü der CLI-Anwendung."""
|
||||
|
||||
# 1. Login-Daten abfragen (kann auch über Umgebungsvariablen INWX_USER/INWX_PASS gesetzt werden)
|
||||
INWX_USER = os.getenv('INWX_USER')
|
||||
INWX_PASS = os.getenv('INWX_PASS')
|
||||
|
||||
if not INWX_USER:
|
||||
INWX_USER = input("Gib deinen INWX-Benutzernamen ein: ")
|
||||
if not INWX_PASS:
|
||||
INWX_PASS = input("Gib dein INWX-Passwort ein: ")
|
||||
|
||||
if not login(INWX_USER, INWX_PASS):
|
||||
return
|
||||
|
||||
# 2. Hauptschleife
|
||||
try:
|
||||
while True:
|
||||
# Das Menü im MC-Stil
|
||||
print("\n" + "=" * 40)
|
||||
print(" INWX DNS-CLI (MC-Style) - DOMAIN-VERWALTUNG")
|
||||
print("=" * 40)
|
||||
print("1: 🌐 **Anzeigen** (nameserver.info)")
|
||||
print("---")
|
||||
print("2: ➕ **Hinzufügen** (nameserver.addRecord)")
|
||||
print("3: ✏️ **Ändern** (nameserver.updateRecord)")
|
||||
print("4: 🗑️ **Löschen** (nameserver.deleteRecord)")
|
||||
print("---")
|
||||
print("9: 🚪 Logout & Beenden")
|
||||
print("-" * 40)
|
||||
|
||||
choice = input("Wähle eine Aktion (1-4 oder 9): ").strip()
|
||||
|
||||
if choice == '1':
|
||||
domain = input("Gib die Domain ein, deren Einträge du sehen möchtest: ").strip()
|
||||
if domain:
|
||||
get_dns_info(domain)
|
||||
elif choice == '2':
|
||||
add_record()
|
||||
elif choice == '3':
|
||||
update_record()
|
||||
elif choice == '4':
|
||||
delete_record()
|
||||
elif choice == '9':
|
||||
break
|
||||
else:
|
||||
print("Ungültige Auswahl. Bitte versuche es erneut.")
|
||||
|
||||
finally:
|
||||
# Stelle sicher, dass immer ausgeloggt wird
|
||||
logout()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main_menu()
|
||||
|
||||
81
inwx_config.py
Normal file
81
inwx_config.py
Normal file
@ -0,0 +1,81 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
# --- Konfiguration ---
|
||||
API_ENDPOINT = "https://api.domrobot.com/jsonrpc/"
|
||||
SESSION_ID = None
|
||||
|
||||
def api_call(method, params={}):
|
||||
"""
|
||||
Führt einen API-Aufruf aus (Post-Login) und gibt die JSON-Antwort zurück.
|
||||
Verwendet die globale SESSION_ID im Cookie-Header.
|
||||
"""
|
||||
global SESSION_ID
|
||||
|
||||
# Stelle sicher, dass die Session-ID für alle Anfragen nach dem Login im Cookie-Header ist
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Cookie": f"domrobot={SESSION_ID}"
|
||||
}
|
||||
|
||||
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❌ API-Fehler bei {method}: {e}")
|
||||
return None
|
||||
|
||||
def login(user, password):
|
||||
"""Loggt sich in die INWX API ein und speichert die Session-ID."""
|
||||
global SESSION_ID
|
||||
|
||||
print("⏳ Versuche, mich einzuloggen...")
|
||||
|
||||
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()
|
||||
if result_json.get('code') == 1000:
|
||||
if 'domrobot' in response.cookies:
|
||||
SESSION_ID = response.cookies['domrobot']
|
||||
print("✅ Login erfolgreich! Session-ID gespeichert.")
|
||||
return True
|
||||
else:
|
||||
print("❌ Login fehlgeschlagen: 'code 1000' erhalten, aber kein Session-Cookie.")
|
||||
else:
|
||||
print(f"❌ Login fehlgeschlagen: {result_json.get('msg', 'Unbekannter Fehler.')}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"\n❌ API-Fehler beim Login-Request: {e}")
|
||||
|
||||
return False
|
||||
|
||||
def logout():
|
||||
"""Loggt sich aus der INWX API aus."""
|
||||
global SESSION_ID
|
||||
if not SESSION_ID:
|
||||
return
|
||||
|
||||
print("\n⏳ Logge mich aus...")
|
||||
# Hier verwenden wir api_call, die jetzt die SESSION_ID verwendet
|
||||
api_call("account.logout", {})
|
||||
SESSION_ID = None
|
||||
print("✅ Logout erfolgreich.")
|
||||
|
||||
122
inwx_dns_functions.py
Normal file
122
inwx_dns_functions.py
Normal file
@ -0,0 +1,122 @@
|
||||
from inwx_config import api_call # Importiere die Basis-API-Funktion
|
||||
|
||||
def get_dns_info(domain):
|
||||
"""Ruft die DNS-Einträge für eine Domain ab und gibt sie im MC-Stil aus."""
|
||||
print(f"\n⏳ Rufe DNS-Einträge für {domain} ab...")
|
||||
result = api_call("nameserver.info", {"domain": domain})
|
||||
|
||||
if result and result.get('code') == 1000 and 'record' in result.get('resData', {}):
|
||||
print(f"✅ DNS-Einträge für **{domain}**:")
|
||||
records = result['resData']['record']
|
||||
|
||||
# Tabelle im MC-Stil ausgeben
|
||||
print("-" * 100)
|
||||
print(f"| {'ID':<10} | {'Name/Host':<15} | {'Typ':<5} | {'TTL':<5} | {'Inhalt/Content':<50} |")
|
||||
print("-" * 100)
|
||||
|
||||
for record in records:
|
||||
# Begrenze Name und Content für eine saubere Ausgabe
|
||||
name_short = record.get('name', '')[:14].ljust(15)
|
||||
content_short = record.get('content', '')[:49].ljust(50)
|
||||
|
||||
print(f"| {str(record['id']):<10} | {name_short} | {record['type']:<5} | {str(record['ttl']):<5} | {content_short} |")
|
||||
|
||||
print("-" * 100)
|
||||
return True
|
||||
elif result and 'msg' in result:
|
||||
print(f"❌ Fehler: {result.get('msg', 'Unbekannter Fehler.')}")
|
||||
else:
|
||||
print("❌ Fehler beim Abrufen der DNS-Einträge (API-Antwort unerwartet).")
|
||||
return False
|
||||
|
||||
def add_record():
|
||||
"""Fügt einen neuen DNS-Eintrag hinzu (nameserver.createRecord)."""
|
||||
print("\n--- NEUEN DNS-EINTRAG HINZUFÜGEN ---")
|
||||
domain = input("Domain (z.B. bouquet24.de): ").strip()
|
||||
name = input("Host/Subdomain (leer lassen für die Hauptdomain '@'): ").strip()
|
||||
record_type = input("Typ (A, CNAME, TXT, MX, etc.): ").strip().upper()
|
||||
content = input("Inhalt/Content (IP-Adresse, Ziel, Text): ").strip()
|
||||
|
||||
# Optional: TTL mit Standardwert 3600
|
||||
try:
|
||||
ttl = int(input("TTL (Sekunden, Standard: 3600): ") or 3600)
|
||||
except ValueError:
|
||||
print("Ungültige TTL. Verwende Standardwert 3600.")
|
||||
ttl = 3600
|
||||
|
||||
params = {
|
||||
"domain": domain,
|
||||
"name": name,
|
||||
"type": record_type,
|
||||
"content": content,
|
||||
"ttl": ttl
|
||||
}
|
||||
|
||||
print(f"\n⏳ Sende Anfrage zum Hinzufügen von {name}.{domain}...")
|
||||
result = api_call("nameserver.createRecord", params)
|
||||
|
||||
if result and result.get('code') == 1000:
|
||||
new_id = result.get('resData', {}).get('id', 'N/A')
|
||||
print(f"✅ Eintrag erfolgreich hinzugefügt! ID: **{new_id}**")
|
||||
else:
|
||||
print(f"❌ Fehler beim Hinzufügen: {result.get('msg', 'Unbekannter Fehler.')}")
|
||||
|
||||
def update_record():
|
||||
"""Ändert einen bestehenden DNS-Eintrag (nameserver.updateRecord)."""
|
||||
print("\n--- BESTEHENDEN DNS-EINTRAG ÄNDERN ---")
|
||||
|
||||
record_id = input("ID des zu ändernden Eintrags (siehe Option 1): ").strip()
|
||||
if not record_id.isdigit():
|
||||
print("❌ Ungültige ID.")
|
||||
return
|
||||
|
||||
# Frage nach den Werten, die geändert werden sollen
|
||||
new_content = input("Neuer Inhalt/Content (leer lassen, um nicht zu ändern): ").strip()
|
||||
new_ttl = input("Neue TTL (Sekunden, leer lassen, um nicht zu ändern): ").strip()
|
||||
|
||||
params = {"id": int(record_id)}
|
||||
if new_content:
|
||||
params["content"] = new_content
|
||||
if new_ttl:
|
||||
try:
|
||||
params["ttl"] = int(new_ttl)
|
||||
except ValueError:
|
||||
print("❌ Ungültige TTL. Abbruch der Änderung.")
|
||||
return
|
||||
|
||||
if len(params) <= 1:
|
||||
print("Keine Änderungen angegeben. Vorgang abgebrochen.")
|
||||
return
|
||||
|
||||
print(f"\n⏳ Sende Anfrage zur Änderung der ID **{record_id}**...")
|
||||
result = api_call("nameserver.updateRecord", params)
|
||||
|
||||
if result and result.get('code') == 1000:
|
||||
print(f"✅ Eintrag ID **{record_id}** erfolgreich aktualisiert.")
|
||||
else:
|
||||
print(f"❌ Fehler beim Ändern: {result.get('msg', 'Unbekannter Fehler.')}")
|
||||
|
||||
def delete_record():
|
||||
"""Löscht einen DNS-Eintrag (nameserver.deleteRecord)."""
|
||||
print("\n--- DNS-EINTRAG LÖSCHEN ---")
|
||||
|
||||
record_id = input("ID des zu löschenden Eintrags (siehe Option 1): ").strip()
|
||||
if not record_id.isdigit():
|
||||
print("❌ Ungültige ID.")
|
||||
return
|
||||
|
||||
confirm = input(f"Soll Eintrag ID **{record_id}** wirklich gelöscht werden? (J/N): ").strip().upper()
|
||||
if confirm != 'J':
|
||||
print("Löschvorgang abgebrochen.")
|
||||
return
|
||||
|
||||
params = {"id": int(record_id)}
|
||||
|
||||
print(f"\n⏳ Sende Anfrage zum Löschen der ID **{record_id}**...")
|
||||
result = api_call("nameserver.deleteRecord", params)
|
||||
|
||||
if result and result.get('code') == 1000:
|
||||
print(f"✅ Eintrag ID **{record_id}** erfolgreich gelöscht.")
|
||||
else:
|
||||
print(f"❌ Fehler beim Löschen: {result.get('msg', 'Unbekannter Fehler.')}")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user