mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-02-04 12:40:07 +00:00
feat: description file for custom theme; use gjson (#433)
* feat: description file for custom theme; use gjson * fix gosec * remove outdated stuff
This commit is contained in:
@@ -2,6 +2,7 @@ package ddns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -14,10 +15,13 @@ import (
|
||||
const baseEndpoint = "https://api.cloudflare.com/client/v4/zones"
|
||||
|
||||
type ProviderCloudflare struct {
|
||||
isIpv4 bool
|
||||
domainConfig *DomainConfig
|
||||
secret string
|
||||
zoneId string
|
||||
ipAddr string
|
||||
recordId string
|
||||
domainConfig *DomainConfig
|
||||
recordType string
|
||||
}
|
||||
|
||||
type cfReq struct {
|
||||
@@ -28,13 +32,6 @@ type cfReq struct {
|
||||
Proxied bool `json:"proxied"`
|
||||
}
|
||||
|
||||
type cfResp struct {
|
||||
Result []struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
func NewProviderCloudflare(s string) *ProviderCloudflare {
|
||||
return &ProviderCloudflare{
|
||||
secret: s,
|
||||
@@ -54,13 +51,19 @@ func (provider *ProviderCloudflare) UpdateDomain(domainConfig *DomainConfig) err
|
||||
|
||||
// 当IPv4和IPv6同时成功才算作成功
|
||||
if provider.domainConfig.EnableIPv4 {
|
||||
if err = provider.addDomainRecord(true); err != nil {
|
||||
provider.isIpv4 = true
|
||||
provider.recordType = getRecordString(provider.isIpv4)
|
||||
provider.ipAddr = provider.domainConfig.Ipv4Addr
|
||||
if err = provider.addDomainRecord(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if provider.domainConfig.EnableIpv6 {
|
||||
if err = provider.addDomainRecord(false); err != nil {
|
||||
provider.isIpv4 = false
|
||||
provider.recordType = getRecordString(provider.isIpv4)
|
||||
provider.ipAddr = provider.domainConfig.Ipv6Addr
|
||||
if err = provider.addDomainRecord(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -68,19 +71,18 @@ func (provider *ProviderCloudflare) UpdateDomain(domainConfig *DomainConfig) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) addDomainRecord(isIpv4 bool) error {
|
||||
err := provider.findDNSRecord(isIpv4)
|
||||
func (provider *ProviderCloudflare) addDomainRecord() error {
|
||||
err := provider.findDNSRecord()
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrGjsonNotFound) {
|
||||
// 添加 DNS 记录
|
||||
return provider.createDNSRecord()
|
||||
}
|
||||
return fmt.Errorf("查找 DNS 记录时出错: %s", err)
|
||||
}
|
||||
|
||||
if provider.recordId == "" {
|
||||
// 添加 DNS 记录
|
||||
return provider.createDNSRecord(isIpv4)
|
||||
} else {
|
||||
// 更新 DNS 记录
|
||||
return provider.updateDNSRecord(isIpv4)
|
||||
}
|
||||
// 更新 DNS 记录
|
||||
return provider.updateDNSRecord()
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) getZoneID() error {
|
||||
@@ -96,35 +98,22 @@ func (provider *ProviderCloudflare) getZoneID() error {
|
||||
return err
|
||||
}
|
||||
|
||||
res := &cfResp{}
|
||||
err = utils.Json.Unmarshal(body, res)
|
||||
result, err := utils.GjsonGet(body, "result.0.id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := res.Result
|
||||
if len(result) > 0 {
|
||||
provider.zoneId = result[0].ID
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("找不到 Zone ID")
|
||||
provider.zoneId = result.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) findDNSRecord(isIPv4 bool) error {
|
||||
var ipType string
|
||||
if isIPv4 {
|
||||
ipType = "A"
|
||||
} else {
|
||||
ipType = "AAAA"
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) findDNSRecord() error {
|
||||
de, _ := url.JoinPath(baseEndpoint, provider.zoneId, "dns_records")
|
||||
du, _ := url.Parse(de)
|
||||
|
||||
q := du.Query()
|
||||
q.Set("name", provider.domainConfig.FullDomain)
|
||||
q.Set("type", ipType)
|
||||
q.Set("type", provider.recordType)
|
||||
du.RawQuery = q.Encode()
|
||||
|
||||
body, err := provider.sendRequest("GET", du.String(), nil)
|
||||
@@ -132,36 +121,21 @@ func (provider *ProviderCloudflare) findDNSRecord(isIPv4 bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
res := &cfResp{}
|
||||
err = utils.Json.Unmarshal(body, res)
|
||||
result, err := utils.GjsonGet(body, "result.0.id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := res.Result
|
||||
if len(result) > 0 {
|
||||
provider.recordId = result[0].ID
|
||||
return nil
|
||||
}
|
||||
|
||||
provider.recordId = result.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) createDNSRecord(isIPv4 bool) error {
|
||||
var ipType, ipAddr string
|
||||
if isIPv4 {
|
||||
ipType = "A"
|
||||
ipAddr = provider.domainConfig.Ipv4Addr
|
||||
} else {
|
||||
ipType = "AAAA"
|
||||
ipAddr = provider.domainConfig.Ipv6Addr
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) createDNSRecord() error {
|
||||
de, _ := url.JoinPath(baseEndpoint, provider.zoneId, "dns_records")
|
||||
data := &cfReq{
|
||||
Name: provider.domainConfig.FullDomain,
|
||||
Type: ipType,
|
||||
Content: ipAddr,
|
||||
Type: provider.recordType,
|
||||
Content: provider.ipAddr,
|
||||
TTL: 60,
|
||||
Proxied: false,
|
||||
}
|
||||
@@ -171,21 +145,12 @@ func (provider *ProviderCloudflare) createDNSRecord(isIPv4 bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) updateDNSRecord(isIPv4 bool) error {
|
||||
var ipType, ipAddr string
|
||||
if isIPv4 {
|
||||
ipType = "A"
|
||||
ipAddr = provider.domainConfig.Ipv4Addr
|
||||
} else {
|
||||
ipType = "AAAA"
|
||||
ipAddr = provider.domainConfig.Ipv6Addr
|
||||
}
|
||||
|
||||
func (provider *ProviderCloudflare) updateDNSRecord() error {
|
||||
de, _ := url.JoinPath(baseEndpoint, provider.zoneId, "dns_records", provider.recordId)
|
||||
data := &cfReq{
|
||||
Name: provider.domainConfig.FullDomain,
|
||||
Type: ipType,
|
||||
Content: ipAddr,
|
||||
Type: provider.recordType,
|
||||
Content: provider.ipAddr,
|
||||
TTL: 60,
|
||||
Proxied: false,
|
||||
}
|
||||
|
||||
@@ -20,3 +20,10 @@ func splitDomain(domain string) (prefix string, realDomain string) {
|
||||
prefix = domain[:len(domain)-len(realDomain)-1]
|
||||
return prefix, realDomain
|
||||
}
|
||||
|
||||
func getRecordString(isIpv4 bool) string {
|
||||
if isIpv4 {
|
||||
return "A"
|
||||
}
|
||||
return "AAAA"
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -19,10 +20,14 @@ import (
|
||||
const te = "https://dnspod.tencentcloudapi.com"
|
||||
|
||||
type ProviderTencentCloud struct {
|
||||
isIpv4 bool
|
||||
domainConfig *DomainConfig
|
||||
recordID uint64
|
||||
recordType string
|
||||
secretID string
|
||||
secretKey string
|
||||
domainConfig *DomainConfig
|
||||
resp *tcResp
|
||||
errCode string
|
||||
ipAddr string
|
||||
}
|
||||
|
||||
type tcReq struct {
|
||||
@@ -36,18 +41,6 @@ type tcReq struct {
|
||||
RecordId uint64 `json:"RecordId,omitempty"`
|
||||
}
|
||||
|
||||
type tcResp struct {
|
||||
Response struct {
|
||||
RecordList []struct {
|
||||
RecordId uint64
|
||||
Value string
|
||||
}
|
||||
Error struct {
|
||||
Code string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewProviderTencentCloud(id, key string) *ProviderTencentCloud {
|
||||
return &ProviderTencentCloud{
|
||||
secretID: id,
|
||||
@@ -64,13 +57,19 @@ func (provider *ProviderTencentCloud) UpdateDomain(domainConfig *DomainConfig) e
|
||||
// 当IPv4和IPv6同时成功才算作成功
|
||||
var err error
|
||||
if provider.domainConfig.EnableIPv4 {
|
||||
if err = provider.addDomainRecord(true); err != nil {
|
||||
provider.isIpv4 = true
|
||||
provider.recordType = getRecordString(provider.isIpv4)
|
||||
provider.ipAddr = provider.domainConfig.Ipv4Addr
|
||||
if err = provider.addDomainRecord(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if provider.domainConfig.EnableIpv6 {
|
||||
if err = provider.addDomainRecord(false); err != nil {
|
||||
provider.isIpv4 = false
|
||||
provider.recordType = getRecordString(provider.isIpv4)
|
||||
provider.ipAddr = provider.domainConfig.Ipv6Addr
|
||||
if err = provider.addDomainRecord(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -78,33 +77,26 @@ func (provider *ProviderTencentCloud) UpdateDomain(domainConfig *DomainConfig) e
|
||||
return err
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) addDomainRecord(isIpv4 bool) error {
|
||||
err := provider.findDNSRecord(isIpv4)
|
||||
func (provider *ProviderTencentCloud) addDomainRecord() error {
|
||||
err := provider.findDNSRecord()
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找 DNS 记录时出错: %s", err)
|
||||
}
|
||||
|
||||
if provider.resp.Response.Error.Code == "ResourceNotFound.NoDataOfRecord" { // 没有找到 DNS 记录
|
||||
return provider.createDNSRecord(isIpv4)
|
||||
} else if provider.resp.Response.Error.Code != "" {
|
||||
return fmt.Errorf("查询 DNS 记录时出错,错误代码为: %s", provider.resp.Response.Error.Code)
|
||||
if provider.errCode == "ResourceNotFound.NoDataOfRecord" { // 没有找到 DNS 记录
|
||||
return provider.createDNSRecord()
|
||||
} else if provider.errCode != "" {
|
||||
return fmt.Errorf("查询 DNS 记录时出错,错误代码为: %s", provider.errCode)
|
||||
}
|
||||
|
||||
// 默认情况下更新 DNS 记录
|
||||
return provider.updateDNSRecord(isIpv4)
|
||||
return provider.updateDNSRecord()
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) findDNSRecord(isIPv4 bool) error {
|
||||
var ipType string
|
||||
if isIPv4 {
|
||||
ipType = "A"
|
||||
} else {
|
||||
ipType = "AAAA"
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) findDNSRecord() error {
|
||||
prefix, realDomain := splitDomain(provider.domainConfig.FullDomain)
|
||||
data := &tcReq{
|
||||
RecordType: ipType,
|
||||
RecordType: provider.recordType,
|
||||
Domain: realDomain,
|
||||
RecordLine: "默认",
|
||||
Subdomain: prefix,
|
||||
@@ -116,32 +108,29 @@ func (provider *ProviderTencentCloud) findDNSRecord(isIPv4 bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
provider.resp = &tcResp{}
|
||||
err = utils.Json.Unmarshal(body, provider.resp)
|
||||
result, err := utils.GjsonGet(body, "Response.RecordList.0.RecordId")
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.ErrGjsonNotFound) {
|
||||
if errCode, err := utils.GjsonGet(body, "Response.Error.Code"); err == nil {
|
||||
provider.errCode = errCode.String()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
provider.recordID = result.Uint()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) createDNSRecord(isIPv4 bool) error {
|
||||
var ipType, ipAddr string
|
||||
if isIPv4 {
|
||||
ipType = "A"
|
||||
ipAddr = provider.domainConfig.Ipv4Addr
|
||||
} else {
|
||||
ipType = "AAAA"
|
||||
ipAddr = provider.domainConfig.Ipv6Addr
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) createDNSRecord() error {
|
||||
prefix, realDomain := splitDomain(provider.domainConfig.FullDomain)
|
||||
data := &tcReq{
|
||||
RecordType: ipType,
|
||||
RecordType: provider.recordType,
|
||||
RecordLine: "默认",
|
||||
Domain: realDomain,
|
||||
SubDomain: prefix,
|
||||
Value: ipAddr,
|
||||
Value: provider.ipAddr,
|
||||
TTL: 600,
|
||||
}
|
||||
|
||||
@@ -150,25 +139,16 @@ func (provider *ProviderTencentCloud) createDNSRecord(isIPv4 bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) updateDNSRecord(isIPv4 bool) error {
|
||||
var ipType, ipAddr string
|
||||
if isIPv4 {
|
||||
ipType = "A"
|
||||
ipAddr = provider.domainConfig.Ipv4Addr
|
||||
} else {
|
||||
ipType = "AAAA"
|
||||
ipAddr = provider.domainConfig.Ipv6Addr
|
||||
}
|
||||
|
||||
func (provider *ProviderTencentCloud) updateDNSRecord() error {
|
||||
prefix, realDomain := splitDomain(provider.domainConfig.FullDomain)
|
||||
data := &tcReq{
|
||||
RecordType: ipType,
|
||||
RecordType: provider.recordType,
|
||||
RecordLine: "默认",
|
||||
Domain: realDomain,
|
||||
SubDomain: prefix,
|
||||
Value: ipAddr,
|
||||
Value: provider.ipAddr,
|
||||
TTL: 600,
|
||||
RecordId: provider.resp.Response.RecordList[0].RecordId,
|
||||
RecordId: provider.recordID,
|
||||
}
|
||||
|
||||
jsonData, _ := utils.Json.Marshal(data)
|
||||
|
||||
36
pkg/utils/gjson.go
Normal file
36
pkg/utils/gjson.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrGjsonNotFound = errors.New("specified path does not exist")
|
||||
ErrGjsonWrongType = errors.New("wrong type")
|
||||
)
|
||||
|
||||
func GjsonGet(json []byte, path string) (gjson.Result, error) {
|
||||
result := gjson.GetBytes(json, path)
|
||||
if !result.Exists() {
|
||||
return result, ErrGjsonNotFound
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GjsonParseStringMap(jsonObject string) (map[string]string, error) {
|
||||
result := gjson.Parse(jsonObject)
|
||||
if !result.IsObject() {
|
||||
return nil, ErrGjsonWrongType
|
||||
}
|
||||
|
||||
ret := make(map[string]string)
|
||||
result.ForEach(func(key, value gjson.Result) bool {
|
||||
ret[key.String()] = value.String()
|
||||
return true
|
||||
})
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
33
pkg/utils/hfs.go
Normal file
33
pkg/utils/hfs.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
// HybridFS combines embed.FS and os.DirFS.
|
||||
type HybridFS struct {
|
||||
embedFS, dir fs.FS
|
||||
}
|
||||
|
||||
func NewHybridFS(embed embed.FS, subDir string, localDir string) (*HybridFS, error) {
|
||||
subFS, err := fs.Sub(embed, subDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &HybridFS{
|
||||
embedFS: subFS,
|
||||
dir: os.DirFS(localDir),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (hfs *HybridFS) Open(name string) (fs.File, error) {
|
||||
// Ensure embed files are not replaced
|
||||
if file, err := hfs.embedFS.Open(name); err == nil {
|
||||
return file, nil
|
||||
}
|
||||
|
||||
return hfs.dir.Open(name)
|
||||
}
|
||||
Reference in New Issue
Block a user