193 lines
4.4 KiB
Go
193 lines
4.4 KiB
Go
package ddns
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/gdy666/lucky/ddnscore.go"
|
|
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
|
)
|
|
|
|
const (
|
|
porkbunEndpoint string = "https://porkbun.com/api/json/v3/dns"
|
|
)
|
|
|
|
type Porkbun struct {
|
|
DNSCommon
|
|
TTL string
|
|
}
|
|
type PorkbunDomainRecord struct {
|
|
Name string `json:"name"` // subdomain
|
|
Type string `json:"type"` // record type, e.g. A AAAA CNAME
|
|
Content string `json:"content"` // value
|
|
Ttl string `json:"ttl"` // default 300
|
|
}
|
|
|
|
type PorkbunResponse struct {
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type PorkbunDomainQueryResponse struct {
|
|
*PorkbunResponse
|
|
Records []PorkbunDomainRecord `json:"records"`
|
|
}
|
|
|
|
type PorkbunApiKey struct {
|
|
AccessKey string `json:"apikey"`
|
|
SecretKey string `json:"secretapikey"`
|
|
}
|
|
|
|
type PorkbunDomainCreateOrUpdateVO struct {
|
|
*PorkbunApiKey
|
|
*PorkbunDomainRecord
|
|
}
|
|
|
|
// Init 初始化
|
|
func (pb *Porkbun) Init(task *ddnscore.DDNSTaskInfo) {
|
|
pb.DNSCommon.Init(task)
|
|
if task.TTL == "" {
|
|
// 默认600s
|
|
pb.TTL = "600"
|
|
} else {
|
|
pb.TTL = task.TTL
|
|
}
|
|
pb.SetCreateUpdateDomainFunc(pb.createUpdateDomain)
|
|
}
|
|
|
|
func (pb *Porkbun) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
|
|
|
var record PorkbunDomainQueryResponse
|
|
// 获取当前域名信息
|
|
err := pb.request(
|
|
porkbunEndpoint+fmt.Sprintf("/retrieveByNameType/%s/%s/%s", domain.DomainName, recordType, domain.SubDomain),
|
|
&PorkbunApiKey{
|
|
AccessKey: pb.task.DNS.ID,
|
|
SecretKey: pb.task.DNS.Secret,
|
|
},
|
|
&record,
|
|
)
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
if record.Status == "SUCCESS" {
|
|
if len(record.Records) > 0 {
|
|
// 存在,更新
|
|
pb.modify(&record, domain, recordType, ipAddr)
|
|
} else {
|
|
// 不存在,创建
|
|
pb.create(domain, recordType, ipAddr)
|
|
}
|
|
} else {
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, "查询现有域名记录失败")
|
|
}
|
|
}
|
|
|
|
// 创建
|
|
func (pb *Porkbun) create(domain *ddnscore.Domain, recordType string, ipAddr string) {
|
|
var response PorkbunResponse
|
|
|
|
err := pb.request(
|
|
porkbunEndpoint+fmt.Sprintf("/create/%s", domain.DomainName),
|
|
&PorkbunDomainCreateOrUpdateVO{
|
|
PorkbunApiKey: &PorkbunApiKey{
|
|
AccessKey: pb.task.DNS.ID,
|
|
SecretKey: pb.task.DNS.Secret,
|
|
},
|
|
PorkbunDomainRecord: &PorkbunDomainRecord{
|
|
Name: domain.SubDomain,
|
|
Type: recordType,
|
|
Content: ipAddr,
|
|
Ttl: pb.TTL,
|
|
},
|
|
},
|
|
&response,
|
|
)
|
|
|
|
if err == nil && response.Status == "SUCCESS" {
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
|
} else {
|
|
errMsg := fmt.Sprintf("新增域名失败:%v\n", response)
|
|
if err != nil {
|
|
errMsg += err.Error()
|
|
}
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
|
}
|
|
}
|
|
|
|
// 修改
|
|
func (pb *Porkbun) modify(record *PorkbunDomainQueryResponse, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
|
|
|
// 相同不修改
|
|
if len(record.Records) > 0 && record.Records[0].Content == ipAddr {
|
|
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
|
} else {
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
|
}
|
|
return
|
|
}
|
|
|
|
var response PorkbunResponse
|
|
|
|
err := pb.request(
|
|
porkbunEndpoint+fmt.Sprintf("/editByNameType/%s/%s/%s", domain.DomainName, recordType, domain.SubDomain),
|
|
&PorkbunDomainCreateOrUpdateVO{
|
|
PorkbunApiKey: &PorkbunApiKey{
|
|
AccessKey: pb.task.DNS.ID,
|
|
SecretKey: pb.task.DNS.Secret,
|
|
},
|
|
PorkbunDomainRecord: &PorkbunDomainRecord{
|
|
Content: ipAddr,
|
|
Ttl: pb.TTL,
|
|
},
|
|
},
|
|
&response,
|
|
)
|
|
|
|
if err == nil && response.Status == "SUCCESS" {
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
|
} else {
|
|
errMsg := fmt.Sprintf("更新域名解析失败:%v\n", response)
|
|
if err != nil {
|
|
errMsg += err.Error()
|
|
}
|
|
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
|
}
|
|
}
|
|
|
|
// request 统一请求接口
|
|
func (pb *Porkbun) request(url string, data interface{}, result interface{}) (err error) {
|
|
jsonStr := make([]byte, 0)
|
|
if data != nil {
|
|
jsonStr, _ = json.Marshal(data)
|
|
}
|
|
req, err := http.NewRequest(
|
|
"POST",
|
|
url,
|
|
bytes.NewBuffer(jsonStr),
|
|
)
|
|
if err != nil {
|
|
log.Println("http.NewRequest失败. Error: ", err)
|
|
return
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
client, e := pb.CreateHTTPClient()
|
|
if e != nil {
|
|
err = e
|
|
return
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
|
}
|