This commit is contained in:
@@ -4,4 +4,4 @@ records:
|
|||||||
ttl_seconds: 60
|
ttl_seconds: 60
|
||||||
- record: dummy.reeselink.com
|
- record: dummy.reeselink.com
|
||||||
provider: unifi
|
provider: unifi
|
||||||
ttl_seconds: 14400
|
ttl_seconds: 60
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
from typing import Literal, TypedDict
|
from typing import Literal, TypedDict
|
||||||
|
|
||||||
|
import requests
|
||||||
import yaml
|
import yaml
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
@@ -67,6 +68,10 @@ UNIFI_SITE_ID = os.getenv("UNIFI_SITE_ID")
|
|||||||
UNIFI_API_TOKEN = os.getenv("UNIFI_API_TOKEN")
|
UNIFI_API_TOKEN = os.getenv("UNIFI_API_TOKEN")
|
||||||
UNIFI_VERIFY_SSL = os.getenv("UNIFI_VERIFY_SSL", "false").lower() == "true"
|
UNIFI_VERIFY_SSL = os.getenv("UNIFI_VERIFY_SSL", "false").lower() == "true"
|
||||||
|
|
||||||
|
NTFY_URL = os.getenv("NTFY_URL", "")
|
||||||
|
NTFY_TOPIC = os.getenv("NTFY_TOPIC", "")
|
||||||
|
NTFY_API_KEY = os.getenv("NTFY_API_KEY", "")
|
||||||
|
|
||||||
|
|
||||||
class Route53RecordType(TypedDict):
|
class Route53RecordType(TypedDict):
|
||||||
record: str
|
record: str
|
||||||
@@ -86,6 +91,28 @@ class RecordYamlStruct(TypedDict):
|
|||||||
records: list[Route53RecordType | UnifiRecordType]
|
records: list[Route53RecordType | UnifiRecordType]
|
||||||
|
|
||||||
|
|
||||||
|
def send_ntfy_notification(title: str, message: str, priority: int = 3) -> None:
|
||||||
|
if not NTFY_URL or not NTFY_TOPIC:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
headers = {
|
||||||
|
"Title": title,
|
||||||
|
"Priority": str(priority),
|
||||||
|
}
|
||||||
|
if NTFY_API_KEY:
|
||||||
|
headers["Authorization"] = f"Bearer {NTFY_API_KEY}"
|
||||||
|
response = requests.post(
|
||||||
|
f"{NTFY_URL}/{NTFY_TOPIC}",
|
||||||
|
data=message.encode(),
|
||||||
|
headers=headers,
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
logger.debug("NTFY notification sent: %s", title)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Failed to send NTFY notification: %s", e)
|
||||||
|
|
||||||
|
|
||||||
def get_ipv4() -> str:
|
def get_ipv4() -> str:
|
||||||
logger.debug("Executing: curl -4 ifconfig.me")
|
logger.debug("Executing: curl -4 ifconfig.me")
|
||||||
result = subprocess.run(["curl", "-4", "ifconfig.me"], capture_output=True)
|
result = subprocess.run(["curl", "-4", "ifconfig.me"], capture_output=True)
|
||||||
@@ -216,30 +243,75 @@ def main() -> None:
|
|||||||
exit(1)
|
exit(1)
|
||||||
logger.info("Public IPv6 is %s", public_ipv6)
|
logger.info("Public IPv6 is %s", public_ipv6)
|
||||||
|
|
||||||
|
route53_success = True
|
||||||
|
unifi_success = True
|
||||||
|
|
||||||
if route53_records:
|
if route53_records:
|
||||||
if not ROUTE53_HOSTED_ZONE_ID:
|
if not ROUTE53_HOSTED_ZONE_ID:
|
||||||
logger.error("ROUTE53_HOSTED_ZONE_ID must be set for Route53 records!")
|
logger.error("ROUTE53_HOSTED_ZONE_ID must be set for Route53 records!")
|
||||||
exit(1)
|
route53_success = False
|
||||||
logger.info("=== Starting Route53 updates (hosted_zone_id=%s) ===", ROUTE53_HOSTED_ZONE_ID)
|
else:
|
||||||
_update_route53_records(route53_records, public_ipv4, public_ipv6)
|
logger.info("=== Starting Route53 updates (hosted_zone_id=%s) ===", ROUTE53_HOSTED_ZONE_ID)
|
||||||
logger.info("=== Finished Route53 updates ===")
|
try:
|
||||||
|
_update_route53_records(route53_records, public_ipv4, public_ipv6)
|
||||||
|
logger.info("=== Finished Route53 updates ===")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Route53 updates failed: %s", e)
|
||||||
|
route53_success = False
|
||||||
|
|
||||||
if unifi_records:
|
if unifi_records:
|
||||||
logger.info("=== Starting UniFi updates ===")
|
logger.info("=== Starting UniFi updates ===")
|
||||||
if not all([UNIFI_HOST, UNIFI_SITE_ID, UNIFI_API_TOKEN]):
|
if not all([UNIFI_HOST, UNIFI_SITE_ID, UNIFI_API_TOKEN]):
|
||||||
logger.error("UNIFI_HOST, UNIFI_SITE_ID, and UNIFI_API_TOKEN must be set for UniFi records!")
|
logger.error("UNIFI_HOST, UNIFI_SITE_ID, and UNIFI_API_TOKEN must be set for UniFi records!")
|
||||||
exit(1)
|
unifi_success = False
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
unifi_config: UnifiConfig = {
|
||||||
|
"host": UNIFI_HOST, # type: ignore
|
||||||
|
"site_id": UNIFI_SITE_ID, # type: ignore
|
||||||
|
"api_token": UNIFI_API_TOKEN, # type: ignore
|
||||||
|
"verify_ssl": UNIFI_VERIFY_SSL,
|
||||||
|
"records": unifi_records, # type: ignore[arg-type]
|
||||||
|
}
|
||||||
|
|
||||||
unifi_config: UnifiConfig = {
|
_update_unifi_records(unifi_config, public_ipv4, public_ipv6)
|
||||||
"host": UNIFI_HOST, # type: ignore
|
logger.info("=== Finished UniFi updates ===")
|
||||||
"site_id": UNIFI_SITE_ID, # type: ignore
|
except Exception as e:
|
||||||
"api_token": UNIFI_API_TOKEN, # type: ignore
|
logger.error("UniFi updates failed: %s", e)
|
||||||
"verify_ssl": UNIFI_VERIFY_SSL,
|
unifi_success = False
|
||||||
"records": unifi_records, # type: ignore[arg-type]
|
|
||||||
}
|
|
||||||
|
|
||||||
_update_unifi_records(unifi_config, public_ipv4, public_ipv6)
|
route53_domains = [r["record"] for r in route53_records]
|
||||||
logger.info("=== Finished UniFi updates ===")
|
unifi_domains = [r["record"] for r in unifi_records]
|
||||||
|
|
||||||
|
route53_lines = []
|
||||||
|
if public_ipv4:
|
||||||
|
for domain in route53_domains:
|
||||||
|
route53_lines.append(f"{domain} (A): {public_ipv4}")
|
||||||
|
if public_ipv6:
|
||||||
|
for domain in route53_domains:
|
||||||
|
route53_lines.append(f"{domain} (AAAA): {public_ipv6}")
|
||||||
|
route53_text = "\n".join(route53_lines) if route53_lines else "No IPs available"
|
||||||
|
|
||||||
|
unifi_lines = []
|
||||||
|
if public_ipv4:
|
||||||
|
for domain in unifi_domains:
|
||||||
|
unifi_lines.append(f"{domain} (A): {public_ipv4}")
|
||||||
|
if public_ipv6:
|
||||||
|
for domain in unifi_domains:
|
||||||
|
unifi_lines.append(f"{domain} (AAAA): {public_ipv6}")
|
||||||
|
unifi_text = "\n".join(unifi_lines) if unifi_lines else "No IPs available"
|
||||||
|
|
||||||
|
if route53_records:
|
||||||
|
if route53_success:
|
||||||
|
send_ntfy_notification("Route53 Update Successful", f"Records updated:\n{route53_text}", priority=4)
|
||||||
|
else:
|
||||||
|
send_ntfy_notification("Route53 Update Failed", f"Records:\n{route53_text}", priority=2)
|
||||||
|
|
||||||
|
if unifi_records:
|
||||||
|
if unifi_success:
|
||||||
|
send_ntfy_notification("UniFi Update Successful", f"Records updated:\n{unifi_text}", priority=4)
|
||||||
|
else:
|
||||||
|
send_ntfy_notification("UniFi Update Failed", f"Records:\n{unifi_text}", priority=2)
|
||||||
|
|
||||||
logger.info("=== DDNS Update Complete ===")
|
logger.info("=== DDNS Update Complete ===")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user