Files
paase d15c927f55 feat: initial commit for ipv64 DNS TUI client
- Implement modular Textual TUI (main, app, widgets, config, api_client)
- Integrate IPv64.net REST API client using httpx
- Support record listing, creation, in-place edit, and deletion
- Add flexible token resolution (.env, env export, interactive prompt)
- Add bilingual README (DE/EN) and project configuration
2026-09-24 13:51:42 +02:00

107 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""IPv64 DNS TUI Client
Author: Pascal Bouquet <pascal@ptbos.de>
License: GNU General Public License v3.0 (GPL-3.0)
Year: 2026
"""
import httpx
BASE_URL = "https://ipv64.net/api.php"
class IPv64Client:
def __init__(self, api_key: str):
self.headers = {"Authorization": f"Bearer {api_key.strip()}"}
async def get_account_info(self) -> dict:
"""[GET] get_account_info: Ruft Kontoinformationen und Limits ab."""
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{BASE_URL}?get_account_info",
headers=self.headers,
timeout=10.0,
)
resp.raise_for_status()
return resp.json()
async def get_domains(self) -> dict:
"""[GET] get_domains: Liefert alle Domains und Records."""
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{BASE_URL}?get_domains",
headers=self.headers,
timeout=10.0,
)
resp.raise_for_status()
return resp.json()
async def add_domain(self, domain_name: str) -> dict:
"""[POST] add_domain: Legt eine neue Domain an."""
data = {"add_domain": domain_name}
async with httpx.AsyncClient() as client:
resp = await client.post(
BASE_URL,
headers=self.headers,
data=data,
timeout=10.0,
)
resp.raise_for_status()
return resp.json()
async def delete_domain(self, domain_name: str) -> dict:
"""[DELETE] del_domain: Löscht Domain mit allen Einträgen."""
data = {"del_domain": domain_name}
async with httpx.AsyncClient() as client:
resp = await client.request(
"DELETE",
BASE_URL,
headers=self.headers,
data=data,
timeout=10.0,
)
resp.raise_for_status()
return resp.json()
async def add_record(
self,
domain: str,
subdomain: str,
typ: str,
content: str,
prio: str = "",
) -> dict:
"""[POST] add_record: DNS-Record anlegen."""
data = {
"add_record": domain,
"praefix": subdomain,
"type": typ.upper(),
"content": content,
}
if prio and prio.strip() and prio.strip().lower() != "none":
data["prio"] = prio.strip()
async with httpx.AsyncClient() as client:
resp = await client.post(
BASE_URL,
headers=self.headers,
data=data,
timeout=10.0,
)
resp.raise_for_status()
return resp.json()
async def delete_record_by_id(self, record_id: int | str) -> dict:
"""[DELETE] del_record per ID."""
data = {"del_record": str(record_id)}
async with httpx.AsyncClient() as client:
resp = await client.request(
"DELETE",
BASE_URL,
headers=self.headers,
data=data,
timeout=10.0,
)
resp.raise_for_status()
return resp.json()