Files
digitalocean-ddns/digitalocean/client.go
T
2021-09-12 20:09:08 -04:00

91 lines
2.0 KiB
Go

package digitalocean
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
type client struct {
baseUrl string
domain string
token string
httpClient *http.Client
}
func NewClient(baseUrl, token, domain string) *client {
return &client{
baseUrl: baseUrl,
domain: domain,
token: token,
httpClient: &http.Client{
Timeout: 30 * time.Second,
},
}
}
func (c *client) GetARecordID() (string, error) {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/domains/%s/records", c.baseUrl, c.domain), nil)
if err != nil {
return "", err
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.token))
var records RecordsResponse
err = c.doRequest(req, &records)
if err != nil {
return "", err
}
for _, record := range records.DomainRecords {
if record.Name == "vpn" && record.Type == "A" {
return strconv.Itoa(int(record.Id)), nil
}
}
return "", ErrNotFound
}
func (c *client) SetARecord(id, ip string) error {
body := fmt.Sprintf(`{"data":%q}`, strings.ReplaceAll(ip, "\n", ""))
req, err := http.NewRequest(http.MethodPatch, fmt.Sprintf("%s/v2/domains/%s/records/%s", c.baseUrl, c.domain, id), bytes.NewBufferString(body))
if err != nil {
return err
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.token))
req.Header.Add("Content-Type", "application/json")
var resp map[string]interface{}
err = c.doRequest(req, &resp)
return err
}
func (c *client) doRequest(req *http.Request, output interface{}) error {
resp, err := c.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusInternalServerError {
return fmt.Errorf("%w: statuscode %d", ErrServerError, resp.StatusCode)
}
if resp.StatusCode >= http.StatusBadRequest {
return fmt.Errorf("%w: statuscode %d", ErrClientError, resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
err = json.Unmarshal(body, &output)
return err
}