feat: option to add own IP api, and better error checks
All checks were successful
golangci-lint / lint (push) Successful in 38s
All checks were successful
golangci-lint / lint (push) Successful in 38s
This commit is contained in:
parent
e937474aa8
commit
e63ab9a14d
4 changed files with 76 additions and 46 deletions
|
@ -18,18 +18,17 @@ this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
utils "git.nadeko.net/fijxu/simple-ddns-client/internal"
|
||||
)
|
||||
|
||||
type Porkbun struct {
|
||||
|
@ -53,10 +52,10 @@ type Config struct {
|
|||
UpdateInterval int `json:"updateInterval"`
|
||||
Provider string `json:"provider"`
|
||||
DnsServer string `json:"dnsServer"`
|
||||
PublicIpApi string `json:"publicIpApi"`
|
||||
Porkbun Porkbun `json:"porkbun"`
|
||||
}
|
||||
|
||||
var client *http.Client
|
||||
var config *Config
|
||||
|
||||
// https://stackoverflow.com/questions/59889882/specifying-dns-server-for-lookup-in-go
|
||||
|
@ -80,22 +79,32 @@ var resolver = &net.Resolver{
|
|||
|
||||
// TODO: Use UPNP, NAT-PMP or with PCP
|
||||
func getIpAddress() string {
|
||||
req := doGetRequest("https://api.ipify.org")
|
||||
req, err := utils.DoGetRequest(config.PublicIpApi)
|
||||
if err != nil {
|
||||
log.Print("Failed to retrieve public ip address from " + config.PublicIpApi + ": " + err.Error())
|
||||
return ""
|
||||
}
|
||||
return string(req)
|
||||
}
|
||||
|
||||
func (p *Porkbun) updateIp() {
|
||||
dnsIp, err := resolver.LookupHost(context.Background(), p.Domain)
|
||||
if err != nil {
|
||||
log.Print("Failed to retrieve IP address for domain " + p.Domain)
|
||||
log.Print("Failed to retrieve IP address for domain " + p.Domain + ": " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
log.Print("Current IP of the record " + p.Domain + " is " + dnsIp[0])
|
||||
if len(dnsIp) > 1 {
|
||||
log.Fatal("The record '" + p.Domain + "' can't contain more than 1 IP address!")
|
||||
}
|
||||
if string(dnsIp[0]) == p.Data.Ip {
|
||||
log.Print("No need to update the IP address of domain '" + p.Domain + "'. IP is already " + p.Data.Ip)
|
||||
return
|
||||
}
|
||||
log.Print("Current IP of the record '" + p.Domain + "' is " + dnsIp[0])
|
||||
|
||||
p.Data.Ip = getIpAddress()
|
||||
|
||||
if string(dnsIp[0]) == p.Data.Ip {
|
||||
log.Print("No need to update the IP address of domain " + p.Domain + ". IP is already " + p.Data.Ip)
|
||||
if p.Data.Ip == "" {
|
||||
log.Print("Failed to retrieve current public IP address")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -111,7 +120,11 @@ func (p *Porkbun) updateIp() {
|
|||
data, _ := json.Marshal(&p.Data)
|
||||
queryUrl := domain + "/" + p.Type + "/" + subDomain
|
||||
|
||||
res := doPostRequest("https://api.porkbun.com/api/json/v3/dns/editByNameType/"+queryUrl, data)
|
||||
res, err := utils.DoPostRequest("https://api.porkbun.com/api/json/v3/dns/editByNameType/"+queryUrl, data)
|
||||
if err != nil {
|
||||
log.Print("Failed to update public IP address: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Porkbun returns `{"status":"SUCCESS"}` if the IP address has been
|
||||
// updated successfully
|
||||
|
@ -145,40 +158,7 @@ func loadConfig(configPath string) *Config {
|
|||
return config
|
||||
}
|
||||
|
||||
func doGetRequest(url string) []byte {
|
||||
request, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
res, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func doPostRequest(url string, data []byte) []byte {
|
||||
request, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
res, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func init() {
|
||||
client = &http.Client{}
|
||||
var configPath string
|
||||
|
||||
flag.StringVar(&configPath, "c", "/etc/simple-ddns-client/config.json", "config.json path")
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"updateInterval": 60,
|
||||
"dnsServer": "1.1.1.1:53",
|
||||
"provider": "porkbun",
|
||||
"publicIpApi": "https://api.ipify.org",
|
||||
"porkbun": {
|
||||
"apiKey": "pk1_xxx",
|
||||
"secretApiKey": "sk1_xxx",
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,3 @@
|
|||
module git.nadeko.net/simple-ddns-client
|
||||
module git.nadeko.net/fijxu/simple-ddns-client
|
||||
|
||||
go 1.23.4
|
49
internal/utils.go
Normal file
49
internal/utils.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var client = &http.Client{}
|
||||
|
||||
func DoGetRequest(url string) ([]byte, error) {
|
||||
request, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func DoPostRequest(url string, data []byte) ([]byte, error) {
|
||||
request, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
Loading…
Add table
Reference in a new issue