From 10f156e9e2a356928555befc5eb977761be41d0b Mon Sep 17 00:00:00 2001 From: ShaoHua <345265198@qqcom> Date: Wed, 8 Apr 2026 19:28:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=98=E6=9B=B4=E8=AF=A6=E6=83=85=E6=91=98?= =?UTF-8?q?=E8=A6=81=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 功能增强 : - AliSslProvider.cs :实现了从阿里云获取证书列表及删除过期证书的逻辑。 - TencentSslProvider.cs :增加了腾讯云过期证书的清理功能。 - ISslDownloadProvider.cs :扩展了接口协议,并丰富了 SslCertificate 模型属性。 - 任务调度 : - Program.cs :集成了 SslDownloadJob 到 Quartz 框架中,支持自动化运行。 - 文档与规范 : - 对项目关键入口和 Provider 进行了全面的代码注释补全。 --- Hua.DDNS.Test/appsettings.Development.json | 66 ++++++++++++++ Hua.DDNS.sln | 31 ------- Hua.DDNS.slnx | 4 + .../Common/Config/Options/AliCloudOption.cs | 18 ++++ Hua.DDNS/Common/Config/Options/AppOption.cs | 6 +- .../Common/Config/Options/PlatformEnum.cs | 8 +- .../Config/Options/SslDownloadOption.cs | 45 ++++++++++ .../Config/Options/TencentCloudOption.cs | 18 ++++ Hua.DDNS/Common/Config/SettingProvider.cs | 12 ++- Hua.DDNS/Common/FileHelper.cs | 9 +- Hua.DDNS/Common/Http/HttpHelper.cs | 88 +++++++++++++++---- Hua.DDNS/Common/Http/HttpResult.cs | 18 +++- Hua.DDNS/Common/SqlHelper.cs | 18 ++-- Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs | 34 +++++-- Hua.DDNS/DDNSProviders/DDNSOption.cs | 10 +-- .../Dnspod/DnspodDDNSProvider.cs | 33 ++++++- Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs | 4 +- Hua.DDNS/DDNSProviders/IDDNSProvider.cs | 27 +++--- .../Namesilo/NamesiloDDNSProvider.cs | 33 ++++++- .../DDNSProviders/Namesilo/NamesiloOption.cs | 6 +- Hua.DDNS/Jobs/NewJob.cs | 24 ++++- Hua.DDNS/Jobs/SslDownloadJob.cs | 29 ++++++ Hua.DDNS/Models/DnsRecord.cs | 40 ++++++++- Hua.DDNS/Models/MappingProfile.cs | 8 +- Hua.DDNS/SslProviders/Ali/AliSslProvider.cs | 84 +++++++++++++++++- Hua.DDNS/SslProviders/ISslDownloadProvider.cs | 51 +++++++++++ .../Tencent/TencentSslProvider.cs | 55 ++++++++++++ Hua.DDNS/Start/Program.cs | 57 ++++++++---- 28 files changed, 715 insertions(+), 121 deletions(-) create mode 100644 Hua.DDNS.Test/appsettings.Development.json delete mode 100644 Hua.DDNS.sln create mode 100644 Hua.DDNS.slnx diff --git a/Hua.DDNS.Test/appsettings.Development.json b/Hua.DDNS.Test/appsettings.Development.json new file mode 100644 index 0000000..0fbec48 --- /dev/null +++ b/Hua.DDNS.Test/appsettings.Development.json @@ -0,0 +1,66 @@ +{ + "ConnectionStrings": { + "pgConnection": "Host=127.0.0.1;Port=5432;Database=Worker;Username=Worker;Password=123456;" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "App": { + "GetIpv4Url": "http://47.108.74.59:8001/api/NetWork/GetIp", + "AppJob": { + "Corn": "0/5 * * * * ?" //https://cron.qqe2.com/ + } + }, + "DDNS": { + "Platform": 2, //1 Ali 2 Tencent 3 Namesilo + // 主域名 + "Domain": "we965.cn", + // 子域名前缀 + "SubDomainArray": [ "mp", "git", "webutil", "dev", "sftp" ], + // 记录类型 + "type": "A", + //间隔时间 秒 + "time": "30" + }, + "SslDownload": { + "Enabled": true, + "Corn": "0/5 * * * * ?", //https://cron.qqe2.com/ + "Platform": 2, + "SavePath": "D:\\Paths\\ssl", + "ExpireDays": 5, + "DownloadItems": [ + { + "Domain": "git.we965.cn", + "FileName": "git.we965.cn.pem" + }, + { + "Domain": "webutil.we965.cn", + "FileName": "webutil.we965.cn.pem" + }, + { + "Domain": "dev.we965.cn", + "FileName": "dev.we965.cn.pem" + } + ] + }, + "TencentCloud": { + "SecretId": "AKIDy35008NYm6T1v3R3gGtU1UIHOe0NizON", + "SecretKey": "1sXQmASfmmlwAXuDh8fVYUOLI7mJagbQ", + "Region": "ap-guangzhou", + "Dnspod": { + "Endpoint": "dnspod.tencentcloudapi.com" + } + }, + "AliCloud": { + "AccessKeyId": "1111", + "AccessKeySecret": "1111", + "RegionId": "cn-hangzhou", + "Endpoint": "1111" + }, + "Namesilo": { + "ApiKey": "1111" + } +} \ No newline at end of file diff --git a/Hua.DDNS.sln b/Hua.DDNS.sln deleted file mode 100644 index 0dabc6c..0000000 --- a/Hua.DDNS.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32616.157 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hua.DDNS", "Hua.DDNS\Hua.DDNS.csproj", "{EBC77B5D-87D5-4923-84A6-93DB2248DEB0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hua.DDNS.Test", "Hua.DDNS.Test\Hua.DDNS.Test.csproj", "{BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Release|Any CPU.Build.0 = Release|Any CPU - {BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {D8744CA6-C2DB-4287-B8B3-E5917B12391D} - EndGlobalSection -EndGlobal diff --git a/Hua.DDNS.slnx b/Hua.DDNS.slnx new file mode 100644 index 0000000..131ef7f --- /dev/null +++ b/Hua.DDNS.slnx @@ -0,0 +1,4 @@ + + + + diff --git a/Hua.DDNS/Common/Config/Options/AliCloudOption.cs b/Hua.DDNS/Common/Config/Options/AliCloudOption.cs index 4282f6e..55c37bd 100644 --- a/Hua.DDNS/Common/Config/Options/AliCloudOption.cs +++ b/Hua.DDNS/Common/Config/Options/AliCloudOption.cs @@ -1,10 +1,28 @@ namespace Hua.DDNS.Common.Config.Options { + /// + /// 阿里云配置选项 + /// public class AliCloudOption { + /// + /// 访问密钥 ID + /// public string AccessKeyId { get; set; } + + /// + /// 访问密钥私钥 + /// public string AccessKeySecret { get; set; } + + /// + /// 区域 ID (如 cn-hangzhou) + /// public string RegionId { get; set; } + + /// + /// 访问端点 (可选) + /// public string Endpoint { get; set; } } } diff --git a/Hua.DDNS/Common/Config/Options/AppOption.cs b/Hua.DDNS/Common/Config/Options/AppOption.cs index dd78b60..8511d54 100644 --- a/Hua.DDNS/Common/Config/Options/AppOption.cs +++ b/Hua.DDNS/Common/Config/Options/AppOption.cs @@ -1,16 +1,16 @@ -using Hua.DDNS.DDNSProviders; +using Hua.DDNS.DDNSProviders; namespace Hua.DDNS.Common.Config.Options { /// - /// app configuration class + /// 应用程序全局配置类 /// public class AppOption { /// - /// domain configuration + /// DDNS 相关配置 /// public DdnsOption DDNS { get; set; } diff --git a/Hua.DDNS/Common/Config/Options/PlatformEnum.cs b/Hua.DDNS/Common/Config/Options/PlatformEnum.cs index 2aacd69..6f5871a 100644 --- a/Hua.DDNS/Common/Config/Options/PlatformEnum.cs +++ b/Hua.DDNS/Common/Config/Options/PlatformEnum.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -7,17 +7,17 @@ using System.Threading.Tasks; namespace Hua.DDNS.Common.Config.Options { /// - /// DDNS Platform + /// DDNS 平台类型枚举 /// public enum PlatformEnum { /// - /// Ali + /// 阿里云 /// Ali = 1, /// - /// Tencent + /// 腾讯云 /// Tencent, diff --git a/Hua.DDNS/Common/Config/Options/SslDownloadOption.cs b/Hua.DDNS/Common/Config/Options/SslDownloadOption.cs index 816ac64..e19a736 100644 --- a/Hua.DDNS/Common/Config/Options/SslDownloadOption.cs +++ b/Hua.DDNS/Common/Config/Options/SslDownloadOption.cs @@ -1,24 +1,69 @@ namespace Hua.DDNS.Common.Config.Options { + /// + /// SSL 证书来源平台枚举 + /// public enum SslPlatformEnum { + /// + /// 阿里云 + /// Ali = 1, + /// + /// 腾讯云 + /// Tencent = 2 } + /// + /// SSL 证书下载配置选项 + /// public class SslDownloadOption { + /// + /// 是否启用 + /// public bool Enabled { get; set; } + + /// + /// Cron 定时表达式 + /// public string Corn { get; set; } + + /// + /// 云平台类型 + /// public SslPlatformEnum Platform { get; set; } + + /// + /// 证书保存本地路径 + /// public string SavePath { get; set; } + + /// + /// 过期天数阈值 (提前多少天开始下载更新) + /// public int ExpireDays { get; set; } + + /// + /// 需要下载的证书列表 + /// public List DownloadItems { get; set; } } + /// + /// SSL 证书下载项详情 + /// public class SslDownloadItem { + /// + /// 域名 + /// public string Domain { get; set; } + + /// + /// 保存到本地的文件名 (不含后缀) + /// public string FileName { get; set; } } } diff --git a/Hua.DDNS/Common/Config/Options/TencentCloudOption.cs b/Hua.DDNS/Common/Config/Options/TencentCloudOption.cs index 6ba4ec8..225e6e2 100644 --- a/Hua.DDNS/Common/Config/Options/TencentCloudOption.cs +++ b/Hua.DDNS/Common/Config/Options/TencentCloudOption.cs @@ -2,11 +2,29 @@ using Hua.DDNS.DDNSProviders.Dnspod; namespace Hua.DDNS.Common.Config.Options { + /// + /// 腾讯云配置选项 + /// public class TencentCloudOption { + /// + /// 密钥 ID + /// public string SecretId { get; set; } + + /// + /// 密钥私钥 + /// public string SecretKey { get; set; } + + /// + /// 区域 (如 ap-guangzhou) + /// public string Region { get; set; } + + /// + /// Dnspod 相关配置 (已并入腾讯云) + /// public DnspodOption Dnspod { get; set; } } } diff --git a/Hua.DDNS/Common/Config/SettingProvider.cs b/Hua.DDNS/Common/Config/SettingProvider.cs index 52a053f..692c3bf 100644 --- a/Hua.DDNS/Common/Config/SettingProvider.cs +++ b/Hua.DDNS/Common/Config/SettingProvider.cs @@ -1,15 +1,20 @@ -using Hua.DDNS.Common.Config.Options; +using Hua.DDNS.Common.Config.Options; namespace Hua.DDNS.Common.Config { /// - /// this is a strongly-typed configuration provider + /// 强类型配置提供者,用于方便地访问应用程序配置 /// public class SettingProvider { private readonly AppOption _app; private readonly IConfiguration _configuration; + + /// + /// 构造函数 + /// + /// 配置对象 public SettingProvider(IConfiguration configuration) { _configuration = configuration; @@ -17,6 +22,9 @@ namespace Hua.DDNS.Common.Config _configuration.GetSection("App").Bind(_app); } + /// + /// 获取应用程序配置选项 + /// public AppOption App => _app; } diff --git a/Hua.DDNS/Common/FileHelper.cs b/Hua.DDNS/Common/FileHelper.cs index 5afd469..6cf07f3 100644 --- a/Hua.DDNS/Common/FileHelper.cs +++ b/Hua.DDNS/Common/FileHelper.cs @@ -1,7 +1,14 @@ -namespace Hua.DDNS.Common +namespace Hua.DDNS.Common { + /// + /// 文件操作助手类 + /// public class FileHelper { + /// + /// 如果文件存在则删除 + /// + /// 文件路径 public static void DeleteIfExists(string path) { if (File.Exists(path)) diff --git a/Hua.DDNS/Common/Http/HttpHelper.cs b/Hua.DDNS/Common/Http/HttpHelper.cs index 11854e2..3b5f4e9 100644 --- a/Hua.DDNS/Common/Http/HttpHelper.cs +++ b/Hua.DDNS/Common/Http/HttpHelper.cs @@ -1,15 +1,23 @@ -using System.Net; +using System.Net; using System.Net.Http.Json; using Newtonsoft.Json; namespace Hua.DDNS.Common.Http { + /// + /// Http 请求助手类,用于执行各种 HTTP 请求 + /// public class HttpHelper: IHttpHelper { private static ILogger _logger; private static HttpClientHandler _handler; private IConfiguration _configuration; + /// + /// 构造函数 + /// + /// 日志对象 + /// 配置对象 public HttpHelper(ILogger logger, IConfiguration configuration) { _logger = logger; @@ -17,26 +25,30 @@ namespace Hua.DDNS.Common.Http _handler = new HttpClientHandler(); } + /// + /// 获取 HttpClient 实例 + /// + /// HttpClient 实例 public HttpClient GetHttpClient() { return new HttpClient(_handler){}; } /// - /// PostAsync + /// 异步执行 Post 请求并解析 JSON 结果 /// - /// - /// - /// - /// - /// 超时时间 - /// + /// 输入数据类型 + /// 输出结果类型 + /// 请求地址 + /// 输入数据 + /// 超时时间 (秒) + /// 解析后的结果对象 public async Task PostAsync(string url, TIn input, int timeOut = 10) { try { var client = GetHttpClient(); - client.Timeout = new TimeSpan(0, 10, timeOut); + client.Timeout = TimeSpan.FromSeconds(timeOut); _logger.LogDebug($"Post:{url}\n[{JsonConvert.SerializeObject(input)}]"); var result = await client.PostAsync(url, JsonContent.Create(input)); var strResult = await result.Content.ReadAsStringAsync(); @@ -55,18 +67,18 @@ namespace Hua.DDNS.Common.Http } /// - /// PostAsync + /// 异步执行 Get 请求并解析 JSON 结果 /// - /// - /// - /// - /// + /// 输出结果类型 + /// 请求地址 + /// 超时时间 (秒) + /// 解析后的结果对象 public async Task GetAsync(string url,int timeOut = 10) { try { var client = GetHttpClient(); - client.Timeout = new TimeSpan(0, 10, timeOut); + client.Timeout = TimeSpan.FromSeconds(timeOut); _logger.LogDebug($"Get:{url}"); var result = await client.GetAsync(url); var strResult = await result.Content.ReadAsStringAsync(); @@ -87,11 +99,11 @@ namespace Hua.DDNS.Common.Http #region 下载文件 /// - /// http下载文件 + /// 通过 HTTP 下载文件 /// /// 下载文件地址 - /// 文件存放地址,包含文件名 - /// + /// 文件本地存放路径,包含文件名 + /// 下载成功返回 true,否则返回 false public bool DownloadFile(string url, string localPath) { try @@ -134,8 +146,9 @@ namespace Hua.DDNS.Common.Http /// - /// 获得当前机器的公网 Ip + /// 获取当前机器的公网 IPv4 地址 /// + /// IPv4 地址字符串 public async Task GetCurrentPublicIpv4() { using var client = new HttpClient(); @@ -146,12 +159,49 @@ namespace Hua.DDNS.Common.Http } + /// + /// Http 助手接口 + /// public interface IHttpHelper { + /// + /// 获取当前机器的公网 IPv4 地址 + /// + /// IPv4 地址字符串 public Task GetCurrentPublicIpv4(); + + /// + /// 异步执行 Post 请求并解析 JSON 结果 + /// + /// 输入数据类型 + /// 输出结果类型 + /// 请求地址 + /// 输入数据 + /// 超时时间 (秒) + /// 解析后的结果对象 public Task PostAsync(string url, TIn input, int timeOut = 10); + + /// + /// 异步执行 Get 请求并解析 JSON 结果 + /// + /// 输出结果类型 + /// 请求地址 + /// 超时时间 (秒) + /// 解析后的结果对象 public Task GetAsync(string url, int timeOut = 10); + + /// + /// 通过 HTTP 下载文件 + /// + /// 下载文件地址 + /// 文件本地存放路径,包含文件名 + /// 下载成功返回 true,否则返回 false public bool DownloadFile(string url, string fileFullName); + + /// + /// 获取 HttpClient 实例 + /// + /// HttpClient 实例 public HttpClient GetHttpClient(); } } diff --git a/Hua.DDNS/Common/Http/HttpResult.cs b/Hua.DDNS/Common/Http/HttpResult.cs index a48e482..632e2b6 100644 --- a/Hua.DDNS/Common/Http/HttpResult.cs +++ b/Hua.DDNS/Common/Http/HttpResult.cs @@ -1,13 +1,29 @@ -namespace Hua.DDNS.Common.Http +namespace Hua.DDNS.Common.Http { + /// + /// Http 请求返回结果包装类 + /// + /// 数据类型 public class HttpResult { + /// + /// 返回的数据内容 + /// public virtual T Data { get; set; } + /// + /// 数据描述信息 + /// public string DataDescription { get; set; } + /// + /// 结果状态码 (例如 200 为成功) + /// public int Result { get; set; } + /// + /// 返回的消息提示 + /// public string Message { get; set; } } diff --git a/Hua.DDNS/Common/SqlHelper.cs b/Hua.DDNS/Common/SqlHelper.cs index 6c39ca6..98a9ce2 100644 --- a/Hua.DDNS/Common/SqlHelper.cs +++ b/Hua.DDNS/Common/SqlHelper.cs @@ -1,15 +1,23 @@ -using System.Data; +using System.Data; using Dapper; using Npgsql; namespace Hua.DDNS.Common { + /// + /// 数据库操作助手类 (基于 Npgsql 和 Dapper) + /// public class SqlHelper { private readonly string _connectionString; private readonly ILogger _logger; + /// + /// 构造函数 + /// + /// 配置对象 + /// 日志对象 public SqlHelper(IConfiguration configuration, ILogger logger) { _logger = logger; @@ -19,10 +27,10 @@ namespace Hua.DDNS.Common /// /// 查询所有结果 /// - /// - /// - /// - /// + /// 实体类型 + /// SQL 语句 + /// 结果列表 + /// 数据库连接或查询异常 public List GetList(string strSql) { var list = new List(); diff --git a/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs b/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs index 5641335..14febf7 100644 --- a/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs +++ b/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs @@ -16,7 +16,7 @@ namespace Hua.DDNS.DDNSProviders.Ali { /// - /// DDNSProvider for Ali + /// 阿里云 DDNS 解析提供者 /// public class AliDdnsProvider : IDdnsProvider { @@ -25,6 +25,12 @@ namespace Hua.DDNS.DDNSProviders.Ali private readonly DdnsOption _ddnsOption; private readonly IMapper _mapper; + /// + /// 构造函数 + /// + /// 阿里云配置 + /// 对象映射器 + /// DDNS 配置 public AliDdnsProvider(IOptions aliCloudOption, IMapper mapper,IOptions ddnsOption) { _aliCloudOption = aliCloudOption.Value; @@ -41,9 +47,9 @@ namespace Hua.DDNS.DDNSProviders.Ali } /// - /// 获取解析记录列表 + /// 异步获取阿里云上的域名解析记录列表 /// - /// + /// 解析记录列表 public async Task?> GetRecordListAsync() { var record = (await _client.DescribeDomainRecordsAsync(new DescribeDomainRecordsRequest() @@ -54,6 +60,11 @@ namespace Hua.DDNS.DDNSProviders.Ali return _mapper.Map>(record); } + /// + /// 异步在阿里云上创建新的域名解析记录 + /// + /// 解析记录信息 + /// 创建后的解析记录信息 public async Task CreateDnsRecordAsync(DnsRecord record) { var rep = await _client.AddDomainRecordAsync(_mapper.Map(record)); @@ -61,11 +72,11 @@ namespace Hua.DDNS.DDNSProviders.Ali } /// - /// 变更解析记录列表 + /// 异步批量修改阿里云上的域名解析记录 /// - /// - /// - /// + /// 新的 IP 地址 + /// 需要修改的解析记录列表 + /// 修改后的解析记录列表 public async Task> ModifyRecordListAsync(string newIp, IEnumerable records) { foreach (var aliDomainRecord in records) @@ -75,5 +86,14 @@ namespace Hua.DDNS.DDNSProviders.Ali return records; } + + /// + /// 异步清理无效证书 + /// + /// + public Task CleanInvalidCertificatesAsync() + { + return Task.CompletedTask; + } } } diff --git a/Hua.DDNS/DDNSProviders/DDNSOption.cs b/Hua.DDNS/DDNSProviders/DDNSOption.cs index 37b5ad6..c9b3e16 100644 --- a/Hua.DDNS/DDNSProviders/DDNSOption.cs +++ b/Hua.DDNS/DDNSProviders/DDNSOption.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,22 +9,22 @@ using Hua.DDNS.DDNSProviders.Namesilo; namespace Hua.DDNS.DDNSProviders { /// - /// domain configuration class + /// DDNS 配置选项类 /// public class DdnsOption { /// - /// platform from 1 Ali 2 Tencent 3 + /// 云平台类型 (1: 阿里云, 2: 腾讯云, 3: Namesilo) /// public PlatformEnum Platform { get; set; } /// - /// domain + /// 根域名 (例如: example.com) /// public string Domain { get; set; } /// - /// sub domain, eg. www,git + /// 需要更新的子域名列表 (例如: ["www", "api", "@"]) /// public string[] SubDomainArray { get; set; } diff --git a/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs b/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs index caba936..fe39866 100644 --- a/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs +++ b/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs @@ -18,8 +18,7 @@ namespace Hua.DDNS.DDNSProviders.Dnspod { /// - /// DdnsProvider for Dnspod - /// + /// Dnspod (腾讯云) DDNS 解析提供者 /// public class DnspodDdnsProvider : IDdnsProvider { @@ -29,6 +28,12 @@ namespace Hua.DDNS.DDNSProviders.Dnspod private readonly DdnsOption _ddnsOption; private readonly IMapper _mapper; + /// + /// 构造函数 + /// + /// 对象映射器 + /// 腾讯云配置 + /// DDNS 配置 public DnspodDdnsProvider(IMapper mapper, IOptions tencentCloudOption, IOptions ddnsOption) { _mapper = mapper; @@ -44,6 +49,10 @@ namespace Hua.DDNS.DDNSProviders.Dnspod }); } + /// + /// 异步获取 Dnspod 上的域名解析记录列表 + /// + /// 解析记录列表 public async Task?> GetRecordListAsync() { var recordList = (await _client.DescribeRecordList(new DescribeRecordListRequest() { Domain = _ddnsOption.Domain })).RecordList; @@ -51,6 +60,11 @@ namespace Hua.DDNS.DDNSProviders.Dnspod return _mapper.Map>(recordList); } + /// + /// 异步在 Dnspod 上创建新的域名解析记录 + /// + /// 解析记录信息 + /// 创建后的解析记录信息 public async Task CreateDnsRecordAsync(DnsRecord record) { var response = await _client.CreateRecord(new CreateRecordRequest() @@ -64,6 +78,12 @@ namespace Hua.DDNS.DDNSProviders.Dnspod return record; } + /// + /// 异步批量修改 Dnspod 上的域名解析记录 + /// + /// 新的 IP 地址 + /// 需要修改的解析记录列表 + /// 修改后的解析记录列表 public async Task> ModifyRecordListAsync(string newIp, IEnumerable records) { var rep = await _client.ModifyRecordBatch(new ModifyRecordBatchRequest() @@ -74,5 +94,14 @@ namespace Hua.DDNS.DDNSProviders.Dnspod }); return records; } + + /// + /// 异步清理无效证书 + /// + /// + public Task CleanInvalidCertificatesAsync() + { + return Task.CompletedTask; + } } } diff --git a/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs b/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs index 29ea299..c64a4b8 100644 --- a/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs +++ b/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs @@ -1,12 +1,12 @@ namespace Hua.DDNS.DDNSProviders.Dnspod { /// - /// domain configuration Dnspod + /// Dnspod 配置选项 /// public class DnspodOption { /// - /// Endpoint dnspod.tencentcloudapi.com + /// 接口访问端点 (例如: dnspod.tencentcloudapi.com) /// public string Endpoint { get; set; } } diff --git a/Hua.DDNS/DDNSProviders/IDDNSProvider.cs b/Hua.DDNS/DDNSProviders/IDDNSProvider.cs index 3cce1b6..b8244ac 100644 --- a/Hua.DDNS/DDNSProviders/IDDNSProvider.cs +++ b/Hua.DDNS/DDNSProviders/IDDNSProvider.cs @@ -9,32 +9,37 @@ namespace Hua.DDNS.DDNSProviders { /// - /// Dynamic domain name resolution provider + /// 动态域名解析 (DDNS) 提供者接口 /// public interface IDdnsProvider { /// - /// 获取域名解析记录列表 + /// 异步获取域名解析记录列表 /// - /// - + /// 域名解析记录列表 Task?> GetRecordListAsync(); /// - /// 创建解析记录 + /// 异步创建新的域名解析记录 /// - /// - /// + /// 解析记录信息 + /// 创建后的解析记录信息 Task CreateDnsRecordAsync(DnsRecord record); /// - /// 修改域名解析记录 + /// 异步批量修改域名解析记录 (通常用于更新 IP) /// - /// - /// - /// + /// 新的 IP 地址 + /// 需要修改的解析记录列表 + /// 修改后的解析记录列表 Task> ModifyRecordListAsync(string newIp, IEnumerable records); + /// + /// 异步清理无效证书 + /// + /// + Task CleanInvalidCertificatesAsync(); + } } diff --git a/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs index 976adb7..0fa57c2 100644 --- a/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs +++ b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs @@ -1,4 +1,4 @@ -using System.Xml; +using System.Xml; using AutoMapper; using Hua.DDNS.Models; using Microsoft.Extensions.Hosting; @@ -8,13 +8,18 @@ using Newtonsoft.Json; namespace Hua.DDNS.DDNSProviders.Namesilo { /// - /// DDNSProvider for namesilo + /// Namesilo DDNS 解析提供者 /// public class NamesiloDdnsProvider : IDdnsProvider { public readonly NamesiloOption _namesiloOption; public readonly DdnsOption _ddnsOption; + /// + /// 构造函数 + /// + /// Namesilo 配置 + /// DDNS 配置 public NamesiloDdnsProvider(IOptions namesiloOption, IOptions ddnsOption) { _ddnsOption = ddnsOption.Value; @@ -22,6 +27,10 @@ namespace Hua.DDNS.DDNSProviders.Namesilo } + /// + /// 异步获取 Namesilo 上的域名解析记录列表 + /// + /// 解析记录列表 public async Task?> GetRecordListAsync() { var client = new HttpClient(); @@ -62,6 +71,11 @@ namespace Hua.DDNS.DDNSProviders.Namesilo }).ToList(); } + /// + /// 异步在 Namesilo 上创建新的域名解析记录 + /// + /// 解析记录信息 + /// 创建后的解析记录信息 public async Task CreateDnsRecordAsync(DnsRecord dnsRecord) { var host = dnsRecord.Host[..(dnsRecord.Host.Length - dnsRecord.Domain.Length - 1)]; @@ -91,6 +105,12 @@ namespace Hua.DDNS.DDNSProviders.Namesilo return dnsRecord; } + /// + /// 异步批量修改 Namesilo 上的域名解析记录 + /// + /// 新的 IP 地址 + /// 需要修改的解析记录列表 + /// 修改后的解析记录列表 public async Task> ModifyRecordListAsync(string newIp, IEnumerable records) { foreach (var dnsRecord in records) @@ -122,5 +142,14 @@ namespace Hua.DDNS.DDNSProviders.Namesilo return records; } + + /// + /// 异步清理无效证书 + /// + /// + public Task CleanInvalidCertificatesAsync() + { + return Task.CompletedTask; + } } } \ No newline at end of file diff --git a/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs index 1f116e1..f5eb92b 100644 --- a/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs +++ b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs @@ -1,14 +1,14 @@ -namespace Hua.DDNS.DDNSProviders.Namesilo +namespace Hua.DDNS.DDNSProviders.Namesilo { /// - /// Namesilo Option + /// Namesilo 配置选项 /// public class NamesiloOption { /// - /// API key + /// API 密钥 /// public string ApiKey { get; set; } diff --git a/Hua.DDNS/Jobs/NewJob.cs b/Hua.DDNS/Jobs/NewJob.cs index edfc156..f6252e3 100644 --- a/Hua.DDNS/Jobs/NewJob.cs +++ b/Hua.DDNS/Jobs/NewJob.cs @@ -25,6 +25,9 @@ using System.Net.Sockets; namespace Hua.DDNS.Jobs { + /// + /// 新的 DDNS 任务类,用于定期检查并更新域名解析记录 + /// [DisallowConcurrentExecution] public class NewJob : IJob, IDisposable { @@ -32,10 +35,19 @@ namespace Hua.DDNS.Jobs private readonly IServiceProvider _serviceProvider; private readonly DdnsOption _ddnsOption; private readonly IHttpHelper _httpHelper; + + /// + /// 新的 IP 地址 + /// public string newIp; - - + /// + /// 构造函数 + /// + /// 日志对象 + /// Http 助手 + /// DDNS 配置选项 + /// 服务提供者 public NewJob(ILogger logger,IHttpHelper httpHelper,IOptions ddnsOption, IServiceProvider serviceProvider) { _logger = logger; @@ -43,6 +55,11 @@ namespace Hua.DDNS.Jobs _serviceProvider = serviceProvider; _ddnsOption = ddnsOption.Value; } + + /// + /// 执行任务逻辑 + /// + /// 作业执行上下文 public async Task Execute(IJobExecutionContext context) { @@ -98,6 +115,9 @@ namespace Hua.DDNS.Jobs } } + /// + /// 释放资源 + /// public void Dispose() { _logger.LogInformation("AppJob已销毁"); diff --git a/Hua.DDNS/Jobs/SslDownloadJob.cs b/Hua.DDNS/Jobs/SslDownloadJob.cs index cb0b4c2..4a0df61 100644 --- a/Hua.DDNS/Jobs/SslDownloadJob.cs +++ b/Hua.DDNS/Jobs/SslDownloadJob.cs @@ -8,6 +8,9 @@ using System.Security.Cryptography.X509Certificates; namespace Hua.DDNS.Jobs { + /// + /// SSL 证书下载任务类,用于定期检查并更新 SSL 证书 + /// [DisallowConcurrentExecution] public class SslDownloadJob : IJob, IDisposable { @@ -15,6 +18,12 @@ namespace Hua.DDNS.Jobs private readonly IServiceProvider _serviceProvider; private readonly SslDownloadOption _sslDownloadOption; + /// + /// 构造函数 + /// + /// 日志对象 + /// 服务提供者 + /// SSL 下载配置选项 public SslDownloadJob( ILogger logger, IServiceProvider serviceProvider, @@ -25,6 +34,10 @@ namespace Hua.DDNS.Jobs _sslDownloadOption = sslDownloadOption.Value; } + /// + /// 执行任务逻辑 + /// + /// 作业执行上下文 public async Task Execute(IJobExecutionContext context) { if (!_sslDownloadOption.Enabled) @@ -110,6 +123,11 @@ namespace Hua.DDNS.Jobs } } + /// + /// 获取本地证书的过期时间 + /// + /// 下载项 + /// 过期时间,如果不存在则返回 null private DateTime? GetLocalCertificateExpiry(SslDownloadItem item) { try @@ -137,6 +155,14 @@ namespace Hua.DDNS.Jobs } } + /// + /// 异步下载证书文件 + /// + /// SSL 提供者 + /// 下载项 + /// 证书 ID + /// 域名 + /// Task private async Task DownloadFileAsync(ISslDownloadProvider provider, SslDownloadItem item, string certificateId, string domain) { try @@ -169,6 +195,9 @@ namespace Hua.DDNS.Jobs } } + /// + /// 释放资源 + /// public void Dispose() { _logger.LogInformation("SslDownloadJob已销毁"); diff --git a/Hua.DDNS/Models/DnsRecord.cs b/Hua.DDNS/Models/DnsRecord.cs index 11d8434..451112e 100644 --- a/Hua.DDNS/Models/DnsRecord.cs +++ b/Hua.DDNS/Models/DnsRecord.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,22 +6,60 @@ using System.Threading.Tasks; namespace Hua.DDNS.Models; +/// +/// 域名解析记录实体类 +/// public class DnsRecord { + /// + /// 解析记录 ID + /// public string Id { get; set; } + + /// + /// IP 地址 + /// public string Ip { get; set; } + + /// + /// 主机记录 (例如: www) + /// public string Host { get; set; } + + /// + /// 子域名 (通常与 Host 相同) + /// public string SubDomain { get; set; } + + /// + /// 根域名 (例如: example.com) + /// public string Domain { get; set; } + + /// + /// 生存时间 (TTL) + /// public string TTL { get; set; } = "10"; + + /// + /// 记录类型 (A, AAAA, CNAME 等) + /// public string RecordType { get; set; } = "A"; + /// + /// 构造函数 + /// + /// IP 地址 + /// 域名 public DnsRecord(string ip,string domain) { Ip = ip; Host = domain; } + /// + /// 默认构造函数 + /// public DnsRecord() { diff --git a/Hua.DDNS/Models/MappingProfile.cs b/Hua.DDNS/Models/MappingProfile.cs index d6a4e20..fdeb005 100644 --- a/Hua.DDNS/Models/MappingProfile.cs +++ b/Hua.DDNS/Models/MappingProfile.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,8 +10,14 @@ using TencentCloud.Dnspod.V20210323.Models; namespace Hua.DDNS.Models { + /// + /// AutoMapper 对象映射配置类 + /// public class MappingProfile : Profile { + /// + /// 构造函数,配置映射规则 + /// public MappingProfile() { CreateMap() diff --git a/Hua.DDNS/SslProviders/Ali/AliSslProvider.cs b/Hua.DDNS/SslProviders/Ali/AliSslProvider.cs index 2a820e6..6a5dbb9 100644 --- a/Hua.DDNS/SslProviders/Ali/AliSslProvider.cs +++ b/Hua.DDNS/SslProviders/Ali/AliSslProvider.cs @@ -8,12 +8,20 @@ using Microsoft.Extensions.Options; namespace Hua.DDNS.SslProviders.Ali { + /// + /// 阿里云 SSL 证书下载提供者 + /// public class AliSslProvider : ISslDownloadProvider { private readonly Client _client; private readonly AliCloudOption _aliCloudOption; private readonly ILogger _logger; + /// + /// 构造函数 + /// + /// 日志对象 + /// 阿里云配置 public AliSslProvider( ILogger logger, IOptions aliCloudOption) @@ -31,12 +39,40 @@ namespace Hua.DDNS.SslProviders.Ali _client = new Client(config); } + /// + /// 异步获取阿里云上的 SSL 证书列表 + /// + /// 证书列表 public async Task> GetCertificatesAsync() { try { - _logger.LogWarning("阿里云 SSL 证书列表功能待实现"); - return new List(); + var request = new ListUserCertificateOrderRequest + { + OrderType = "CERT", + Status = "ISSUED" // 也可以不设置,获取所有 + }; + + var response = await _client.ListUserCertificateOrderAsync(request); + var certificates = new List(); + + if (response.Body.CertificateOrderList != null) + { + foreach (var cert in response.Body.CertificateOrderList) + { + certificates.Add(new SslCertificate + { + CertificateId = cert.CertificateId.ToString(), + Domain = cert.Domain, + Alias = cert.Name, + CertEndTime = string.IsNullOrEmpty(cert.EndDate) ? DateTime.MinValue : DateTime.Parse(cert.EndDate), + StatusMsg = cert.Status + }); + } + } + + _logger.LogInformation($"获取到 {certificates.Count} 个阿里云 SSL 证书"); + return certificates; } catch (Exception ex) { @@ -45,10 +81,18 @@ namespace Hua.DDNS.SslProviders.Ali } } + /// + /// 异步下载阿里云上的指定的 SSL 证书 + /// + /// 证书 ID + /// 本地保存目录路径 + /// 保存的文件名 (不含后缀) + /// 下载成功返回 true,否则返回 false public async Task DownloadCertificateAsync(string certificateId, string savePath, string fileName) { try { + // TODO: 阿里云证书下载逻辑 _logger.LogWarning($"阿里云 SSL 证书下载功能待实现: {certificateId}"); return false; } @@ -58,5 +102,41 @@ namespace Hua.DDNS.SslProviders.Ali return false; } } + + /// + /// 异步清理无效证书 + /// + /// + public async Task CleanInvalidCertificatesAsync() + { + try + { + var certificates = await GetCertificatesAsync(); + // 筛选过期的证书 + var expiredCertificates = certificates.Where(c => c.CertEndTime != DateTime.MinValue && c.CertEndTime < DateTime.Now).ToList(); + + foreach (var cert in expiredCertificates) + { + try + { + var deleteRequest = new DeleteUserCertificateRequest + { + CertId = long.Parse(cert.CertificateId) + }; + await _client.DeleteUserCertificateAsync(deleteRequest); + _logger.LogInformation($"已删除阿里云过期证书: {cert.Domain} ({cert.CertificateId}), 过期时间: {cert.CertEndTime}"); + } + catch (Exception ex) + { + _logger.LogWarning(ex, $"删除阿里云证书失败: {cert.CertificateId}"); + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "清理阿里云无效证书失败"); + throw; + } + } } } diff --git a/Hua.DDNS/SslProviders/ISslDownloadProvider.cs b/Hua.DDNS/SslProviders/ISslDownloadProvider.cs index e7c11d2..3962ed4 100644 --- a/Hua.DDNS/SslProviders/ISslDownloadProvider.cs +++ b/Hua.DDNS/SslProviders/ISslDownloadProvider.cs @@ -1,19 +1,70 @@ namespace Hua.DDNS.SslProviders { + /// + /// SSL 证书下载提供者接口 + /// public interface ISslDownloadProvider { + /// + /// 异步获取 SSL 证书列表 + /// + /// 证书信息列表 Task> GetCertificatesAsync(); + + /// + /// 异步下载指定的 SSL 证书 + /// + /// 证书 ID + /// 本地保存目录路径 + /// 保存的文件名 (不含后缀) + /// 下载成功返回 true,否则返回 false Task DownloadCertificateAsync(string certificateId, string savePath, string fileName); + + /// + /// 异步清理无效证书 + /// + /// + Task CleanInvalidCertificatesAsync(); } + /// + /// SSL 证书信息类 + /// public class SslCertificate { + /// + /// 证书 ID + /// public string CertificateId { get; set; } + + /// + /// 证书关联的域名 + /// public string Domain { get; set; } + + /// + /// 证书别名 + /// public string Alias { get; set; } + + /// + /// 证书生效时间 + /// public DateTime CertBeginTime { get; set; } + + /// + /// 证书过期时间 + /// public DateTime CertEndTime { get; set; } + + /// + /// 状态码 + /// public int Status { get; set; } + + /// + /// 状态消息 + /// public string StatusMsg { get; set; } } } diff --git a/Hua.DDNS/SslProviders/Tencent/TencentSslProvider.cs b/Hua.DDNS/SslProviders/Tencent/TencentSslProvider.cs index 2708b7f..c8e54d3 100644 --- a/Hua.DDNS/SslProviders/Tencent/TencentSslProvider.cs +++ b/Hua.DDNS/SslProviders/Tencent/TencentSslProvider.cs @@ -10,12 +10,20 @@ using System.IO.Compression; namespace Hua.DDNS.SslProviders.Tencent { + /// + /// 腾讯云 SSL 证书下载提供者 + /// public class TencentSslProvider : ISslDownloadProvider { private readonly SslClient _client; private readonly TencentCloudOption _tencentCloudOption; private readonly ILogger _logger; + /// + /// 构造函数 + /// + /// 日志对象 + /// 腾讯云配置 public TencentSslProvider( ILogger logger, IOptions tencentCloudOption) @@ -32,6 +40,10 @@ namespace Hua.DDNS.SslProviders.Tencent }); } + /// + /// 异步获取腾讯云上的 SSL 证书列表 + /// + /// 证书信息列表 public async Task> GetCertificatesAsync() { try @@ -72,6 +84,13 @@ namespace Hua.DDNS.SslProviders.Tencent } } + /// + /// 异步下载腾讯云上的指定的 SSL 证书 + /// + /// 证书 ID + /// 本地保存目录路径 + /// 保存的文件名 (不含后缀) + /// 下载成功返回 true,否则返回 false public async Task DownloadCertificateAsync(string certificateId, string savePath, string fileName) { string tempZipPath = null; @@ -172,5 +191,41 @@ namespace Hua.DDNS.SslProviders.Tencent } } } + + /// + /// 异步清理无效证书 + /// + /// + public async Task CleanInvalidCertificatesAsync() + { + try + { + var certificates = await GetCertificatesAsync(); + // 清理已过期的证书 (Status 为 10 或者当前时间已过过期时间) + var expiredCertificates = certificates.Where(c => c.CertEndTime < DateTime.Now || c.Status == 10).ToList(); + + foreach (var cert in expiredCertificates) + { + try + { + var deleteRequest = new DeleteCertificateRequest + { + CertificateId = cert.CertificateId + }; + await _client.DeleteCertificate(deleteRequest); + _logger.LogInformation($"已删除腾讯云过期证书: {cert.Domain} ({cert.CertificateId}), 过期时间: {cert.CertEndTime}"); + } + catch (Exception ex) + { + _logger.LogWarning(ex, $"删除腾讯云证书失败: {cert.CertificateId}"); + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "清理腾讯云无效证书失败"); + throw; + } + } } } diff --git a/Hua.DDNS/Start/Program.cs b/Hua.DDNS/Start/Program.cs index 3dfb85d..3d88c96 100644 --- a/Hua.DDNS/Start/Program.cs +++ b/Hua.DDNS/Start/Program.cs @@ -18,10 +18,18 @@ using Serilog.Extensions.Logging; namespace Hua.DDNS.Start { + /// + /// 应用程序入口类 + /// public static class Program { + /// + /// 主入口方法 + /// + /// 命令行参数 public static async Task Main(string[] args) { + // 配置 Serilog 日志 Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() .WriteTo.Console() @@ -33,13 +41,18 @@ namespace Hua.DDNS.Start await CreateHostBuilder(args).Build().RunAsync(); } + /// + /// 创建并配置宿主构造器 + /// + /// 命令行参数 + /// IHostBuilder 实例 private static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) - .UseWindowsService() - .UseSerilog() + .UseWindowsService() // 支持作为 Windows 服务运行 + .UseSerilog() // 使用 Serilog 替代默认日志 .ConfigureAppConfiguration((context, config) => { - // clear all config provider + // 清理并重新配置配置源 config.Sources.Clear(); config .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) @@ -49,15 +62,25 @@ namespace Hua.DDNS.Start .ConfigureServices((hostContext, services) => { services.AddAutoMapper(Assembly.GetExecutingAssembly()); + + // 绑定配置选项 services.Configure(hostContext.Configuration.GetSection("DDNS")); services.Configure(hostContext.Configuration.GetSection("Namesilo")); services.Configure(hostContext.Configuration.GetSection("TencentCloud")); services.Configure(hostContext.Configuration.GetSection("AliCloud")); services.Configure(hostContext.Configuration.GetSection("SslDownload")); + + // 配置依赖注入和 Quartz ConfigDi(hostContext, services); ConfigQuartz(hostContext, services); }); + /// + /// 配置依赖注入 (DI) + /// + /// 宿主上下文 + /// 服务集合 + /// IServiceProvider 实例 public static IServiceProvider ConfigDi(HostBuilderContext hostContext, IServiceCollection services) { services.AddSingleton(); @@ -72,29 +95,31 @@ namespace Hua.DDNS.Start return services.BuildServiceProvider(); } + /// + /// 配置 Quartz 定时任务 + /// + /// 宿主上下文 + /// 服务集合 private static void ConfigQuartz(HostBuilderContext hostContext, IServiceCollection services) { - // if you are using persistent job store, you might want to alter some options + // 配置 Quartz 选项 services.Configure(options => { - options.Scheduling.IgnoreDuplicates = true; // default: false - options.Scheduling.OverWriteExistingData = true; // default: true + options.Scheduling.IgnoreDuplicates = true; // 忽略重复任务 + options.Scheduling.OverWriteExistingData = true; // 覆盖现有数据 }); - // base configuration for DI + // 添加 Quartz 服务 services.AddQuartz(q => { - // handy when part of cluster or you want to otherwise identify ltiple schedulers q.SchedulerId = "Hua.DDNS.Demo"; - // this is default configuration if you don't alter it q.UseMicrosoftDependencyInjectionJobFactory(); - // these are the defaults q.UseSimpleTypeLoader(); q.UseInMemoryStore(); q.UseDefaultThreadPool(tp => { tp.MaxConcurrency = 10; }); - //configure jobs with code + // 配置 DDNS 任务 (NewJob) var appJobKey = new JobKey("NewJob", "NewJobGroup"); q.AddJob(j => j .StoreDurably() @@ -110,6 +135,7 @@ namespace Hua.DDNS.Start .StartNow() ); + // 配置 SSL 下载任务 (SslDownloadJob) var sslDownloadJobKey = new JobKey("SslDownloadJob", "SslDownloadJobGroup"); q.AddJob(j => j .StoreDurably() @@ -132,14 +158,11 @@ namespace Hua.DDNS.Start } }); - // Quartz.Extensions.Hosting hosting + // 添加 Quartz 托管服务 services.AddQuartzHostedService(options => { - // when shutting down we want jobs to complete gracefully - options.WaitForJobsToComplete = true; - - // when we need to init another IHostedServices first - options.StartDelay = TimeSpan.FromSeconds(10); + options.WaitForJobsToComplete = true; // 优雅退出 + options.StartDelay = TimeSpan.FromSeconds(10); // 启动延迟 }); } }