forked from TrueCloudLab/lego
179 lines
3.6 KiB
Go
179 lines
3.6 KiB
Go
|
package rimuhosting
|
||
|
|
||
|
import (
|
||
|
"encoding/xml"
|
||
|
"errors"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"regexp"
|
||
|
|
||
|
querystring "github.com/google/go-querystring/query"
|
||
|
)
|
||
|
|
||
|
// Base URL for the RimuHosting DNS services.
|
||
|
const (
|
||
|
DefaultZonomiBaseURL = "https://zonomi.com/app/dns/dyndns.jsp"
|
||
|
DefaultRimuHostingBaseURL = "https://rimuhosting.com/app/dns/dyndns.jsp"
|
||
|
)
|
||
|
|
||
|
// Action names.
|
||
|
const (
|
||
|
SetAction = "SET"
|
||
|
QueryAction = "QUERY"
|
||
|
DeleteAction = "DELETE"
|
||
|
)
|
||
|
|
||
|
// Client the RimuHosting/Zonomi client.
|
||
|
type Client struct {
|
||
|
apiKey string
|
||
|
|
||
|
HTTPClient *http.Client
|
||
|
BaseURL string
|
||
|
}
|
||
|
|
||
|
// NewClient Creates a RimuHosting/Zonomi client.
|
||
|
func NewClient(apiKey string) *Client {
|
||
|
return &Client{
|
||
|
HTTPClient: http.DefaultClient,
|
||
|
BaseURL: DefaultZonomiBaseURL,
|
||
|
apiKey: apiKey,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// FindTXTRecords Finds TXT records.
|
||
|
// ex:
|
||
|
// - https://zonomi.com/app/dns/dyndns.jsp?action=QUERY&name=example.com&api_key=apikeyvaluehere
|
||
|
// - https://zonomi.com/app/dns/dyndns.jsp?action=QUERY&name=**.example.com&api_key=apikeyvaluehere
|
||
|
func (c Client) FindTXTRecords(domain string) ([]Record, error) {
|
||
|
action := ActionParameter{
|
||
|
Action: QueryAction,
|
||
|
Name: domain,
|
||
|
Type: "TXT",
|
||
|
}
|
||
|
|
||
|
resp, err := c.DoActions(action)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return resp.Actions.Action.Records, nil
|
||
|
}
|
||
|
|
||
|
// DoActions performs actions.
|
||
|
func (c Client) DoActions(actions ...ActionParameter) (*DNSAPIResult, error) {
|
||
|
if len(actions) == 0 {
|
||
|
return nil, errors.New("no action")
|
||
|
}
|
||
|
|
||
|
resp := &DNSAPIResult{}
|
||
|
|
||
|
if len(actions) == 1 {
|
||
|
action := actionParameter{
|
||
|
ActionParameter: actions[0],
|
||
|
APIKey: c.apiKey,
|
||
|
}
|
||
|
|
||
|
err := c.do(action, resp)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return resp, nil
|
||
|
}
|
||
|
|
||
|
multi := c.toMultiParameters(actions)
|
||
|
err := c.do(multi, resp)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return resp, nil
|
||
|
}
|
||
|
|
||
|
func (c Client) toMultiParameters(params []ActionParameter) multiActionParameter {
|
||
|
multi := multiActionParameter{
|
||
|
APIKey: c.apiKey,
|
||
|
}
|
||
|
|
||
|
for _, parameters := range params {
|
||
|
multi.Action = append(multi.Action, parameters.Action)
|
||
|
multi.Name = append(multi.Name, parameters.Name)
|
||
|
multi.Type = append(multi.Type, parameters.Type)
|
||
|
multi.Value = append(multi.Value, parameters.Value)
|
||
|
multi.TTL = append(multi.TTL, parameters.TTL)
|
||
|
}
|
||
|
|
||
|
return multi
|
||
|
}
|
||
|
|
||
|
func (c Client) do(params interface{}, data interface{}) error {
|
||
|
baseURL, err := url.Parse(c.BaseURL)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
v, err := querystring.Values(params)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
exp := regexp.MustCompile(`(%5B)(%5D)(\d+)=`)
|
||
|
|
||
|
baseURL.RawQuery = exp.ReplaceAllString(v.Encode(), "${1}${3}${2}=")
|
||
|
|
||
|
req, err := http.NewRequest(http.MethodGet, baseURL.String(), nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
resp, err := c.HTTPClient.Do(req)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
defer func() { _ = resp.Body.Close() }()
|
||
|
|
||
|
all, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if resp.StatusCode/100 != 2 {
|
||
|
r := APIError{}
|
||
|
err = xml.Unmarshal(all, &r)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
if data != nil {
|
||
|
err := xml.Unmarshal(all, data)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// AddRecord helper to create an action to add a TXT record.
|
||
|
func AddRecord(domain string, content string, ttl int) ActionParameter {
|
||
|
return ActionParameter{
|
||
|
Action: SetAction,
|
||
|
Name: domain,
|
||
|
Type: "TXT",
|
||
|
Value: content,
|
||
|
TTL: ttl,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// DeleteRecord helper to create an action to delete a TXT record.
|
||
|
func DeleteRecord(domain string, content string) ActionParameter {
|
||
|
return ActionParameter{
|
||
|
Action: DeleteAction,
|
||
|
Name: domain,
|
||
|
Type: "TXT",
|
||
|
Value: content,
|
||
|
}
|
||
|
}
|