diff --git a/ReadMe.md b/ReadMe.md
index 9b5a02c..bd0bd87 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -13,12 +13,12 @@
- 支持更新多个域名的记录。
- 支持更新指定线路的记录。
- 支持Docker容器,支持x64、ARMv7和ARMv8。
-- IP发生变化时,使用WebHook通知。
+- IP发生变化时,使用WebHook或者Server酱通知。
# 使用方法
### Docker
-```
+```shell
docker run -d --restart=always --net=host \
-e "AKID=[ALIYUN's AccessKey-ID]" \
-e "AKSCT=[ALIYUN's AccessKey-Secret]" \
@@ -29,6 +29,44 @@ docker run -d --restart=always --net=host \
-e "TYPE=A,AAAA" \
sanjusss/aliyun-ddns
```
+docker-compose
+```yaml
+version: '2.17.3'
+services:
+ # 阿里云DDNS服务
+ ddns:
+ image: sanjusss/aliyun-ddns
+ container_name: ddns
+ restart: always
+ environment:
+ # 时区
+ - TZ=Asia/Shanghai
+ # 阿里云的Access Key ID
+ - AKID=Access Key ID
+ # 阿里云的Access Key Secret
+ - AKSCT=Access Key Secret
+ # 需要更新的域名,可以用“,”隔开
+ - DOMAIN=ddns.aliyun.win
+ # 更新间隔,单位秒。建议大于等于TTL/2
+ #- REDO=
+ # 服务器缓存解析记录的时长,单位秒,普通用户最小为600
+ # - TTL= 600
+ # 输出日志时的时区,单位小时
+ # - TIMEZONE=
+ # 需要更改的记录类型,可以用“,”隔开,只能是“A”、“AAAA”或“A,AAAA”
+ - TYPE=A,AAAA
+ # 检查IPv4地址时,仅使用中国服务器
+ # - CNIPV4=
+ # WEBHOOK推送地址
+ # - WEBHOOK=
+ # 是否检查本地网卡IP。此选项将禁用在线API的IP检查。
+ # 网络模式必须设置为host
+ # - CHECKLOCAL=true
+ # Server酱SendKey参数
+ # - SENDKEY=
+ network_mode: "host"
+ privileged: true
+```
| 环境变量名称 | 注释 | 默认值 |
| :---- | :----- | :--- |
|AKID|阿里云的Access Key ID。[获取阿里云AccessToken](https://usercenter.console.aliyun.com/)|access key id|
@@ -40,6 +78,7 @@ docker run -d --restart=always --net=host \
|TYPE|需要更改的记录类型,可以用“,”隔开,只能是“A”、“AAAA”或“A,AAAA”。|A,AAAA|
|CNIPV4|检查IPv4地址时,仅使用中国服务器。|false|
|WEBHOOK|WEBHOOK推送地址。|无|
+|SENDKEY|Server酱SendKey。|无|
|CHECKLOCAL|是否检查本地网卡IP。此选项将禁用在线API的IP检查。
网络模式必须设置为host。
(Windows版docker无法读取本机IP)|false|
|IPV4NETS|本地网卡的IPv4网段。格式示例:“192.168.1.0/24”。多个网段用“,”隔开。|无|
|IPV6NETS|本地网卡的IPv6网段。格式示例:“240e::/16”。多个网段用“,”隔开。|无|
@@ -79,6 +118,7 @@ dotnet aliyun-ddns.dll \
|type|需要更改的记录类型,可以用“,”隔开,只能是“A”、“AAAA”或“A,AAAA”。|A,AAAA|
|cnipv4|检查IPv4地址时,仅使用中国服务器。|false|
|webhook|WEBHOOK推送地址。|无|
+|sendKey|Server酱SendKey。|无|
|checklocal|是否检查本地网卡IP。此选项将禁用在线API的IP检查。|false|
|ipv4nets|本地网卡的IPv4网段。格式示例:“192.168.1.0/24”。多个网段用“,”隔开。|无|
|ipv6nets|本地网卡的IPv6网段。格式示例:“240e::/16”。多个网段用“,”隔开。|无|
diff --git a/aliyun-ddns/DomainUpdater.cs b/aliyun-ddns/DomainUpdater.cs
index c03ec1f..53f932e 100644
--- a/aliyun-ddns/DomainUpdater.cs
+++ b/aliyun-ddns/DomainUpdater.cs
@@ -3,6 +3,7 @@
using Aliyun.Acs.Core.Profile;
using aliyun_ddns.Common;
using aliyun_ddns.WebHook;
+using aliyun_ddns.ServerChan;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -145,6 +146,7 @@ private void Update(string[] domains, HashSet targetTypes)
if (items.Count > 0)
{
WebHookAction.Push(items);
+ ServerChanAction.Push(items);
}
}
diff --git a/aliyun-ddns/Options.cs b/aliyun-ddns/Options.cs
index 908996e..21ae345 100644
--- a/aliyun-ddns/Options.cs
+++ b/aliyun-ddns/Options.cs
@@ -35,6 +35,9 @@ public class Options
[Option('h',"webhook", Required = false, Default = null, HelpText = "WEB HOOK推送地址。")]
public string WebHook { get; set; } = null;
+ [Option('k',"sendKey", Required = false, Default = null, HelpText = "Server酱SendKey。")]
+ public string SendKey { get; set; } = null;
+
[Option('c', "checklocal", Required = false, Default = false, HelpText = "是否检查本地网卡IP。此选项将禁用在线API的IP检查。")]
public bool CheckLocalNetworkAdaptor { get; set; } = false;
@@ -80,6 +83,7 @@ private void InitOptionsFromEnvironment()
Domain = GetEnvironmentVariable("DOMAIN") ?? Domain;
Type = GetEnvironmentVariable("TYPE") ?? Type;
WebHook = GetEnvironmentVariable("WEBHOOK") ?? WebHook;
+ SendKey = GetEnvironmentVariable("SENDKEY") ?? SendKey;
IPv4Networks = GetEnvironmentVariable("IPV4NETS") ?? IPv4Networks;
IPv6Networks = GetEnvironmentVariable("IPV6NETS") ?? IPv6Networks;
diff --git a/aliyun-ddns/ServerChan/ServerChanAction.cs b/aliyun-ddns/ServerChan/ServerChanAction.cs
new file mode 100644
index 0000000..3359dd4
--- /dev/null
+++ b/aliyun-ddns/ServerChan/ServerChanAction.cs
@@ -0,0 +1,60 @@
+using aliyun_ddns.Common;
+using aliyun_ddns.WebHook;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Text;
+
+namespace aliyun_ddns.ServerChan
+{
+ public static class ServerChanAction
+ {
+ public static void Push(IEnumerable items)
+ {
+ string sendKey = Options.Instance.SendKey;
+ if (string.IsNullOrWhiteSpace(sendKey))
+ {
+ return;
+ }
+
+ try
+ {
+ StringBuilder url = new StringBuilder("https://sctapi.ftqq.com/");
+ url.Append(sendKey).Append(".send");
+ DateTime now = DateTime.Now;
+ StringBuilder textBuilder = new StringBuilder($"以下域名在{ now }发生变化:");
+ foreach (var i in items)
+ {
+ textBuilder.Append($"\n{ i.domain }({ i.recordType }) => { i.ip }");
+ }
+
+ dynamic o = new
+ {
+ title = "域名变化通知",
+ desp = textBuilder.ToString()
+ };
+
+ string content = JsonConvert.SerializeObject(o);
+ using (var http = new HttpClient())
+ {
+ StringContent sc = new StringContent(content, Encoding.UTF8, "application/json");
+ http.PostAsync(url.ToString(), sc).Wait();
+ }
+
+ Log.Print("成功推送Server酱。");
+ }
+ catch (Exception e)
+ {
+ Log.Print($"推送Server酱时发生异常:\n{ e }");
+ }
+ }
+
+ private static long ToTimestamp(DateTime dt)
+ {
+ return (dt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
+ }
+ }
+}