Skip to content

Commit

Permalink
DD24
Browse files Browse the repository at this point in the history
  • Loading branch information
qdm12 committed Mar 17, 2021
1 parent 3ad9168 commit c9e2208
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Cloudflare
- DDNSS.de
- DigitalOcean
- [DD24](domaindiscount24.com)
- DonDominio
- DNSOMatic
- DNSPod
Expand Down Expand Up @@ -130,6 +131,7 @@ Check the documentation for your DNS provider:
- [Cloudflare](https://github.com/qdm12/ddns-updater/blob/master/docs/cloudflare.md)
- [DDNSS.de](https://github.com/qdm12/ddns-updater/blob/master/docs/ddnss.de.md)
- [DigitalOcean](https://github.com/qdm12/ddns-updater/blob/master/docs/digitalocean.md)
- [DD24](https://github.com/qdm12/ddns-updater/blob/master/docs/domaindiscount24.md)
- [DonDominio](https://github.com/qdm12/ddns-updater/blob/master/docs/dondominio.md)
- [DNSOMatic](https://github.com/qdm12/ddns-updater/blob/master/docs/dnsomatic.md)
- [DNSPod](https://github.com/qdm12/ddns-updater/blob/master/docs/dnspod.md)
Expand Down
29 changes: 29 additions & 0 deletions docs/dd24.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Domain Discount 24

## Configuration

### Example

```json
{
"settings": [
{
"provider": "dd24",
"domain": "domain.com",
"host": "@",
"password": "password",
"ip_version": "ipv4"
}
]
}
```

### Compulsory parameters

- `"domain"`
- `"host"` is your host and can be a subdomain or `"@"`
- `"password"` is your password

### Optional parameters

- `"ip_version"` can be `ipv4` (A records) or `ipv6` (AAAA records), defaults to `ipv4 or ipv6`
2 changes: 2 additions & 0 deletions internal/constants/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "github.com/qdm12/ddns-updater/internal/models"
const (
CLOUDFLARE models.Provider = "cloudflare"
DIGITALOCEAN models.Provider = "digitalocean"
DD24 models.Provider = "dd24"
DDNSSDE models.Provider = "ddnss"
DONDOMINIO models.Provider = "dondominio"
DNSOMATIC models.Provider = "dnsomatic"
Expand Down Expand Up @@ -34,6 +35,7 @@ func ProviderChoices() []models.Provider {
return []models.Provider{
CLOUDFLARE,
DIGITALOCEAN,
DD24,
DDNSSDE,
DONDOMINIO,
DNSOMATIC,
Expand Down
2 changes: 2 additions & 0 deletions internal/params/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ func makeSettingsFromObject(common commonSettings, rawSettings json.RawMessage,
settingsConstructor = settings.NewCloudflare
case constants.DIGITALOCEAN:
settingsConstructor = settings.NewDigitalOcean
case constants.DD24:
settingsConstructor = settings.NewDD24
case constants.DDNSSDE:
settingsConstructor = settings.NewDdnss
case constants.DONDOMINIO:
Expand Down
143 changes: 143 additions & 0 deletions internal/settings/dd24.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package settings

import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/url"
"strings"

"github.com/qdm12/ddns-updater/internal/constants"
"github.com/qdm12/ddns-updater/internal/models"
"github.com/qdm12/ddns-updater/internal/regex"
)

type dd24 struct {
domain string
host string
ipVersion models.IPVersion
password string
useProviderIP bool
}

func NewDD24(data json.RawMessage, domain, host string, ipVersion models.IPVersion,
_ regex.Matcher) (s Settings, err error) {
extraSettings := struct {
Password string `json:"password"`
UseProviderIP bool `json:"provider_ip"`
}{}
if err := json.Unmarshal(data, &extraSettings); err != nil {
return nil, err
}
d := &dd24{
domain: domain,
host: host,
ipVersion: ipVersion,
password: extraSettings.Password,
useProviderIP: extraSettings.UseProviderIP,
}
if err := d.isValid(); err != nil {
return nil, err
}
return d, nil
}

func (d *dd24) isValid() error {
if len(d.password) == 0 {
return ErrEmptyPassword
}
return nil
}

func (d *dd24) String() string {
return toString(d.domain, d.host, constants.DD24, d.ipVersion)
}

func (d *dd24) Domain() string {
return d.domain
}

func (d *dd24) Host() string {
return d.host
}

func (d *dd24) IPVersion() models.IPVersion {
return d.ipVersion
}

func (d *dd24) Proxied() bool {
return false
}

func (d *dd24) BuildDomainName() string {
return buildDomainName(d.host, d.domain)
}

func (d *dd24) HTML() models.HTMLRow {
return models.HTMLRow{
Domain: models.HTML(fmt.Sprintf("<a href=\"http://%s\">%s</a>", d.BuildDomainName(), d.BuildDomainName())),
Host: models.HTML(d.Host()),
Provider: "<a href=\"https://www.domaindiscount24.com/\">DD24</a>",
IPVersion: models.HTML(d.ipVersion),
}
}

func (d *dd24) setHeaders(request *http.Request) {
setUserAgent(request)
}

func (d *dd24) Update(ctx context.Context, client *http.Client, ip net.IP) (newIP net.IP, err error) {
// see https://www.domaindiscount24.com/faq/en/dynamic-dns
u := url.URL{
Scheme: "https",
Host: "dynamicdns.key-systems.net",
Path: "/update.php",
}
values := url.Values{}
values.Set("hostname", d.BuildDomainName())
values.Set("password", d.password)
if d.useProviderIP {
values.Set("hostname", "auto")
} else {
values.Set("hostname", ip.String())
}
u.RawQuery = values.Encode()

request, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
d.setHeaders(request)

response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()

b, err := io.ReadAll(response.Body)
if err != nil {
return nil, fmt.Errorf("%w: %s", ErrUnmarshalResponse, err)
}
s := string(b)

if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%w: %d: %s",
ErrBadHTTPStatus, response.StatusCode, bodyDataToSingleLine(s))
}

s = strings.ToLower(s)

switch {
case strings.Contains(s, "authorization failed"):
return nil, ErrAuth
case s == "":
return ip, nil
// TODO missing cases
default:
return nil, fmt.Errorf("%w: %s", ErrUnknownResponse, s)
}
}

0 comments on commit c9e2208

Please sign in to comment.