Skip to content

Commit

Permalink
add Dynu provider (#214)
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyYe authored Sep 29, 2023
1 parent 6a63c03 commit 2fb2cf6
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 0 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
- [Strato](#strato)
- [LoopiaSE](#loopiase)
- [OVH](#ovh)
- [Dynu](#dynu)
- [Notifications](#notifications)
- [Email](#email)
- [Telegram](#telegram)
Expand Down Expand Up @@ -94,6 +95,7 @@
| [LoopiaSE][loopiase] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| [Hetzner][hetzner] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| [OVH][ovh] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| [Dynu][dunu] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |

[cloudflare]: https://cloudflare.com
[google.domains]: https://domains.google
Expand All @@ -110,6 +112,7 @@
[loopiase]: https://www.loopia.se/
[hetzner]: https://hetzner.com/
[ovh]: https://www.ovh.com
[dynu]: https://www.dynu.com/

Tip: You can follow this [issue](https://github.com/TimothyYe/godns/issues/76) to view the current status of DDNS for root domains.

Expand Down Expand Up @@ -719,6 +722,35 @@ More info: [help.ovhcloud.com](https://help.ovhcloud.com/csm/en-gb-api-getting-s
</details>
#### Dynu
For Dynu, you need to configure the `password`, config 1 default domain & subdomain.
<details>
<summary>Example</summary>
```json
{
"provider": "Dynu",
"password": "Your_Password",
"domains": [
{
"domain_name": "your_domain.com",
"sub_domains": [
"your_subdomain"
]
}
],
"resolver": "8.8.8.8",
"ip_urls": ["https://api.ip.sb/ip"],
"ip_type": "IPv4",
"interval": 300,
"socks5_proxy": ""
}
```
</details>
### Notifications
GoDNS can send a notification each time the IP changes.
Expand Down
76 changes: 76 additions & 0 deletions internal/provider/dynu/dynu_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package dynu

import (
"fmt"
"io"
"net/http"
"strings"

"github.com/TimothyYe/godns/internal/settings"
"github.com/TimothyYe/godns/internal/utils"
log "github.com/sirupsen/logrus"
)

const (
// URL the API address for dynu.
URL = "https://api.dynu.com/nic/update?hostname=%s&password=%s&%s"
)

// DNSProvider struct.
type DNSProvider struct {
configuration *settings.Settings
}

// Init passes DNS settings and store it to provider instance.
func (provider *DNSProvider) Init(conf *settings.Settings) {
provider.configuration = conf
}

func (provider *DNSProvider) UpdateIP(domainName, subdomainName, ip string) error {
hostname := subdomainName + "." + domainName
client := utils.GetHTTPClient(provider.configuration)
return provider.update(client, hostname, subdomainName, ip)
}

func (provider *DNSProvider) update(client *http.Client, hostname, subdomain string, currentIP string) error {
var ip string
if strings.ToUpper(provider.configuration.IPType) == utils.IPV4 {
ip = fmt.Sprintf("myip=%s", currentIP)
} else if strings.ToUpper(provider.configuration.IPType) == utils.IPV6 {
ip = fmt.Sprintf("myipv6=%s", currentIP)
}

req, _ := http.NewRequest("GET", fmt.Sprintf(
URL,
hostname,
utils.GetMD5Hash(provider.configuration.Password),
ip), nil)

if provider.configuration.UserAgent != "" {
req.Header.Add("User-Agent", provider.configuration.UserAgent)
}

// update IP with HTTP GET request
resp, err := client.Do(req)
if err != nil {
// handle error
log.Error("Failed to update sub domain:", subdomain)
return err
}

defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.Error(err)
}
}(resp.Body)

body, err := io.ReadAll(resp.Body)
if err != nil || !strings.Contains(string(body), "good") {
log.Error("Failed to update the IP", err)
return err
}

log.Infof("IP updated to: %s", currentIP)
return nil
}
3 changes: 3 additions & 0 deletions internal/provider/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/TimothyYe/godns/internal/provider/dnspod"
"github.com/TimothyYe/godns/internal/provider/dreamhost"
"github.com/TimothyYe/godns/internal/provider/duck"
"github.com/TimothyYe/godns/internal/provider/dynu"
"github.com/TimothyYe/godns/internal/provider/dynv6"
"github.com/TimothyYe/godns/internal/provider/google"
"github.com/TimothyYe/godns/internal/provider/he"
Expand Down Expand Up @@ -56,6 +57,8 @@ func GetProvider(conf *settings.Settings) (IDNSProvider, error) {
provider = &hetzner.DNSProvider{}
case utils.OVH:
provider = &ovh.DNSProvider{}
case utils.DYNU:
provider = &dynu.DNSProvider{}
default:
return nil, fmt.Errorf("Unknown provider '%s'", conf.Provider)
}
Expand Down
2 changes: 2 additions & 0 deletions internal/utils/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const (
DREAMHOST = "Dreamhost"
// DYNV6 for Dynv6.
DYNV6 = "Dynv6"
// DYNU for Dynu.
DYNU = "Dynu"
// NOIP for NoIP.
NOIP = "NoIP"
// SCALEWAY for Scaleway.
Expand Down
13 changes: 13 additions & 0 deletions internal/utils/hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package utils

import (
"crypto/md5"
"encoding/hex"
)

// GetMD5Hash returns the MD5 hash of the input string.
func GetMD5Hash(input string) string {
hasher := md5.New()
hasher.Write([]byte(input))
return hex.EncodeToString(hasher.Sum(nil))
}
25 changes: 25 additions & 0 deletions internal/utils/hash_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package utils

import "testing"

func TestGetMD5Hash(t *testing.T) {
type args struct {
input string
}
tests := []struct {
name string
args args
want string
}{
{"test1", args{"test"}, "098f6bcd4621d373cade4e832627b4f6"},
{"test2", args{"test2"}, "ad0234829205b9033196ba818f7a872b"},
{"test3", args{"test3"}, "8ad8757baa8564dc136c1e07507f4a98"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetMD5Hash(tt.args.input); got != tt.want {
t.Errorf("GetMD5Hash() = %v, want %v", got, tt.want)
}
})
}
}
4 changes: 4 additions & 0 deletions internal/utils/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func CheckSettings(config *settings.Settings) error {
if config.LoginToken == "" {
return errors.New("login token cannot be empty")
}
case DYNU:
if config.Password == "" {
return errors.New("password cannot be empty")
}
case DYNV6:
if config.LoginToken == "" {
return errors.New("login token cannot be empty")
Expand Down

0 comments on commit 2fb2cf6

Please sign in to comment.