parent
a5b58811a3
commit
6a1ce52507
|
@ -15,7 +15,7 @@ lucky
|
|||
*.out
|
||||
*.log
|
||||
*.upx
|
||||
|
||||
lucky.conf
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
|
|
@ -6,12 +6,13 @@ import (
|
|||
)
|
||||
|
||||
type AppInfo struct {
|
||||
AppName string
|
||||
Version string
|
||||
OS string
|
||||
ARCH string
|
||||
Date string
|
||||
RunTime string
|
||||
AppName string
|
||||
Version string
|
||||
OS string
|
||||
ARCH string
|
||||
Date string
|
||||
RunTime string
|
||||
GoVersion string
|
||||
}
|
||||
|
||||
var appInfo AppInfo
|
||||
|
@ -27,6 +28,7 @@ func InitAppInfo(version, date string) {
|
|||
appInfo.OS = runtime.GOOS
|
||||
appInfo.ARCH = runtime.GOARCH
|
||||
appInfo.RunTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
appInfo.GoVersion = runtime.Version()
|
||||
|
||||
time.Now().Format("2006-01-02T15:04:05Z")
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//Copyright 2022 gdy, 272288813@qq.com
|
||||
// Copyright 2022 gdy, 272288813@qq.com
|
||||
package config
|
||||
|
||||
import (
|
||||
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
@ -68,7 +69,7 @@ var programConfigureMutex sync.RWMutex
|
|||
var programConfigure *ProgramConfigure
|
||||
var configurePath string
|
||||
|
||||
//var readConfigureFileOnce sync.Once
|
||||
// var readConfigureFileOnce sync.Once
|
||||
var checkConfigureFileOnce sync.Once
|
||||
var configureFileSign int8 = -1
|
||||
|
||||
|
@ -108,8 +109,7 @@ func SetConfig(p *ProgramConfigure) error {
|
|||
func GetConfig() *ProgramConfigure {
|
||||
programConfigureMutex.RLock()
|
||||
defer programConfigureMutex.RUnlock()
|
||||
var conf ProgramConfigure
|
||||
conf = *programConfigure
|
||||
conf := *programConfigure
|
||||
return &conf
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ func GetDDNSConfigure() DDNSConfigure {
|
|||
return conf
|
||||
}
|
||||
|
||||
//保存基础配置
|
||||
// 保存基础配置
|
||||
func SetBaseConfigure(conf *BaseConfigure) error {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
|
@ -179,6 +179,11 @@ func SetDDNSConfigure(conf *DDNSConfigure) error {
|
|||
|
||||
func Read(filePath string) (err error) {
|
||||
|
||||
if runtime.GOOS == "windows" && filePath == "" {
|
||||
filePath = "lucky.conf"
|
||||
log.Printf("未指定配置文件路径,使用默认路径lucky所在位置,默认配置文件名lucky.conf")
|
||||
}
|
||||
|
||||
pc, err := readProgramConfigure(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
353
config/ddns.go
353
config/ddns.go
|
@ -2,25 +2,11 @@ package config
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/stringsp"
|
||||
)
|
||||
|
||||
// Ipv4Reg IPv4正则
|
||||
const Ipv4Reg = `((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])`
|
||||
|
||||
// Ipv6Reg IPv6正则
|
||||
const Ipv6Reg = `((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))`
|
||||
|
||||
var ipUrlAddrMap sync.Map
|
||||
|
||||
type DDNSConfigure struct {
|
||||
Enable bool `json:"Enable"`
|
||||
HttpClientSecureVerify bool `json:"HttpClientSecureVerify"`
|
||||
|
@ -45,23 +31,21 @@ type DDNSTask struct {
|
|||
Webhook
|
||||
TTL string `json:"TTL"`
|
||||
HttpClientTimeout int `json:"HttpClientTimeout"`
|
||||
//-------------------------------------
|
||||
//IpCache IpCache `json:"-"`
|
||||
DomainsState DomainsState `json:"-"`
|
||||
}
|
||||
|
||||
type Webhook struct {
|
||||
WebhookEnable bool `json:"WebhookEnable"` //Webhook开关
|
||||
WebhookCallOnGetIPfail bool `json:"WebhookCallOnGetIPfail"` //获取IP失败时触发Webhook 开关
|
||||
WebhookURL string `json:"WebhookURL"`
|
||||
WebhookMethod string `json:"WebhookMethod"`
|
||||
WebhookHeaders []string `json:"WebhookHeaders"`
|
||||
WebhookRequestBody string `json:"WebhookRequestBody"`
|
||||
WebhookSuccessContent []string `json:"WebhookSuccessContent"` //接口调用成功包含的内容
|
||||
WebhookProxy string `json:"WebhookProxy"` //使用DNS代理设置 ""表示禁用,"dns"表示使用dns的代理设置
|
||||
WebhookProxyAddr string `json:"WebhookProxyAddr"` //代理服务器IP
|
||||
WebhookProxyUser string `json:"WebhookProxyUser"` //代理用户
|
||||
WebhookProxyPassword string `json:"WebhookProxyPassword"` //代理密码
|
||||
WebhookEnable bool `json:"WebhookEnable"` //Webhook开关
|
||||
WebhookCallOnGetIPfail bool `json:"WebhookCallOnGetIPfail"` //获取IP失败时触发Webhook 开关
|
||||
WebhookURL string `json:"WebhookURL"`
|
||||
WebhookMethod string `json:"WebhookMethod"`
|
||||
WebhookHeaders []string `json:"WebhookHeaders"`
|
||||
WebhookRequestBody string `json:"WebhookRequestBody"`
|
||||
WebhookDisableCallbackSuccessContentCheck bool `json:"WebhookDisableCallbackSuccessContentCheck"` //禁用成功调用返回检测
|
||||
WebhookSuccessContent []string `json:"WebhookSuccessContent"` //接口调用成功包含的内容
|
||||
WebhookProxy string `json:"WebhookProxy"` //使用DNS代理设置 ""表示禁用,"dns"表示使用dns的代理设置
|
||||
WebhookProxyAddr string `json:"WebhookProxyAddr"` //代理服务器IP
|
||||
WebhookProxyUser string `json:"WebhookProxyUser"` //代理用户
|
||||
WebhookProxyPassword string `json:"WebhookProxyPassword"` //代理密码
|
||||
}
|
||||
|
||||
// DNSConfig DNS配置
|
||||
|
@ -81,26 +65,13 @@ type DNSConfig struct {
|
|||
}
|
||||
|
||||
type DNSCallback struct {
|
||||
URL string `json:"URL"` //请求地址
|
||||
Method string `json:"Method"` //请求方法
|
||||
Headers []string `json:"Headers"`
|
||||
RequestBody string `json:"RequestBody"`
|
||||
Server string `json:"Server"` //预设服务商
|
||||
CallbackSuccessContent []string `json:"CallbackSuccessContent"` //接口调用成功包含内容
|
||||
}
|
||||
|
||||
//Check 检测IP是否有改变
|
||||
func (d *DDNSTask) IPChangeCheck(newAddr string) bool {
|
||||
if newAddr == "" {
|
||||
return true
|
||||
}
|
||||
// 地址改变
|
||||
if d.DomainsState.IpAddr != newAddr {
|
||||
//log.Printf("公网地址改变:[%s]===>[%s]", d.DomainsInfo.IpAddr, newAddr)
|
||||
d.DomainsState.IpAddr = newAddr
|
||||
return true
|
||||
}
|
||||
return false
|
||||
URL string `json:"URL"` //请求地址
|
||||
Method string `json:"Method"` //请求方法
|
||||
Headers []string `json:"Headers"`
|
||||
RequestBody string `json:"RequestBody"`
|
||||
Server string `json:"Server"` //预设服务商
|
||||
DisableCallbackSuccessContentCheck bool `json:"DisableCallbackSuccessContentCheck"` //禁用成功调用返回检测
|
||||
CallbackSuccessContent []string `json:"CallbackSuccessContent"` //接口调用成功包含内容
|
||||
}
|
||||
|
||||
var checkIPv4URLList = []string{"https://4.ipw.cn", "http://v4.ip.zxinc.org/getip", "https://myip4.ipip.net", "https://www.taobao.com/help/getip.php", "https://ddns.oray.com/checkip", "https://ip.3322.net", "https://v4.myip.la"}
|
||||
|
@ -157,25 +128,10 @@ var DefaultIPv4DNSServerList = []string{
|
|||
// programConfigure.DDNSTaskList[taskIndex].IpCache.ForceCompare = force
|
||||
// }
|
||||
|
||||
func CleanIPUrlAddrMap() {
|
||||
keys := []string{}
|
||||
ipUrlAddrMap.Range(func(key, value any) bool {
|
||||
keys = append(keys, key.(string))
|
||||
return true
|
||||
})
|
||||
for _, k := range keys {
|
||||
ipUrlAddrMap.Delete(k)
|
||||
}
|
||||
}
|
||||
|
||||
func DDNSTaskListTaskDetailsInit() {
|
||||
func DDNSTaskListConfigureCheck() {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
for i := range programConfigure.DDNSTaskList {
|
||||
programConfigure.DDNSTaskList[i].DomainsState.Init(programConfigure.DDNSTaskList[i].Domains)
|
||||
programConfigure.DDNSTaskList[i].DomainsState.SetDomainUpdateStatus(UpdateWaiting, "")
|
||||
|
||||
//
|
||||
if programConfigure.DDNSTaskList[i].DNS.ForceInterval < 60 {
|
||||
programConfigure.DDNSTaskList[i].DNS.ForceInterval = 60
|
||||
} else if programConfigure.DDNSTaskList[i].DNS.ForceInterval > 360000 {
|
||||
|
@ -190,23 +146,6 @@ func DDNSTaskListTaskDetailsInit() {
|
|||
}
|
||||
}
|
||||
|
||||
func DDNSTaskIPCacheCheck(taskKey, ip string) (bool, error) {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
taskIndex := -1
|
||||
|
||||
for i := range programConfigure.DDNSTaskList {
|
||||
if programConfigure.DDNSTaskList[i].TaskKey == taskKey {
|
||||
taskIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if taskIndex == -1 {
|
||||
return true, fmt.Errorf("找不到key对应的DDNS任务")
|
||||
}
|
||||
return programConfigure.DDNSTaskList[taskIndex].IPChangeCheck(ip), nil
|
||||
}
|
||||
|
||||
func DDNSTaskSetWebhookCallResult(taskKey string, result bool, message string) {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
|
@ -226,29 +165,20 @@ func DDNSTaskSetWebhookCallResult(taskKey string, result bool, message string) {
|
|||
|
||||
}
|
||||
|
||||
type DDNSTaskDetails struct {
|
||||
DDNSTask
|
||||
TaskState DomainsState `json:"TaskState"`
|
||||
}
|
||||
|
||||
func GetDDNSTaskList() []DDNSTaskDetails {
|
||||
func GetDDNSTaskConfigureList() []*DDNSTask {
|
||||
programConfigureMutex.RLock()
|
||||
defer programConfigureMutex.RUnlock()
|
||||
|
||||
var resList []DDNSTaskDetails
|
||||
var resList []*DDNSTask
|
||||
|
||||
for i := range programConfigure.DDNSTaskList {
|
||||
var info DDNSTaskDetails
|
||||
programConfigure.DDNSTaskList[i].DomainsState.Mutex.RLock()
|
||||
info.DDNSTask = programConfigure.DDNSTaskList[i]
|
||||
info.TaskState = programConfigure.DDNSTaskList[i].DomainsState
|
||||
programConfigure.DDNSTaskList[i].DomainsState.Mutex.RUnlock()
|
||||
resList = append(resList, info)
|
||||
task := programConfigure.DDNSTaskList[i]
|
||||
resList = append(resList, &task)
|
||||
}
|
||||
return resList
|
||||
}
|
||||
|
||||
func GetDDNSTaskByKey(taskKey string) *DDNSTaskDetails {
|
||||
func GetDDNSTaskByKey(taskKey string) *DDNSTask {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
taskIndex := -1
|
||||
|
@ -262,51 +192,15 @@ func GetDDNSTaskByKey(taskKey string) *DDNSTaskDetails {
|
|||
if taskIndex == -1 {
|
||||
return nil
|
||||
}
|
||||
var info DDNSTaskDetails
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.Mutex.RLock()
|
||||
info.DDNSTask = programConfigure.DDNSTaskList[taskIndex]
|
||||
info.TaskState = programConfigure.DDNSTaskList[taskIndex].DomainsState
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.Mutex.RUnlock()
|
||||
return &info
|
||||
}
|
||||
res := programConfigure.DDNSTaskList[taskIndex]
|
||||
|
||||
func DDNSTaskListFlushDomainsDetails(taskKey string, state *DomainsState) {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
taskIndex := -1
|
||||
|
||||
for i := range programConfigure.DDNSTaskList {
|
||||
if programConfigure.DDNSTaskList[i].TaskKey == taskKey {
|
||||
taskIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if taskIndex == -1 {
|
||||
return
|
||||
}
|
||||
|
||||
var checkDomains []*Domain
|
||||
//防止有域名被删除
|
||||
for _, new := range state.Domains {
|
||||
for j, pre := range programConfigure.DDNSTaskList[taskIndex].DomainsState.Domains {
|
||||
if strings.Compare(new.String(), pre.String()) == 0 {
|
||||
checkDomains = append(checkDomains, programConfigure.DDNSTaskList[taskIndex].DomainsState.Domains[j])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.Domains = checkDomains
|
||||
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState = *state
|
||||
return &res
|
||||
}
|
||||
|
||||
func DDNSTaskListAdd(task *DDNSTask) error {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
task.TaskKey = stringsp.GetRandomString(16)
|
||||
task.DomainsState.Init(task.Domains)
|
||||
task.DomainsState.SetDomainUpdateStatus(UpdateWaiting, "")
|
||||
programConfigure.DDNSTaskList = append(programConfigure.DDNSTaskList, *task)
|
||||
return Save()
|
||||
}
|
||||
|
@ -382,31 +276,10 @@ func EnableDDNSTaskByKey(taskKey string, enable bool) error {
|
|||
return fmt.Errorf("开关DDNS任务失败,TaskKey不存在")
|
||||
}
|
||||
programConfigure.DDNSTaskList[taskIndex].Enable = enable
|
||||
if enable {
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.SetDomainUpdateStatus(UpdateWaiting, "")
|
||||
} else {
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.SetDomainUpdateStatus(UpdateStop, "")
|
||||
}
|
||||
|
||||
return Save()
|
||||
}
|
||||
|
||||
func UpdateDomainsStateByTaskKey(taskKey string, status updateStatusType, message string) {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
taskIndex := -1
|
||||
|
||||
for i := range programConfigure.DDNSTaskList {
|
||||
if programConfigure.DDNSTaskList[i].TaskKey == taskKey {
|
||||
taskIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if taskIndex == -1 {
|
||||
return
|
||||
}
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.SetDomainUpdateStatus(status, message)
|
||||
}
|
||||
|
||||
func UpdateTaskToDDNSTaskList(taskKey string, task DDNSTask) error {
|
||||
programConfigureMutex.Lock()
|
||||
defer programConfigureMutex.Unlock()
|
||||
|
@ -434,15 +307,7 @@ func UpdateTaskToDDNSTaskList(taskKey string, task DDNSTask) error {
|
|||
programConfigure.DDNSTaskList[taskIndex].DNS = task.DNS
|
||||
programConfigure.DDNSTaskList[taskIndex].Webhook = task.Webhook
|
||||
programConfigure.DDNSTaskList[taskIndex].TTL = task.TTL
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.IpAddr = ""
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.Init(task.Domains)
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.IPAddrHistory = task.DomainsState.IPAddrHistory
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.WebhookCallHistroy = task.DomainsState.WebhookCallHistroy
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.SetDomainUpdateStatus(UpdateWaiting, "")
|
||||
programConfigure.DDNSTaskList[taskIndex].HttpClientTimeout = task.HttpClientTimeout
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.WebhookCallErrorMsg = ""
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.WebhookCallResult = false
|
||||
programConfigure.DDNSTaskList[taskIndex].DomainsState.WebhookCallTime = ""
|
||||
|
||||
return Save()
|
||||
}
|
||||
|
@ -459,165 +324,3 @@ func DeleteDDNSTaskListlice(a []DDNSTask, deleteIndex int) []DDNSTask {
|
|||
}
|
||||
|
||||
//****************************
|
||||
|
||||
func (d *DDNSTask) GetIpAddr() (result string) {
|
||||
if d.TaskType == "IPv6" {
|
||||
return d.getIpv6Addr()
|
||||
}
|
||||
return d.getIpv4Addr()
|
||||
}
|
||||
|
||||
// getIpv4Addr 获得IPv4地址
|
||||
func (d *DDNSTask) getIpv4Addr() (result string) {
|
||||
// 判断从哪里获取IP
|
||||
if d.GetType == "netInterface" {
|
||||
result = GetIPFromNetInterface("IPv4", d.NetInterface, d.IPReg)
|
||||
// 从网卡获取IP
|
||||
// ipv4, _, err := GetNetInterface()
|
||||
// if err != nil {
|
||||
// log.Println("从网卡获得IPv4失败!")
|
||||
// return
|
||||
// }
|
||||
|
||||
// for _, netInterface := range ipv4 {
|
||||
// if netInterface.NetInterfaceName == d.NetInterface && len(netInterface.AddressList) > 0 {
|
||||
// return netInterface.AddressList[0]
|
||||
// }
|
||||
// }
|
||||
|
||||
// log.Println("从网卡中获得IPv4失败! 网卡名: ", d.NetInterface)
|
||||
return
|
||||
}
|
||||
|
||||
ddnsGlobalConf := GetDDNSConfigure()
|
||||
|
||||
client, err := httputils.CreateHttpClient(
|
||||
ddnsGlobalConf.HttpClientSecureVerify,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
time.Duration(d.HttpClientTimeout)*time.Second)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, url := range d.URL {
|
||||
url = strings.TrimSpace(url)
|
||||
|
||||
mapIp, ok := ipUrlAddrMap.Load(url)
|
||||
if ok {
|
||||
//log.Printf("URL[%s]已缓存IP[%s]", url, mapIp)
|
||||
result = mapIp.(string)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
//log.Printf("连接失败!%s查看接口能否返回IPv4地址</a>,", url)
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("读取IPv4结果失败! 接口:%s", url)
|
||||
continue
|
||||
}
|
||||
comp := regexp.MustCompile(Ipv4Reg)
|
||||
result = comp.FindString(string(body))
|
||||
if result != "" {
|
||||
ipUrlAddrMap.Store(url, result)
|
||||
return
|
||||
}
|
||||
// else {
|
||||
// log.Printf("获取IPv4结果失败! 接口: %s ,返回值: %s\n", url, result)
|
||||
// }
|
||||
}
|
||||
|
||||
log.Printf("所有查询公网IPv4的接口均获取IPv4结果失败,请检查接口或当前网络情况")
|
||||
return
|
||||
}
|
||||
|
||||
// getIpv6Addr 获得IPv6地址
|
||||
func (d *DDNSTask) getIpv6Addr() (result string) {
|
||||
// 判断从哪里获取IP
|
||||
if d.GetType == "netInterface" {
|
||||
// 从网卡获取IP
|
||||
// _, ipv6, err := GetNetInterface()
|
||||
// if err != nil {
|
||||
// log.Println("从网卡获得IPv6失败!")
|
||||
// return
|
||||
// }
|
||||
|
||||
// for _, netInterface := range ipv6 {
|
||||
// if netInterface.NetInterfaceName == d.NetInterface && len(netInterface.AddressList) > 0 {
|
||||
// if d.IPReg != "" {
|
||||
// log.Printf("IPv6将使用正则表达式 %s 进行匹配\n", d.IPReg)
|
||||
// for i := 0; i < len(netInterface.AddressList); i++ {
|
||||
// matched, err := regexp.MatchString(d.IPReg, netInterface.AddressList[i])
|
||||
// if matched && err == nil {
|
||||
// log.Println("匹配成功! 匹配到地址: ", netInterface.AddressList[i])
|
||||
// return netInterface.AddressList[i]
|
||||
// }
|
||||
// log.Printf("第 %d 个地址 %s 不匹配, 将匹配下一个地址\n", i+1, netInterface.AddressList[i])
|
||||
// }
|
||||
// log.Println("没有匹配到任何一个IPv6地址, 将使用第一个地址")
|
||||
// }
|
||||
// return netInterface.AddressList[0]
|
||||
// }
|
||||
// }
|
||||
|
||||
// log.Println("从网卡中获得IPv6失败! 网卡名: ", d.NetInterface)
|
||||
result = GetIPFromNetInterface("IPv6", d.NetInterface, d.IPReg)
|
||||
return
|
||||
}
|
||||
|
||||
ddnsGlobalConf := GetDDNSConfigure()
|
||||
client, err := httputils.CreateHttpClient(
|
||||
!ddnsGlobalConf.HttpClientSecureVerify,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
time.Duration(d.HttpClientTimeout)*time.Second)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, url := range d.URL {
|
||||
url = strings.TrimSpace(url)
|
||||
|
||||
mapIp, ok := ipUrlAddrMap.Load(url)
|
||||
if ok {
|
||||
//log.Printf("URL[%s]已缓存IP[%s]", url, mapIp)
|
||||
result = mapIp.(string)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
//log.Printf("连接失败! %s查看接口能否返回IPv6地址 ", url)
|
||||
continue
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println("读取IPv6结果失败! 接口: ", url)
|
||||
continue
|
||||
}
|
||||
comp := regexp.MustCompile(Ipv6Reg)
|
||||
result = comp.FindString(string(body))
|
||||
if result != "" {
|
||||
ipUrlAddrMap.Store(url, result)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("所有查询公网IPv6的接口均获取IPv6结果失败,请检查接口或当前网络情况")
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//Copyright 2022 gdy, 272288813@qq.com
|
||||
// Copyright 2022 gdy, 272288813@qq.com
|
||||
package config
|
||||
|
||||
import "time"
|
||||
|
||||
type WhiteListConfigure struct {
|
||||
BaseConfigure WhiteListBaseConfigure `json:"BaseConfigure`
|
||||
BaseConfigure WhiteListBaseConfigure `json:"BaseConfigure"`
|
||||
WhiteList []WhiteListItem `json:"WhiteList"` //白名单列表
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
"github.com/gdy666/lucky/thirdlib/jeessy2/ddns-go/util"
|
||||
)
|
||||
|
@ -22,15 +22,18 @@ type Alidns struct {
|
|||
TTL string
|
||||
}
|
||||
|
||||
// AlidnsRecord record
|
||||
type AlidnsRecord struct {
|
||||
DomainName string
|
||||
RecordID string
|
||||
Value string
|
||||
}
|
||||
|
||||
// AlidnsSubDomainRecords 记录
|
||||
type AlidnsSubDomainRecords struct {
|
||||
TotalCount int
|
||||
DomainRecords struct {
|
||||
Record []struct {
|
||||
DomainName string
|
||||
RecordID string
|
||||
Value string
|
||||
}
|
||||
Record []AlidnsRecord
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +44,7 @@ type AlidnsResp struct {
|
|||
}
|
||||
|
||||
// Init 初始化
|
||||
func (ali *Alidns) Init(task *config.DDNSTask) {
|
||||
func (ali *Alidns) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
ali.DNSCommon.Init(task)
|
||||
|
||||
if task.TTL == "" {
|
||||
|
@ -53,26 +56,33 @@ func (ali *Alidns) Init(task *config.DDNSTask) {
|
|||
ali.SetCreateUpdateDomainFunc(ali.createUpdateDomain)
|
||||
}
|
||||
|
||||
func (ali *Alidns) createUpdateDomain(recordType, ipAddr string, domain *config.Domain) {
|
||||
var record AlidnsSubDomainRecords
|
||||
func (ali *Alidns) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
||||
var records AlidnsSubDomainRecords
|
||||
// 获取当前域名信息
|
||||
params := url.Values{}
|
||||
params := domain.GetCustomParams()
|
||||
params.Set("Action", "DescribeSubDomainRecords")
|
||||
params.Set("DomainName", domain.DomainName)
|
||||
params.Set("SubDomain", domain.GetFullDomain())
|
||||
params.Set("Type", recordType)
|
||||
err := ali.request(params, &record)
|
||||
err := ali.request(params, &records)
|
||||
|
||||
if err != nil {
|
||||
errMsg := "更新失败[001]:\n"
|
||||
errMsg += err.Error()
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if record.TotalCount > 0 {
|
||||
if records.TotalCount > 0 {
|
||||
// 默认第一个
|
||||
recordSelected := records.DomainRecords.Record[0]
|
||||
if params.Has("RecordId") {
|
||||
for i := 0; i < len(records.DomainRecords.Record); i++ {
|
||||
if records.DomainRecords.Record[i].RecordID == params.Get("RecordId") {
|
||||
recordSelected = records.DomainRecords.Record[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
// 存在,更新
|
||||
ali.modify(record, domain, recordType, ipAddr)
|
||||
ali.modify(recordSelected, domain, recordType, ipAddr)
|
||||
} else {
|
||||
// 不存在,创建
|
||||
ali.create(domain, recordType, ipAddr)
|
||||
|
@ -80,8 +90,8 @@ func (ali *Alidns) createUpdateDomain(recordType, ipAddr string, domain *config.
|
|||
}
|
||||
|
||||
// 创建
|
||||
func (ali *Alidns) create(domain *config.Domain, recordType string, ipAddr string) {
|
||||
params := url.Values{}
|
||||
func (ali *Alidns) create(domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
params := domain.GetCustomParams()
|
||||
params.Set("Action", "AddDomainRecord")
|
||||
params.Set("DomainName", domain.DomainName)
|
||||
params.Set("RR", domain.GetSubDomain())
|
||||
|
@ -93,28 +103,29 @@ func (ali *Alidns) create(domain *config.Domain, recordType string, ipAddr strin
|
|||
err := ali.request(params, &result)
|
||||
|
||||
if err == nil && result.RecordID != "" {
|
||||
//log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("新增域名解析 %s 失败!", domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, err.Error())
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
func (ali *Alidns) modify(record AlidnsSubDomainRecords, domain *config.Domain, recordType string, ipAddr string) {
|
||||
func (ali *Alidns) modify(recordSelected AlidnsRecord, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
|
||||
// 相同不修改
|
||||
if len(record.DomainRecords.Record) > 0 && record.DomainRecords.Record[0].Value == ipAddr {
|
||||
//log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
if recordSelected.Value == ipAddr {
|
||||
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params := domain.GetCustomParams()
|
||||
params.Set("Action", "UpdateDomainRecord")
|
||||
params.Set("RR", domain.GetSubDomain())
|
||||
params.Set("RecordId", record.DomainRecords.Record[0].RecordID)
|
||||
params.Set("RecordId", recordSelected.RecordID)
|
||||
params.Set("Type", recordType)
|
||||
params.Set("Value", ipAddr)
|
||||
params.Set("TTL", ali.TTL)
|
||||
|
@ -123,11 +134,9 @@ func (ali *Alidns) modify(record AlidnsSubDomainRecords, domain *config.Domain,
|
|||
err := ali.request(params, &result)
|
||||
|
||||
if err == nil && result.RecordID != "" {
|
||||
//log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("更新域名解析 %s 失败!", domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, err.Error())
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,9 +163,9 @@ func (ali *Alidns) request(params url.Values, result interface{}) (err error) {
|
|||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
//err = util.GetHTTPResponse(resp, alidnsEndpoint, err, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
|
||||
return
|
||||
return httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
"github.com/gdy666/lucky/thirdlib/jeessy2/ddns-go/util"
|
||||
)
|
||||
|
@ -68,7 +68,7 @@ type BaiduCreateRequest struct {
|
|||
ZoneName string `json:"zoneName"`
|
||||
}
|
||||
|
||||
func (baidu *BaiduCloud) Init(task *config.DDNSTask) {
|
||||
func (baidu *BaiduCloud) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
baidu.DNSCommon.Init(task)
|
||||
|
||||
if task.TTL == "" {
|
||||
|
@ -85,7 +85,7 @@ func (baidu *BaiduCloud) Init(task *config.DDNSTask) {
|
|||
baidu.SetCreateUpdateDomainFunc(baidu.createUpdateDomain)
|
||||
}
|
||||
|
||||
func (baidu *BaiduCloud) createUpdateDomain(recordType, ipAddr string, domain *config.Domain) {
|
||||
func (baidu *BaiduCloud) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
||||
var records BaiduRecordsResp
|
||||
|
||||
requestBody := BaiduListRequest{
|
||||
|
@ -98,7 +98,7 @@ func (baidu *BaiduCloud) createUpdateDomain(recordType, ipAddr string, domain *c
|
|||
if err != nil {
|
||||
errMsg := "更新失败[001]:\n"
|
||||
errMsg += err.Error()
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,8 @@ func (baidu *BaiduCloud) createUpdateDomain(recordType, ipAddr string, domain *c
|
|||
}
|
||||
}
|
||||
|
||||
//create 创建新的解析
|
||||
func (baidu *BaiduCloud) create(domain *config.Domain, recordType string, ipAddr string) {
|
||||
// create 创建新的解析
|
||||
func (baidu *BaiduCloud) create(domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
var baiduCreateRequest = BaiduCreateRequest{
|
||||
Domain: domain.GetSubDomain(), //处理一下@
|
||||
RdType: recordType,
|
||||
|
@ -131,19 +131,22 @@ func (baidu *BaiduCloud) create(domain *config.Domain, recordType string, ipAddr
|
|||
err := baidu.request("POST", baiduEndpoint+"/v1/domain/resolve/add", baiduCreateRequest, &result)
|
||||
if err == nil {
|
||||
//log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("新增域名解析 %s 失败!", domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, err.Error())
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
//modify 更新解析
|
||||
func (baidu *BaiduCloud) modify(record BaiduRecord, domain *config.Domain, rdType string, ipAddr string) {
|
||||
// modify 更新解析
|
||||
func (baidu *BaiduCloud) modify(record BaiduRecord, domain *ddnscore.Domain, rdType string, ipAddr string) {
|
||||
//没有变化直接跳过
|
||||
if record.Rdata == ipAddr {
|
||||
//log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
}
|
||||
return
|
||||
}
|
||||
var baiduModifyRequest = BaiduModifyRequest{
|
||||
|
@ -160,10 +163,10 @@ func (baidu *BaiduCloud) modify(record BaiduRecord, domain *config.Domain, rdTyp
|
|||
err := baidu.request("POST", baiduEndpoint+"/v1/domain/resolve/edit", baiduModifyRequest, &result)
|
||||
if err == nil {
|
||||
//log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("更新域名解析 %s 失败!", domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, err.Error())
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +196,9 @@ func (baidu *BaiduCloud) request(method string, url string, data interface{}, re
|
|||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
err = httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
return httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@ package ddns
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
)
|
||||
|
||||
|
@ -15,7 +17,7 @@ type Callback struct {
|
|||
}
|
||||
|
||||
// Init 初始化
|
||||
func (cb *Callback) Init(task *config.DDNSTask) {
|
||||
func (cb *Callback) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
cb.DNSCommon.Init(task)
|
||||
|
||||
if task.TTL == "" {
|
||||
|
@ -37,7 +39,7 @@ func CopyHeadersMap(sm map[string]string) map[string]string {
|
|||
return dm
|
||||
}
|
||||
|
||||
func (cb *Callback) createUpdateDomain(recordType, ipAddr string, domain *config.Domain) {
|
||||
func (cb *Callback) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
||||
|
||||
url := replacePara(cb.task.DNS.Callback.URL, ipAddr, domain, recordType, cb.TTL)
|
||||
requestBody := replacePara(cb.task.DNS.Callback.RequestBody, ipAddr, domain, recordType, cb.TTL)
|
||||
|
@ -60,19 +62,25 @@ func (cb *Callback) createUpdateDomain(recordType, ipAddr string, domain *config
|
|||
callErr := cb.CallbackHttpClientDo(cb.task.DNS.Callback.Method, url, requestBody, headers, succcssCotentList)
|
||||
|
||||
if callErr != nil {
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, callErr.Error())
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, callErr.Error())
|
||||
return
|
||||
}
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
}
|
||||
|
||||
// replacePara 替换参数
|
||||
func replacePara(orgPara, ipAddr string, domain *config.Domain, recordType string, ttl string) (newPara string) {
|
||||
func replacePara(orgPara, ipAddr string, domain *ddnscore.Domain, recordType string, ttl string) (newPara string) {
|
||||
orgPara = strings.ReplaceAll(orgPara, "#{ip}", ipAddr)
|
||||
orgPara = strings.ReplaceAll(orgPara, "#{domain}", domain.String())
|
||||
orgPara = strings.ReplaceAll(orgPara, "#{recordType}", recordType)
|
||||
orgPara = strings.ReplaceAll(orgPara, "#{ttl}", ttl)
|
||||
|
||||
for k, v := range domain.GetCustomParams() {
|
||||
if len(v) == 1 {
|
||||
orgPara = strings.ReplaceAll(orgPara, "#{"+k+"}", v[0])
|
||||
}
|
||||
}
|
||||
|
||||
return orgPara
|
||||
}
|
||||
|
||||
|
@ -80,7 +88,9 @@ func (cb *Callback) CallbackHttpClientDo(method, url, requestBody string, header
|
|||
|
||||
globalDDNSConf := config.GetDDNSConfigure()
|
||||
dnsConf := cb.task.DNS
|
||||
respStr, err := httputils.GetStringGoutDoHttpRequest(
|
||||
statusCode, respStr, err := httputils.GetStringGoutDoHttpRequest(
|
||||
"tcp",
|
||||
"",
|
||||
method,
|
||||
url,
|
||||
requestBody,
|
||||
|
@ -94,8 +104,18 @@ func (cb *Callback) CallbackHttpClientDo(method, url, requestBody string, header
|
|||
if err != nil {
|
||||
return fmt.Errorf("Callback 调用接口[%s]出错:%s", url, err.Error())
|
||||
}
|
||||
|
||||
if cb.task.DNS.Callback.DisableCallbackSuccessContentCheck {
|
||||
if statusCode == http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("调用接口失败:\n statusCode:%d\n%s", statusCode, respStr)
|
||||
}
|
||||
|
||||
//log.Printf("接口[%s]调用响应:%s\n", url, respStr)
|
||||
|
||||
//fmt.Printf("statusCode:%d\n", statusCode)
|
||||
|
||||
for _, successContent := range callbackSuccessContent {
|
||||
if strings.Contains(respStr, successContent) {
|
||||
return nil
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
)
|
||||
|
||||
|
@ -56,7 +56,7 @@ type CloudflareStatus struct {
|
|||
}
|
||||
|
||||
// Init 初始化
|
||||
func (cf *Cloudflare) Init(task *config.DDNSTask) {
|
||||
func (cf *Cloudflare) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
cf.DNSCommon.Init(task)
|
||||
|
||||
if task.TTL == "" {
|
||||
|
@ -73,7 +73,7 @@ func (cf *Cloudflare) Init(task *config.DDNSTask) {
|
|||
cf.SetCreateUpdateDomainFunc(cf.createUpdateDomain)
|
||||
}
|
||||
|
||||
func (cf *Cloudflare) createUpdateDomain(recordType, ipAddr string, domain *config.Domain) {
|
||||
func (cf *Cloudflare) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
||||
result, err := cf.getZones(domain)
|
||||
if err != nil || len(result.Result) != 1 {
|
||||
errMsg := "更新失败[001]:\n"
|
||||
|
@ -82,7 +82,7 @@ func (cf *Cloudflare) createUpdateDomain(recordType, ipAddr string, domain *conf
|
|||
} else {
|
||||
errMsg += fmt.Sprintf("%v", result)
|
||||
}
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
||||
return
|
||||
}
|
||||
zoneID := result.Result[0].ID
|
||||
|
@ -101,7 +101,7 @@ func (cf *Cloudflare) createUpdateDomain(recordType, ipAddr string, domain *conf
|
|||
if err != nil {
|
||||
errMsg += err.Error()
|
||||
}
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ func (cf *Cloudflare) createUpdateDomain(recordType, ipAddr string, domain *conf
|
|||
}
|
||||
|
||||
// 创建
|
||||
func (cf *Cloudflare) create(zoneID string, domain *config.Domain, recordType string, ipAddr string) {
|
||||
func (cf *Cloudflare) create(zoneID string, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
record := &CloudflareRecord{
|
||||
Type: recordType,
|
||||
Name: domain.String(),
|
||||
|
@ -132,21 +132,24 @@ func (cf *Cloudflare) create(zoneID string, domain *config.Domain, recordType st
|
|||
)
|
||||
if err == nil && status.Success {
|
||||
//log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("新增域名解析 %s 失败!Messages: %s", domain, status.Messages)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, err.Error())
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
func (cf *Cloudflare) modify(result CloudflareRecordsResp, zoneID string, domain *config.Domain, recordType string, ipAddr string) {
|
||||
func (cf *Cloudflare) modify(result CloudflareRecordsResp, zoneID string, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
|
||||
for _, record := range result.Result {
|
||||
// 相同不修改
|
||||
if record.Content == ipAddr {
|
||||
//log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
}
|
||||
continue
|
||||
}
|
||||
var status CloudflareStatus
|
||||
|
@ -162,20 +165,20 @@ func (cf *Cloudflare) modify(result CloudflareRecordsResp, zoneID string, domain
|
|||
|
||||
if err == nil && status.Success {
|
||||
//log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("更新域名解析 %s 失败!Messages: %s", domain, status.Messages)
|
||||
errMsg := "更新失败"
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获得域名记录列表
|
||||
func (cf *Cloudflare) getZones(domain *config.Domain) (result CloudflareZonesResp, err error) {
|
||||
func (cf *Cloudflare) getZones(domain *ddnscore.Domain) (result CloudflareZonesResp, err error) {
|
||||
err = cf.request(
|
||||
"GET",
|
||||
fmt.Sprintf(zonesAPI+"?name=%s&status=%s&per_page=%s", domain.DomainName, "active", "50"),
|
||||
|
@ -210,7 +213,9 @@ func (cf *Cloudflare) request(method string, url string, data interface{}, resul
|
|||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
err = httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
return httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ddns
|
||||
|
||||
import "github.com/gdy666/lucky/config"
|
||||
import "github.com/gdy666/lucky/ddnscore.go"
|
||||
|
||||
// DNS interface
|
||||
type DNS interface {
|
||||
Init(task *config.DDNSTask)
|
||||
Init(task *ddnscore.DDNSTaskInfo)
|
||||
// 添加或更新IPv4/IPv6记录
|
||||
AddUpdateDomainRecords() string
|
||||
}
|
||||
|
|
|
@ -8,26 +8,28 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/stringsp"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
type DNSCommon struct {
|
||||
//Domains *config.Domains
|
||||
createUpdateDomainFunc func(recordType, ipaddr string, domain *config.Domain)
|
||||
task *config.DDNSTask
|
||||
createUpdateDomainFunc func(recordType, ipaddr string, domain *ddnscore.Domain)
|
||||
task *ddnscore.DDNSTaskInfo
|
||||
}
|
||||
|
||||
func (d *DNSCommon) SetCreateUpdateDomainFunc(f func(recordType, ipaddr string, domain *config.Domain)) {
|
||||
func (d *DNSCommon) SetCreateUpdateDomainFunc(f func(recordType, ipaddr string, domain *ddnscore.Domain)) {
|
||||
d.createUpdateDomainFunc = f
|
||||
}
|
||||
|
||||
func (d *DNSCommon) Init(task *config.DDNSTask) {
|
||||
func (d *DNSCommon) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
d.task = task
|
||||
}
|
||||
|
||||
//添加或更新IPv4/IPv6记录
|
||||
// 添加或更新IPv4/IPv6记录
|
||||
func (d *DNSCommon) AddUpdateDomainRecords() string {
|
||||
if d.task.TaskType == "IPv6" {
|
||||
|
||||
|
@ -37,19 +39,26 @@ func (d *DNSCommon) AddUpdateDomainRecords() string {
|
|||
}
|
||||
|
||||
func (d *DNSCommon) addUpdateDomainRecords(recordType string) string {
|
||||
ipAddr, change, domains := d.task.DomainsState.CheckIPChange(recordType, d.task.TaskKey, d.task.GetIpAddr)
|
||||
d.task.DomainsState.SetIPAddr(ipAddr)
|
||||
ipAddr, change := d.task.CheckIPChange()
|
||||
defer ddnscore.DDNSTaskInfoMapUpdateDomainInfo(d.task)
|
||||
|
||||
d.task.TaskState.SetIPAddr(ipAddr)
|
||||
//及时刷新IP地址显示
|
||||
config.DDNSTaskListFlushDomainsDetails(d.task.TaskKey, &d.task.DomainsState)
|
||||
ddnscore.DDNSTaskInfoMapUpdateIPInfo(d.task)
|
||||
|
||||
if ipAddr == "" {
|
||||
d.task.DomainsState.SetDomainUpdateStatus(config.UpdatePause, "获取公网IP失败")
|
||||
d.task.TaskState.SetDomainUpdateStatus(ddnscore.UpdatePause, "获取公网IP失败")
|
||||
|
||||
return ipAddr
|
||||
}
|
||||
|
||||
preFaildDomains := []*config.Domain{}
|
||||
//var preFaildDomains []ddnscore.Domain
|
||||
|
||||
if time.Since(d.task.DomainsState.LastSyncTime) > time.Second*time.Duration(d.task.DNS.ForceInterval) {
|
||||
checkDoamins := d.task.TaskState.Domains
|
||||
|
||||
//log.Printf("时间间隔:%d秒", time.Since(d.task.TaskState.LastSyncTime)/time.Second)
|
||||
|
||||
if time.Since(d.task.TaskState.LastSyncTime) > time.Second*time.Duration(d.task.DNS.ForceInterval-1) {
|
||||
//log.Printf("DDNS任务[%s]强制更新", d.task.TaskName)
|
||||
change = true
|
||||
goto sync
|
||||
|
@ -58,60 +67,87 @@ func (d *DNSCommon) addUpdateDomainRecords(recordType string) string {
|
|||
//设置原先状态成功的为继续成功
|
||||
//不成功的就更新
|
||||
if !change { //公网IP没有改变
|
||||
for i := range domains { //如果原先状态成功或不改变就刷新时间
|
||||
if domains[i].UpdateStatus == config.UpdatedNothing || domains[i].UpdateStatus == config.UpdatedSuccess {
|
||||
domains[i].SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
checkDoamins = []ddnscore.Domain{}
|
||||
for i := range d.task.TaskState.Domains { //如果原先状态成功或不改变就刷新时间
|
||||
if d.task.TaskState.Domains[i].UpdateStatus == ddnscore.UpdatedNothing ||
|
||||
d.task.TaskState.Domains[i].UpdateStatus == ddnscore.UpdatedSuccess {
|
||||
d.task.TaskState.Domains[i].SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
ddnscore.DDNSTaskInfoMapUpdateDomainInfo(d.task)
|
||||
continue
|
||||
}
|
||||
preFaildDomains = append(preFaildDomains, domains[i])
|
||||
checkDoamins = append(checkDoamins, d.task.TaskState.Domains[i])
|
||||
}
|
||||
|
||||
if len(preFaildDomains) == 0 {
|
||||
if len(checkDoamins) == 0 {
|
||||
return ipAddr
|
||||
}
|
||||
domains = preFaildDomains
|
||||
}
|
||||
|
||||
sync:
|
||||
if change {
|
||||
syncTime := time.Now()
|
||||
defer func() {
|
||||
//记录最近一次同步操作时间
|
||||
d.task.DomainsState.LastSyncTime = time.Now()
|
||||
d.task.TaskState.LastSyncTime = syncTime
|
||||
}()
|
||||
}
|
||||
|
||||
for _, domain := range domains {
|
||||
for i, _ := range checkDoamins {
|
||||
|
||||
if d.createUpdateDomainFunc == nil {
|
||||
log.Printf("ddns createUpdateDomainFunc undefine")
|
||||
break
|
||||
}
|
||||
|
||||
domain := getDomainItem(checkDoamins[i].String(), &d.task.TaskState.Domains)
|
||||
if domain == nil {
|
||||
log.Printf("getDomainItem nil")
|
||||
continue
|
||||
}
|
||||
|
||||
if d.task.DNS.ResolverDoaminCheck {
|
||||
//<-time.After(time.Second)
|
||||
|
||||
domainResolverIPaddr, _ := ResolveDomainAtServerList(recordType, domain.String(), d.task.DNS.DNSServerList)
|
||||
//log.Printf("domain:%s domainResolverIPaddr:%s ,ipaddr:%s", domain.String(), domainResolverIPaddr, ipAddr)
|
||||
|
||||
if domainResolverIPaddr == ipAddr {
|
||||
if domain.UpdateStatus == config.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
domain.SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
}
|
||||
ddnscore.DDNSTaskInfoMapUpdateDomainInfo(d.task)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
d.createUpdateDomainFunc(recordType, ipAddr, domain)
|
||||
ddnscore.DDNSTaskInfoMapUpdateDomainInfo(d.task)
|
||||
}
|
||||
|
||||
return ipAddr
|
||||
}
|
||||
|
||||
func getDomainItem(fullDomain string, domains *[]ddnscore.Domain) *ddnscore.Domain {
|
||||
if domains == nil {
|
||||
return nil
|
||||
}
|
||||
for i, domain := range *domains {
|
||||
if domain.String() == fullDomain {
|
||||
return &(*domains)[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
func (d *DNSCommon) CreateHTTPClient() (*http.Client, error) {
|
||||
ddnsGlobalConf := config.GetDDNSConfigure()
|
||||
return httputils.CreateHttpClient(
|
||||
"tcp",
|
||||
"",
|
||||
!ddnsGlobalConf.HttpClientSecureVerify,
|
||||
d.task.DNS.HttpClientProxyType,
|
||||
d.task.DNS.HttpClientProxyAddr,
|
||||
|
@ -120,7 +156,7 @@ func (d *DNSCommon) CreateHTTPClient() (*http.Client, error) {
|
|||
time.Duration(d.task.HttpClientTimeout)*time.Second)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
func ResolveDomainAtServerList(queryType, domain string, dnsServerList []string) (string, error) {
|
||||
|
||||
if len(dnsServerList) == 0 {
|
||||
|
@ -138,6 +174,11 @@ func ResolveDomainAtServerList(queryType, domain string, dnsServerList []string)
|
|||
return "", fmt.Errorf("queryType error:%s", queryType)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(domain, "*.") {
|
||||
randomStr := stringsp.GetRandomString(8)
|
||||
domain = strings.Replace(domain, "*", randomStr, 1)
|
||||
}
|
||||
|
||||
domain = dns.Fqdn(domain)
|
||||
domain, err := idna.ToASCII(domain)
|
||||
if err != nil {
|
||||
|
|
116
ddns/dnspod.go
116
ddns/dnspod.go
|
@ -5,7 +5,7 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
)
|
||||
|
||||
|
@ -43,7 +43,7 @@ type DnspodStatus struct {
|
|||
}
|
||||
|
||||
// Init 初始化
|
||||
func (dnspod *Dnspod) Init(task *config.DDNSTask) {
|
||||
func (dnspod *Dnspod) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
dnspod.DNSCommon.Init(task)
|
||||
|
||||
if task.TTL == "" {
|
||||
|
@ -55,12 +55,12 @@ func (dnspod *Dnspod) Init(task *config.DDNSTask) {
|
|||
dnspod.SetCreateUpdateDomainFunc(dnspod.createUpdateDomain)
|
||||
}
|
||||
|
||||
func (dnspod *Dnspod) createUpdateDomain(recordType, ipAddr string, domain *config.Domain) {
|
||||
func (dnspod *Dnspod) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
||||
result, err := dnspod.getRecordList(domain, recordType)
|
||||
if err != nil {
|
||||
errMsg := "更新失败[001]:\n"
|
||||
errMsg += err.Error()
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -74,85 +74,91 @@ func (dnspod *Dnspod) createUpdateDomain(recordType, ipAddr string, domain *conf
|
|||
}
|
||||
|
||||
// 创建
|
||||
func (dnspod *Dnspod) create(result DnspodRecordListResp, domain *config.Domain, recordType string, ipAddr string) {
|
||||
status, err := dnspod.commonRequest(
|
||||
recordCreateAPI,
|
||||
url.Values{
|
||||
"login_token": {dnspod.task.DNS.ID + "," + dnspod.task.DNS.Secret},
|
||||
"domain": {domain.DomainName},
|
||||
"sub_domain": {domain.GetSubDomain()},
|
||||
"record_type": {recordType},
|
||||
"record_line": {"默认"},
|
||||
"value": {ipAddr},
|
||||
"ttl": {dnspod.TTL},
|
||||
"format": {"json"},
|
||||
},
|
||||
domain,
|
||||
)
|
||||
func (dnspod *Dnspod) create(result DnspodRecordListResp, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
params := domain.GetCustomParams()
|
||||
params.Add("login_token", dnspod.task.DNS.ID+","+dnspod.task.DNS.Secret)
|
||||
params.Add("domain", domain.DomainName)
|
||||
params.Add("sub_domain", domain.GetSubDomain())
|
||||
params.Add("record_type", recordType)
|
||||
params.Add("value", ipAddr)
|
||||
params.Add("ttl", dnspod.TTL)
|
||||
params.Add("format", "json")
|
||||
|
||||
if !params.Has("record_line") {
|
||||
params.Add("record_line", "默认")
|
||||
}
|
||||
|
||||
status, err := dnspod.commonRequest(recordCreateAPI, params, domain)
|
||||
if err == nil && status.Status.Code == "1" {
|
||||
//log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("新增域名解析 %s 失败!Code: %s, Message: %s", domain, status.Status.Code, status.Status.Message)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, fmt.Sprintf("Code: %s, Message: %s", status.Status.Code, status.Status.Message))
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, fmt.Sprintf("Code: %s, Message: %s", status.Status.Code, status.Status.Message))
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
func (dnspod *Dnspod) modify(result DnspodRecordListResp, domain *config.Domain, recordType string, ipAddr string) {
|
||||
func (dnspod *Dnspod) modify(result DnspodRecordListResp, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
for _, record := range result.Records {
|
||||
// 相同不修改
|
||||
if record.Value == ipAddr {
|
||||
//log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
}
|
||||
continue
|
||||
}
|
||||
status, err := dnspod.commonRequest(
|
||||
recordModifyURL,
|
||||
url.Values{
|
||||
"login_token": {dnspod.task.DNS.ID + "," + dnspod.task.DNS.Secret},
|
||||
"domain": {domain.DomainName},
|
||||
"sub_domain": {domain.GetSubDomain()},
|
||||
"record_type": {recordType},
|
||||
"record_line": {"默认"},
|
||||
"record_id": {record.ID},
|
||||
"value": {ipAddr},
|
||||
"ttl": {dnspod.TTL},
|
||||
"format": {"json"},
|
||||
},
|
||||
domain,
|
||||
)
|
||||
params := domain.GetCustomParams()
|
||||
params.Add("login_token", dnspod.task.DNS.ID+","+dnspod.task.DNS.Secret)
|
||||
params.Add("domain", domain.DomainName)
|
||||
params.Add("sub_domain", domain.GetSubDomain())
|
||||
params.Add("record_type", recordType)
|
||||
params.Add("value", ipAddr)
|
||||
params.Add("ttl", dnspod.TTL)
|
||||
params.Add("format", "json")
|
||||
params.Add("record_id", record.ID)
|
||||
|
||||
if !params.Has("record_line") {
|
||||
params.Add("record_line", "默认")
|
||||
}
|
||||
status, err := dnspod.commonRequest(recordModifyURL, params, domain)
|
||||
if err == nil && status.Status.Code == "1" {
|
||||
//log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("更新域名解析 %s 失败!Code: %s, Message: %s", domain, status.Status.Code, status.Status.Message)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, fmt.Sprintf("Code: %s, Message: %s", status.Status.Code, status.Status.Message))
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, fmt.Sprintf("Code: %s, Message: %s", status.Status.Code, status.Status.Message))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 公共
|
||||
func (dnspod *Dnspod) commonRequest(apiAddr string, values url.Values, domain *config.Domain) (status DnspodStatus, err error) {
|
||||
resp, err := http.PostForm(
|
||||
func (dnspod *Dnspod) commonRequest(apiAddr string, values url.Values, domain *ddnscore.Domain) (status DnspodStatus, err error) {
|
||||
resp, e := http.PostForm(
|
||||
apiAddr,
|
||||
values,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
|
||||
err = httputils.GetAndParseJSONResponseFromHttpResponse(resp, &status)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获得域名记录列表
|
||||
func (dnspod *Dnspod) getRecordList(domain *config.Domain, typ string) (result DnspodRecordListResp, err error) {
|
||||
values := url.Values{
|
||||
"login_token": {dnspod.task.DNS.ID + "," + dnspod.task.DNS.Secret},
|
||||
"domain": {domain.DomainName},
|
||||
"record_type": {typ},
|
||||
"sub_domain": {domain.GetSubDomain()},
|
||||
"format": {"json"},
|
||||
}
|
||||
func (dnspod *Dnspod) getRecordList(domain *ddnscore.Domain, typ string) (result DnspodRecordListResp, err error) {
|
||||
params := domain.GetCustomParams()
|
||||
params.Add("login_token", dnspod.task.DNS.ID+","+dnspod.task.DNS.Secret)
|
||||
params.Add("domain", domain.DomainName)
|
||||
params.Add("record_type", typ)
|
||||
params.Add("sub_domain", domain.GetSubDomain())
|
||||
params.Add("format", "json")
|
||||
|
||||
client, e := dnspod.CreateHTTPClient()
|
||||
if e != nil {
|
||||
|
@ -162,9 +168,15 @@ func (dnspod *Dnspod) getRecordList(domain *config.Domain, typ string) (result D
|
|||
|
||||
resp, err := client.PostForm(
|
||||
recordListAPI,
|
||||
values,
|
||||
params,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
|
||||
err = httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
"github.com/gdy666/lucky/thirdlib/jeessy2/ddns-go/util"
|
||||
)
|
||||
|
@ -50,7 +50,7 @@ type HuaweicloudRecordsets struct {
|
|||
}
|
||||
|
||||
// Init 初始化
|
||||
func (hw *Huaweicloud) Init(task *config.DDNSTask) {
|
||||
func (hw *Huaweicloud) Init(task *ddnscore.DDNSTaskInfo) {
|
||||
hw.DNSCommon.Init(task)
|
||||
|
||||
if task.TTL == "" {
|
||||
|
@ -67,7 +67,7 @@ func (hw *Huaweicloud) Init(task *config.DDNSTask) {
|
|||
hw.SetCreateUpdateDomainFunc(hw.createUpdateDomain)
|
||||
}
|
||||
|
||||
func (hw *Huaweicloud) createUpdateDomain(recordType, ipAddr string, domain *config.Domain) {
|
||||
func (hw *Huaweicloud) createUpdateDomain(recordType, ipAddr string, domain *ddnscore.Domain) {
|
||||
var records HuaweicloudRecordsResp
|
||||
|
||||
err := hw.request(
|
||||
|
@ -80,7 +80,7 @@ func (hw *Huaweicloud) createUpdateDomain(recordType, ipAddr string, domain *con
|
|||
if err != nil {
|
||||
errMsg := "更新失败[001]:\n"
|
||||
errMsg += err.Error()
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, errMsg)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ func (hw *Huaweicloud) createUpdateDomain(recordType, ipAddr string, domain *con
|
|||
}
|
||||
|
||||
// 创建
|
||||
func (hw *Huaweicloud) create(domain *config.Domain, recordType string, ipAddr string) {
|
||||
func (hw *Huaweicloud) create(domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
zone, err := hw.getZones(domain)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -135,20 +135,23 @@ func (hw *Huaweicloud) create(domain *config.Domain, recordType string, ipAddr s
|
|||
)
|
||||
if err == nil && (len(result.Records) > 0 && result.Records[0] == ipAddr) {
|
||||
//log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("新增域名解析 %s 失败!Status: %s", domain, result.Status)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, result.Status)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
func (hw *Huaweicloud) modify(record HuaweicloudRecordsets, domain *config.Domain, recordType string, ipAddr string) {
|
||||
func (hw *Huaweicloud) modify(record HuaweicloudRecordsets, domain *ddnscore.Domain, recordType string, ipAddr string) {
|
||||
|
||||
// 相同不修改
|
||||
if len(record.Records) > 0 && record.Records[0] == ipAddr {
|
||||
//log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedNothing, "")
|
||||
if domain.UpdateStatus == ddnscore.UpdatedFailed {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedNothing, "")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -167,15 +170,15 @@ func (hw *Huaweicloud) modify(record HuaweicloudRecordsets, domain *config.Domai
|
|||
|
||||
if err == nil && (len(result.Records) > 0 && result.Records[0] == ipAddr) {
|
||||
//log.Printf("更新域名解析 %s 成功!IP: %s, 状态: %s", domain, ipAddr, result.Status)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedSuccess, "")
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedSuccess, "")
|
||||
} else {
|
||||
//log.Printf("更新域名解析 %s 失败!Status: %s", domain, result.Status)
|
||||
domain.SetDomainUpdateStatus(config.UpdatedFailed, result.Status)
|
||||
domain.SetDomainUpdateStatus(ddnscore.UpdatedFailed, result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
// 获得域名记录列表
|
||||
func (hw *Huaweicloud) getZones(domain *config.Domain) (result HuaweicloudZonesResp, err error) {
|
||||
func (hw *Huaweicloud) getZones(domain *ddnscore.Domain) (result HuaweicloudZonesResp, err error) {
|
||||
err = hw.request(
|
||||
"GET",
|
||||
fmt.Sprintf(huaweicloudEndpoint+"/v2/zones?name=%s", domain.DomainName),
|
||||
|
@ -218,7 +221,8 @@ func (hw *Huaweicloud) request(method string, url string, data interface{}, resu
|
|||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
err = httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
|
||||
return
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return httputils.GetAndParseJSONResponseFromHttpResponse(resp, result)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
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.GetSubDomain()),
|
||||
&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 := "新增域名失败"
|
||||
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.GetSubDomain()),
|
||||
&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 := "更新域名解析失败"
|
||||
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)
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/service"
|
||||
)
|
||||
|
||||
|
@ -30,19 +31,29 @@ var wg sync.WaitGroup
|
|||
|
||||
// RunOnce RunOnce
|
||||
func syncAllDomainsOnce(params ...any) {
|
||||
ddnsTaskList := config.GetDDNSTaskList()
|
||||
config.CleanIPUrlAddrMap()
|
||||
ddnsTaskList := ddnscore.GetDDNSTaskInfoList()
|
||||
ddnscore.CleanIPUrlAddrMap()
|
||||
ddnsConf := config.GetDDNSConfigure()
|
||||
|
||||
//log.Printf("批量执行DDNS任务")
|
||||
taskBeginTime := time.Now()
|
||||
|
||||
//fmt.Printf("ddnsTaskList:%v\n", ddnsTaskList)
|
||||
|
||||
for index := range ddnsTaskList {
|
||||
|
||||
task := ddnsTaskList[index]
|
||||
if !task.Enable {
|
||||
config.UpdateDomainsStateByTaskKey(task.TaskKey, config.UpdateStop, "")
|
||||
continue
|
||||
}
|
||||
|
||||
if time.Since(task.TaskState.LastWorkTime) < time.Second*15 {
|
||||
//log.Printf("[%s]太接近,忽略", task.TaskName)
|
||||
continue
|
||||
}
|
||||
|
||||
//log.Printf("task[%s] enable\n", task.TaskName)
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
|
@ -55,10 +66,10 @@ func syncAllDomainsOnce(params ...any) {
|
|||
log.Printf("syncDDNSTask[%s]panic:\n%v", task.TaskName, recoverErr)
|
||||
log.Printf("%s", debug.Stack())
|
||||
}()
|
||||
syncDDNSTask(&task)
|
||||
syncDDNSTask(task)
|
||||
}()
|
||||
|
||||
<-time.After(time.Second)
|
||||
<-time.After(time.Millisecond * 600)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
|
@ -68,6 +79,7 @@ func syncAllDomainsOnce(params ...any) {
|
|||
|
||||
nextTaskTimer := time.Second*time.Duration(ddnsConf.Intervals) - usedTime
|
||||
|
||||
//debug.FreeOSMemory()
|
||||
//log.Printf("syncAllDomainsOnce 任务完成")
|
||||
DDNSService.Timer = time.NewTimer(nextTaskTimer)
|
||||
}
|
||||
|
@ -79,8 +91,8 @@ func syncTaskDomainsOnce(params ...any) {
|
|||
case "syncDDNSTask":
|
||||
{
|
||||
//log.Printf("syncTaskDomainsOnce 单DDNS任务更新:%s", taskKey)
|
||||
config.CleanIPUrlAddrMap()
|
||||
task := config.GetDDNSTaskByKey(taskKey)
|
||||
ddnscore.CleanIPUrlAddrMap()
|
||||
task := ddnscore.GetDDNSTaskInfoByKey(taskKey)
|
||||
syncDDNSTask(task)
|
||||
}
|
||||
default:
|
||||
|
@ -89,7 +101,7 @@ func syncTaskDomainsOnce(params ...any) {
|
|||
|
||||
}
|
||||
|
||||
func syncDDNSTask(task *config.DDNSTaskDetails) {
|
||||
func syncDDNSTask(task *ddnscore.DDNSTaskInfo) {
|
||||
if task == nil {
|
||||
return
|
||||
}
|
||||
|
@ -107,15 +119,18 @@ func syncDDNSTask(task *config.DDNSTaskDetails) {
|
|||
dnsSelected = &Callback{}
|
||||
case "baiducloud":
|
||||
dnsSelected = &BaiduCloud{}
|
||||
case "porkbun":
|
||||
dnsSelected = &Porkbun{}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
dnsSelected.Init(&task.DDNSTask)
|
||||
dnsSelected.Init(task)
|
||||
|
||||
dnsSelected.AddUpdateDomainRecords()
|
||||
task.ExecWebhook(&task.TaskState)
|
||||
ddnscore.DDNSTaskInfoMapUpdate(task)
|
||||
task.TaskState.LastWorkTime = time.Now() //记录最近一次检测时间,防止批量检测和单个检测时间间隔过于接近
|
||||
|
||||
//task.DomainsState.IpAddr = ipaddr
|
||||
task.ExecWebhook(&task.DomainsState)
|
||||
|
||||
config.DDNSTaskListFlushDomainsDetails(task.TaskKey, &task.DomainsState)
|
||||
//
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package ddnscore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
)
|
||||
|
||||
var taskInfoMap sync.Map
|
||||
var taskInfoMapMutex sync.RWMutex
|
||||
var webLastAccessDDNSTaskListLastTime int64
|
||||
|
||||
// 记录最后的前端请求DDNS任务列表时间
|
||||
func FLushWebLastAccessDDNSTaskListLastTime() {
|
||||
atomic.StoreInt64(&webLastAccessDDNSTaskListLastTime, time.Now().Unix())
|
||||
}
|
||||
|
||||
// webAccessAvalid 判断前端访问是否处于活跃时间内
|
||||
func webAccessAvalid() bool {
|
||||
lastTime := atomic.LoadInt64(&webLastAccessDDNSTaskListLastTime)
|
||||
return time.Now().Unix()-lastTime <= 5
|
||||
}
|
||||
|
||||
func EnableDDNSTaskByKey(key string, enable bool) error {
|
||||
taskInfoMapMutex.Lock()
|
||||
defer taskInfoMapMutex.Unlock()
|
||||
taskInfo, ok := taskInfoMap.Load(key)
|
||||
if !ok {
|
||||
return fmt.Errorf("DDNSTaskInfoMap key[%s] no found", key)
|
||||
}
|
||||
if enable {
|
||||
taskInfo.(*DDNSTaskState).SetDomainUpdateStatus(UpdateWaiting, "")
|
||||
} else {
|
||||
taskInfo.(*DDNSTaskState).SetDomainUpdateStatus(UpdateStop, "")
|
||||
}
|
||||
return config.EnableDDNSTaskByKey(key, enable)
|
||||
}
|
||||
|
||||
func DDNSTaskInfoMapUpdate(task *DDNSTaskInfo) {
|
||||
taskInfoMapMutex.Lock()
|
||||
defer taskInfoMapMutex.Unlock()
|
||||
|
||||
preInfo, ok := taskInfoMap.Load(task.TaskKey)
|
||||
if ok {
|
||||
var checkDomains []Domain
|
||||
//防止有域名被删除
|
||||
for i, new := range task.TaskState.Domains {
|
||||
for _, pre := range preInfo.(*DDNSTaskState).Domains {
|
||||
if strings.Compare(new.String(), pre.String()) == 0 {
|
||||
checkDomains = append(checkDomains, task.TaskState.Domains[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
task.TaskState.Domains = checkDomains
|
||||
|
||||
if len(preInfo.(*DDNSTaskState).Domains) > 0 && preInfo.(*DDNSTaskState).Domains[0].UpdateStatus == UpdateStop {
|
||||
task.TaskState.SetDomainUpdateStatus(UpdateStop, "")
|
||||
}
|
||||
|
||||
taskInfoMap.Store(task.TaskKey, &task.TaskState)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 即时更新IP相关数据信息
|
||||
func DDNSTaskInfoMapUpdateIPInfo(task *DDNSTaskInfo) {
|
||||
if !webAccessAvalid() {
|
||||
//log.Printf("前端没有访问,不即时更新")
|
||||
return
|
||||
}
|
||||
//log.Printf("前端没有访问,不即时更新")
|
||||
|
||||
taskInfoMapMutex.Lock()
|
||||
defer taskInfoMapMutex.Unlock()
|
||||
state, ok := taskInfoMap.Load(task.TaskKey)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
state.(*DDNSTaskState).IpAddr = task.TaskState.IpAddr
|
||||
state.(*DDNSTaskState).IPAddrHistory = task.TaskState.IPAddrHistory
|
||||
}
|
||||
|
||||
func DDNSTaskInfoMapUpdateDomainInfo(task *DDNSTaskInfo) {
|
||||
if !webAccessAvalid() {
|
||||
//log.Printf("前端没有访问,不即时更新")
|
||||
return
|
||||
}
|
||||
//log.Printf("前端有访问,即时更新")
|
||||
|
||||
taskInfoMapMutex.Lock()
|
||||
defer taskInfoMapMutex.Unlock()
|
||||
state, ok := taskInfoMap.Load(task.TaskKey)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
state.(*DDNSTaskState).Domains = task.TaskState.Domains
|
||||
}
|
||||
|
||||
//func DDNSTaskInfo
|
||||
|
||||
func DDNSTaskInfoMapDelete(key string) {
|
||||
taskInfoMapMutex.Lock()
|
||||
defer taskInfoMapMutex.Unlock()
|
||||
taskInfoMap.Delete(key)
|
||||
}
|
||||
|
||||
func UpdateDomainsStateByTaskKey(key, status, message string) {
|
||||
taskInfoMapMutex.Lock()
|
||||
defer taskInfoMapMutex.Unlock()
|
||||
preInfo, ok := taskInfoMap.Load(key)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
preInfo.(*DDNSTaskState).SetDomainUpdateStatus(status, message)
|
||||
}
|
||||
|
||||
func GetDDNSTaskInfoList() []*DDNSTaskInfo {
|
||||
taskInfoMapMutex.RLock()
|
||||
defer taskInfoMapMutex.RUnlock()
|
||||
ddnsTaskList := config.GetDDNSTaskConfigureList()
|
||||
var res []*DDNSTaskInfo
|
||||
for i := range ddnsTaskList {
|
||||
ti := CreateDDNSTaskInfo(ddnsTaskList[i])
|
||||
res = append(res, &ti)
|
||||
taskInfoMap.Store(ddnsTaskList[i].TaskKey, &ti.TaskState)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func GetDDNSTaskInfoByKey(key string) *DDNSTaskInfo {
|
||||
taskInfoMapMutex.RLock()
|
||||
defer taskInfoMapMutex.RUnlock()
|
||||
ddnsConf := config.GetDDNSTaskByKey(key)
|
||||
if ddnsConf == nil {
|
||||
return nil
|
||||
}
|
||||
info := CreateDDNSTaskInfo(ddnsConf)
|
||||
return &info
|
||||
}
|
||||
|
||||
func CreateDDNSTaskInfo(task *config.DDNSTask) DDNSTaskInfo {
|
||||
var res DDNSTaskInfo
|
||||
res.DDNSTask = *task
|
||||
info, ok := taskInfoMap.Load(task.TaskKey)
|
||||
if ok {
|
||||
res.TaskState = *info.(*DDNSTaskState)
|
||||
} else {
|
||||
var ds DDNSTaskState
|
||||
ds.Init(res.Domains)
|
||||
if task.Enable {
|
||||
ds.SetDomainUpdateStatus(UpdateWaiting, "")
|
||||
} else {
|
||||
ds.SetDomainUpdateStatus(UpdateStop, "")
|
||||
}
|
||||
|
||||
res.TaskState = ds
|
||||
}
|
||||
return res
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package ddnscore
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// UpdatedNothing 未改变
|
||||
UpdatedNothing string = "域名IP和公网IP一致"
|
||||
// UpdatedFailed 更新失败
|
||||
UpdatedFailed = "失败"
|
||||
// UpdatedSuccess 更新成功
|
||||
UpdatedSuccess = "成功"
|
||||
// UpdateStop 暂停
|
||||
UpdateStop = "停止同步"
|
||||
//UpdatePause 暂停 获取IP失败时暂停
|
||||
UpdatePause = "暂停同步"
|
||||
// UpdateWaiting
|
||||
UpdateWaiting = "等待更新"
|
||||
)
|
||||
|
||||
// Domain 域名实体
|
||||
type Domain struct {
|
||||
DomainName string
|
||||
SubDomain string
|
||||
CustomParams string
|
||||
|
||||
UpdateStatus string // 更新状态
|
||||
LastUpdateStatusTime string //最后更新状态的时间
|
||||
Message string
|
||||
UpdateHistroy []any
|
||||
}
|
||||
|
||||
type UpdateHistroyItem struct {
|
||||
UpdateStatus string
|
||||
UpdateTime string
|
||||
}
|
||||
|
||||
func (d *Domain) String() string {
|
||||
if d.SubDomain != "" {
|
||||
return d.SubDomain + "." + d.DomainName
|
||||
}
|
||||
return d.DomainName
|
||||
}
|
||||
|
||||
// GetFullDomain 返回完整子域名
|
||||
func (d *Domain) GetFullDomain() string {
|
||||
if d.SubDomain != "" {
|
||||
return d.SubDomain + "." + d.DomainName
|
||||
}
|
||||
return "@" + "." + d.DomainName
|
||||
}
|
||||
|
||||
// GetCustomParams not be nil
|
||||
func (d *Domain) GetCustomParams() url.Values {
|
||||
if d.CustomParams != "" {
|
||||
q, err := url.ParseQuery(d.CustomParams)
|
||||
if err == nil {
|
||||
return q
|
||||
}
|
||||
}
|
||||
return url.Values{}
|
||||
}
|
||||
|
||||
// GetSubDomain 获得子域名,为空返回@
|
||||
// 阿里云,dnspod需要
|
||||
func (d *Domain) GetSubDomain() string {
|
||||
if d.SubDomain != "" {
|
||||
return d.SubDomain
|
||||
}
|
||||
return "@"
|
||||
}
|
||||
|
||||
func (d *Domain) SetDomainUpdateStatus(status string, message string) {
|
||||
|
||||
if status != UpdateWaiting {
|
||||
if status != UpdateStop || d.UpdateStatus != UpdateStop {
|
||||
d.LastUpdateStatusTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
// 状态更新历史记录
|
||||
hi := UpdateHistroyItem{UpdateStatus: string(status), UpdateTime: d.LastUpdateStatusTime}
|
||||
d.UpdateHistroy = append(d.UpdateHistroy, hi)
|
||||
if len(d.UpdateHistroy) > 10 {
|
||||
d.UpdateHistroy = DeleteAnyListlice(d.UpdateHistroy, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
d.UpdateStatus = status
|
||||
d.Message = message
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package config
|
||||
package ddnscore
|
||||
|
||||
import (
|
||||
"log"
|
|
@ -0,0 +1,177 @@
|
|||
package ddnscore
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
)
|
||||
|
||||
// Ipv4Reg IPv4正则
|
||||
const Ipv4Reg = `((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])`
|
||||
|
||||
// Ipv6Reg IPv6正则
|
||||
const Ipv6Reg = `((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))`
|
||||
|
||||
var ipUrlAddrMap sync.Map
|
||||
|
||||
type DDNSTaskInfo struct {
|
||||
config.DDNSTask
|
||||
TaskState DDNSTaskState `json:"TaskState"`
|
||||
}
|
||||
|
||||
func (d *DDNSTaskInfo) getIpAddr() (result string) {
|
||||
if d.TaskType == "IPv6" {
|
||||
return d.getIpv6Addr()
|
||||
}
|
||||
return d.getIpv4Addr()
|
||||
}
|
||||
|
||||
// CheckIPChange 检测公网IP是否改变
|
||||
func (d *DDNSTaskInfo) CheckIPChange() (ipAddr string, change bool) {
|
||||
ipAddr = d.getIpAddr()
|
||||
|
||||
checkIPChange := d.TaskState.IPChangeCheck(ipAddr)
|
||||
|
||||
if checkIPChange {
|
||||
return ipAddr, true
|
||||
}
|
||||
|
||||
//IP没变化
|
||||
return ipAddr, false
|
||||
}
|
||||
|
||||
// getIpv4Addr 获得IPv4地址
|
||||
func (d *DDNSTaskInfo) getIpv4Addr() (result string) {
|
||||
// 判断从哪里获取IP
|
||||
if d.GetType == "netInterface" {
|
||||
result = GetIPFromNetInterface("IPv4", d.NetInterface, d.IPReg)
|
||||
return
|
||||
}
|
||||
|
||||
ddnsGlobalConf := config.GetDDNSConfigure()
|
||||
|
||||
client, err := httputils.CreateHttpClient(
|
||||
"tcp4",
|
||||
"",
|
||||
ddnsGlobalConf.HttpClientSecureVerify,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
time.Duration(d.HttpClientTimeout)*time.Second)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, url := range d.URL {
|
||||
url = strings.TrimSpace(url)
|
||||
|
||||
mapIp, ok := ipUrlAddrMap.Load(url)
|
||||
if ok {
|
||||
//log.Printf("URL[%s]已缓存IP[%s]", url, mapIp)
|
||||
result = mapIp.(string)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
//log.Printf("连接失败!%s查看接口能否返回IPv4地址</a>,", url)
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("读取IPv4结果失败! 接口:%s", url)
|
||||
continue
|
||||
}
|
||||
comp := regexp.MustCompile(Ipv4Reg)
|
||||
result = comp.FindString(string(body))
|
||||
if result != "" {
|
||||
ipUrlAddrMap.Store(url, result)
|
||||
return
|
||||
}
|
||||
// else {
|
||||
// log.Printf("获取IPv4结果失败! 接口: %s ,返回值: %s\n", url, result)
|
||||
// }
|
||||
}
|
||||
|
||||
log.Printf("所有查询公网IPv4的接口均获取IPv4结果失败,请检查接口或当前网络情况")
|
||||
return
|
||||
}
|
||||
|
||||
// getIpv6Addr 获得IPv6地址
|
||||
func (d *DDNSTaskInfo) getIpv6Addr() (result string) {
|
||||
// 判断从哪里获取IP
|
||||
if d.GetType == "netInterface" {
|
||||
result = GetIPFromNetInterface("IPv6", d.NetInterface, d.IPReg)
|
||||
return
|
||||
}
|
||||
|
||||
ddnsGlobalConf := config.GetDDNSConfigure()
|
||||
client, err := httputils.CreateHttpClient(
|
||||
"tcp6",
|
||||
"",
|
||||
!ddnsGlobalConf.HttpClientSecureVerify,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
time.Duration(d.HttpClientTimeout)*time.Second)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, url := range d.URL {
|
||||
url = strings.TrimSpace(url)
|
||||
|
||||
mapIp, ok := ipUrlAddrMap.Load(url)
|
||||
if ok {
|
||||
//log.Printf("URL[%s]已缓存IP[%s]", url, mapIp)
|
||||
result = mapIp.(string)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
//log.Printf("连接失败! %s查看接口能否返回IPv6地址 ", url)
|
||||
continue
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println("读取IPv6结果失败! 接口: ", url)
|
||||
continue
|
||||
}
|
||||
comp := regexp.MustCompile(Ipv6Reg)
|
||||
result = comp.FindString(string(body))
|
||||
if result != "" {
|
||||
ipUrlAddrMap.Store(url, result)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("所有查询公网IPv6的接口均获取IPv6结果失败,请检查接口或当前网络情况")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CleanIPUrlAddrMap() {
|
||||
keys := []string{}
|
||||
ipUrlAddrMap.Range(func(key, value any) bool {
|
||||
keys = append(keys, key.(string))
|
||||
return true
|
||||
})
|
||||
for _, k := range keys {
|
||||
ipUrlAddrMap.Delete(k)
|
||||
}
|
||||
}
|
|
@ -1,45 +1,29 @@
|
|||
package config
|
||||
package ddnscore
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// UpdatedNothing 未改变
|
||||
UpdatedNothing updateStatusType = "域名IP和公网IP一致"
|
||||
// UpdatedFailed 更新失败
|
||||
UpdatedFailed = "失败"
|
||||
// UpdatedSuccess 更新成功
|
||||
UpdatedSuccess = "成功"
|
||||
// UpdateStop 暂停
|
||||
UpdateStop = "停止同步"
|
||||
//UpdatePause 暂停 获取IP失败时暂停
|
||||
UpdatePause = "暂停同步"
|
||||
// UpdateWaiting
|
||||
UpdateWaiting = "等待更新"
|
||||
)
|
||||
|
||||
// 固定的主域名
|
||||
var staticMainDomains = []string{"com.cn", "org.cn", "net.cn", "ac.cn", "eu.org"}
|
||||
|
||||
// 获取ip失败的次数
|
||||
|
||||
// Domains Ipv4/Ipv6 DomainsState
|
||||
type DomainsState struct {
|
||||
// Domains Ipv4/Ipv6 DDNSTaskState
|
||||
type DDNSTaskState struct {
|
||||
IpAddr string
|
||||
Domains []*Domain
|
||||
Domains []Domain
|
||||
WebhookCallTime string `json:"WebhookCallTime"` //最后触发时间
|
||||
WebhookCallResult bool `json:"WebhookCallResult"` //触发结果
|
||||
WebhookCallErrorMsg string `json:"WebhookCallErrorMsg"` //触发错误信息
|
||||
LastSyncTime time.Time `json:"-"` //记录最新一次同步操作时间
|
||||
LastWorkTime time.Time `json:"-"`
|
||||
|
||||
IPAddrHistory []any `json:"IPAddrHistory"`
|
||||
WebhookCallHistroy []any `json:"WebhookCallHistroy"`
|
||||
|
||||
Mutex *sync.RWMutex `json:"-"`
|
||||
}
|
||||
|
||||
type IPAddrHistoryItem struct {
|
||||
|
@ -47,33 +31,12 @@ type IPAddrHistoryItem struct {
|
|||
RecordTime string
|
||||
}
|
||||
|
||||
// Domain 域名实体
|
||||
type Domain struct {
|
||||
DomainName string
|
||||
SubDomain string
|
||||
|
||||
UpdateStatus updateStatusType // 更新状态
|
||||
LastUpdateStatusTime string //最后更新状态的时间
|
||||
Message string
|
||||
|
||||
UpdateHistroy []any
|
||||
|
||||
rwmutex *sync.RWMutex
|
||||
}
|
||||
|
||||
type UpdateHistroyItem struct {
|
||||
UpdateStatus string
|
||||
UpdateTime string
|
||||
}
|
||||
|
||||
type WebhookCallHistroyItem struct {
|
||||
CallTime string
|
||||
CallResult string
|
||||
}
|
||||
|
||||
func (d *DomainsState) SetIPAddr(ipaddr string) {
|
||||
d.Mutex.Lock()
|
||||
defer d.Mutex.Unlock()
|
||||
func (d *DDNSTaskState) SetIPAddr(ipaddr string) {
|
||||
if d.IpAddr == ipaddr {
|
||||
return
|
||||
}
|
||||
|
@ -82,18 +45,12 @@ func (d *DomainsState) SetIPAddr(ipaddr string) {
|
|||
|
||||
hi := IPAddrHistoryItem{IPaddr: ipaddr, RecordTime: time.Now().Local().Format("2006-01-02 15:04:05")}
|
||||
d.IPAddrHistory = append(d.IPAddrHistory, hi)
|
||||
|
||||
if len(d.IPAddrHistory) > 10 {
|
||||
d.IPAddrHistory = DeleteAnyListlice(d.IPAddrHistory, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (d Domain) String() string {
|
||||
if d.SubDomain != "" {
|
||||
return d.SubDomain + "." + d.DomainName
|
||||
}
|
||||
return d.DomainName
|
||||
}
|
||||
|
||||
func DeleteAnyListlice(a []any, deleteIndex int) []any {
|
||||
j := 0
|
||||
for i := range a {
|
||||
|
@ -105,13 +62,13 @@ func DeleteAnyListlice(a []any, deleteIndex int) []any {
|
|||
return a[:j]
|
||||
}
|
||||
|
||||
func (d *DomainsState) SetDomainUpdateStatus(status updateStatusType, message string) {
|
||||
func (d *DDNSTaskState) SetDomainUpdateStatus(status string, message string) {
|
||||
for i := range d.Domains {
|
||||
d.Domains[i].SetDomainUpdateStatus(status, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DomainsState) SetWebhookResult(result bool, errMsg string) {
|
||||
func (d *DDNSTaskState) SetWebhookResult(result bool, errMsg string) {
|
||||
d.WebhookCallResult = result
|
||||
d.WebhookCallErrorMsg = errMsg
|
||||
d.WebhookCallTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
|
@ -128,60 +85,21 @@ func (d *DomainsState) SetWebhookResult(result bool, errMsg string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *Domain) SetDomainUpdateStatus(status updateStatusType, message string) {
|
||||
d.rwmutex.Lock()
|
||||
defer d.rwmutex.Unlock()
|
||||
d.UpdateStatus = status
|
||||
if status != UpdateWaiting && status != UpdateStop {
|
||||
d.LastUpdateStatusTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
|
||||
// 状态更新历史记录
|
||||
hi := UpdateHistroyItem{UpdateStatus: string(status), UpdateTime: d.LastUpdateStatusTime}
|
||||
d.UpdateHistroy = append(d.UpdateHistroy, hi)
|
||||
if len(d.UpdateHistroy) > 10 {
|
||||
d.UpdateHistroy = DeleteAnyListlice(d.UpdateHistroy, 0)
|
||||
}
|
||||
}
|
||||
d.Message = message
|
||||
|
||||
}
|
||||
|
||||
// GetFullDomain 获得全部的,子域名
|
||||
func (d Domain) GetFullDomain() string {
|
||||
if d.SubDomain != "" {
|
||||
return d.SubDomain + "." + d.DomainName
|
||||
}
|
||||
return "@" + "." + d.DomainName
|
||||
}
|
||||
|
||||
// GetSubDomain 获得子域名,为空返回@
|
||||
// 阿里云,dnspod需要
|
||||
func (d Domain) GetSubDomain() string {
|
||||
if d.SubDomain != "" {
|
||||
return d.SubDomain
|
||||
}
|
||||
return "@"
|
||||
}
|
||||
|
||||
func (d *DomainsState) Init(domains []string) {
|
||||
if d.Mutex == nil {
|
||||
d.Mutex = &sync.RWMutex{}
|
||||
}
|
||||
|
||||
func (d *DDNSTaskState) Init(domains []string) {
|
||||
d.Domains = d.checkParseDomains(domains)
|
||||
|
||||
}
|
||||
|
||||
// checkParseDomains 校验并解析用户输入的域名
|
||||
func (d *DomainsState) checkParseDomains(domainArr []string) (domains []*Domain) {
|
||||
func (d *DDNSTaskState) checkParseDomains(domainArr []string) (domains []Domain) {
|
||||
for _, domainStr := range domainArr {
|
||||
domainStr = strings.TrimSpace(domainStr)
|
||||
if domainStr != "" {
|
||||
domain := &Domain{}
|
||||
|
||||
dp := strings.Split(domainStr, ":")
|
||||
dplen := len(dp)
|
||||
if dplen == 1 { // 自动识别域名
|
||||
domain := &Domain{}
|
||||
domain.rwmutex = d.Mutex
|
||||
sp := strings.Split(domainStr, ".")
|
||||
length := len(sp)
|
||||
if length <= 1 {
|
||||
|
@ -205,10 +123,7 @@ func (d *DomainsState) checkParseDomains(domainArr []string) (domains []*Domain)
|
|||
domain.SubDomain = domainStr[:domainLen]
|
||||
}
|
||||
|
||||
domains = append(domains, domain)
|
||||
} else if dplen == 2 { // 主机记录:域名 格式
|
||||
domain := &Domain{}
|
||||
domain.rwmutex = d.Mutex
|
||||
sp := strings.Split(dp[1], ".")
|
||||
length := len(sp)
|
||||
if length <= 1 {
|
||||
|
@ -217,29 +132,38 @@ func (d *DomainsState) checkParseDomains(domainArr []string) (domains []*Domain)
|
|||
}
|
||||
domain.DomainName = dp[1]
|
||||
domain.SubDomain = dp[0]
|
||||
domains = append(domains, domain)
|
||||
} else {
|
||||
log.Println(domainStr, "域名不正确")
|
||||
continue
|
||||
}
|
||||
|
||||
// 参数条件
|
||||
if strings.Contains(domain.DomainName, "?") {
|
||||
u, err := url.Parse("http://" + domain.DomainName)
|
||||
if err != nil {
|
||||
log.Println(domainStr, "域名解析失败")
|
||||
continue
|
||||
}
|
||||
domain.DomainName = u.Host
|
||||
domain.CustomParams = u.Query().Encode()
|
||||
}
|
||||
domains = append(domains, *domain)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CheckIPChange 检测公网IP是否改变
|
||||
func (domains *DomainsState) CheckIPChange(recordType, taskKey string, getAddrFunc func() string) (ipAddr string, change bool, retDomains []*Domain) {
|
||||
ipAddr = getAddrFunc()
|
||||
|
||||
checkIPChange, err := DDNSTaskIPCacheCheck(taskKey, domains.IpAddr)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("DDNSTaskIPCacheCheck 失败:%s", err.Error())
|
||||
// Check 检测IP是否有改变
|
||||
func (state *DDNSTaskState) IPChangeCheck(newAddr string) bool {
|
||||
if newAddr == "" {
|
||||
return true
|
||||
}
|
||||
// 地址改变
|
||||
if state.IpAddr != newAddr {
|
||||
//log.Printf("公网地址改变:[%s]===>[%s]", d.DomainsInfo.IpAddr, newAddr)
|
||||
//domains.IpAddr = newAddr
|
||||
return true
|
||||
}
|
||||
|
||||
if err != nil || checkIPChange {
|
||||
return ipAddr, true, domains.Domains
|
||||
}
|
||||
|
||||
//IP没变化
|
||||
return ipAddr, false, domains.Domains
|
||||
return false
|
||||
}
|
|
@ -1,41 +1,40 @@
|
|||
package config
|
||||
package ddnscore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/httputils"
|
||||
)
|
||||
|
||||
// updateStatusType 更新状态
|
||||
type updateStatusType string
|
||||
|
||||
// ExecWebhook 添加或更新IPv4/IPv6记录
|
||||
func (d *DDNSTask) ExecWebhook(domains *DomainsState) {
|
||||
func (d *DDNSTaskInfo) ExecWebhook(state *DDNSTaskState) {
|
||||
if !d.WebhookEnable {
|
||||
return
|
||||
}
|
||||
|
||||
if domains.IpAddr == "" && !d.WebhookCallOnGetIPfail {
|
||||
if state.IpAddr == "" && !d.WebhookCallOnGetIPfail {
|
||||
return
|
||||
}
|
||||
|
||||
tryUpdate := hasDomainTryToUpdate(domains.Domains)
|
||||
hasUpdate := hasDomainTryToUpdate(&state.Domains)
|
||||
|
||||
if d.WebhookURL != "" && (tryUpdate || (domains.IpAddr == "" && d.WebhookCallOnGetIPfail)) {
|
||||
if d.WebhookURL != "" && (hasUpdate || (state.IpAddr == "" && d.WebhookCallOnGetIPfail)) {
|
||||
|
||||
//log.Printf("DDNS任务【%s】触发Webhook", d.TaskName)
|
||||
|
||||
nowTime := time.Now().Format("2006-01-02 15:04:05")
|
||||
|
||||
url := replaceWebhookPara(domains, nowTime, d.WebhookURL)
|
||||
requestBody := replaceWebhookPara(domains, nowTime, d.WebhookRequestBody)
|
||||
url := d.replaceWebhookPara(nowTime, d.WebhookURL)
|
||||
requestBody := d.replaceWebhookPara(nowTime, d.WebhookRequestBody)
|
||||
|
||||
//headersStr := cb.task.DNS.Callback.Headers
|
||||
var headerStrList []string
|
||||
for i := range d.WebhookHeaders {
|
||||
header := replaceWebhookPara(domains, nowTime, d.WebhookHeaders[i])
|
||||
header := d.replaceWebhookPara(nowTime, d.WebhookHeaders[i])
|
||||
headerStrList = append(headerStrList, header)
|
||||
}
|
||||
|
||||
|
@ -43,7 +42,7 @@ func (d *DDNSTask) ExecWebhook(domains *DomainsState) {
|
|||
|
||||
succcssCotentList := []string{}
|
||||
for i := range d.WebhookSuccessContent {
|
||||
content := replaceWebhookPara(domains, nowTime, d.WebhookSuccessContent[i])
|
||||
content := d.replaceWebhookPara(nowTime, d.WebhookSuccessContent[i])
|
||||
succcssCotentList = append(succcssCotentList, content)
|
||||
}
|
||||
|
||||
|
@ -51,17 +50,17 @@ func (d *DDNSTask) ExecWebhook(domains *DomainsState) {
|
|||
|
||||
if callErr != nil {
|
||||
//log.Printf("WebHook 调用出错:%s", callErr.Error())
|
||||
domains.SetWebhookResult(false, callErr.Error())
|
||||
state.SetWebhookResult(false, callErr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//log.Printf("Webhook 调用成功")
|
||||
domains.SetWebhookResult(true, "")
|
||||
state.SetWebhookResult(true, "")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func WebhookTest(d *DDNSTask, url, method, WebhookRequestBody, proxy, addr, user, passwd string, headerList, successContentListraw []string) (string, error) {
|
||||
func WebhookTest(d *DDNSTaskInfo, url, method, WebhookRequestBody, proxy, addr, user, passwd string, headerList, successContentListraw []string) (string, error) {
|
||||
nowTime := time.Now().Format("2006-01-02 15:04:05")
|
||||
url = replaceWebhookTestPara(url, nowTime)
|
||||
requestBody := replaceWebhookTestPara(WebhookRequestBody, nowTime)
|
||||
|
@ -83,7 +82,7 @@ func WebhookTest(d *DDNSTask, url, method, WebhookRequestBody, proxy, addr, user
|
|||
succcssCotentList = append(succcssCotentList, content)
|
||||
}
|
||||
|
||||
globalDDNSConf := GetDDNSConfigure()
|
||||
globalDDNSConf := config.GetDDNSConfigure()
|
||||
proxyType := ""
|
||||
proxyAddr := ""
|
||||
proxyUser := ""
|
||||
|
@ -112,7 +111,9 @@ func WebhookTest(d *DDNSTask, url, method, WebhookRequestBody, proxy, addr, user
|
|||
//fmt.Printf("proxyType:%s\taddr:%s\t,user[%s]passwd[%s]\n", proxyType, proxyAddr, proxyUser, proxyPasswd)
|
||||
|
||||
//dnsConf := cb.task.DNS
|
||||
respStr, err := httputils.GetStringGoutDoHttpRequest(
|
||||
_, respStr, err := httputils.GetStringGoutDoHttpRequest(
|
||||
"tcp",
|
||||
"",
|
||||
method,
|
||||
url,
|
||||
requestBody,
|
||||
|
@ -136,9 +137,9 @@ func WebhookTest(d *DDNSTask, url, method, WebhookRequestBody, proxy, addr, user
|
|||
return respStr, fmt.Errorf("接口调用出错,未匹配预设成功返回的字符串")
|
||||
}
|
||||
|
||||
func (d *DDNSTask) webhookHttpClientDo(method, url, requestBody string, headers map[string]string, callbackSuccessContent []string) error {
|
||||
func (d *DDNSTaskInfo) webhookHttpClientDo(method, url, requestBody string, headers map[string]string, callbackSuccessContent []string) error {
|
||||
|
||||
globalDDNSConf := GetDDNSConfigure()
|
||||
globalDDNSConf := config.GetDDNSConfigure()
|
||||
proxyType := ""
|
||||
proxyAddr := ""
|
||||
proxyUser := ""
|
||||
|
@ -165,7 +166,9 @@ func (d *DDNSTask) webhookHttpClientDo(method, url, requestBody string, headers
|
|||
}
|
||||
|
||||
//dnsConf := cb.task.DNS
|
||||
respStr, err := httputils.GetStringGoutDoHttpRequest(
|
||||
statusCode, respStr, err := httputils.GetStringGoutDoHttpRequest(
|
||||
"tcp",
|
||||
"",
|
||||
method,
|
||||
url,
|
||||
requestBody,
|
||||
|
@ -180,6 +183,13 @@ func (d *DDNSTask) webhookHttpClientDo(method, url, requestBody string, headers
|
|||
return fmt.Errorf("webhook 调用接口[%s]出错:%s", url, err.Error())
|
||||
}
|
||||
|
||||
if d.WebhookDisableCallbackSuccessContentCheck {
|
||||
if statusCode == http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("webhook调用接口失败:\n statusCode:%d\n%s", statusCode, respStr)
|
||||
}
|
||||
|
||||
for _, successContent := range callbackSuccessContent {
|
||||
if strings.Contains(respStr, successContent) {
|
||||
|
||||
|
@ -191,8 +201,8 @@ func (d *DDNSTask) webhookHttpClientDo(method, url, requestBody string, headers
|
|||
}
|
||||
|
||||
// DomainsIsChange
|
||||
func hasDomainTryToUpdate(domains []*Domain) bool {
|
||||
for _, v46 := range domains {
|
||||
func hasDomainTryToUpdate(domains *[]Domain) bool {
|
||||
for _, v46 := range *domains {
|
||||
switch v46.UpdateStatus {
|
||||
case UpdatedFailed:
|
||||
return true
|
||||
|
@ -221,10 +231,10 @@ func replaceWebhookTestPara(orgPara, nowTime string) (newPara string) {
|
|||
}
|
||||
|
||||
// replacePara 替换参数 #{successDomains},#{failedDomains}
|
||||
func replaceWebhookPara(d *DomainsState, nowTime, orgPara string) (newPara string) {
|
||||
ipAddrText := d.IpAddr
|
||||
func (d *DDNSTaskInfo) replaceWebhookPara(nowTime, orgPara string) (newPara string) {
|
||||
ipAddrText := d.TaskState.IpAddr
|
||||
|
||||
successDomains, failedDomains := getDomainsStr(d.Domains)
|
||||
successDomains, failedDomains := d.getDomainsStr(&d.TaskState.Domains)
|
||||
if ipAddrText == "" {
|
||||
ipAddrText = "获取IP失败"
|
||||
successDomains = ""
|
||||
|
@ -245,11 +255,11 @@ func replaceWebhookPara(d *DomainsState, nowTime, orgPara string) (newPara strin
|
|||
}
|
||||
|
||||
// getDomainsStr 用逗号分割域名,分类域名返回,成功和失败的
|
||||
func getDomainsStr(domains []*Domain) (string, string) {
|
||||
func (d *DDNSTaskInfo) getDomainsStr(domains *[]Domain) (string, string) {
|
||||
var successDomainBuf strings.Builder
|
||||
var failedDomainsBuf strings.Builder
|
||||
for _, v46 := range domains {
|
||||
if v46.UpdateStatus == UpdatedFailed {
|
||||
for _, v46 := range *domains {
|
||||
if v46.UpdateStatus == UpdatedFailed || (d.Webhook.WebhookCallOnGetIPfail && v46.UpdateStatus == UpdatePause) {
|
||||
if failedDomainsBuf.Len() > 0 {
|
||||
failedDomainsBuf.WriteString(",")
|
||||
}
|
||||
|
@ -257,7 +267,8 @@ func getDomainsStr(domains []*Domain) (string, string) {
|
|||
continue
|
||||
}
|
||||
|
||||
if v46.UpdateStatus == UpdatedNothing || v46.UpdateStatus == UpdatedSuccess {
|
||||
//if v46.UpdateStatus == UpdatedNothing || v46.UpdateStatus == UpdatedSuccess {
|
||||
if v46.UpdateStatus == UpdatedSuccess {
|
||||
if successDomainBuf.Len() > 0 {
|
||||
successDomainBuf.WriteString(",")
|
||||
}
|
3
main.go
3
main.go
|
@ -82,7 +82,8 @@ func main() {
|
|||
|
||||
rule.EnableAllRelayRule() //开启规则
|
||||
|
||||
config.DDNSTaskListTaskDetailsInit()
|
||||
//config.DDNSTaskListTaskDetailsInit()
|
||||
config.DDNSTaskListConfigureCheck()
|
||||
ddnsConf := config.GetDDNSConfigure()
|
||||
if ddnsConf.Enable {
|
||||
ddns.Run(time.Duration(ddnsConf.FirstCheckDelay)*time.Second, time.Duration(ddnsConf.Intervals)*time.Second)
|
||||
|
|
|
@ -11,11 +11,19 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
var globalTransportMap map[string]*http.Transport
|
||||
var globalTransportMapMutex sync.Mutex
|
||||
|
||||
func init() {
|
||||
globalTransportMap = make(map[string]*http.Transport)
|
||||
}
|
||||
|
||||
func GetAndParseJSONResponseFromHttpResponse(resp *http.Response, result interface{}) error {
|
||||
bytes, err := GetBytesFromHttpResponse(resp)
|
||||
if err != nil {
|
||||
|
@ -31,7 +39,7 @@ func GetAndParseJSONResponseFromHttpResponse(resp *http.Response, result interfa
|
|||
return nil
|
||||
}
|
||||
|
||||
//GetStringFromHttpResponse 从response获取
|
||||
// GetStringFromHttpResponse 从response获取
|
||||
func GetBytesFromHttpResponse(resp *http.Response) ([]byte, error) {
|
||||
if resp == nil || resp.Body == nil {
|
||||
return []byte{}, fmt.Errorf("resp.Body = nil")
|
||||
|
@ -51,7 +59,7 @@ func GetBytesFromHttpResponse(resp *http.Response) ([]byte, error) {
|
|||
return body, err
|
||||
}
|
||||
|
||||
//GetStringFromHttpResponse 从response获取
|
||||
// GetStringFromHttpResponse 从response获取
|
||||
func GetStringFromHttpResponse(resp *http.Response) (string, error) {
|
||||
respBytes, err := GetBytesFromHttpResponse(resp)
|
||||
if err != nil {
|
||||
|
@ -60,12 +68,55 @@ func GetStringFromHttpResponse(resp *http.Response) (string, error) {
|
|||
return string(respBytes), nil
|
||||
}
|
||||
|
||||
func NewTransport(secureSkipVerify bool, proxyType, proxyUrl, user, passwd string) (*http.Transport, error) {
|
||||
type transportIt struct {
|
||||
Network string
|
||||
LocalAddr string
|
||||
ProxyType string
|
||||
ProxyUrl string
|
||||
User string
|
||||
Passwd string
|
||||
SecureSkipVerify bool
|
||||
}
|
||||
|
||||
func (t *transportIt) String() string {
|
||||
return fmt.Sprintf("%s,%s,%s,%s,%s,%s,%v", t.Network, t.LocalAddr, t.ProxyType, t.ProxyUrl, t.User, t.Passwd, t.SecureSkipVerify)
|
||||
}
|
||||
|
||||
// NewTransport
|
||||
// transportNetwork 网络类型 tcp tcp4 tcp6
|
||||
// localAddr 指定网卡出口
|
||||
func NewTransport(transportNetwork,
|
||||
localAddrStr string,
|
||||
secureSkipVerify bool,
|
||||
proxyType,
|
||||
proxyUrl,
|
||||
user,
|
||||
passwd string) (*http.Transport, error) {
|
||||
var transport *http.Transport
|
||||
proxyType = strings.ToLower(proxyType)
|
||||
ti := transportIt{
|
||||
Network: transportNetwork,
|
||||
LocalAddr: localAddrStr,
|
||||
ProxyType: proxyType,
|
||||
ProxyUrl: proxyUrl,
|
||||
User: user,
|
||||
Passwd: passwd,
|
||||
SecureSkipVerify: secureSkipVerify}
|
||||
|
||||
globalTransportMapMutex.Lock()
|
||||
defer globalTransportMapMutex.Unlock()
|
||||
|
||||
tr, ok := globalTransportMap[ti.String()]
|
||||
if ok {
|
||||
//log.Printf("map[%s]已存在", ti.String())
|
||||
return tr, nil
|
||||
}
|
||||
//log.Printf("map[%s]未存在", ti.String())
|
||||
|
||||
switch proxyType {
|
||||
case "http", "https":
|
||||
{
|
||||
//log.Printf("http proxy Transport network:%s", transportNetwork)
|
||||
if !strings.Contains(proxyUrl, "http") {
|
||||
proxyUrl = fmt.Sprintf("%s://%s", proxyType, proxyUrl)
|
||||
}
|
||||
|
@ -78,25 +129,47 @@ func NewTransport(secureSkipVerify bool, proxyType, proxyUrl, user, passwd strin
|
|||
urlProxy.User = url.UserPassword(user, passwd)
|
||||
}
|
||||
|
||||
var localAddr net.Addr
|
||||
localAddr = nil
|
||||
|
||||
if localAddrStr != "" {
|
||||
lAddr, err := net.ResolveTCPAddr(transportNetwork, localAddrStr+":0")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NewTransport=> ResolveTCPAddr localAddr:%s error:%s", localAddrStr, err.Error())
|
||||
}
|
||||
localAddr = lAddr
|
||||
}
|
||||
|
||||
dialer := (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
LocalAddr: localAddr,
|
||||
})
|
||||
|
||||
transport = &http.Transport{
|
||||
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: secureSkipVerify},
|
||||
Proxy: http.ProxyURL(urlProxy),
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, err error) {
|
||||
return dialer.Dial(transportNetwork, addr)
|
||||
},
|
||||
ForceAttemptHTTP2: true,
|
||||
Dial: dialer.Dial,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
case "socket5", "socks5":
|
||||
{
|
||||
//log.Printf("socket5 proxy Transport network:%s", transportNetwork)
|
||||
var userAuth proxy.Auth
|
||||
if user != "" && passwd != "" {
|
||||
userAuth.User = user
|
||||
userAuth.Password = passwd
|
||||
}
|
||||
|
||||
dialer, err := proxy.SOCKS5("tcp", proxyUrl, &userAuth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NewTransport=>proxy.SOCKS5 error:%s", err.Error())
|
||||
|
@ -105,31 +178,58 @@ func NewTransport(secureSkipVerify bool, proxyType, proxyUrl, user, passwd strin
|
|||
transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: secureSkipVerify},
|
||||
DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, err error) {
|
||||
return dialer.Dial(network, addr)
|
||||
return dialer.Dial(transportNetwork, addr)
|
||||
},
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
//log.Printf("default Transport network:%s", transportNetwork)
|
||||
var localAddr net.Addr
|
||||
|
||||
localAddr = nil
|
||||
if localAddrStr != "" {
|
||||
lAddr, err := net.ResolveTCPAddr(transportNetwork, localAddrStr+":0")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NewTransport=> ResolveTCPAddr localAddr:%s error:%s", localAddrStr, err.Error())
|
||||
}
|
||||
localAddr = lAddr
|
||||
}
|
||||
|
||||
dialer := (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
LocalAddr: localAddr,
|
||||
})
|
||||
|
||||
transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: secureSkipVerify},
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
DisableKeepAlives: true,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: secureSkipVerify},
|
||||
DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, err error) {
|
||||
return dialer.Dial(transportNetwork, addr)
|
||||
},
|
||||
Dial: dialer.Dial,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
globalTransportMap[ti.String()] = transport
|
||||
|
||||
return transport, nil
|
||||
}
|
||||
|
||||
|
@ -147,5 +247,6 @@ func CreateHeadersMap(headers []string) map[string]string {
|
|||
value := header[kvSpliteIndex+1:]
|
||||
hm[key] = value
|
||||
}
|
||||
|
||||
return hm
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
"github.com/guonaihong/gout/dataflow"
|
||||
)
|
||||
|
||||
func NewGout(secureSkipVerify bool, proxyType, proxyUrl, user, passwd string, timeout time.Duration) (*dataflow.Gout, error) {
|
||||
httpClient, err := CreateHttpClient(secureSkipVerify, proxyType, proxyUrl, user, passwd, timeout)
|
||||
func NewGout(transportNetwork, localAddr string, secureSkipVerify bool, proxyType, proxyUrl, user, passwd string, timeout time.Duration) (*dataflow.Gout, error) {
|
||||
httpClient, err := CreateHttpClient(transportNetwork, localAddr, secureSkipVerify, proxyType, proxyUrl, user, passwd, timeout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateHttpClient error:%s", err.Error())
|
||||
}
|
||||
|
@ -19,8 +19,16 @@ func NewGout(secureSkipVerify bool, proxyType, proxyUrl, user, passwd string, ti
|
|||
return gout.New(httpClient), nil
|
||||
}
|
||||
|
||||
func GetAndParseJSONResponseFromGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl, user, passwd string, headers map[string]string, secureSkipVerify bool, timeout time.Duration, result interface{}) error {
|
||||
bytes, err := GetBytesFromGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl, user, passwd, headers, secureSkipVerify, timeout)
|
||||
func GetAndParseJSONResponseFromGoutDoHttpRequest(transportNetwork, localAddr, method, url, requestBody, proxyType, proxyUrl, user, passwd string,
|
||||
headers map[string]string, secureSkipVerify bool, timeout time.Duration, result interface{}) error {
|
||||
_, bytes, err := GetBytesFromGoutDoHttpRequest(
|
||||
transportNetwork,
|
||||
localAddr,
|
||||
method,
|
||||
url,
|
||||
requestBody,
|
||||
proxyType,
|
||||
proxyUrl, user, passwd, headers, secureSkipVerify, timeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetBytesFromHttpResponse err:%s", err.Error())
|
||||
}
|
||||
|
@ -33,23 +41,27 @@ func GetAndParseJSONResponseFromGoutDoHttpRequest(method, url, requestBody, prox
|
|||
return nil
|
||||
}
|
||||
|
||||
func GetStringGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl, user, passwd string, headers map[string]string, secureSkipVerify bool, timeout time.Duration) (string, error) {
|
||||
bytes, err := GetBytesFromGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl, user, passwd, headers, secureSkipVerify, timeout)
|
||||
func GetStringGoutDoHttpRequest(transportNetwork, localAddr, method, url, requestBody, proxyType, proxyUrl, user, passwd string,
|
||||
headers map[string]string, secureSkipVerify bool, timeout time.Duration) (int, string, error) {
|
||||
statusCode, bytes, err := GetBytesFromGoutDoHttpRequest(transportNetwork, localAddr, method, url, requestBody, proxyType, proxyUrl, user, passwd, headers, secureSkipVerify, timeout)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return 0, "", err
|
||||
}
|
||||
return string(bytes), nil
|
||||
return statusCode, string(bytes), nil
|
||||
}
|
||||
|
||||
func GetBytesFromGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl, user, passwd string, headers map[string]string, secureSkipVerify bool, timeout time.Duration) ([]byte, error) {
|
||||
func GetBytesFromGoutDoHttpRequest(transportNetwork, localAddr, method, url, requestBody, proxyType, proxyUrl, user, passwd string,
|
||||
headers map[string]string, secureSkipVerify bool, timeout time.Duration) (int, []byte, error) {
|
||||
gout, err := NewGout(
|
||||
transportNetwork,
|
||||
localAddr,
|
||||
secureSkipVerify,
|
||||
proxyType,
|
||||
proxyUrl,
|
||||
user,
|
||||
passwd, timeout)
|
||||
if err != nil {
|
||||
return []byte{}, fmt.Errorf("GoutDoHttpRequest err:%s", err.Error())
|
||||
return 0, []byte{}, fmt.Errorf("GoutDoHttpRequest err:%s", err.Error())
|
||||
}
|
||||
|
||||
switch strings.ToLower(method) {
|
||||
|
@ -62,7 +74,7 @@ func GetBytesFromGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl
|
|||
case "delete":
|
||||
gout.DELETE(url)
|
||||
default:
|
||||
return []byte{}, fmt.Errorf("未支持的Callback请求方法:%s", method)
|
||||
return 0, []byte{}, fmt.Errorf("未支持的Callback请求方法:%s", method)
|
||||
}
|
||||
|
||||
basicAuthUserName, BasicAuthUserNameOk := headers["BasicAuthUserName"]
|
||||
|
@ -86,9 +98,9 @@ func GetBytesFromGoutDoHttpRequest(method, url, requestBody, proxyType, proxyUrl
|
|||
|
||||
resp, err := gout.Response()
|
||||
if err != nil {
|
||||
return []byte{}, fmt.Errorf("gout.Response() error:%s", err.Error())
|
||||
return 0, []byte{}, fmt.Errorf("gout.Response() error:%s", err.Error())
|
||||
}
|
||||
respByte, respErr := GetBytesFromHttpResponse(resp)
|
||||
|
||||
return GetBytesFromHttpResponse(resp)
|
||||
|
||||
return resp.StatusCode, respByte, respErr
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func CreateHttpClient(secureSkipVerify bool, proxyType, proxyUrl, user, passwd string, timeout time.Duration) (*http.Client, error) {
|
||||
transport, err := NewTransport(secureSkipVerify, proxyType, proxyUrl, user, passwd)
|
||||
func CreateHttpClient(transportNetwork, localAddr string, secureSkipVerify bool, proxyType, proxyUrl, user, passwd string, timeout time.Duration) (*http.Client, error) {
|
||||
|
||||
transport, err := NewTransport(transportNetwork, localAddr, secureSkipVerify, proxyType, proxyUrl, user, passwd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -8,8 +8,8 @@
|
|||
|
||||
|
||||
<title>Lucky(大吉)</title>
|
||||
<script type="module" crossorigin src="/assets/index.85a8bea4.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.c38c8b21.css">
|
||||
<script type="module" crossorigin src="/assets/index.eb4bbca4.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.633495a9.css">
|
||||
</head>
|
||||
<body style="margin:0">
|
||||
<div id="app"></div>
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
<div class="InfoDivRadius">
|
||||
<div class="line">
|
||||
{{Info.AppName}} version:{{Info.Version}}
|
||||
{{Info.AppName}} version:{{Info.Version}} {{Info.OS}}({{Info.ARCH}})
|
||||
</div>
|
||||
<div class="line">
|
||||
{{Info.OS}}({{Info.ARCH}})
|
||||
|
||||
</div>
|
||||
<div class="line">
|
||||
作者:古大羊 编译于{{Info.Date}}
|
||||
作者:古大羊 {{Info.GoVersion}} 编译时间:{{Info.Date}}
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
|
@ -58,7 +58,8 @@ var Info = ref({
|
|||
Version:"1.0.0",
|
||||
OS:"unknow",
|
||||
ARCH:"unknow",
|
||||
Date:"2022-07-25"
|
||||
Date:"2022-07-25",
|
||||
GoVersion:""
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -350,6 +350,15 @@
|
|||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="DDNSForm.DNS.Name == 'porkbun'">
|
||||
<el-form-item label-width="auto">
|
||||
<el-link type="primary" style="font-size: small;"
|
||||
href="https://porkbun.com/account/api" target="_blank">
|
||||
创建 Access
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="DDNSForm.DNS.Name == 'callback'">
|
||||
<el-form-item label-width="auto">
|
||||
<p style="font-size:1px">支持的变量 #{ip}, #{domain}, #{recordType}, #{ttl}</p>
|
||||
|
@ -511,20 +520,30 @@
|
|||
</el-tooltip>
|
||||
|
||||
|
||||
<el-tooltip class="box-item" effect="dark" :trigger-keys="[]" content="">
|
||||
<template #content>用于判断记录接口是否成功调用,多种表示成功的不同字符串请分多行写<br />
|
||||
支持的变量<br />
|
||||
#{ip} : 外网IP<br />
|
||||
#{domain} : 域名<br />
|
||||
#{recordType} : A 或者 AAAA <br />
|
||||
#{ttl} : TTL值</template>
|
||||
<el-form-item label="接口调用成功包含的字符串" label-width="auto">
|
||||
<el-input v-model="DDNSFormCallbackSuccessContentArea"
|
||||
:autosize="{ minRows: 3, maxRows: 5 }" type="textarea" autocomplete="off"
|
||||
placeholder="" />
|
||||
<el-tooltip content="禁用接口调用成功字符串检测,开启后仅以http StatusCode==200判断接口是否成功调用." placement="top">
|
||||
|
||||
<el-form-item label="禁用接口调用成功字符串检测" label-width="auto">
|
||||
<el-switch v-model="DDNSForm.DNS.Callback.DisableCallbackSuccessContentCheck"
|
||||
inline-prompt width="50px" active-text="是" inactive-text="否" />
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
|
||||
<div v-show="!DDNSForm.DNS.Callback.DisableCallbackSuccessContentCheck">
|
||||
<el-tooltip class="box-item" effect="dark" :trigger-keys="[]" content="">
|
||||
<template #content>用于判断记录接口是否成功调用,多种表示成功的不同字符串请分多行写<br />
|
||||
支持的变量<br />
|
||||
#{ip} : 外网IP<br />
|
||||
#{domain} : 域名<br />
|
||||
#{recordType} : A 或者 AAAA <br />
|
||||
#{ttl} : TTL值</template>
|
||||
<el-form-item label="接口调用成功包含的字符串" label-width="auto">
|
||||
<el-input v-model="DDNSFormCallbackSuccessContentArea"
|
||||
:autosize="{ minRows: 3, maxRows: 5 }" type="textarea" autocomplete="off"
|
||||
placeholder="" />
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -710,11 +729,10 @@
|
|||
|
||||
<div v-show="DDNSForm.WebhookEnable">
|
||||
|
||||
<el-tooltip class="box-item" effect="dark"
|
||||
content="获取IP失败时同样触发Webhook,默认不开启">
|
||||
<el-tooltip class="box-item" effect="dark" content="获取IP失败时同样触发Webhook,默认不开启">
|
||||
<el-form-item label="获取IP失败时触发Webhook" label-width="auto">
|
||||
<el-switch v-model="DDNSForm.WebhookCallOnGetIPfail" inline-prompt width="50px" active-text="启用"
|
||||
inactive-text="禁用" />
|
||||
<el-switch v-model="DDNSForm.WebhookCallOnGetIPfail" inline-prompt width="50px"
|
||||
active-text="启用" inactive-text="禁用" />
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
|
||||
|
@ -825,7 +843,7 @@
|
|||
<el-tooltip class="box-item" effect="dark" content="">
|
||||
<template #content>支持的变量 <br />
|
||||
#{ipAddr} : 当前公网IP<br />
|
||||
#{time} : 触发Webhook的时间 <br />
|
||||
#{time} : 触发Webhook的时间 <br />
|
||||
#{successDomains} : 更新/添加成功的域名列表,域名之间用,号分隔<br />
|
||||
#{successDomainsLine} : 更新/添加成功的域名列表,域名之间用'\n'分隔<br />
|
||||
#{failedDomains} : 更新/添加失败的域名列表,域名之间用,号分隔<br />
|
||||
|
@ -886,6 +904,18 @@
|
|||
</el-tooltip>
|
||||
|
||||
|
||||
|
||||
<el-tooltip content="禁用Webhook接口调用成功字符串检测,开启后仅以http StatusCode==200判断接口是否成功调用."
|
||||
placement="top">
|
||||
|
||||
<el-form-item label="禁用Webhook接口调用成功字符串检测" label-width="auto">
|
||||
<el-switch v-model="DDNSForm.WebhookDisableCallbackSuccessContentCheck"
|
||||
inline-prompt width="50px" active-text="是" inactive-text="否" />
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
|
||||
|
||||
<div v-show="!DDNSForm.WebhookDisableCallbackSuccessContentCheck">
|
||||
<el-tooltip class="box-item" effect="dark" :trigger-keys="[]" content="">
|
||||
<template #content>用于判断记录Webhook 接口是否成功调用<br />
|
||||
多种表示成功的不同字符串请分多行写<br />
|
||||
|
@ -901,7 +931,7 @@
|
|||
placeholder="" />
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -1021,6 +1051,7 @@ var taskList = ref([{
|
|||
Headers: [""],
|
||||
RequestBody: "",
|
||||
Server: "",
|
||||
DisableCallbackSuccessContentCheck:false,
|
||||
CallbackSuccessContent: [""]
|
||||
},
|
||||
|
||||
|
@ -1030,6 +1061,7 @@ var taskList = ref([{
|
|||
WebhookMethod: "",
|
||||
WebhookHeaders: [""],
|
||||
WebhookRequestBody: "",
|
||||
WebhookDisableCallbackSuccessContentCheck:false,
|
||||
WebhookSuccessContent: [""],
|
||||
WebhookProxy: "",
|
||||
WebhookProxyAddr: "",
|
||||
|
@ -1249,6 +1281,10 @@ const DNSServerList = [
|
|||
value: 'huaweicloud',
|
||||
label: '华为云',
|
||||
},
|
||||
{
|
||||
value: 'porkbun',
|
||||
label: 'Porkbun',
|
||||
},
|
||||
{
|
||||
value: 'callback',
|
||||
label: '自定义(Callback)',
|
||||
|
@ -1331,7 +1367,7 @@ const WebhookServerSelectChange = (server : string)=>{
|
|||
content:[
|
||||
[{tag:"text",text:"IP地址:#{ipAddr}"}],
|
||||
[{tag:"text",text:"域名更新成功列表:#{successDomainsLine}"}],
|
||||
[{tag:"text",text:"域名更新失败列表:#{successDomainsLine}"}],
|
||||
[{tag:"text",text:"域名更新失败列表:#{failedDomainsLine}"}],
|
||||
[{tag:"text",text:"Webhook触发时间: \n#{time}"}],
|
||||
]
|
||||
}
|
||||
|
@ -1419,6 +1455,8 @@ const getIDLabel = () => {
|
|||
return "Access Key Id"
|
||||
case "baiducloud":
|
||||
return "AccessKey ID"
|
||||
case "porkbun":
|
||||
return "API Key"
|
||||
case "callback":
|
||||
return "URL"
|
||||
default:
|
||||
|
@ -1440,6 +1478,8 @@ const getSecretLabel = () => {
|
|||
return "Secret Access Key"
|
||||
case "baiducloud":
|
||||
return "AccessKey Secret"
|
||||
case "porkbun":
|
||||
return "Secret Key"
|
||||
case "callback":
|
||||
return "RequestBody"
|
||||
default:
|
||||
|
@ -1458,6 +1498,8 @@ const showDNSIDFormItem = () => {
|
|||
return true
|
||||
case "baiducloud":
|
||||
return true
|
||||
case "porkbun":
|
||||
return true
|
||||
case "callback":
|
||||
return false
|
||||
default:
|
||||
|
@ -1478,6 +1520,8 @@ const showDNSSecretFormItem = () => {
|
|||
return true
|
||||
case "baiducloud":
|
||||
return true
|
||||
case "porkbun":
|
||||
return true
|
||||
case "callback":
|
||||
return false
|
||||
default:
|
||||
|
@ -1539,6 +1583,7 @@ const DDNSForm = ref(
|
|||
Headers: [""],
|
||||
RequestBody: "",
|
||||
Server: "",
|
||||
DisableCallbackSuccessContentCheck:false,
|
||||
CallbackSuccessContent: [""],
|
||||
},
|
||||
},
|
||||
|
@ -1548,6 +1593,7 @@ const DDNSForm = ref(
|
|||
WebhookMethod: "",
|
||||
WebhookHeaders: [""],
|
||||
WebhookRequestBody: "",
|
||||
WebhookDisableCallbackSuccessContentCheck:false,
|
||||
WebhookSuccessContent: [""],
|
||||
WebhookProxy: "",
|
||||
WebhookProxyAddr: "",
|
||||
|
@ -1585,6 +1631,7 @@ const preDDNSFrom = ref(
|
|||
Headers: [""],
|
||||
RequestBody: "",
|
||||
Server: "",
|
||||
DisableCallbackSuccessContentCheck:false,
|
||||
CallbackSuccessContent: [""],
|
||||
},
|
||||
},
|
||||
|
@ -1594,6 +1641,7 @@ const preDDNSFrom = ref(
|
|||
WebhookMethod: "",
|
||||
WebhookHeaders: [""],
|
||||
WebhookRequestBody: "",
|
||||
WebhookDisableCallbackSuccessContentCheck:false,
|
||||
WebhookSuccessContent: [""],
|
||||
WebhookProxy: "",
|
||||
WebhookProxyAddr: "",
|
||||
|
@ -1650,6 +1698,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
Headers: [""],
|
||||
RequestBody: "",
|
||||
Server: "other",
|
||||
DisableCallbackSuccessContentCheck:false,
|
||||
CallbackSuccessContent: [],
|
||||
}
|
||||
}
|
||||
|
@ -1659,6 +1708,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
DDNSForm.value.WebhookMethod = "get"
|
||||
DDNSForm.value.WebhookHeaders = []
|
||||
DDNSForm.value.WebhookRequestBody = ""
|
||||
DDNSForm.value.WebhookDisableCallbackSuccessContentCheck=false,
|
||||
DDNSForm.value.WebhookSuccessContent = []
|
||||
DDNSForm.value.WebhookProxy = ""
|
||||
DDNSForm.value.WebhookProxyAddr = ""
|
||||
|
@ -1701,6 +1751,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
Method: "get",
|
||||
Headers: [""],
|
||||
RequestBody: "",
|
||||
DisableCallbackSuccessContentCheck:false,
|
||||
CallbackSuccessContent: [],
|
||||
Server: "other",
|
||||
}
|
||||
|
@ -1711,6 +1762,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
preDDNSFrom.value.WebhookMethod = "get"
|
||||
preDDNSFrom.value.WebhookHeaders = []
|
||||
preDDNSFrom.value.WebhookRequestBody = ""
|
||||
preDDNSFrom.value.WebhookDisableCallbackSuccessContentCheck=false,
|
||||
preDDNSFrom.value.WebhookSuccessContent = []
|
||||
preDDNSFrom.value.WebhookProxy = ""
|
||||
preDDNSFrom.value.WebhookProxyAddr = ""
|
||||
|
@ -1745,6 +1797,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
Headers: task.DNS.Callback.Headers,
|
||||
RequestBody: task.DNS.Callback.RequestBody,
|
||||
Server: task.DNS.Callback.Server,
|
||||
DisableCallbackSuccessContentCheck:task.DNS.Callback.DisableCallbackSuccessContentCheck,
|
||||
CallbackSuccessContent: task.DNS.Callback.CallbackSuccessContent
|
||||
}
|
||||
}
|
||||
|
@ -1754,6 +1807,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
DDNSForm.value.WebhookRequestBody = task.WebhookRequestBody
|
||||
DDNSForm.value.WebhookMethod = task.WebhookMethod
|
||||
DDNSForm.value.WebhookHeaders = task.WebhookHeaders
|
||||
DDNSForm.value.WebhookDisableCallbackSuccessContentCheck = task.WebhookDisableCallbackSuccessContentCheck
|
||||
DDNSForm.value.WebhookSuccessContent = task.WebhookSuccessContent
|
||||
DDNSForm.value.WebhookProxy = task.WebhookProxy
|
||||
DDNSForm.value.WebhookProxyAddr = task.WebhookProxyAddr
|
||||
|
@ -1795,6 +1849,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
Headers: task.DNS.Callback.Headers,
|
||||
RequestBody: task.DNS.Callback.RequestBody,
|
||||
CallbackSuccessContent: task.DNS.Callback.CallbackSuccessContent,
|
||||
DisableCallbackSuccessContentCheck:task.DNS.Callback.DisableCallbackSuccessContentCheck,
|
||||
Server: task.DNS.Callback.Server,
|
||||
}
|
||||
}
|
||||
|
@ -1803,6 +1858,7 @@ const showAddOrAlterWhiteListDialog = (optionType: string, task: any) => {
|
|||
preDDNSFrom.value.WebhookHeaders = task.WebhookHeaders
|
||||
preDDNSFrom.value.WebhookCallOnGetIPfail = task.WebhookCallOnGetIPfail
|
||||
preDDNSFrom.value.WebhookURL = task.WebhookURL
|
||||
preDDNSFrom.value.WebhookDisableCallbackSuccessContentCheck = task.WebhookDisableCallbackSuccessContentCheck
|
||||
preDDNSFrom.value.WebhookSuccessContent = task.WebhookSuccessContent
|
||||
preDDNSFrom.value.WebhookRequestBody = task.WebhookRequestBody
|
||||
preDDNSFrom.value.WebhookProxy = task.WebhookProxy
|
||||
|
@ -2085,8 +2141,16 @@ const checkDDNSFormAvalid = () => {
|
|||
return "Webhook 代理设置服务器地址不能为空"
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.WebhookDisableCallbackSuccessContentCheck && data.WebhookSuccessContent.length == 0) {
|
||||
return "Webhook接口调用成功包含的字符串不能为空,如果要指定为空请禁用检测"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//清空无用数据
|
||||
if (data.DNS.Name == "callback") {
|
||||
data.DNS.ID = ""
|
||||
|
@ -2094,8 +2158,15 @@ const checkDDNSFormAvalid = () => {
|
|||
if (data.DNS.Callback.Method == "get") {
|
||||
data.DNS.Callback.RequestBody = ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
data.DNS.Callback = { URL: "", Method: "", Headers: [], RequestBody: "", Server: "", CallbackSuccessContent: [] }
|
||||
data.DNS.Callback = {
|
||||
URL: "",
|
||||
Method: "",
|
||||
Headers: [],
|
||||
RequestBody: "", Server: "", CallbackSuccessContent: [],DisableCallbackSuccessContentCheck:false }
|
||||
}
|
||||
|
||||
if (data.WebhookEnable) {
|
||||
|
@ -2122,11 +2193,14 @@ const checkDNSData = (dns: any) => {
|
|||
return "请选择Callback的请求方法"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (dns.Callback.URL == "") {
|
||||
return "Callback 接口地址不能为空"
|
||||
}
|
||||
|
||||
if (!dns.Callback.DisableCallbackSuccessContentCheck && dns.Callback.CallbackSuccessContent.length==0){
|
||||
return "接口调用成功包含的字符串不能为空,如果要指定为空请禁用检测"
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if (dns.Secret == "" || dns.ID == "") {
|
||||
|
@ -2159,6 +2233,7 @@ const autocompleteCallbackForm = () => {
|
|||
DDNSForm.value.DNS.Callback.Headers = []
|
||||
DDNSForm.value.DNS.Callback.Method = 'get'
|
||||
DDNSForm.value.DNS.Callback.RequestBody = ""
|
||||
DDNSForm.value.DNS.Callback.DisableCallbackSuccessContentCheck = false
|
||||
DDNSForm.value.DNS.Callback.CallbackSuccessContent = ["chenggong", "chongfu", "ok"]
|
||||
DDNSFormCallbackSuccessContentArea.value = 'chenggong\nchongfu\nok'
|
||||
break;
|
||||
|
@ -2168,6 +2243,7 @@ const autocompleteCallbackForm = () => {
|
|||
DDNSForm.value.DNS.Callback.Headers = []
|
||||
DDNSForm.value.DNS.Callback.Method = 'get'
|
||||
DDNSForm.value.DNS.Callback.RequestBody = ""
|
||||
DDNSForm.value.DNS.Callback.DisableCallbackSuccessContentCheck = false
|
||||
DDNSForm.value.DNS.Callback.CallbackSuccessContent = ["nochg #{ip}", "good #{ip}"]
|
||||
DDNSFormCallbackSuccessContentArea.value = 'nochg #{ip}\ngood #{ip}'
|
||||
break;
|
||||
|
@ -2181,6 +2257,7 @@ const autocompleteCallbackForm = () => {
|
|||
DDNSForm.value.DNS.Callback.Headers = []
|
||||
DDNSForm.value.DNS.Callback.Method = 'get'
|
||||
DDNSForm.value.DNS.Callback.RequestBody = ""
|
||||
DDNSForm.value.DNS.Callback.DisableCallbackSuccessContentCheck = false
|
||||
DDNSForm.value.DNS.Callback.CallbackSuccessContent = ["addresses updated"]
|
||||
DDNSFormCallbackSuccessContentArea.value = 'addresses updated\n'
|
||||
break;
|
||||
|
@ -2194,6 +2271,7 @@ const autocompleteCallbackForm = () => {
|
|||
DDNSForm.value.DNS.Callback.Headers = []
|
||||
DDNSForm.value.DNS.Callback.Method = 'get'
|
||||
DDNSForm.value.DNS.Callback.RequestBody = ""
|
||||
DDNSForm.value.DNS.Callback.DisableCallbackSuccessContentCheck = false
|
||||
DDNSForm.value.DNS.Callback.CallbackSuccessContent = ["nochg", "good #{ip}"]
|
||||
DDNSFormCallbackSuccessContentArea.value = 'nochg\ngood #{ip}'
|
||||
break;
|
||||
|
|
|
@ -32,8 +32,8 @@ type WebLog struct {
|
|||
|
||||
func (wlog *WebLogs) Write(p []byte) (n int, err error) {
|
||||
nowTime := time.Now()
|
||||
tripContent := strings.TrimSpace(string(p)[20:])
|
||||
content := fmt.Sprintf("%s %s", nowTime.Format("2006-01-02 15:04:05"), tripContent)
|
||||
// tripContent := strings.TrimSpace(string(p)[20:])
|
||||
// content := fmt.Sprintf("%s %s", nowTime.Format("2006-01-02 15:04:05"), tripContent)
|
||||
|
||||
if webLogs.preTimeStamp == nowTime.UnixNano() {
|
||||
webLogs.timeStampIndex++
|
||||
|
@ -41,7 +41,7 @@ func (wlog *WebLogs) Write(p []byte) (n int, err error) {
|
|||
webLogs.timeStampIndex = 0
|
||||
}
|
||||
|
||||
l := WebLog{Timestamp: nowTime.UnixNano() + webLogs.timeStampIndex, Log: content}
|
||||
l := WebLog{Timestamp: nowTime.UnixNano() + webLogs.timeStampIndex, Log: strings.TrimSpace(string(p))}
|
||||
|
||||
webLogsStore = append(webLogsStore, l)
|
||||
webLogs.preTimeStamp = nowTime.UnixNano()
|
||||
|
|
53
web/web.go
53
web/web.go
|
@ -6,8 +6,8 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -25,6 +25,7 @@ import (
|
|||
|
||||
"github.com/gdy666/lucky/base"
|
||||
"github.com/gdy666/lucky/config"
|
||||
"github.com/gdy666/lucky/ddnscore.go"
|
||||
"github.com/gdy666/lucky/rule"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/fileutils"
|
||||
"github.com/gdy666/lucky/thirdlib/gdylib/ginutils"
|
||||
|
@ -212,7 +213,7 @@ func restoreConfigure(c *gin.Context) {
|
|||
}
|
||||
defer src.Close()
|
||||
|
||||
fileBytes, err := ioutil.ReadAll(src)
|
||||
fileBytes, err := io.ReadAll(src)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 1, "msg": fmt.Sprintf("ioutil.ReadAll err:%s", err.Error())})
|
||||
return
|
||||
|
@ -253,12 +254,12 @@ func enableddns(c *gin.Context) {
|
|||
var err error
|
||||
|
||||
if enable == "true" {
|
||||
err = config.EnableDDNSTaskByKey(key, true)
|
||||
err = ddnscore.EnableDDNSTaskByKey(key, true)
|
||||
if err == nil {
|
||||
service.Message("ddns", "syncDDNSTask", key)
|
||||
}
|
||||
} else {
|
||||
err = config.EnableDDNSTaskByKey(key, false)
|
||||
err = ddnscore.EnableDDNSTaskByKey(key, false)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -277,6 +278,8 @@ func deleteDDNSTask(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
ddnscore.DDNSTaskInfoMapDelete(taskKey)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "msg": ""})
|
||||
}
|
||||
|
||||
|
@ -289,7 +292,8 @@ func ddnsTaskList(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
taskList := config.GetDDNSTaskList()
|
||||
taskList := ddnscore.GetDDNSTaskInfoList()
|
||||
ddnscore.FLushWebLastAccessDDNSTaskListLastTime()
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "data": taskList})
|
||||
}
|
||||
|
@ -346,6 +350,8 @@ func alterDDNSTask(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
ddnscore.DDNSTaskInfoMapDelete(taskKey)
|
||||
|
||||
if requestObj.Enable {
|
||||
service.Message("ddns", "syncDDNSTask", taskKey)
|
||||
}
|
||||
|
@ -397,6 +403,12 @@ func dealRequestDDNSTask(t *config.DDNSTask) {
|
|||
t.URL = []string{}
|
||||
}
|
||||
|
||||
if t.DNS.Name == "callback" {
|
||||
if t.DNS.Callback.DisableCallbackSuccessContentCheck {
|
||||
t.DNS.Callback.CallbackSuccessContent = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
if !t.WebhookEnable {
|
||||
t.WebhookHeaders = []string{}
|
||||
t.WebhookMethod = ""
|
||||
|
@ -528,7 +540,7 @@ func whilelistAdd(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "msg": fmt.Sprintf("IP已记录进白名单"), "ip": c.ClientIP(), " effective_time": lifeTime})
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "msg": "IP已记录进白名单", "ip": c.ClientIP(), " effective_time": lifeTime})
|
||||
}
|
||||
|
||||
func whitelistConfigure(c *gin.Context) {
|
||||
|
@ -556,7 +568,6 @@ func alterWhitelistConfigure(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0})
|
||||
return
|
||||
}
|
||||
|
||||
func checkLocalIP(c *gin.Context) {
|
||||
|
@ -729,7 +740,7 @@ func baseconfigure(c *gin.Context) {
|
|||
}
|
||||
|
||||
func netinterfaces(c *gin.Context) {
|
||||
ipv4NetInterfaces, ipv6Netinterfaces, err := config.GetNetInterface()
|
||||
ipv4NetInterfaces, ipv6Netinterfaces, err := ddnscore.GetNetInterface()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 1, "msg": fmt.Sprintf("获取网卡列表出错:%s", err.Error())})
|
||||
return
|
||||
|
@ -764,16 +775,16 @@ func webhookTest(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
responseStr, err := config.WebhookTest(&ddnsTask.DDNSTask,
|
||||
request.WebhookURL,
|
||||
request.WebhookMethod,
|
||||
request.WebhookRequestBody,
|
||||
request.WebhookProxy,
|
||||
request.WebhookProxyAddr,
|
||||
request.WebhookProxyUser,
|
||||
request.WebhookProxyPassword,
|
||||
request.WebhookHeaders,
|
||||
request.WebhookSuccessContent)
|
||||
// responseStr, err := config.WebhookTest(&ddnsTask.DDNSTask,
|
||||
// request.WebhookURL,
|
||||
// request.WebhookMethod,
|
||||
// request.WebhookRequestBody,
|
||||
// request.WebhookProxy,
|
||||
// request.WebhookProxyAddr,
|
||||
// request.WebhookProxyUser,
|
||||
// request.WebhookProxyPassword,
|
||||
// request.WebhookHeaders,
|
||||
// request.WebhookSuccessContent)
|
||||
|
||||
//fmt.Printf("request:%s\n", request)
|
||||
|
||||
|
@ -782,7 +793,7 @@ func webhookTest(c *gin.Context) {
|
|||
msg = err.Error()
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "msg": msg, "Response": responseStr})
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "msg": msg, "Response": "responseStr"})
|
||||
}
|
||||
|
||||
func IPRegTest(c *gin.Context) {
|
||||
|
@ -790,7 +801,7 @@ func IPRegTest(c *gin.Context) {
|
|||
netinterface := c.Query("netinterface")
|
||||
ipreg := c.Query("ipreg")
|
||||
|
||||
ip := config.GetIPFromNetInterface(iptype, netinterface, ipreg)
|
||||
ip := ddnscore.GetIPFromNetInterface(iptype, netinterface, ipreg)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"ret": 0, "ip": ip})
|
||||
}
|
||||
|
@ -1067,7 +1078,7 @@ func GetCpuPercent() float64 {
|
|||
return percent[0]
|
||||
}
|
||||
|
||||
//跨域访问:cross origin resource share
|
||||
// 跨域访问:cross origin resource share
|
||||
func CrosHandler() gin.HandlerFunc {
|
||||
return func(context *gin.Context) {
|
||||
method := context.Request.Method
|
||||
|
|
Loading…
Reference in New Issue