full code here: # run in bash: python3 script.py

import json
import requests

config = {
    "credentials": {
        "accountId": "66cd45876e29a3ef12708d785326d439",
        "token": "9rdS_iQ4GexfUDNM_PTqCxQVphQ5lfCHPzbuJqRA"
    },
    "record": {
        "zone": "34e2aa3dcff21eea38e9d2cb2df24460",
        "dynamaic": [
            {"domain": "marco-leong.com", "ttl": 1800, "type": "A", "proxied": True, "name": "yun"},
            {"domain": "marco-leong.com", "ttl": 1800, "type": "A", "proxied": True, "name": "jelly"},
            {"domain": "marco-leong.com", "ttl": 1800, "type": "A", "proxied": False, "name": "wire"},
            {"domain": "marco-leong.com", "ttl": 1800, "type": "A", "proxied": True, "name": "note"}
        ],
        "static": [
            {"domain": "marco-leong.com", "ttl": 1800, "type": "A", "name": "gate", "ip": "14.202.104.118"}
        ]
    }
}


# Get current external IP
def get_external_ip():
    response = requests.get('https://api.ipify.org')
    return response.text

# Fetch existing DNS records from Cloudflare
def get_existing_records(account_id, zone_id, token):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records"
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }
    response = requests.get(url, headers=headers)
    return response.json()

# Update DNS records in Cloudflare
def update_dns_record(record_id, account_id, zone_id, token, ip, name):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}"
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }
    data = {
        'type': 'A',
        'name': name,
        'content': ip,
        'ttl': 1800,
        'proxied': True
    }
    response = requests.put(url, headers=headers, json=data)
    return response.json()

# Create new DNS record in Cloudflare
def create_dns_record(account_id, zone_id, token, ip, name):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records"
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }
    data = {
        'type': 'A',
        'name': name,
        'content': ip,
        'ttl': 1800,
        'proxied': True
    }
    response = requests.post(url, headers=headers, json=data)
    return response.json()

@service
def ddns():
    # Load the configuration from the JSON file
    account_id = config['credentials']['accountId']
    token = config['credentials']['token']
    zone_id = config['record']['zone']

    
    current_ip = get_external_ip()
    existing_records = get_existing_records(account_id, zone_id, token)

    # Check dynamic records
    for record in config['record']['dynamaic']:
        name = record['name']+"."+record['domain']
        # Check if the record exists
        found = False
        for existing_record in existing_records['result']:
            if existing_record['name'] == name:
                found = True
                if existing_record['content'] != current_ip:
                    print(f"Updating record {name} from IP {existing_record['content']} to {current_ip}")
                    update_dns_record(existing_record['id'], account_id, zone_id, token, current_ip, name)
                else:
                    print("✔ \"" + name + "\" is up-to-date")
                break
        if not found:
            print(f"Creating record {name} with IP {current_ip}")
            create_dns_record(account_id, zone_id, token, current_ip, name)

    # Check static records
    for static_record in config['record']['static']:
        name = static_record['name'] + "." + static_record['domain']
        # Check if the record exists
        found = False
        for existing_record in existing_records['result']:
            if existing_record['name'] == name:
                found = True
                # Compare IPs
                current_ip = existing_record['content']
                if current_ip != static_record['ip']:
                    print(f"Updating static record {name} from IP {current_ip} to {static_record['ip']}")
                    update_dns_record(existing_record['id'], account_id, zone_id, token, static_record['ip'], name)
                else:
                    print("✔ \"" + name + "\" is up-to-date")
                break 
        if not found:
            print(f"Creating static record {name} with IP {static_record['ip']}")
            create_dns_record(account_id, zone_id, token, static_record['ip'], name)
            
if __name__ == "__main__":
    main()

why, 2025-02-12 13:32:22.187 ERROR (MainThread) [custom_components.pyscript.file.ddns.ddns] Exception in <file.ddns.ddns> line 28:
RuntimeError: Caught blocking call to putrequest with args (<urllib3.connection.HTTPSConnection object at 0x7f72463a4a50>, 'GET', '/') inside the event loop by custom integration 'pyscript' at custom_components/pyscript/eval.py, line 1982: return func(*args, **kwargs). (offender: /usr/local/lib/python3.13/site-packages/urllib3/connection.py, line 219: return _HTTPConnection.putrequest(self, method, url, *args, **kwargs)), please create a bug report at https://github.com/custom-components/pyscript/issues