commit daf7f88148b3f65bc2d71dec4b44d03bbf926b0c Author: puffaboo Date: Sun Jul 31 12:57:34 2022 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..647415d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +nc.conf +ncddns diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..845213e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module ncddns + +go 1.18 diff --git a/main.go b/main.go new file mode 100644 index 0000000..b5b3e0b --- /dev/null +++ b/main.go @@ -0,0 +1,107 @@ +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() + fatal("ip", err) + cfg, err := Config(*cfgPath) + fatal("config", err) + for _, cfgEntry := range cfg { + fmt.Println(cfgEntry.Domain) + err = Set(ip, cfgEntry.Domain, cfgEntry.Password, "*") + fatal(cfgEntry.Domain, err) + err = Set(ip, cfgEntry.Domain, cfgEntry.Password, "@") + 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 +} + +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 +}