1package easydns
2
3import (
4	"bytes"
5	"encoding/json"
6	"fmt"
7	"io"
8	"net/http"
9	"path"
10)
11
12const defaultEndpoint = "https://rest.easydns.net"
13
14type zoneRecord struct {
15	ID      string `json:"id,omitempty"`
16	Domain  string `json:"domain"`
17	Host    string `json:"host"`
18	TTL     string `json:"ttl"`
19	Prio    string `json:"prio"`
20	Type    string `json:"type"`
21	Rdata   string `json:"rdata"`
22	LastMod string `json:"last_mod,omitempty"`
23	Revoked int    `json:"revoked,omitempty"`
24	NewHost string `json:"new_host,omitempty"`
25}
26
27type addRecordResponse struct {
28	Msg    string     `json:"msg"`
29	Tm     int        `json:"tm"`
30	Data   zoneRecord `json:"data"`
31	Status int        `json:"status"`
32}
33
34func (d *DNSProvider) addRecord(domain string, record interface{}) (string, error) {
35	pathAdd := path.Join("/zones/records/add", domain, "TXT")
36
37	response := &addRecordResponse{}
38	err := d.doRequest(http.MethodPut, pathAdd, record, response)
39	if err != nil {
40		return "", err
41	}
42
43	recordID := response.Data.ID
44
45	return recordID, nil
46}
47
48func (d *DNSProvider) deleteRecord(domain, recordID string) error {
49	pathDelete := path.Join("/zones/records", domain, recordID)
50
51	return d.doRequest(http.MethodDelete, pathDelete, nil, nil)
52}
53
54func (d *DNSProvider) doRequest(method, resource string, requestMsg, responseMsg interface{}) error {
55	reqBody := &bytes.Buffer{}
56	if requestMsg != nil {
57		err := json.NewEncoder(reqBody).Encode(requestMsg)
58		if err != nil {
59			return err
60		}
61	}
62
63	endpoint, err := d.config.Endpoint.Parse(resource + "?format=json")
64	if err != nil {
65		return err
66	}
67
68	request, err := http.NewRequest(method, endpoint.String(), reqBody)
69	if err != nil {
70		return err
71	}
72
73	request.Header.Set("Content-Type", "application/json")
74	request.Header.Set("Accept", "application/json")
75	request.SetBasicAuth(d.config.Token, d.config.Key)
76
77	response, err := d.config.HTTPClient.Do(request)
78	if err != nil {
79		return err
80	}
81	defer response.Body.Close()
82
83	if response.StatusCode >= http.StatusBadRequest {
84		body, err := io.ReadAll(response.Body)
85		if err != nil {
86			return fmt.Errorf("%d: failed to read response body: %w", response.StatusCode, err)
87		}
88
89		return fmt.Errorf("%d: request failed: %v", response.StatusCode, string(body))
90	}
91
92	if responseMsg != nil {
93		return json.NewDecoder(response.Body).Decode(responseMsg)
94	}
95
96	return nil
97}
98