Files
ddns-go/dns/namecheap.go
jeessy2 eec98404fe feat: support english (#967)
* feat: init the i18n

* fix: porkbun

* refactor: http_util GetHTTPResponse

* fix: save

* fix: add more i18n

* feat: i18n at writing.html

* feat: README EN

* fix: default api

* fix: pic
2024-01-11 15:52:53 +08:00

136 lines
3.1 KiB
Go

package dns
import (
"io"
"net/http"
"strings"
"github.com/jeessy2/ddns-go/v5/config"
"github.com/jeessy2/ddns-go/v5/util"
)
const (
nameCheapEndpoint string = "https://dynamicdns.park-your-domain.com/update?host=#{host}&domain=#{domain}&password=#{password}&ip=#{ip}"
)
// NameCheap Domain
type NameCheap struct {
DNS config.DNS
Domains config.Domains
lastIpv4 string
lastIpv6 string
}
// NameCheap 修改域名解析结果
type NameCheapResp struct {
Status string
Errors []string
}
// Init 初始化
func (nc *NameCheap) Init(dnsConf *config.DnsConfig, ipv4cache *util.IpCache, ipv6cache *util.IpCache) {
nc.Domains.Ipv4Cache = ipv4cache
nc.Domains.Ipv6Cache = ipv6cache
nc.lastIpv4 = ipv4cache.Addr
nc.lastIpv6 = ipv6cache.Addr
nc.DNS = dnsConf.DNS
nc.Domains.GetNewIp(dnsConf)
}
// AddUpdateDomainRecords 添加或更新IPv4/IPv6记录
func (nc *NameCheap) AddUpdateDomainRecords() config.Domains {
nc.addUpdateDomainRecords("A")
nc.addUpdateDomainRecords("AAAA")
return nc.Domains
}
func (nc *NameCheap) addUpdateDomainRecords(recordType string) {
ipAddr, domains := nc.Domains.GetNewIpResult(recordType)
if ipAddr == "" {
return
}
// 防止多次发送Webhook通知
if recordType == "A" {
if nc.lastIpv4 == ipAddr {
util.Log("你的IPv4未变化, 未触发 %s 请求", "NameCheap")
return
}
} else {
// https://www.namecheap.com/support/knowledgebase/article.aspx/29/11/how-to-dynamically-update-the-hosts-ip-with-an-http-request/
util.Log("Namecheap 不支持更新 IPv6")
return
}
for _, domain := range domains {
nc.modify(domain, recordType, ipAddr)
}
}
// 修改
func (nc *NameCheap) modify(domain *config.Domain, recordType string, ipAddr string) {
var result NameCheapResp
err := nc.request(&result, ipAddr, domain)
if err != nil {
util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, result)
domain.UpdateStatus = config.UpdatedFailed
return
}
switch result.Status {
case "Success":
util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
default:
util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, result)
domain.UpdateStatus = config.UpdatedFailed
}
}
// request 统一请求接口
func (nc *NameCheap) request(result *NameCheapResp, ipAddr string, domain *config.Domain) (err error) {
var url string = nameCheapEndpoint
url = strings.ReplaceAll(url, "#{host}", domain.GetSubDomain())
url = strings.ReplaceAll(url, "#{domain}", domain.DomainName)
url = strings.ReplaceAll(url, "#{password}", nc.DNS.Secret)
url = strings.ReplaceAll(url, "#{ip}", ipAddr)
req, err := http.NewRequest(
http.MethodGet,
url,
http.NoBody,
)
if err != nil {
util.Log("异常信息: %s", err)
return
}
client := util.CreateHTTPClient()
resp, err := client.Do(req)
if err != nil {
util.Log("异常信息: %s", err)
return
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
util.Log("异常信息: %s", err)
return err
}
status := string(data)
if strings.Contains(status, "<ErrCount>0</ErrCount>") {
result.Status = "Success"
} else {
result.Status = status
}
return
}