inwx_domains_owner: optionalen Zeitstempel im citeq-TXT auswerten
TXT-Werte koennen jetzt 'citeq:<ziffer>;<YYYYMMDD>;' lauten. get_group() liefert (ziffer, datum); die Domains werden je Gruppe (und im Block 'Ohne Zuordnung') nach Datum absteigend sortiert (juengste oben, undatierte ans Ende) und das Datum als eigene Spalte ausgegeben. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+46
-12
@@ -85,11 +85,15 @@ def load_owners():
|
|||||||
|
|
||||||
|
|
||||||
def get_group(domain):
|
def get_group(domain):
|
||||||
"""Ermittelt die Gruppen-Ziffer aus dem citeq:-TXT-Eintrag einer Domain.
|
"""Ermittelt Gruppen-Ziffer und optionalen Zeitstempel aus dem citeq:-TXT.
|
||||||
|
|
||||||
Nutzt eine echte DNS-Abfrage (dig +short TXT) und funktioniert daher
|
Nutzt eine echte DNS-Abfrage (dig +short TXT) und funktioniert daher
|
||||||
unabhängig davon, wo die DNS-Zone gehostet wird. Liefert die Ziffer als
|
unabhängig davon, wo die DNS-Zone gehostet wird. Der TXT-Wert hat die Form
|
||||||
String oder None, wenn kein passender TXT-Eintrag gefunden wird.
|
'citeq:<ziffer>' oder – mit Zeitstempel – 'citeq:<ziffer>;<YYYYMMDD>;'
|
||||||
|
(der abschließende Strichpunkt ist optional).
|
||||||
|
|
||||||
|
Liefert das Tupel (ziffer, datum), jeweils als String oder None, wenn kein
|
||||||
|
passender TXT-Eintrag bzw. kein Datum gefunden wird.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
out = subprocess.run(
|
out = subprocess.run(
|
||||||
@@ -98,20 +102,25 @@ def get_group(domain):
|
|||||||
)
|
)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("⚠️ 'dig' nicht gefunden – Gruppen können nicht ermittelt werden.")
|
print("⚠️ 'dig' nicht gefunden – Gruppen können nicht ermittelt werden.")
|
||||||
return None
|
return None, None
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
if out.returncode != 0:
|
if out.returncode != 0:
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
for line in out.stdout.splitlines():
|
for line in out.stdout.splitlines():
|
||||||
# dig liefert TXT-Werte in Anführungszeichen, lange Werte ggf. in
|
# dig liefert TXT-Werte in Anführungszeichen, lange Werte ggf. in
|
||||||
# mehreren Teilen ("teil1" "teil2") -> zusammenfügen und entkleiden.
|
# mehreren Teilen ("teil1" "teil2") -> zusammenfügen und entkleiden.
|
||||||
content = line.replace('" "', '').strip().strip('"')
|
content = line.replace('" "', '').strip().strip('"')
|
||||||
if content.startswith(TXT_PREFIX):
|
if content.startswith(TXT_PREFIX):
|
||||||
return content[len(TXT_PREFIX):].strip()
|
rest = content[len(TXT_PREFIX):].strip()
|
||||||
return None
|
# Ziffer und optionalen Zeitstempel am Semikolon trennen.
|
||||||
|
parts = [p.strip() for p in rest.split(";")]
|
||||||
|
ziffer = parts[0] if parts and parts[0] else None
|
||||||
|
datum = parts[1] if len(parts) > 1 and parts[1] else None
|
||||||
|
return ziffer, datum
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
def tld_of(domain):
|
def tld_of(domain):
|
||||||
@@ -153,6 +162,18 @@ def fmt_price(value):
|
|||||||
return f"{value:.2f}".replace(".", ",") + " €"
|
return f"{value:.2f}".replace(".", ",") + " €"
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_date(datum):
|
||||||
|
"""Formatiert einen Zeitstempel 'YYYYMMDD' als 'DD.MM.YYYY'.
|
||||||
|
|
||||||
|
Liefert '-' bei fehlendem und den Rohwert bei unerwartetem Format.
|
||||||
|
"""
|
||||||
|
if not datum:
|
||||||
|
return "-"
|
||||||
|
if len(datum) == 8 and datum.isdigit():
|
||||||
|
return f"{datum[6:8]}.{datum[4:6]}.{datum[0:4]}"
|
||||||
|
return datum
|
||||||
|
|
||||||
|
|
||||||
def print_group_sums(recs, ziffer, prices):
|
def print_group_sums(recs, ziffer, prices):
|
||||||
"""Gibt für eine Gruppe die Anzahl Domains pro Top-Level-Domain aus.
|
"""Gibt für eine Gruppe die Anzahl Domains pro Top-Level-Domain aus.
|
||||||
|
|
||||||
@@ -177,7 +198,18 @@ def format_domain_line(rec):
|
|||||||
ns = "(keine NS-Einträge gefunden)"
|
ns = "(keine NS-Einträge gefunden)"
|
||||||
else:
|
else:
|
||||||
ns = ", ".join(rec['ns'])
|
ns = ", ".join(rec['ns'])
|
||||||
return f" {rec['name']:<35} {rec['status']:<8} {ns}"
|
return f" {rec['name']:<35} {rec['status']:<8} {fmt_date(rec['datum']):<12} {ns}"
|
||||||
|
|
||||||
|
|
||||||
|
def sort_by_date_desc(recs):
|
||||||
|
"""Sortiert Domains nach Zeitstempel absteigend (jüngste zuerst).
|
||||||
|
|
||||||
|
Domains ohne Zeitstempel wandern ans Ende. Bei gleichem Datum bleibt die
|
||||||
|
vorherige (alphabetische) Reihenfolge erhalten – sorted() ist stabil, auch
|
||||||
|
mit reverse=True.
|
||||||
|
"""
|
||||||
|
recs.sort(key=lambda r: (r['datum'] is not None, r['datum'] or ""), reverse=True)
|
||||||
|
return recs
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -198,10 +230,12 @@ def main():
|
|||||||
records = []
|
records = []
|
||||||
for d in domains:
|
for d in domains:
|
||||||
name = d.get('domain', '')
|
name = d.get('domain', '')
|
||||||
|
ziffer, datum = get_group(name)
|
||||||
records.append({
|
records.append({
|
||||||
'name': name,
|
'name': name,
|
||||||
'status': d.get('status', ''),
|
'status': d.get('status', ''),
|
||||||
'ziffer': get_group(name),
|
'ziffer': ziffer,
|
||||||
|
'datum': datum,
|
||||||
'ns': get_nameservers(api, name),
|
'ns': get_nameservers(api, name),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -212,7 +246,7 @@ def main():
|
|||||||
print()
|
print()
|
||||||
for ziffer, klarname in owners.items():
|
for ziffer, klarname in owners.items():
|
||||||
print(f"{ziffer} ({klarname})")
|
print(f"{ziffer} ({klarname})")
|
||||||
matching = [r for r in records if r['ziffer'] == ziffer]
|
matching = sort_by_date_desc([r for r in records if r['ziffer'] == ziffer])
|
||||||
if matching:
|
if matching:
|
||||||
for rec in matching:
|
for rec in matching:
|
||||||
print(format_domain_line(rec))
|
print(format_domain_line(rec))
|
||||||
@@ -222,7 +256,7 @@ def main():
|
|||||||
print() # Leerzeile zwischen den Gruppen
|
print() # Leerzeile zwischen den Gruppen
|
||||||
|
|
||||||
# Domains, die keiner Ziffer aus domain_owner zugeordnet sind
|
# Domains, die keiner Ziffer aus domain_owner zugeordnet sind
|
||||||
rest = [r for r in records if r['ziffer'] not in owners]
|
rest = sort_by_date_desc([r for r in records if r['ziffer'] not in owners])
|
||||||
if rest:
|
if rest:
|
||||||
print("Ohne Zuordnung")
|
print("Ohne Zuordnung")
|
||||||
for rec in rest:
|
for rec in rest:
|
||||||
|
|||||||
Reference in New Issue
Block a user