package main import ( "flag" "fmt" "io" "io/ioutil" "ncddns/mod" "ncddns/providers/gandi" "ncddns/providers/namecheap" "ncddns/providers/porkbun" "net/http" "os" "strings" ) var ( byName = map[string]IPSetter{ "namecheap": namecheap.Client{}, "gandi": gandi.Client{}, "porkbun": porkbun.Client{}, } ) type IPSetter interface { IPSet([]mod.IPSetRequest) error } type DomainTuple struct { Domain string Password string Setter IPSetter } 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, ",", 3) if len(parts) != 3 { continue } setter, ok := byName[parts[0]] if !ok { return nil, fmt.Errorf("line [%s] has unsupported provider [%s]", line, parts[0]) } tuples = append(tuples, DomainTuple{ Domain: parts[1], Password: parts[2], Setter: setter, }) } 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 = cfgEntry.Setter.IPSet([]mod.IPSetRequest{ { IP: ip, Domain: cfgEntry.Domain, Password: cfgEntry.Password, Host: "*", }, { IP: ip, Domain: cfgEntry.Domain, Password: cfgEntry.Password, Host: "@", }, }) 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 strings.TrimSpace(string(body)), nil }