diff --git a/README.md b/README.md
index f8fa21f..5fd2618 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
[![GitHub release](https://img.shields.io/github/release/jeessy2/ddns-go.svg?logo=github&style=flat-square) ![GitHub release downloads](https://img.shields.io/github/downloads/jeessy2/ddns-go/total?logo=github)](https://github.com/jeessy2/ddns-go/releases/latest) [![Go version](https://img.shields.io/github/go-mod/go-version/jeessy2/ddns-go)](https://github.com/jeessy2/ddns-go/blob/master/go.mod) [![](https://goreportcard.com/badge/github.com/jeessy2/ddns-go/v5)](https://goreportcard.com/report/github.com/jeessy2/ddns-go/v5) [![](https://img.shields.io/docker/image-size/jeessy/ddns-go)](https://registry.hub.docker.com/r/jeessy/ddns-go) [![](https://img.shields.io/docker/pulls/jeessy/ddns-go)](https://registry.hub.docker.com/r/jeessy/ddns-go)
+中文 | [English](https://github.com/jeessy2/ddns-go/blob/master/README_EN.md)
+
自动获得你的公网 IPv4 或 IPv6 地址,并解析到对应的域名服务。
- [特性](#特性)
@@ -16,7 +18,7 @@
## 特性
- 支持Mac、Windows、Linux系统,支持ARM、x86架构
-- 支持的域名服务商 `Alidns(阿里云)` `Dnspod(腾讯云)` `Cloudflare` `华为云` `Callback` `百度云` `Porkbun` `GoDaddy` `Google Domain`
+- 支持的域名服务商 `阿里云` `腾讯云` `Dnspod` `Cloudflare` `华为云` `Callback` `百度云` `Porkbun` `GoDaddy` `Google Domain`
- 支持接口/网卡/[命令](https://github.com/jeessy2/ddns-go/wiki/通过命令获取IP参考)获取IP
- 支持以服务的方式运行
- 默认间隔5分钟同步一次
@@ -35,20 +37,18 @@
## 系统中使用
- 从 [Releases](https://github.com/jeessy2/ddns-go/releases) 下载并解压 ddns-go
-- [可选] 使用 [Homebrew](https://brew.sh) 安装 [ddns-go](https://formulae.brew.sh/formula/ddns-go):
-
- ```bash
- brew install ddns-go
- ```
-
-- 双击运行, 如没有找到配置, 程序将自动打开 http://127.0.0.1:9876
-- [可选] 安装服务
+- 安装服务
- Mac/Linux: `sudo ./ddns-go -s install`
- Win(以管理员打开cmd): `.\ddns-go.exe -s install`
- [可选] 服务卸载
- Mac/Linux: `sudo ./ddns-go -s uninstall`
- Win(以管理员打开cmd): `.\ddns-go.exe -s uninstall`
-- [可选] 支持安装或启动时带参数 `-l`监听地址 `-f`同步间隔时间(秒) `-cacheTimes`间隔N次与服务商比对 `-c`自定义配置文件路径 `-noweb`不启动web服务 `-skipVerify`跳过证书验证 `-dns` 自定义 DNS 服务器。如:`./ddns-go -s install -l :9877 -f 600 -c /Users/name/ddns-go.yaml`
+- [可选] 支持安装带参数 `-l`监听地址 `-f`同步间隔时间(秒) `-cacheTimes`间隔N次与服务商比对 `-c`自定义配置文件路径 `-noweb`不启动web服务 `-skipVerify`跳过证书验证 `-dns` 自定义 DNS 服务器。如:`./ddns-go -s install -l :9876 -f 600 -c /Users/name/ddns-go.yaml`
+- [可选] 使用 [Homebrew](https://brew.sh) 安装 [ddns-go](https://formulae.brew.sh/formula/ddns-go):
+
+ ```bash
+ brew install ddns-go
+ ```
> [!NOTE]
> 通过合理的配置 `-f` 和 `-cacheTimes` 可以实现 IP 变化即时触发更新且不会被 DDNS 服务商限流, 例如 `-f 10 -cacheTimes 360` 效果为每 10 秒检查一次本地 IP 变化, 每小时去公网对比一下 IP 变化
@@ -61,7 +61,7 @@
docker run -d --name ddns-go --restart=always --net=host -v /opt/ddns-go:/root jeessy/ddns-go
```
-- 在浏览器中打开`http://主机IP:9876`,修改你的配置,成功
+- 在浏览器中打开`http://主机IP:9876`,并修改你的配置
- [可选] 使用 `ghcr.io` 镜像
diff --git a/README_EN.md b/README_EN.md
new file mode 100644
index 0000000..718b310
--- /dev/null
+++ b/README_EN.md
@@ -0,0 +1,140 @@
+# ddns-go
+
+[![GitHub release](https://img.shields.io/github/release/jeessy2/ddns-go.svg?logo=github&style=flat-square) ![GitHub release downloads](https://img.shields.io/github/downloads/jeessy2/ddns-go/total?logo=github)](https://github.com/jeessy2/ddns-go/releases/latest) [![Go version](https://img.shields.io/github/go-mod/go-version/jeessy2/ddns-go)](https://github.com/jeessy2/ddns-go/blob/master/go.mod) [![](https://goreportcard.com/badge/github.com/jeessy2/ddns-go/v5)](https://goreportcard.com/report/github.com/jeessy2/ddns-go/v5) [![](https://img.shields.io/docker/image-size/jeessy/ddns-go)](https://registry.hub.docker.com/r/jeessy/ddns-go) [![](https://img.shields.io/docker/pulls/jeessy/ddns-go)](https://registry.hub.docker.com/r/jeessy/ddns-go)
+
+[中文](https://github.com/jeessy2/ddns-go/blob/master/README.md) | English
+
+Automatically obtain your public IPv4 or IPv6 address and resolve it to the corresponding domain name service.
+
+- [Features](#Features)
+- [Use in system](#Use-in-system)
+- [Use in docker](#Use-in-docker)
+- [Webhook](#webhook)
+- [Callback](#callback)
+- [Web interfaces](#Web-interfaces)
+
+## Features
+
+- Support Mac, Windows, Linux system, support ARM, x86 architecture
+- Support domain service providers `Aliyun` `Tencent` `Dnspod` `Cloudflare` `Huawei` `Callback` `Baidu` `Porkbun` `GoDaddy` `Google Domain` `Namecheap` `NameSilo`
+- Support interface / netcard / command to get IP
+- Support running as a service
+- Default interval is 5 minutes
+- Support configuring multiple DNS service providers at the same time
+- Support multiple domain name resolution at the same time
+- Support multi-level domain name
+- Configured on the web page, simple and convenient
+- In the web page, you can quickly view the latest 50 logs
+- Support Webhook notification
+- Support TTL
+
+> [!NOTE]
+> If you enable public network access, it is recommended to use Nginx and other reverse proxy software to enable HTTPS access to ensure security.
+
+## Use in system
+
+- Download and unzip ddns-go from [Releases](https://github.com/jeessy2/ddns-go/releases)
+- Run in service mode
+ - Mac/Linux: `sudo ./ddns-go -s install`
+ - Win(Run as administrator): `.\ddns-go.exe -s install`
+- [Optional] Uninstall service
+ - Mac/Linux: `sudo ./ddns-go -s uninstall`
+ - Win(Run as administrator): `.\ddns-go.exe -s uninstall`
+- [Optional] Support installation with parameters `-l` listen address `-f` Sync frequency(seconds) `-cacheTimes` interval N times compared with service providers `-c` custom configuration file path `-noweb` does not start web service `-skipVerify` skip certificate verification `-dns` custom DNS server. example:`./ddns-go -s install -l :9876 -f 600 -c /Users/name/ddns-go.yaml`
+- [Optional] You can use [Homebrew](https://brew.sh) to install [ddns-go](https://formulae.brew.sh/formula/ddns-go)
+
+ ```bash
+ brew install ddns-go
+ ```
+
+## Use in docker
+
+- Mount the host directory, use the docker host mode. You can replace `/opt/ddns-go` with any directory on your host, the configuration file is a hidden file
+
+ ```bash
+ docker run -d --name ddns-go --restart=always --net=host -v /opt/ddns-go:/root jeessy/ddns-go
+ ```
+
+- Open `http://DOCKER_IP:9876` in the browser, modify your configuration
+
+- [Optional] Use `ghcr.io` mirror
+
+ ```bash
+ docker run -d --name ddns-go --restart=always --net=host -v /opt/ddns-go:/root ghcr.io/jeessy2/ddns-go
+ ```
+
+- [Optional] Support startup with parameters `-l`listen address `-f`Sync frequency(seconds)
+
+ ```bash
+ docker run -d --name ddns-go --restart=always --net=host -v /opt/ddns-go:/root jeessy/ddns-go -l :9877 -f 600
+ ```
+
+- [Optional] Without using docker host mode
+
+ ```bash
+ docker run -d --name ddns-go --restart=always -p 9876:9876 -v /opt/ddns-go:/root jeessy/ddns-go
+ ```
+
+## Webhook
+
+- Support webhook, when the domain name is updated successfully or not, the URL filled in will be called back
+- Support variables
+
+ | Variable name | Comments |
+ | ---- | ---- |
+ | #{ipv4Addr} | The new IPv4 |
+ | #{ipv4Result} | IPv4 update result: `no changed` `success` `failed`|
+ | #{ipv4Domains} | IPv4 domains,Split by `,` |
+ | #{ipv6Addr} | The new IPv6 |
+ | #{ipv6Result} | IPv6 update result: `no changed` `success` `failed`|
+ | #{ipv6Domains} | IPv6 domains,Split by `,` |
+
+- If RequestBody is empty, it is a `GET` request, otherwise it is a `POST` request
+
+- Telegram
+
+ [ddns-telegram-bot](https://github.com/WingLim/ddns-telegram-bot)
+
+- Discord
+
+ - Discord client -> Server -> Channel Settings -> Integration -> View Webhook -> New Webhook -> Copy Webhook URL
+ - Input the `Webhook URL` copied from Discord in the URL
+ - Input in RequestBody
+ ```json
+ {
+ "content": "The domain name #{ipv4Domains} dynamically resolves to #{ipv4Result}.",
+ "embeds": [
+ {
+ "description": "Domains: #{ipv4Domains}, Result: #{ipv4Result}, IP: #{ipv4Addr}",
+ "color": 15258703,
+ "author": {
+ "name": "DDNS"
+ },
+ "footer": {
+ "text": "DDNS #{ipv4Result}"
+ }
+ }
+ ]
+ }
+ ```
+
+
+- [More webhook configuration reference](https://github.com/jeessy2/ddns-go/issues/327)
+
+## Callback
+
+- Support more third-party DNS service providers through custom callback
+- Callback will be called as many times as there are lines in the configured domain name
+- Support variables
+
+ | Variable name | Comments |
+ | ---- | ---- |
+ | #{ip} | The new IPv4/IPv6 address|
+ | #{domain} | Current domain |
+ | #{recordType} | Record type `A` or `AAAA` |
+ | #{ttl} | TTL |
+- If RequestBody is empty, it is a `GET` request, otherwise it is a `POST` request
+
+## Web interfaces
+
+![screenshots](https://raw.githubusercontent.com/jeessy2/ddns-go/master/ddns-web.png)
diff --git a/config/config.go b/config/config.go
index c37db0e..0ef1133 100755
--- a/config/config.go
+++ b/config/config.go
@@ -60,6 +60,8 @@ type Config struct {
Webhook
// 禁止公网访问
NotAllowWanAccess bool
+ // 语言
+ Lang string
}
// ConfigCache ConfigCache
@@ -92,14 +94,14 @@ func GetConfigCached() (conf Config, err error) {
byt, err := os.ReadFile(configFilePath)
if err != nil {
- log.Println(configFilePath + " 读取失败")
+ util.Log("异常信息: %s", err)
cache.Err = err
return *cache.ConfigSingle, err
}
err = yaml.Unmarshal(byt, cache.ConfigSingle)
if err != nil {
- log.Println("反序列化配置文件失败", err)
+ util.Log("异常信息: %s", err)
cache.Err = err
return *cache.ConfigSingle, err
}
@@ -109,6 +111,9 @@ func GetConfigCached() (conf Config, err error) {
cache.ConfigSingle.NotAllowWanAccess = true
}
+ // 初始化语言
+ util.InitLogLang(cache.ConfigSingle.Lang)
+
// remove err
cache.Err = nil
return *cache.ConfigSingle, err
@@ -161,7 +166,7 @@ func (conf *Config) SaveConfig() (err error) {
return
}
- log.Printf("配置文件已保存在: %s\n", configFilePath)
+ util.Log("配置文件已保存在: %s", configFilePath)
// 清空配置缓存
cache.ConfigSingle = nil
@@ -172,7 +177,7 @@ func (conf *Config) SaveConfig() (err error) {
func (conf *DnsConfig) getIpv4AddrFromInterface() string {
ipv4, _, err := GetNetInterface()
if err != nil {
- log.Println("从网卡获得IPv4失败!")
+ util.Log("从网卡获得IPv4失败")
return ""
}
@@ -182,7 +187,7 @@ func (conf *DnsConfig) getIpv4AddrFromInterface() string {
}
}
- log.Println("从网卡中获得IPv4失败! 网卡名: ", conf.Ipv4.NetInterface)
+ util.Log("从网卡中获得IPv4失败! 网卡名: %s", conf.Ipv4.NetInterface)
return ""
}
@@ -193,20 +198,20 @@ func (conf *DnsConfig) getIpv4AddrFromUrl() string {
url = strings.TrimSpace(url)
resp, err := client.Get(url)
if err != nil {
- log.Printf("连接失败! 点击查看接口能否返回IPv4地址\n", url)
- log.Printf("错误信息: %s\n", err)
+ util.Log("通过接口获取IPv4失败! 接口地址: %s", url)
+ util.Log("异常信息: %s", err)
continue
}
defer resp.Body.Close()
lr := io.LimitReader(resp.Body, 1024000)
body, err := io.ReadAll(lr)
if err != nil {
- log.Println("读取IPv4结果失败! 接口: ", url)
+ util.Log("异常信息: %s", err)
continue
}
result := Ipv4Reg.FindString(string(body))
if result == "" {
- log.Printf("获取IPv4结果失败! 接口: %s ,返回值: %s\n", url, result)
+ util.Log("获取IPv4结果失败! 接口: %s ,返回值: %s", url, string(body))
}
return result
}
@@ -243,14 +248,14 @@ func (conf *DnsConfig) getAddrFromCmd(addrType string) string {
// run cmd
out, err := execCmd.CombinedOutput()
if err != nil {
- log.Printf("获取%s结果失败! 未能成功执行命令:%s,错误:%q,退出状态码:%s\n", addrType, execCmd.String(), out, err)
+ util.Log("获取%s结果失败! 未能成功执行命令:%s, 错误:%q, 退出状态码:%s", addrType, execCmd.String(), out, err)
return ""
}
str := string(out)
// get result
result := comp.FindString(str)
if result == "" {
- log.Printf("获取%s结果失败! 命令:%s,标准输出:%q\n", addrType, execCmd.String(), str)
+ util.Log("获取%s结果失败! 命令: %s, 标准输出: %q", addrType, execCmd.String(), str)
}
return result
}
@@ -269,7 +274,7 @@ func (conf *DnsConfig) GetIpv4Addr() string {
// 从命令行获取 IP
return conf.getAddrFromCmd("IPv4")
default:
- log.Println("IPv4 的 获取 IP 方式 未知!")
+ log.Println("IPv4's get IP method is unknown")
return "" // unknown type
}
}
@@ -277,7 +282,7 @@ func (conf *DnsConfig) GetIpv4Addr() string {
func (conf *DnsConfig) getIpv6AddrFromInterface() string {
_, ipv6, err := GetNetInterface()
if err != nil {
- log.Println("从网卡获得IPv6失败!")
+ util.Log("从网卡获得IPv6失败")
return ""
}
@@ -289,34 +294,32 @@ func (conf *DnsConfig) getIpv6AddrFromInterface() string {
num, err := strconv.Atoi(conf.Ipv6.IPv6Reg[1:])
if err == nil {
if num > 0 {
- log.Printf("IPv6将使用第 %d 个IPv6地址\n", num)
if num <= len(netInterface.Address) {
return netInterface.Address[num-1]
}
- log.Printf("未找到第 %d 个IPv6地址! 将使用第一个IPv6地址\n", num)
+ util.Log("未找到第 %d 个IPv6地址! 将使用第一个IPv6地址", num)
return netInterface.Address[0]
}
- log.Printf("IPv6匹配表达式 %s 不正确! 最小从1开始\n", conf.Ipv6.IPv6Reg)
+ util.Log("IPv6匹配表达式 %s 不正确! 最小从1开始", conf.Ipv6.IPv6Reg)
return ""
}
}
// 正则表达式匹配
- log.Printf("IPv6将使用正则表达式 %s 进行匹配\n", conf.Ipv6.IPv6Reg)
+ util.Log("IPv6将使用正则表达式 %s 进行匹配", conf.Ipv6.IPv6Reg)
for i := 0; i < len(netInterface.Address); i++ {
matched, err := regexp.MatchString(conf.Ipv6.IPv6Reg, netInterface.Address[i])
if matched && err == nil {
- log.Println("匹配成功! 匹配到地址: ", netInterface.Address[i])
+ util.Log("匹配成功! 匹配到地址: ", netInterface.Address[i])
return netInterface.Address[i]
}
- log.Printf("第 %d 个地址 %s 不匹配, 将匹配下一个地址\n", i+1, netInterface.Address[i])
}
- log.Println("没有匹配到任何一个IPv6地址, 将使用第一个地址")
+ util.Log("没有匹配到任何一个IPv6地址, 将使用第一个地址")
}
return netInterface.Address[0]
}
}
- log.Println("从网卡中获得IPv6失败! 网卡名: ", conf.Ipv6.NetInterface)
+ util.Log("从网卡中获得IPv6失败! 网卡名: %s", conf.Ipv6.NetInterface)
return ""
}
@@ -327,8 +330,8 @@ func (conf *DnsConfig) getIpv6AddrFromUrl() string {
url = strings.TrimSpace(url)
resp, err := client.Get(url)
if err != nil {
- log.Printf("连接失败! 点击查看接口能否返回IPv6地址, 参考说明:点击访问\n", url, "https://github.com/jeessy2/ddns-go#使用ipv6")
- log.Printf("错误信息: %s\n", err)
+ util.Log("通过接口获取IPv6失败! 接口地址: %s", url)
+ util.Log("异常信息: %s", err)
continue
}
@@ -336,12 +339,12 @@ func (conf *DnsConfig) getIpv6AddrFromUrl() string {
lr := io.LimitReader(resp.Body, 1024000)
body, err := io.ReadAll(lr)
if err != nil {
- log.Println("读取IPv6结果失败! 接口: ", url)
+ util.Log("异常信息: %s", err)
continue
}
result := Ipv6Reg.FindString(string(body))
if result == "" {
- log.Printf("获取IPv6结果失败! 接口: %s ,返回值: %s\n", url, result)
+ util.Log("获取IPv6结果失败! 接口: %s ,返回值: %s", url, result)
}
return result
}
@@ -362,7 +365,7 @@ func (conf *DnsConfig) GetIpv6Addr() (result string) {
// 从命令行获取 IP
return conf.getAddrFromCmd("IPv6")
default:
- log.Println("IPv6 的 获取 IP 方式 未知!")
+ log.Println("IPv6's get IP method is unknown")
return "" // unknown type
}
}
diff --git a/config/domains.go b/config/domains.go
index f48a6bb..47cbd9a 100644
--- a/config/domains.go
+++ b/config/domains.go
@@ -1,7 +1,6 @@
package config
import (
- "log"
"net/url"
"strings"
@@ -81,7 +80,7 @@ func (domains *Domains) GetNewIp(dnsConf *DnsConfig) {
if domains.Ipv4Cache.TimesFailedIP == 3 {
domains.Ipv4Domains[0].UpdateStatus = UpdatedFailed
}
- log.Println("未能获取IPv4地址, 将不会更新")
+ util.Log("未能获取IPv4地址, 将不会更新")
}
}
@@ -97,7 +96,7 @@ func (domains *Domains) GetNewIp(dnsConf *DnsConfig) {
if domains.Ipv6Cache.TimesFailedIP == 3 {
domains.Ipv6Domains[0].UpdateStatus = UpdatedFailed
}
- log.Println("未能获取IPv6地址, 将不会更新")
+ util.Log("未能获取IPv6地址, 将不会更新")
}
}
@@ -124,7 +123,8 @@ func checkParseDomains(domainArr []string) (domains []*Domain) {
case 1: // 不使用冒号分割,自动识别域名
domainName, err := publicsuffix.EffectiveTLDPlusOne(domainStr)
if err != nil {
- log.Println(domainStr, "域名不正确:", err)
+ util.Log("域名: %s 不正确", domainStr)
+ util.Log("异常信息: %s", err)
continue
}
domain.DomainName = domainName
@@ -136,21 +136,21 @@ func checkParseDomains(domainArr []string) (domains []*Domain) {
case 2: // 使用冒号分隔,为 子域名:根域名 格式
sp := strings.Split(dp[1], ".")
if len(sp) <= 1 {
- log.Println(domainStr, "域名不正确")
+ util.Log("域名: %s 不正确", domainStr)
continue
}
domain.DomainName = dp[1]
domain.SubDomain = dp[0]
default:
- log.Println(domainStr, "域名不正确")
+ util.Log("域名: %s 不正确", domainStr)
continue
}
// 参数条件
if len(qp) == 2 {
- u, err := url.Parse("http://baidu.com?" + qp[1])
+ u, err := url.Parse("https://baidu.com?" + qp[1])
if err != nil {
- log.Println(domainStr, "域名解析失败")
+ util.Log("域名: %s 解析失败", domainStr)
continue
}
domain.CustomParams = u.Query().Encode()
@@ -166,7 +166,7 @@ func (domains *Domains) GetNewIpResult(recordType string) (ipAddr string, retDom
if domains.Ipv6Cache.Check(domains.Ipv6Addr) {
return domains.Ipv6Addr, domains.Ipv6Domains
} else {
- log.Printf("IPv6未改变,将等待 %d 次后与DNS服务商进行比对\n", domains.Ipv6Cache.Times)
+ util.Log("IPv6未改变, 将等待 %d 次后与DNS服务商进行比对", domains.Ipv6Cache.Times)
return "", domains.Ipv6Domains
}
}
@@ -174,7 +174,7 @@ func (domains *Domains) GetNewIpResult(recordType string) (ipAddr string, retDom
if domains.Ipv4Cache.Check(domains.Ipv4Addr) {
return domains.Ipv4Addr, domains.Ipv4Domains
} else {
- log.Printf("IPv4未改变,将等待 %d 次后与DNS服务商进行比对\n", domains.Ipv4Cache.Times)
+ util.Log("IPv4未改变, 将等待 %d 次后与DNS服务商进行比对", domains.Ipv4Cache.Times)
return "", domains.Ipv4Domains
}
}
diff --git a/config/webhook.go b/config/webhook.go
index 5283038..1b7f1f6 100644
--- a/config/webhook.go
+++ b/config/webhook.go
@@ -3,7 +3,6 @@ package config
import (
"encoding/json"
"fmt"
- "log"
"net/http"
"net/url"
"strings"
@@ -48,7 +47,7 @@ func ExecWebhook(domains *Domains, conf *Config) (v4Status updateStatusType, v6S
if v4Status == UpdatedFailed || v6Status == UpdatedFailed {
updatedFailedTimes++
if updatedFailedTimes != 3 {
- log.Println("将不会触发Webhook,仅在第 3 次失败时触发一次Webhook,当前失败次数:", updatedFailedTimes)
+ util.Log("将不会触发Webhook, 仅在第 3 次失败时触发一次Webhook, 当前失败次数:%d", updatedFailedTimes)
return
}
} else {
@@ -66,18 +65,18 @@ func ExecWebhook(domains *Domains, conf *Config) (v4Status updateStatusType, v6S
contentType = "application/json"
} else if hasJSONPrefix(postPara) {
// 如果 RequestBody 的 JSON 无效但前缀为 JSON,提示无效
- log.Println("RequestBody 的 JSON 无效!")
+ util.Log("Webhook中的 RequestBody JSON 无效")
}
}
requestURL := replacePara(domains, conf.WebhookURL, v4Status, v6Status)
u, err := url.Parse(requestURL)
if err != nil {
- log.Println("Webhook配置中的URL不正确")
+ util.Log("Webhook配置中的URL不正确")
return
}
req, err := http.NewRequest(method, fmt.Sprintf("%s://%s%s?%s", u.Scheme, u.Host, u.Path, u.Query().Encode()), strings.NewReader(postPara))
if err != nil {
- log.Println("创建Webhook请求异常, Err:", err)
+ util.Log("Webhook调用失败! 异常信息:%s", err)
return
}
@@ -89,11 +88,11 @@ func ExecWebhook(domains *Domains, conf *Config) (v4Status updateStatusType, v6S
clt := util.CreateHTTPClient()
resp, err := clt.Do(req)
- body, err := util.GetHTTPResponseOrg(resp, requestURL, err)
+ body, err := util.GetHTTPResponseOrg(resp, err)
if err == nil {
- log.Printf("Webhook调用成功, 返回数据: %q\n", string(body))
+ util.Log("Webhook调用成功! 返回数据:%s", string(body))
} else {
- log.Printf("Webhook调用失败,Err:%s\n", err)
+ util.Log("Webhook调用失败! 异常信息:%s", err)
}
}
return
@@ -122,11 +121,11 @@ func getDomainsStatus(domains []*Domain) updateStatusType {
// replacePara 替换参数
func replacePara(domains *Domains, orgPara string, ipv4Result updateStatusType, ipv6Result updateStatusType) (newPara string) {
orgPara = strings.ReplaceAll(orgPara, "#{ipv4Addr}", domains.Ipv4Addr)
- orgPara = strings.ReplaceAll(orgPara, "#{ipv4Result}", string(ipv4Result))
+ orgPara = strings.ReplaceAll(orgPara, "#{ipv4Result}", util.LogStr(string(ipv4Result))) // i18n
orgPara = strings.ReplaceAll(orgPara, "#{ipv4Domains}", getDomainsStr(domains.Ipv4Domains))
orgPara = strings.ReplaceAll(orgPara, "#{ipv6Addr}", domains.Ipv6Addr)
- orgPara = strings.ReplaceAll(orgPara, "#{ipv6Result}", string(ipv6Result))
+ orgPara = strings.ReplaceAll(orgPara, "#{ipv6Result}", util.LogStr(string(ipv6Result))) // i18n
orgPara = strings.ReplaceAll(orgPara, "#{ipv6Domains}", getDomainsStr(domains.Ipv6Domains))
return orgPara
@@ -153,7 +152,7 @@ func checkParseHeaders(headerStr string) (headers map[string]string) {
if headerStr != "" {
parts := strings.Split(headerStr, ":")
if len(parts) != 2 {
- log.Println(headerStr, "Header不正确")
+ util.Log("Webhook Header不正确: %s", headerStr)
continue
}
headers[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
diff --git a/ddns-web.png b/ddns-web.png
index 86ee5af..8446b9e 100644
Binary files a/ddns-web.png and b/ddns-web.png differ
diff --git a/dns/alidns.go b/dns/alidns.go
index 9e2ebe1..4c5e4e7 100644
--- a/dns/alidns.go
+++ b/dns/alidns.go
@@ -2,7 +2,6 @@ package dns
import (
"bytes"
- "log"
"net/http"
"net/url"
@@ -82,6 +81,7 @@ func (ali *Alidns) addUpdateDomainRecords(recordType string) {
err := ali.request(params, &records)
if err != nil {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -120,10 +120,10 @@ 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)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!", domain)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -133,7 +133,7 @@ func (ali *Alidns) modify(recordSelected AlidnsRecord, domain *config.Domain, re
// 相同不修改
if recordSelected.Value == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
@@ -149,10 +149,10 @@ func (ali *Alidns) modify(recordSelected AlidnsRecord, domain *config.Domain, re
err := ali.request(params, &result)
if err == nil && result.RecordID != "" {
- log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!", domain)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -170,13 +170,13 @@ func (ali *Alidns) request(params url.Values, result interface{}) (err error) {
req.URL.RawQuery = params.Encode()
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
client := util.CreateHTTPClient()
resp, err := client.Do(req)
- err = util.GetHTTPResponse(resp, alidnsEndpoint, err, result)
+ err = util.GetHTTPResponse(resp, err, result)
return
}
diff --git a/dns/baidu.go b/dns/baidu.go
index 8cc5b59..f47de5a 100644
--- a/dns/baidu.go
+++ b/dns/baidu.go
@@ -3,7 +3,6 @@ package dns
import (
"bytes"
"encoding/json"
- "log"
"net/http"
"strconv"
@@ -110,6 +109,7 @@ func (baidu *BaiduCloud) addUpdateDomainRecords(recordType string) {
err := baidu.request("POST", baiduEndpoint+"/v1/domain/resolve/list", requestBody, &records)
if err != nil {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -143,10 +143,10 @@ 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)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!", domain)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -155,7 +155,7 @@ func (baidu *BaiduCloud) create(domain *config.Domain, recordType string, ipAddr
func (baidu *BaiduCloud) modify(record BaiduRecord, domain *config.Domain, rdType string, ipAddr string) {
//没有变化直接跳过
if record.Rdata == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
var baiduModifyRequest = BaiduModifyRequest{
@@ -171,10 +171,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)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!", domain)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -193,7 +193,7 @@ func (baidu *BaiduCloud) request(method string, url string, data interface{}, re
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
@@ -201,7 +201,7 @@ func (baidu *BaiduCloud) request(method string, url string, data interface{}, re
client := util.CreateHTTPClient()
resp, err := client.Do(req)
- err = util.GetHTTPResponse(resp, url, err, result)
+ err = util.GetHTTPResponse(resp, err, result)
return
}
diff --git a/dns/callback.go b/dns/callback.go
index ec91d9f..9fb4f7e 100644
--- a/dns/callback.go
+++ b/dns/callback.go
@@ -2,7 +2,6 @@ package dns
import (
"encoding/json"
- "log"
"net/http"
"net/url"
"strings"
@@ -53,12 +52,12 @@ func (cb *Callback) addUpdateDomainRecords(recordType string) {
// 防止多次发送Webhook通知
if recordType == "A" {
if cb.lastIpv4 == ipAddr {
- log.Println("你的IPv4未变化, 未触发Callback")
+ util.Log("你的IPv4未变化, 未触发 %s 请求", "Callback")
return
}
} else {
if cb.lastIpv6 == ipAddr {
- log.Println("你的IPv6未变化, 未触发Callback")
+ util.Log("你的IPv6未变化, 未触发 %s 请求", "Callback")
return
}
}
@@ -77,24 +76,24 @@ func (cb *Callback) addUpdateDomainRecords(recordType string) {
requestURL := replacePara(cb.DNS.ID, ipAddr, domain, recordType, cb.TTL)
u, err := url.Parse(requestURL)
if err != nil {
- log.Println("Callback的URL不正确")
+ util.Log("Callback的URL不正确")
return
}
req, err := http.NewRequest(method, u.String(), strings.NewReader(postPara))
if err != nil {
- log.Println("创建Callback请求异常, Err:", err)
+ util.Log("异常信息: %s", err)
return
}
req.Header.Add("content-type", contentType)
clt := util.CreateHTTPClient()
resp, err := clt.Do(req)
- body, err := util.GetHTTPResponseOrg(resp, requestURL, err)
+ body, err := util.GetHTTPResponseOrg(resp, err)
if err == nil {
- log.Printf("Callback调用成功, 域名: %s, IP: %s, 返回数据: %s, \n", domain, ipAddr, string(body))
+ util.Log("Callback调用成功, 域名: %s, IP: %s, 返回数据: %s", domain, ipAddr, string(body))
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("Callback调用失败,Err:%s\n", err)
+ util.Log("Callback调用失败, 异常信息: %s", err)
domain.UpdateStatus = config.UpdatedFailed
}
}
diff --git a/dns/cloudflare.go b/dns/cloudflare.go
index c7d7977..6324c8f 100644
--- a/dns/cloudflare.go
+++ b/dns/cloudflare.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
- "log"
"net/http"
"strconv"
@@ -93,6 +92,7 @@ func (cf *Cloudflare) addUpdateDomainRecords(recordType string) {
// get zone
result, err := cf.getZones(domain)
if err != nil || len(result.Result) != 1 {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -108,6 +108,7 @@ func (cf *Cloudflare) addUpdateDomainRecords(recordType string) {
)
if err != nil || !records.Success {
+ util.Log("查询域名信息发生异常! %s", err)
return
}
@@ -139,10 +140,10 @@ func (cf *Cloudflare) create(zoneID string, domain *config.Domain, recordType st
&status,
)
if err == nil && status.Success {
- log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!Messages: %s", domain, status.Messages)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -152,7 +153,7 @@ func (cf *Cloudflare) modify(result CloudflareRecordsResp, zoneID string, domain
for _, record := range result.Result {
// 相同不修改
if record.Content == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
continue
}
var status CloudflareStatus
@@ -169,10 +170,10 @@ func (cf *Cloudflare) modify(result CloudflareRecordsResp, zoneID string, domain
&status,
)
if err == nil && status.Success {
- log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!Messages: %s", domain, status.Messages)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -202,7 +203,7 @@ func (cf *Cloudflare) request(method string, url string, data interface{}, resul
bytes.NewBuffer(jsonStr),
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
req.Header.Set("Authorization", "Bearer "+cf.DNS.Secret)
@@ -210,7 +211,7 @@ func (cf *Cloudflare) request(method string, url string, data interface{}, resul
client := util.CreateHTTPClient()
resp, err := client.Do(req)
- err = util.GetHTTPResponse(resp, url, err, result)
+ err = util.GetHTTPResponse(resp, err, result)
return
}
diff --git a/dns/dnspod.go b/dns/dnspod.go
index b164bec..01f6e6c 100644
--- a/dns/dnspod.go
+++ b/dns/dnspod.go
@@ -1,7 +1,6 @@
package dns
import (
- "log"
"net/url"
"github.com/jeessy2/ddns-go/v5/config"
@@ -76,6 +75,7 @@ func (dnspod *Dnspod) addUpdateDomainRecords(recordType string) {
for _, domain := range domains {
result, err := dnspod.getRecordList(domain, recordType)
if err != nil {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -117,10 +117,10 @@ func (dnspod *Dnspod) create(domain *config.Domain, recordType string, ipAddr st
status, err := dnspod.commonRequest(recordCreateAPI, params, domain)
if err == nil && status.Status.Code == "1" {
- log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!Code: %s, Message: %s", domain, status.Status.Code, status.Status.Message)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, status.Status.Message)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -130,7 +130,7 @@ func (dnspod *Dnspod) modify(record DnspodRecord, domain *config.Domain, recordT
// 相同不修改
if record.Value == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
@@ -149,10 +149,10 @@ func (dnspod *Dnspod) modify(record DnspodRecord, domain *config.Domain, recordT
}
status, err := dnspod.commonRequest(recordModifyURL, params, domain)
if err == nil && status.Status.Code == "1" {
- log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!Code: %s, Message: %s", domain, status.Status.Code, status.Status.Message)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, status.Status.Message)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -165,7 +165,7 @@ func (dnspod *Dnspod) commonRequest(apiAddr string, values url.Values, domain *c
values,
)
- err = util.GetHTTPResponse(resp, apiAddr, err, &status)
+ err = util.GetHTTPResponse(resp, err, &status)
return
}
@@ -186,7 +186,7 @@ func (dnspod *Dnspod) getRecordList(domain *config.Domain, typ string) (result D
params,
)
- err = util.GetHTTPResponse(resp, recordListAPI, err, &result)
+ err = util.GetHTTPResponse(resp, err, &result)
return
}
diff --git a/dns/godaddy.go b/dns/godaddy.go
index b7516cd..e4958c3 100644
--- a/dns/godaddy.go
+++ b/dns/godaddy.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
- "log"
"net/http"
"strconv"
@@ -59,12 +58,12 @@ func (g *GoDaddyDNS) updateDomainRecord(recordType string, ipAddr string, domain
// 防止多次发送Webhook通知
if recordType == "A" {
if g.lastIpv4 == ipAddr {
- log.Println("你的IPv4未变化, 未触发Godaddy请求")
+ util.Log("你的IPv4未变化, 未触发 %s 请求", "godaddy")
return
}
} else {
if g.lastIpv6 == ipAddr {
- log.Println("你的IPv6未变化, 未触发Godaddy请求")
+ util.Log("你的IPv6未变化, 未触发 %s 请求", "godaddy")
return
}
}
@@ -77,10 +76,10 @@ func (g *GoDaddyDNS) updateDomainRecord(recordType string, ipAddr string, domain
Type: recordType,
}})
if err == nil {
- log.Printf("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!", domain)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -115,6 +114,6 @@ func (g *GoDaddyDNS) sendReq(method string, rType string, domain *config.Domain,
}
req.Header = g.header
resp, err := g.client.Do(req)
- _, err = util.GetHTTPResponseOrg(resp, path, err)
+ _, err = util.GetHTTPResponseOrg(resp, err)
return err
}
diff --git a/dns/google_domain.go b/dns/google_domain.go
index 813017f..44fc81a 100644
--- a/dns/google_domain.go
+++ b/dns/google_domain.go
@@ -2,7 +2,6 @@ package dns
import (
"io"
- "log"
"net/http"
"net/url"
"strings"
@@ -55,12 +54,12 @@ func (gd *GoogleDomain) addUpdateDomainRecords(recordType string) {
// 防止多次发送Webhook通知
if recordType == "A" {
if gd.lastIpv4 == ipAddr {
- log.Println("你的IPv4未变化, 未触发Google请求")
+ util.Log("你的IPv4未变化, 未触发 %s 请求", "GoogleDomain")
return
}
} else {
if gd.lastIpv6 == ipAddr {
- log.Println("你的IPv6未变化, 未触发Google请求")
+ util.Log("你的IPv6未变化, 未触发 %s 请求", "GoogleDomain")
return
}
}
@@ -80,19 +79,19 @@ func (gd *GoogleDomain) modify(domain *config.Domain, recordType string, ipAddr
err := gd.request(params, &result)
if err != nil {
- log.Printf("修改域名解析 %s 失败!", domain)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
return
}
switch result.Status {
case "nochg":
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
case "good":
- log.Printf("修改域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
default:
- log.Printf("修改域名解析 %s 失败!Status: %s", domain, result.Status)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, result)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -107,7 +106,7 @@ func (gd *GoogleDomain) request(params url.Values, result *GoogleDomainResp) (er
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
@@ -117,7 +116,7 @@ func (gd *GoogleDomain) request(params url.Values, result *GoogleDomainResp) (er
client := util.CreateHTTPClient()
resp, err := client.Do(req)
if err != nil {
- log.Println("client.Do失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
diff --git a/dns/huawei.go b/dns/huawei.go
index f60d1ea..789c650 100644
--- a/dns/huawei.go
+++ b/dns/huawei.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
- "log"
"net/http"
"strconv"
@@ -94,6 +93,7 @@ func (hw *Huaweicloud) addUpdateDomainRecords(recordType string) {
)
if err != nil {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -124,7 +124,7 @@ func (hw *Huaweicloud) create(domain *config.Domain, recordType string, ipAddr s
return
}
if len(zone.Zones) == 0 {
- log.Println("未能找到公网域名, 请检查域名是否添加")
+ util.Log("在DNS服务商中未找到域名: %s", domain.String())
return
}
@@ -150,10 +150,10 @@ func (hw *Huaweicloud) create(domain *config.Domain, recordType string, ipAddr s
&result,
)
if err == nil && (len(result.Records) > 0 && result.Records[0] == ipAddr) {
- log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!Status: %s", domain, result.Status)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -163,7 +163,7 @@ func (hw *Huaweicloud) modify(record HuaweicloudRecordsets, domain *config.Domai
// 相同不修改
if len(record.Records) > 0 && record.Records[0] == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
@@ -181,10 +181,10 @@ 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)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!Status: %s", domain, result.Status)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -215,7 +215,7 @@ func (hw *Huaweicloud) request(method string, url string, data interface{}, resu
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
@@ -229,7 +229,7 @@ func (hw *Huaweicloud) request(method string, url string, data interface{}, resu
client := util.CreateHTTPClient()
resp, err := client.Do(req)
- err = util.GetHTTPResponse(resp, url, err, result)
+ err = util.GetHTTPResponse(resp, err, result)
return
}
diff --git a/dns/internal/wait_net.go b/dns/internal/wait_net.go
index 204a7d5..8dcfef4 100644
--- a/dns/internal/wait_net.go
+++ b/dns/internal/wait_net.go
@@ -1,7 +1,6 @@
package internal
import (
- "log"
"strings"
"time"
@@ -28,15 +27,14 @@ func WaitForNetworkConnected(addresses []string) {
// 如果 err 包含回环地址([::1]:53)则表示没有 DNS 服务器,设置 DNS 服务器
if strings.Contains(err.Error(), loopbackServer) && !find {
server := "1.1.1.1:53"
- log.Printf("解析回环地址 %s 失败!将默认使用 %s,可参考文档通过 -dns 自定义 DNS 服务器",
- loopbackServer, server)
-
+ util.Log("本机DNS异常! 将默认使用 %s, 可参考文档通过 -dns 自定义 DNS 服务器", loopbackServer, server)
util.NewDialerResolver(server)
find = true
continue
}
- log.Printf("等待网络连接:%s。%s 后重试...", err, timeout)
+ util.Log("等待网络连接: %s", err)
+ util.Log("%s 后重试...", timeout)
// 等待 5 秒后重试
time.Sleep(timeout)
continue
diff --git a/dns/namecheap.go b/dns/namecheap.go
index d82a229..e54c5e4 100644
--- a/dns/namecheap.go
+++ b/dns/namecheap.go
@@ -2,7 +2,6 @@ package dns
import (
"io"
- "log"
"net/http"
"strings"
@@ -56,17 +55,13 @@ func (nc *NameCheap) addUpdateDomainRecords(recordType string) {
// 防止多次发送Webhook通知
if recordType == "A" {
if nc.lastIpv4 == ipAddr {
- log.Println("你的IPv4未变化, 未触发Namecheap请求")
+ util.Log("你的IPv4未变化, 未触发 %s 请求", "NameCheap")
return
}
} else {
// https://www.namecheap.com/support/knowledgebase/article.aspx/29/11/how-to-dynamically-update-the-hosts-ip-with-an-http-request/
- log.Println("Namecheap DDNS 不支持更新 IPv6!")
+ util.Log("Namecheap 不支持更新 IPv6")
return
- // if nc.lastIpv6 == ipAddr {
- // log.Println("你的IPv6未变化, 未触发Namecheap请求")
- // return
- // }
}
for _, domain := range domains {
@@ -80,17 +75,17 @@ func (nc *NameCheap) modify(domain *config.Domain, recordType string, ipAddr str
err := nc.request(&result, ipAddr, domain)
if err != nil {
- log.Printf("修改域名解析 %s 失败!", domain)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, result)
domain.UpdateStatus = config.UpdatedFailed
return
}
switch result.Status {
case "Success":
- log.Printf("修改域名解析 %s 成功!IP: %s\n", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
default:
- log.Printf("修改域名解析 %s 失败!Status: %s\n", domain, result.Status)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, result)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -110,21 +105,21 @@ func (nc *NameCheap) request(result *NameCheapResp, ipAddr string, domain *confi
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
client := util.CreateHTTPClient()
resp, err := client.Do(req)
if err != nil {
- log.Println("client.Do失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
- log.Println("请求namecheap失败")
+ util.Log("异常信息: %s", err)
return err
}
diff --git a/dns/namesilo.go b/dns/namesilo.go
index 80a5607..6b762d1 100644
--- a/dns/namesilo.go
+++ b/dns/namesilo.go
@@ -3,7 +3,6 @@ package dns
import (
"encoding/xml"
"io"
- "log"
"net/http"
"strings"
@@ -97,7 +96,7 @@ func (ns *NameSilo) addUpdateDomainRecords(recordType string) {
// 拿到DNS记录列表,从列表中去取对应域名的id,有id进行修改,没ID进行新增
records, err := ns.listRecords(domain)
if err != nil {
- log.Printf("获取域名列表 %s 失败!", domain)
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -110,7 +109,7 @@ func (ns *NameSilo) addUpdateDomainRecords(recordType string) {
} else {
recordID = record.RecordID
if record.Value == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
}
@@ -127,21 +126,21 @@ func (ns *NameSilo) modify(domain *config.Domain, recordID, recordType, ipAddr s
requestType = "新增"
result, err = ns.request(ipAddr, domain, "", recordType, nameSiloAddRecordEndpoint)
} else {
- requestType = "修改"
+ requestType = "更新"
result, err = ns.request(ipAddr, domain, recordID, "", nameSiloUpdateRecordEndpoint)
}
if err != nil {
- log.Printf("修改域名解析 %s 失败!", domain)
+ util.Log("异常信息: %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
var resp NameSiloResp
xml.Unmarshal([]byte(result), &resp)
if resp.Reply.Code == 300 {
- log.Printf("%s 域名解析 %s 成功!IP: %s\n", requestType, domain, ipAddr)
+ util.Log(requestType+"域名解析 %s 成功! IP: %s\n", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("%s 域名解析 %s 失败!Deatil: %s\n", requestType, domain, resp.Reply.Detail)
+ util.Log(requestType+"域名解析 %s 失败! 异常信息: %s", domain, resp.Reply.Detail)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -172,14 +171,14 @@ func (ns *NameSilo) request(ipAddr string, domain *config.Domain, recordID, reco
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
client := util.CreateHTTPClient()
resp, err := client.Do(req)
if err != nil {
- log.Println("client.Do失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
diff --git a/dns/porkbun.go b/dns/porkbun.go
index 057ff37..56cb45e 100644
--- a/dns/porkbun.go
+++ b/dns/porkbun.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
- "log"
"net/http"
"github.com/jeessy2/ddns-go/v5/config"
@@ -87,26 +86,27 @@ func (pb *Porkbun) addUpdateDomainRecords(recordType string) {
)
if err != nil {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
if record.Status == "SUCCESS" {
if len(record.Records) > 0 {
// 存在,更新
- pb.modify(&record, domain, &recordType, &ipAddr)
+ pb.modify(&record, domain, recordType, ipAddr)
} else {
// 不存在,创建
- pb.create(domain, &recordType, &ipAddr)
+ pb.create(domain, recordType, ipAddr)
}
} else {
- log.Printf("查询现有域名记录失败")
+ util.Log("在DNS服务商中未找到域名: %s", domain.String())
domain.UpdateStatus = config.UpdatedFailed
}
}
}
// 创建
-func (pb *Porkbun) create(domain *config.Domain, recordType *string, ipAddr *string) {
+func (pb *Porkbun) create(domain *config.Domain, recordType string, ipAddr string) {
var response PorkbunResponse
err := pb.request(
@@ -118,8 +118,8 @@ func (pb *Porkbun) create(domain *config.Domain, recordType *string, ipAddr *str
},
PorkbunDomainRecord: &PorkbunDomainRecord{
Name: &domain.SubDomain,
- Type: recordType,
- Content: ipAddr,
+ Type: &recordType,
+ Content: &ipAddr,
Ttl: &pb.TTL,
},
},
@@ -127,34 +127,34 @@ func (pb *Porkbun) create(domain *config.Domain, recordType *string, ipAddr *str
)
if err == nil && response.Status == "SUCCESS" {
- log.Printf("新增域名解析 %s 成功!IP: %s", domain, *ipAddr)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!", domain)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
// 修改
-func (pb *Porkbun) modify(record *PorkbunDomainQueryResponse, domain *config.Domain, recordType *string, ipAddr *string) {
+func (pb *Porkbun) modify(record *PorkbunDomainQueryResponse, domain *config.Domain, recordType string, ipAddr string) {
// 相同不修改
- if len(record.Records) > 0 && *record.Records[0].Content == *ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", *ipAddr, domain)
+ if len(record.Records) > 0 && *record.Records[0].Content == ipAddr {
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
var response PorkbunResponse
err := pb.request(
- porkbunEndpoint+fmt.Sprintf("/editByNameType/%s/%s/%s", domain.DomainName, *recordType, domain.SubDomain),
+ porkbunEndpoint+fmt.Sprintf("/editByNameType/%s/%s/%s", domain.DomainName, recordType, domain.SubDomain),
&PorkbunDomainCreateOrUpdateVO{
PorkbunApiKey: &PorkbunApiKey{
AccessKey: pb.DNSConfig.ID,
SecretKey: pb.DNSConfig.Secret,
},
PorkbunDomainRecord: &PorkbunDomainRecord{
- Content: ipAddr,
+ Content: &ipAddr,
Ttl: &pb.TTL,
},
},
@@ -162,10 +162,10 @@ func (pb *Porkbun) modify(record *PorkbunDomainQueryResponse, domain *config.Dom
)
if err == nil && response.Status == "SUCCESS" {
- log.Printf("更新域名解析 %s 成功!IP: %s", domain, *ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!", domain)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -182,14 +182,14 @@ func (pb *Porkbun) request(url string, data interface{}, result interface{}) (er
bytes.NewBuffer(jsonStr),
)
if err != nil {
- log.Println("http.NewRequest失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
req.Header.Set("Content-Type", "application/json")
client := util.CreateHTTPClient()
resp, err := client.Do(req)
- err = util.GetHTTPResponse(resp, url, err, result)
+ err = util.GetHTTPResponse(resp, err, result)
return
}
diff --git a/dns/tencent_cloud.go b/dns/tencent_cloud.go
index 7c5687c..f778172 100644
--- a/dns/tencent_cloud.go
+++ b/dns/tencent_cloud.go
@@ -3,7 +3,6 @@ package dns
import (
"bytes"
"encoding/json"
- "log"
"net/http"
"strconv"
@@ -99,6 +98,7 @@ func (tc *TencentCloud) addUpdateDomainRecords(recordType string) {
for _, domain := range domains {
result, err := tc.getRecordList(domain, recordType)
if err != nil {
+ util.Log("查询域名信息发生异常! %s", err)
domain.UpdateStatus = config.UpdatedFailed
return
}
@@ -143,10 +143,10 @@ func (tc *TencentCloud) create(domain *config.Domain, recordType string, ipAddr
&status,
)
if err == nil && status.Response.Error.Code == "" {
- log.Printf("新增域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("新增域名解析 %s 失败!Code: %s, Message: %s", domain, status.Response.Error.Code, status.Response.Error.Message)
+ util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, status.Response.Error.Message)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -156,7 +156,7 @@ func (tc *TencentCloud) create(domain *config.Domain, recordType string, ipAddr
func (tc *TencentCloud) modify(record TencentCloudRecord, domain *config.Domain, recordType string, ipAddr string) {
// 相同不修改
if record.Value == ipAddr {
- log.Printf("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
+ util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
return
}
var status TencentCloudStatus
@@ -172,10 +172,10 @@ func (tc *TencentCloud) modify(record TencentCloudRecord, domain *config.Domain,
&status,
)
if err == nil && status.Response.Error.Code == "" {
- log.Printf("更新域名解析 %s 成功!IP: %s", domain, ipAddr)
+ util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
domain.UpdateStatus = config.UpdatedSuccess
} else {
- log.Printf("更新域名解析 %s 失败!Code: %s, Message: %s", domain, status.Response.Error.Code, status.Response.Error.Message)
+ util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, status.Response.Error.Message)
domain.UpdateStatus = config.UpdatedFailed
}
}
@@ -218,7 +218,7 @@ func (tc *TencentCloud) request(action string, data interface{}, result interfac
bytes.NewBuffer(jsonStr),
)
if err != nil {
- log.Println("http.NewRequest 失败. Error: ", err)
+ util.Log("异常信息: %s", err)
return
}
@@ -229,7 +229,7 @@ func (tc *TencentCloud) request(action string, data interface{}, result interfac
client := util.CreateHTTPClient()
resp, err := client.Do(req)
- err = util.GetHTTPResponse(resp, tencentCloudEndPoint, err, result)
+ err = util.GetHTTPResponse(resp, err, result)
return
}
diff --git a/go.mod b/go.mod
index 4c2fd79..ddae7fd 100644
--- a/go.mod
+++ b/go.mod
@@ -9,4 +9,7 @@ require (
gopkg.in/yaml.v3 v3.0.1
)
-require golang.org/x/sys v0.16.0 // indirect
+require (
+ golang.org/x/sys v0.16.0 // indirect
+ golang.org/x/text v0.14.0
+)
diff --git a/go.sum b/go.sum
index 14ae5a7..062bd88 100644
--- a/go.sum
+++ b/go.sum
@@ -7,6 +7,8 @@ golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/main.go b/main.go
index a8f02c7..fb54695 100644
--- a/main.go
+++ b/main.go
@@ -2,6 +2,7 @@ package main
import (
"embed"
+ "errors"
"flag"
"fmt"
"log"
@@ -24,34 +25,34 @@ import (
// ddns-go 版本
// ddns-go version
-var versionFlag = flag.Bool("v", false, "ddns-go 版本")
+var versionFlag = flag.Bool("v", false, "ddns-go version")
// 更新 ddns-go
-var updateFlag = flag.Bool("u", false, "更新 ddns-go")
+var updateFlag = flag.Bool("u", false, "Upgrade ddns-go to the latest version")
// 监听地址
-var listen = flag.String("l", ":9876", "监听地址")
+var listen = flag.String("l", ":9876", "Listen address")
// 更新频率(秒)
-var every = flag.Int("f", 300, "同步间隔时间(秒)")
+var every = flag.Int("f", 300, "Sync frequency(seconds)")
// 缓存次数
-var ipCacheTimes = flag.Int("cacheTimes", 5, "间隔N次与服务商比对")
+var ipCacheTimes = flag.Int("cacheTimes", 5, "Interval N times compared with service providers")
// 服务管理
-var serviceType = flag.String("s", "", "服务管理, 支持install, uninstall, restart")
+var serviceType = flag.String("s", "", "Service management (install|uninstall|restart)")
// 配置文件路径
-var configFilePath = flag.String("c", util.GetConfigFilePathDefault(), "自定义配置文件路径")
+var configFilePath = flag.String("c", util.GetConfigFilePathDefault(), "config file path")
// Web 服务
-var noWebService = flag.Bool("noweb", false, "不启动 web 服务")
+var noWebService = flag.Bool("noweb", false, "No web service")
// 跳过验证证书
-var skipVerify = flag.Bool("skipVerify", false, "跳过验证证书, 适合不能升级的老系统")
+var skipVerify = flag.Bool("skipVerify", false, "Skip certificate verification")
// 自定义 DNS 服务器
-var customDNSServer = flag.String("dns", "", "自定义 DNS 服务器(例如 1.1.1.1)")
+var customDNSServer = flag.String("dns", "", "Custom DNS server, example: 8.8.8.8")
//go:embed static
var staticEmbeddedFiles embed.FS
@@ -73,7 +74,7 @@ func main() {
return
}
if _, err := net.ResolveTCPAddr("tcp", *listen); err != nil {
- log.Fatalf("解析监听地址异常,%s", err)
+ log.Fatalf("Parse listen address failed! Exception: %s", err)
}
os.Setenv(web.VersionEnv, version)
if *configFilePath != "" {
@@ -111,9 +112,9 @@ func main() {
// 非服务方式运行
switch s.Platform() {
case "windows-service":
- log.Println("可使用 .\\ddns-go.exe -s install 安装服务运行")
+ util.Log("可使用 .\\ddns-go.exe -s install 安装服务运行")
default:
- log.Println("可使用 sudo ./ddns-go -s install 安装服务运行")
+ util.Log("可使用 sudo ./ddns-go -s install 安装服务运行")
}
run()
}
@@ -163,11 +164,11 @@ func runWebServer() error {
http.HandleFunc("/ipv6NetInterface", web.BasicAuth(web.Ipv6NetInterfaces))
http.HandleFunc("/webhookTest", web.BasicAuth(web.WebhookTest))
- log.Println("监听", *listen, "...")
+ util.Log("监听 %s", *listen)
l, err := net.Listen("tcp", *listen)
if err != nil {
- return fmt.Errorf("监听端口发生异常, 请检查端口是否被占用: %w", err)
+ return errors.New(util.LogStr("监听端口发生异常, 请检查端口是否被占用! %s", err))
}
// 没有配置, 自动打开浏览器
@@ -211,7 +212,7 @@ func getService() service.Service {
svcConfig := &service.Config{
Name: "ddns-go",
DisplayName: "ddns-go",
- Description: "简单好用的DDNS。自动更新域名解析到公网IP(支持阿里云、腾讯云dnspod、Cloudflare、Callback、华为云、百度云、Porkbun、GoDaddy、Google Domain)",
+ Description: "Simple and easy to use DDNS. Automatically update domain name resolution to public IP (Support Aliyun, Tencent Cloud, Dnspod, Cloudflare, Callback, Huawei Cloud, Baidu Cloud, Porkbun, GoDaddy...)",
Arguments: []string{"-l", *listen, "-f", strconv.Itoa(*every), "-cacheTimes", strconv.Itoa(*ipCacheTimes), "-c", *configFilePath},
Dependencies: depends,
Option: options,
@@ -247,9 +248,9 @@ func uninstallService() {
}
}
if err := s.Uninstall(); err == nil {
- log.Println("ddns-go 服务卸载成功!")
+ util.Log("ddns-go 服务卸载成功")
} else {
- log.Printf("ddns-go 服务卸载失败, ERR: %s\n", err)
+ util.Log("ddns-go 服务卸载失败, 异常信息: %s", err)
}
}
@@ -262,7 +263,7 @@ func installService() {
// 服务未知,创建服务
if err = s.Install(); err == nil {
s.Start()
- log.Println("安装 ddns-go 服务成功! 请打开浏览器并进行配置。")
+ util.Log("安装 ddns-go 服务成功! 请打开浏览器并进行配置")
if service.ChosenSystem().String() == "unix-systemv" {
if _, err := exec.Command("/etc/init.d/ddns-go", "enable").Output(); err != nil {
log.Println(err)
@@ -273,12 +274,11 @@ func installService() {
}
return
}
-
- log.Printf("安装 ddns-go 服务失败, ERR: %s\n", err)
+ util.Log("安装 ddns-go 服务失败, 异常信息: %s", err)
}
if status != service.StatusUnknown {
- log.Println("ddns-go 服务已安装, 无需再次安装")
+ util.Log("ddns-go 服务已安装, 无需再次安装")
}
}
@@ -289,15 +289,15 @@ func restartService() {
if err == nil {
if status == service.StatusRunning {
if err = s.Restart(); err == nil {
- log.Println("重启 ddns-go 服务成功!")
+ util.Log("重启 ddns-go 服务成功")
}
} else if status == service.StatusStopped {
if err = s.Start(); err == nil {
- log.Println("启动 ddns-go 服务成功!")
+ util.Log("启动 ddns-go 服务成功")
}
}
} else {
- log.Println("ddns-go 服务未安装, 请先安装服务")
+ util.Log("ddns-go 服务未安装, 请先安装服务")
}
}
@@ -308,7 +308,7 @@ func autoOpenExplorer() {
if err != nil {
if util.IsRunInDocker() {
// docker中运行, 提示
- fmt.Println("Docker中运行, 请在浏览器中打开 http://docker主机IP:端口 进行配置")
+ util.Log("Docker中运行, 请在浏览器中打开 http://docker主机IP:9876 进行配置")
} else {
// 主机运行, 打开浏览器
addr, err := net.ResolveTCPAddr("tcp", *listen)
diff --git a/static/common.css b/static/common.css
index d07015e..9988113 100644
--- a/static/common.css
+++ b/static/common.css
@@ -226,6 +226,5 @@ main {
margin-right: 8px;
line-height: 0;
text-align: center;
- vertical-align: text-bottom;
font-size: 16px;
}
\ No newline at end of file
diff --git a/util/http_util.go b/util/http_util.go
index 40d1e43..3622c88 100644
--- a/util/http_util.go
+++ b/util/http_util.go
@@ -4,21 +4,17 @@ import (
"encoding/json"
"fmt"
"io"
- "log"
"net/http"
)
// GetHTTPResponse 处理HTTP结果,返回序列化的json
-func GetHTTPResponse(resp *http.Response, url string, err error, result interface{}) error {
- body, err := GetHTTPResponseOrg(resp, url, err)
+func GetHTTPResponse(resp *http.Response, err error, result interface{}) error {
+ body, err := GetHTTPResponseOrg(resp, err)
if err == nil {
// log.Println(string(body))
if len(body) != 0 {
err = json.Unmarshal(body, &result)
- if err != nil {
- log.Printf("请求接口%s解析json结果失败! ERROR: %s\n", url, err)
- }
}
}
@@ -27,9 +23,8 @@ func GetHTTPResponse(resp *http.Response, url string, err error, result interfac
}
// GetHTTPResponseOrg 处理HTTP结果,返回byte
-func GetHTTPResponseOrg(resp *http.Response, url string, err error) ([]byte, error) {
+func GetHTTPResponseOrg(resp *http.Response, err error) ([]byte, error) {
if err != nil {
- log.Printf("请求接口%s失败! ERROR: %s\n", url, err)
return nil, err
}
@@ -38,14 +33,12 @@ func GetHTTPResponseOrg(resp *http.Response, url string, err error) ([]byte, err
body, err := io.ReadAll(lr)
if err != nil {
- log.Printf("请求接口%s失败! ERROR: %s\n", url, err)
+ return nil, err
}
// 300及以上状态码都算异常
if resp.StatusCode >= 300 {
- errMsg := fmt.Sprintf("请求接口 %s 失败! 返回内容: %s ,返回状态码: %d\n", url, string(body), resp.StatusCode)
- log.Println(errMsg)
- err = fmt.Errorf(errMsg)
+ err = fmt.Errorf(LogStr("返回内容: %s ,返回状态码: %d", string(body), resp.StatusCode))
}
return body, err
diff --git a/util/messages.go b/util/messages.go
new file mode 100644
index 0000000..7b053e8
--- /dev/null
+++ b/util/messages.go
@@ -0,0 +1,128 @@
+package util
+
+import (
+ "log"
+ "strings"
+
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+)
+
+var logPrinter = message.NewPrinter(language.English)
+
+func init() {
+
+ message.SetString(language.English, "可使用 .\\ddns-go.exe -s install 安装服务运行", "You can use 'sudo .\\ddns-go -s install' to install service")
+ message.SetString(language.English, "可使用 sudo ./ddns-go -s install 安装服务运行", "You can use 'sudo ./ddns-go -s install' to install service")
+ message.SetString(language.English, "监听 %s", "Listen on %s")
+ message.SetString(language.English, "配置文件已保存在: %s", "Config file has been saved to: %s")
+
+ message.SetString(language.English, "你的IP %s 没有变化, 域名 %s", "Your's IP %s has not changed! Domain: %s")
+ message.SetString(language.English, "新增域名解析 %s 成功! IP: %s", "Added domain %s successfully! IP: %s")
+ message.SetString(language.English, "新增域名解析 %s 失败! 异常信息: %s", "Added domain %s failed! Result: %s")
+
+ message.SetString(language.English, "更新域名解析 %s 成功! IP: %s", "Updated domain %s successfully! IP: %s")
+ message.SetString(language.English, "更新域名解析 %s 失败! 异常信息: %s", "Updated domain %s failed! Result: %s")
+
+ message.SetString(language.English, "你的IPv4未变化, 未触发 %s 请求", "Your's IPv4 has not changed, %s request has not been triggered")
+ message.SetString(language.English, "你的IPv6未变化, 未触发 %s 请求", "Your's IPv6 has not changed, %s request has not been triggered")
+ message.SetString(language.English, "Namecheap 不支持更新 IPv6", "Namecheap don't supports IPv6")
+
+ // http_util
+ message.SetString(language.English, "异常信息: %s", "Exception: %s")
+ message.SetString(language.English, "查询域名信息发生异常! %s", "Query domain info failed! %s")
+ message.SetString(language.English, "返回内容: %s ,返回状态码: %d", "Response body: %s ,Response status code: %d")
+ message.SetString(language.English, "通过接口获取IPv4失败! 接口地址: %s", "Get IPv4 from %s failed")
+ message.SetString(language.English, "通过接口获取IPv6失败! 接口地址: %s", "Get IPv6 from %s failed")
+ message.SetString(language.English, "将不会触发Webhook, 仅在第 3 次失败时触发一次Webhook, 当前失败次数:%d", "Webhook will not be triggered, only trigger once when the third failure, current failure times: %d")
+ message.SetString(language.English, "在DNS服务商中未找到域名: %s", "Domain %s not found in DNS provider")
+
+ // webhook
+ message.SetString(language.English, "Webhook配置中的URL不正确", "Webhook url is incorrect")
+ message.SetString(language.English, "Webhook中的 RequestBody JSON 无效", "Webhook RequestBody JSON is invalid")
+ message.SetString(language.English, "Webhook调用成功! 返回数据:%s", "Webhook called successfully! Response body: %s")
+ message.SetString(language.English, "Webhook调用失败! 异常信息:%s", "Webhook called failed! Exception: %s")
+ message.SetString(language.English, "Webhook Header不正确: %s", "Webhook header is invalid: %s")
+ message.SetString(language.English, "请输入Webhook的URL", "Please enter the Webhook url")
+
+ // callback
+ message.SetString(language.English, "Callback的URL不正确", "Callback url is incorrect")
+ message.SetString(language.English, "Callback调用成功, 域名: %s, IP: %s, 返回数据: %s", "Webhook called successfully! Domain: %s, IP: %s, Response body: %s")
+ message.SetString(language.English, "Callback调用失败, 异常信息: %s", "Webhook called failed! Exception: %s")
+
+ // save
+ message.SetString(language.English, "若通过公网访问, 仅允许在ddns-go启动后 5 分钟内完成首次配置", "If accessed via the public network, only allow the first configuration to be completed within 5 minutes after ddns-go starts")
+ message.SetString(language.English, "若从未设置过帐号密码, 仅允许在ddns-go启动后 5 分钟内设置, 请重启ddns-go", "If you have never set an account password, you can only set it within 5 minutes after ddns-go starts, please restart ddns-go")
+ message.SetString(language.English, "启用外网访问, 必须输入登录用户名/密码", "Enable external network access, you must enter the login username/password")
+ message.SetString(language.English, "修改 '通过命令获取' 必须设置帐号密码,请先设置帐号密码", "Modify 'Get by command' must set username/password, please set username/password first")
+ message.SetString(language.English, "密码不安全!尝试使用更长的密码", "insecure password, try using a longer password")
+
+ // config
+ message.SetString(language.English, "从网卡获得IPv4失败", "Get IPv4 from network card failed")
+ message.SetString(language.English, "从网卡中获得IPv4失败! 网卡名: %s", "Get IPv4 from network card failed! Network card name: %s")
+ message.SetString(language.English, "获取IPv4结果失败! 接口: %s ,返回值: %s", "Get IPv4 result failed! Interface: %s ,Result: %s")
+ message.SetString(language.English, "获取%s结果失败! 未能成功执行命令:%s, 错误:%q, 退出状态码:%s", "Get %s result failed! Command: %s, Error: %q, Exit status code: %s")
+ message.SetString(language.English, "获取%s结果失败! 命令: %s, 标准输出: %q", "Get %s result failed! Command: %s, Stdout: %q")
+ message.SetString(language.English, "从网卡获得IPv6失败", "Get IPv6 from network card failed")
+ message.SetString(language.English, "从网卡中获得IPv6失败! 网卡名: %s", "Get IPv6 from network card failed! Network card name: %s")
+ message.SetString(language.English, "获取IPv6结果失败! 接口: %s ,返回值: %s", "Get IPv6 result failed! Interface: %s ,Result: %s")
+ message.SetString(language.English, "未找到第 %d 个IPv6地址! 将使用第一个IPv6地址", "%dth IPv6 address not found! Will use the first IPv6 address")
+ message.SetString(language.English, "IPv6匹配表达式 %s 不正确! 最小从1开始", "IPv6 match expression %s is incorrect! Minimum start from 1")
+ message.SetString(language.English, "IPv6将使用正则表达式 %s 进行匹配", "IPv6 will use regular expression %s for matching")
+ message.SetString(language.English, "匹配成功! 匹配到地址: %s", "Match successfully! Matched address: %s")
+ message.SetString(language.English, "没有匹配到任何一个IPv6地址, 将使用第一个地址", "No IPv6 address matched, will use the first address")
+ message.SetString(language.English, "未能获取IPv4地址, 将不会更新", "Failed to get IPv4 address, will not update")
+ message.SetString(language.English, "未能获取IPv6地址, 将不会更新", "Failed to get IPv6 address, will not update")
+
+ // domains
+ message.SetString(language.English, "域名: %s 不正确", "The domain %s is incorrect")
+ message.SetString(language.English, "域名: %s 解析失败", "The domain %s resolution failed")
+ message.SetString(language.English, "IPv6未改变, 将等待 %d 次后与DNS服务商进行比对", "IPv6 has not changed, will wait %d times to compare with DNS provider")
+ message.SetString(language.English, "IPv4未改变, 将等待 %d 次后与DNS服务商进行比对", "IPv4 has not changed, will wait %d times to compare with DNS provider")
+
+ message.SetString(language.English, "本机DNS异常! 将默认使用 %s, 可参考文档通过 -dns 自定义 DNS 服务器", "Local DNS exception! Will use %s by default, you can use -dns to customize DNS server")
+ message.SetString(language.English, "等待网络连接: %s", "Waiting for network connection: %s")
+ message.SetString(language.English, "%s 后重试...", "Retry after %s")
+
+ // main
+ message.SetString(language.English, "监听端口发生异常, 请检查端口是否被占用! %s", "Listen port failed, please check if the port is occupied! %s")
+ message.SetString(language.English, "Docker中运行, 请在浏览器中打开 http://docker主机IP:9876 进行配置", "Running in Docker, please open http://docker-host-ip:9876 in the browser for configuration")
+ message.SetString(language.English, "ddns-go 服务卸载成功", "ddns-go service uninstalled successfully")
+ message.SetString(language.English, "ddns-go 服务卸载失败, 异常信息: %s", "ddns-go service uninstalled failed, Exception: %s")
+ message.SetString(language.English, "安装 ddns-go 服务成功! 请打开浏览器并进行配置", "Install ddns-go service successfully! Please open the browser and configure it")
+ message.SetString(language.English, "安装 ddns-go 服务失败, 异常信息: %s", "Install ddns-go service failed, Exception: %s")
+ message.SetString(language.English, "ddns-go 服务已安装, 无需再次安装", "ddns-go service has been installed, no need to install again")
+ message.SetString(language.English, "重启 ddns-go 服务成功", "restart ddns-go service successfully")
+ message.SetString(language.English, "启动 ddns-go 服务成功", "start ddns-go service successfully")
+ message.SetString(language.English, "ddns-go 服务未安装, 请先安装服务", "ddns-go service is not installed, please install the service first")
+
+ // login
+ message.SetString(language.English, "%q 配置文件为空, 超过3小时禁止从公网访问", "%q configuration file is empty, public network access is prohibited for more than 3 hours")
+ message.SetString(language.English, "%q 被禁止从公网访问", "%q is prohibited from accessing the public network")
+ message.SetString(language.English, "%q 登陆失败超过5次! 并延时5分钟响应", "%q login failed more than 5 times! And delay 5 minutes to respond")
+ message.SetString(language.English, "%q 帐号密码不正确", "%q username or password is incorrect")
+ message.SetString(language.English, "%q 请求登陆", "%q request login")
+
+ // webhook通知
+ message.SetString(language.English, "未改变", "no changed")
+ message.SetString(language.English, "失败", "failed")
+ message.SetString(language.English, "成功", "success")
+
+}
+
+func Log(key string, args ...interface{}) {
+ log.Println(LogStr(key, args...))
+}
+
+func LogStr(key string, args ...interface{}) string {
+ return logPrinter.Sprintf(key, args...)
+}
+
+func InitLogLang(lang string) string {
+ logLang := language.English
+ if strings.HasPrefix(lang, "zh") {
+ logLang = language.Chinese
+ }
+ logPrinter = message.NewPrinter(logLang)
+ return logLang.String()
+}
diff --git a/util/update/release.go b/util/update/release.go
index 7085f9e..4e1f0ca 100644
--- a/util/update/release.go
+++ b/util/update/release.go
@@ -41,8 +41,9 @@ func getLatest(repo string) (*Release, error) {
}
var result ReleaseResp
- err = util.GetHTTPResponse(resp, u, err, &result)
+ err = util.GetHTTPResponse(resp, err, &result)
if err != nil {
+ util.Log("异常信息: %s", err)
return nil, err
}
diff --git a/web/basic_auth.go b/web/basic_auth.go
index cc41896..fb6afa1 100644
--- a/web/basic_auth.go
+++ b/web/basic_auth.go
@@ -3,7 +3,6 @@ package web
import (
"bytes"
"encoding/base64"
- "log"
"net/http"
"strings"
"time"
@@ -30,7 +29,7 @@ func BasicAuth(f ViewFunc) ViewFunc {
if err != nil && time.Now().Unix()-startTime > 3*60*60 &&
(!util.IsPrivateNetwork(r.RemoteAddr) || !util.IsPrivateNetwork(r.Host)) {
w.WriteHeader(http.StatusForbidden)
- log.Printf("%q 配置文件为空, 超过3小时禁止从公网访问。\n", util.GetRequestIPStr(r))
+ util.Log("%q 配置文件为空, 超过3小时禁止从公网访问", util.GetRequestIPStr(r))
return
}
@@ -38,7 +37,7 @@ func BasicAuth(f ViewFunc) ViewFunc {
if conf.NotAllowWanAccess {
if !util.IsPrivateNetwork(r.RemoteAddr) || !util.IsPrivateNetwork(r.Host) {
w.WriteHeader(http.StatusForbidden)
- log.Printf("%q 被禁止从公网访问!\n", util.GetRequestIPStr(r))
+ util.Log("%q 被禁止从公网访问", util.GetRequestIPStr(r))
return
}
}
@@ -51,7 +50,7 @@ func BasicAuth(f ViewFunc) ViewFunc {
}
if ld.FailTimes >= 5 {
- log.Printf("%q 登陆失败超过5次! 并延时5分钟响应!\n", util.GetRequestIPStr(r))
+ util.Log("%q 登陆失败超过5次! 并延时5分钟响应", util.GetRequestIPStr(r))
time.Sleep(5 * time.Minute)
if ld.FailTimes >= 5 {
ld.FailTimes = 0
@@ -84,7 +83,7 @@ func BasicAuth(f ViewFunc) ViewFunc {
}
ld.FailTimes = ld.FailTimes + 1
- log.Printf("%q 帐号密码不正确!\n", util.GetRequestIPStr(r))
+ util.Log("%q 帐号密码不正确", util.GetRequestIPStr(r))
}
// 认证失败,提示 401 Unauthorized
@@ -92,6 +91,6 @@ func BasicAuth(f ViewFunc) ViewFunc {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
// 401 状态码
w.WriteHeader(http.StatusUnauthorized)
- log.Printf("%q 请求登陆!\n", util.GetRequestIPStr(r))
+ util.Log("%q 请求登陆", util.GetRequestIPStr(r))
}
}
diff --git a/web/password.go b/web/password.go
deleted file mode 100644
index 3418255..0000000
--- a/web/password.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package web
-
-import (
- "errors"
- "fmt"
- "strings"
-
- passwordvalidator "github.com/wagslane/go-password-validator"
-)
-
-const (
- replaceChars = `!@$&*`
- sepChars = `_-., `
- otherSpecialChars = `"#%'()+/:;<=>?[\]^{|}~`
- lowerChars = `abcdefghijklmnopqrstuvwxyz`
- upperChars = `ABCDEFGHIJKLMNOPQRSTUVWXYZ`
- digitsChars = `0123456789`
-)
-
-// validatePassword 在密码大于或等于 minEntropy 时返回 nil。如果不是则返回错误。
-// 这解释了如何加强密码。向客户端显示此错误是安全的。
-//
-// https://github.com/wagslane/go-password-validator/blob/v0.3.0/validate.go#L13
-func validatePassword(password string, minEntropy float64) error {
- entropy := passwordvalidator.GetEntropy(password)
- if entropy >= minEntropy {
- return nil
- }
-
- hasReplace := false
- hasSep := false
- hasOtherSpecial := false
- hasLower := false
- hasUpper := false
- hasDigits := false
- for _, c := range password {
- if strings.ContainsRune(replaceChars, c) {
- hasReplace = true
- continue
- }
- if strings.ContainsRune(sepChars, c) {
- hasSep = true
- continue
- }
- if strings.ContainsRune(otherSpecialChars, c) {
- hasOtherSpecial = true
- continue
- }
- if strings.ContainsRune(lowerChars, c) {
- hasLower = true
- continue
- }
- if strings.ContainsRune(upperChars, c) {
- hasUpper = true
- continue
- }
- if strings.ContainsRune(digitsChars, c) {
- hasDigits = true
- continue
- }
- }
-
- allMessages := []string{}
-
- if !hasOtherSpecial || !hasSep || !hasReplace {
- allMessages = append(allMessages, "包含更多特殊字符")
- }
- if !hasLower {
- allMessages = append(allMessages, "使用小写字母")
- }
- if !hasUpper {
- allMessages = append(allMessages, "使用大写字母")
- }
- if !hasDigits {
- allMessages = append(allMessages, "使用数字")
- }
-
- if len(allMessages) > 0 {
- return fmt.Errorf(
- "密码不安全!尝试%v或使用更长的密码",
- strings.Join(allMessages, ","),
- )
- }
-
- return errors.New("密码不安全!尝试使用更长的密码")
-}
diff --git a/web/save.go b/web/save.go
index d05dc12..5070049 100755
--- a/web/save.go
+++ b/web/save.go
@@ -9,6 +9,7 @@ import (
"github.com/jeessy2/ddns-go/v5/config"
"github.com/jeessy2/ddns-go/v5/dns"
"github.com/jeessy2/ddns-go/v5/util"
+ passwordvalidator "github.com/wagslane/go-password-validator"
)
var startTime = time.Now().Unix()
@@ -31,6 +32,10 @@ func checkAndSave(request *http.Request) string {
usernameNew := strings.TrimSpace(request.FormValue("Username"))
passwordNew := request.FormValue("Password")
+ // 国际化
+ accept := request.Header.Get("Accept-Language")
+ conf.Lang = util.InitLogLang(accept)
+
// 验证安全性后才允许设置保存配置文件:
if time.Now().Unix()-startTime > 5*60 {
firstTime := err != nil
@@ -38,14 +43,14 @@ func checkAndSave(request *http.Request) string {
// 首次设置 && 通过外网访问 必需在服务启动的 5 分钟内
if firstTime &&
(!util.IsPrivateNetwork(request.RemoteAddr) || !util.IsPrivateNetwork(request.Host)) {
- return "若通过公网访问,仅允许在ddns-go启动后 5 分钟内完成首次配置"
+ return util.LogStr("若通过公网访问, 仅允许在ddns-go启动后 5 分钟内完成首次配置")
}
// 非首次设置 && 从未设置过帐号密码 && 本次设置了帐号或密码 必须在5分钟内
if !firstTime &&
(conf.Username == "" && conf.Password == "") &&
(usernameNew != "" || passwordNew != "") {
- return "若从未设置过帐号密码,仅允许在ddns-go启动后 5 分钟内设置,请重启ddns-go"
+ return util.LogStr("若从未设置过帐号密码, 仅允许在ddns-go启动后 5 分钟内设置, 请重启ddns-go")
}
}
@@ -59,7 +64,7 @@ func checkAndSave(request *http.Request) string {
// 如启用公网访问,帐号密码不能为空
if !conf.NotAllowWanAccess && (conf.Username == "" || conf.Password == "") {
- return "启用外网访问, 必须输入登录用户名/密码"
+ return util.LogStr("启用外网访问, 必须输入登录用户名/密码")
}
// 如果密码不为空则检查是否够强, 内/外网要求强度不同
@@ -68,16 +73,16 @@ func checkAndSave(request *http.Request) string {
if conf.NotAllowWanAccess {
minEntropyBits = 25
}
- err = validatePassword(passwordNew, minEntropyBits)
+ err = passwordvalidator.Validate(passwordNew, minEntropyBits)
if err != nil {
- return err.Error()
+ return util.LogStr("密码不安全!尝试使用更长的密码")
}
}
dnsConfFromJS := []dnsConf4JS{}
err = json.Unmarshal([]byte(request.FormValue("DnsConf")), &dnsConfFromJS)
if err != nil {
- return "解析配置失败,请重试"
+ return "Please refresh the browser and try again"
}
dnsConfArray := []config.DnsConfig{}
empty := dnsConf4JS{}
@@ -125,7 +130,7 @@ func checkAndSave(request *http.Request) string {
// 修改cmd需要验证:必须设置帐号密码
if (conf.Username == "" && conf.Password == "") &&
(c.Ipv4.Cmd != dnsConf.Ipv4.Cmd || c.Ipv6.Cmd != dnsConf.Ipv6.Cmd) {
- return "修改 \"通过命令获取\" 必须设置帐号密码,请先设置帐号密码"
+ return util.LogStr("修改 '通过命令获取' 必须设置帐号密码,请先设置帐号密码")
}
}
diff --git a/web/webhookTest.go b/web/webhookTest.go
index d7c9524..b1399fc 100755
--- a/web/webhookTest.go
+++ b/web/webhookTest.go
@@ -1,7 +1,7 @@
package web
import (
- "log"
+ "github.com/jeessy2/ddns-go/v5/util"
"net/http"
"strings"
@@ -38,6 +38,6 @@ func WebhookTest(writer http.ResponseWriter, request *http.Request) {
if url != "" {
config.ExecWebhook(fakeDomains, fakeConfig)
} else {
- log.Println("请输入Webhook的URL")
+ util.Log("请输入Webhook的URL")
}
}
diff --git a/web/writing.html b/web/writing.html
index 843a925..58d8ba4 100755
--- a/web/writing.html
+++ b/web/writing.html
@@ -1,4 +1,4 @@
-
+
@@ -32,7 +32,7 @@
id="logsBtn"
onclick="showHideLogs()"
>
- 日志
+ Logs
-
+
@@ -57,7 +57,7 @@
style="margin-left: auto; margin-right: 0"
>
@@ -85,7 +85,7 @@
@@ -561,7 +567,7 @@
id="WebhookHeaders_help"
class="form-text text-muted"
>
- 一行一个Header, 如:Authorization: Bearer API_KEY
+ One header per line, such as: Authorization: Bearer API_KEY
@@ -574,7 +580,7 @@
id="webhookTestBtn"
aria-describedby="webhookTestBtn_help"
>
- 模拟测试Webhook
+ Try it
+
+