func (c *Client) AddTxtRecord(zoneName, fqdn, value string, ttl int) error {
	host := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), zoneName))
	reqURL, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "add-record.json"))
	if err != nil {
		return fmt.Errorf("failed to parse endpoint: %w", err)
	}
	q := reqURL.Query()
	q.Set("domain-name", zoneName)
	q.Set("host", host)
	q.Set("record", value)
	q.Set("ttl", strconv.Itoa(ttlRounder(ttl)))
	q.Set("record-type", "TXT")
	reqURL.RawQuery = q.Encode()
	raw, err := c.doRequest(http.MethodPost, reqURL)
	if err != nil {
		return err
	}
	resp := apiResponse{}
	if err = json.Unmarshal(raw, &resp); err != nil {
		return fmt.Errorf("failed to unmarshal API response: %w: %s", err, string(raw))
	}
	if resp.Status != "Success" {
		return fmt.Errorf("failed to add TXT record: %s %s", resp.Status, resp.StatusDescription)
	}
	return nil
}
AddTxtRecord adds a TXT record.
package internal
import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"
	"github.com/go-acme/lego/v4/challenge/dns01"
)
const defaultBaseURL = "https://api.cloudns.net/dns/"
type Client struct {
	authID       string
	subAuthID    string
	authPassword string
	HTTPClient   *http.Client
	BaseURL      *url.URL
}
func NewClient(authID, subAuthID, authPassword string) (*Client, error) {
	if authID == "" && subAuthID == "" {
		return nil, errors.New("credentials missing: authID or subAuthID")
	}
	if authPassword == "" {
		return nil, errors.New("credentials missing: authPassword")
	}
	baseURL, err := url.Parse(defaultBaseURL)
	if err != nil {
		return nil, err
	}
	return &Client{
		authID:       authID,
		subAuthID:    subAuthID,
		authPassword: authPassword,
		HTTPClient:   &http.Client{},
		BaseURL:      baseURL,
	}, nil
}
func (c *Client) GetZone(authFQDN string) (*Zone, error) {
	authZone, err := dns01.FindZoneByFqdn(authFQDN)
	if err != nil {
		return nil, err
	}
	authZoneName := dns01.UnFqdn(authZone)
	endpoint, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "get-zone-info.json"))
	if err != nil {
		return nil, fmt.Errorf("failed to parse endpoint: %w", err)
	}
	q := endpoint.Query()
	q.Set("domain-name", authZoneName)
	endpoint.RawQuery = q.Encode()
	result, err := c.doRequest(http.MethodGet, endpoint)
	if err != nil {
		return nil, err
	}
	var zone Zone
	if len(result) > 0 {
		if err = json.Unmarshal(result, &zone); err != nil {
			return nil, fmt.Errorf("failed to unmarshal zone: %w", err)
		}
	}
	if zone.Name == authZoneName {
		return &zone, nil
	}
	return nil, fmt.Errorf("zone %s not found for authFQDN %s", authZoneName, authFQDN)
}
func (c *Client) FindTxtRecord(zoneName, fqdn string) (*TXTRecord, error) {
	host := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), zoneName))
	reqURL, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "records.json"))
	if err != nil {
		return nil, fmt.Errorf("failed to parse endpoint: %w", err)
	}
	q := reqURL.Query()
	q.Set("domain-name", zoneName)
	q.Set("host", host)
	q.Set("type", "TXT")
	reqURL.RawQuery = q.Encode()
	result, err := c.doRequest(http.MethodGet, reqURL)
	if err != nil {
		return nil, err
	}
	if string(result) == "[]" {
		return nil, nil
	}
	var records map[string]TXTRecord
	if err = json.Unmarshal(result, &records); err != nil {
		return nil, fmt.Errorf("failed to unmarshall TXT records: %w: %s", err, string(result))
	}
	for _, record := range records {
		if record.Host == host && record.Type == "TXT" {
			return &record, nil
		}
	}
	return nil, nil
}
func (c *Client) ListTxtRecords(zoneName, fqdn string) ([]TXTRecord, error) {
	host := dns01.UnFqdn(strings.TrimSuffix(dns01.UnFqdn(fqdn), zoneName))
	reqURL, err := c.BaseURL.Parse(path.Join(c.BaseURL.Path, "records.json"))
	if err != nil {
		return nil, fmt.Errorf("failed to parse endpoint: %w", err)
	}
	q := reqURL.Query()
	q.Set("domain-name", zoneName)
	q.Set("host", host)
	q.Set("type", "TXT")
	reqURL.RawQuery = q.Encode()
	result, err := c.doRequest(http.MethodGet, reqURL)
	if err != nil {
		return nil, err
	}
	if string(result) == "[]" {
		return nil, nil
	}
	var raw map[string]TXTRecord
	if err = json.Unmarshal(result, &raw); err != nil {
		return nil, fmt.Errorf("failed to unmarshall TXT records: %w: %s", err, string(result))
	}
	var records []TXTRecord
	for _, record := range raw {
		if record.Host == host && record.Type == "TXT" {
			records = append(records, record)
		}
	}
	return records, nil
}