initial commit
This commit is contained in:
commit
d6f01c31c0
|
@ -0,0 +1,2 @@
|
||||||
|
nc.conf
|
||||||
|
ncddns
|
|
@ -0,0 +1,132 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
baseURL = "https://dynamicdns.park-your-domain.com/update?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DomainTuple struct {
|
||||||
|
Domain string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Config(path string) ([]DomainTuple, error) {
|
||||||
|
conf, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read conf: %w", err)
|
||||||
|
}
|
||||||
|
tuples := []DomainTuple{}
|
||||||
|
for _, line := range strings.Split(string(conf), "\n") {
|
||||||
|
line := strings.TrimSpace(line)
|
||||||
|
if !strings.Contains(line, "=") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parts := strings.SplitN(line, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tuples = append(tuples, DomainTuple{
|
||||||
|
Domain: parts[0],
|
||||||
|
Password: parts[1],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return tuples, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatal(name string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, name, err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfgPath := flag.String("config", "nc.conf", "config file path")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
ip, err := IP()
|
||||||
|
if err != nil {
|
||||||
|
fatal("ip", err)
|
||||||
|
}
|
||||||
|
cfg, err := Config(*cfgPath)
|
||||||
|
if err != nil {
|
||||||
|
fatal("config", err)
|
||||||
|
}
|
||||||
|
for _, cfgEntry := range cfg {
|
||||||
|
fmt.Println(cfgEntry.Domain)
|
||||||
|
if err := Set(ip, cfgEntry.Domain, cfgEntry.Password, "*"); err != nil {
|
||||||
|
fatal(cfgEntry.Domain, err)
|
||||||
|
}
|
||||||
|
if err := Set(ip, cfgEntry.Domain, cfgEntry.Password, "@"); err != nil {
|
||||||
|
fatal(cfgEntry.Domain, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IP() (string, error) {
|
||||||
|
resp, err := http.Get("https://ipv4.icanhazip.com")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("get ip: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("read body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(body), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
ResponseNumber int16 `xml:"response>ResponseNumber"`
|
||||||
|
ResponseString string `xml:"response>ResponseString"`
|
||||||
|
}
|
||||||
|
type Err struct {
|
||||||
|
Err1, Err2, Err3, Err4 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type NameCheapXMLResponse struct {
|
||||||
|
Command string
|
||||||
|
Language string
|
||||||
|
ErrCount int
|
||||||
|
Errors []Err
|
||||||
|
ResponseCount int
|
||||||
|
Responses []Response
|
||||||
|
Done bool
|
||||||
|
Debug []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func Set(ip, domain, password, host string) error {
|
||||||
|
params := url.Values{}
|
||||||
|
params.Add("host", host)
|
||||||
|
params.Add("domain", domain)
|
||||||
|
params.Add("password", password)
|
||||||
|
params.Add("ip", ip)
|
||||||
|
|
||||||
|
resp, err := http.Get(fmt.Sprintf("%s%s", baseURL, params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("request: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
fmt.Fprintf(os.Stderr, "got status [%d]: %s\n", resp.StatusCode, string(data))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue