diff --git a/Hua.DDNS.Test/AppJobTest.cs b/Hua.DDNS.Test/AppJobTest.cs index 2ab5558..a4996df 100644 --- a/Hua.DDNS.Test/AppJobTest.cs +++ b/Hua.DDNS.Test/AppJobTest.cs @@ -22,7 +22,7 @@ namespace Hua.DDNS.Test .Build(); var sc = DIConfig.ConfigureServices(config); - var job = sc.GetService(); + var job = sc.GetService(); job?.Execute(null); } diff --git a/Hua.DDNS/Common/Config/Options/AppOption.cs b/Hua.DDNS/Common/Config/Options/AppOption.cs index 4efe455..dd78b60 100644 --- a/Hua.DDNS/Common/Config/Options/AppOption.cs +++ b/Hua.DDNS/Common/Config/Options/AppOption.cs @@ -1,4 +1,6 @@ -namespace Hua.DDNS.Common.Config.Options +using Hua.DDNS.DDNSProviders; + +namespace Hua.DDNS.Common.Config.Options { /// @@ -10,6 +12,7 @@ /// /// domain configuration /// - public DomainOption Domain { get; set; } + public DdnsOption DDNS { get; set; } + } } diff --git a/Hua.DDNS/Common/Config/Options/PlatformEnum.cs b/Hua.DDNS/Common/Config/Options/PlatformEnum.cs index e4bf83a..2aacd69 100644 --- a/Hua.DDNS/Common/Config/Options/PlatformEnum.cs +++ b/Hua.DDNS/Common/Config/Options/PlatformEnum.cs @@ -19,6 +19,11 @@ namespace Hua.DDNS.Common.Config.Options /// /// Tencent /// - Tencent + Tencent, + + /// + /// Namesilo + /// + Namesilo } } diff --git a/Hua.DDNS/Common/Http/HttpHelper.cs b/Hua.DDNS/Common/Http/HttpHelper.cs index 06af31b..7df79aa 100644 --- a/Hua.DDNS/Common/Http/HttpHelper.cs +++ b/Hua.DDNS/Common/Http/HttpHelper.cs @@ -118,7 +118,7 @@ namespace Hua.DDNS.Common.Http /// - /// 获得当前机器的公网 IP + /// 获得当前机器的公网 Ip /// public async Task GetCurrentPublicIpv4() { diff --git a/Hua.DDNS/DDNSProviders/Ali/AliDDNSOption.cs b/Hua.DDNS/DDNSProviders/Ali/AliDDNSOption.cs new file mode 100644 index 0000000..b8f7c70 --- /dev/null +++ b/Hua.DDNS/DDNSProviders/Ali/AliDDNSOption.cs @@ -0,0 +1,25 @@ +namespace Hua.DDNS.DDNSProviders.Ali +{ + /// + /// domain configuration Ali + /// + public class AliDdnsOption + { + + /// + /// Id, the id and key from DnsPod + /// + public string Id { get; set; } + + /// + /// Key + /// + public string Key { get; set; } + + /// + /// Endpoint + /// + public string Endpoint { get; set; } + } + +} diff --git a/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs b/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs new file mode 100644 index 0000000..7398830 --- /dev/null +++ b/Hua.DDNS/DDNSProviders/Ali/AliDDNSProvider.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AlibabaCloud.OpenApiClient.Models; +using AlibabaCloud.SDK.Alidns20150109; +using AlibabaCloud.SDK.Alidns20150109.Models; +using AutoMapper; +using Hua.DDNS.Common.Config.Options; +using Hua.DDNS.Models; +using Microsoft.Extensions.Options; + +namespace Hua.DDNS.DDNSProviders.Ali +{ + + /// + /// DDNSProvider for Ali + /// + public class AliDdnsProvider : IDdnsProvider + { + private readonly Client _client; + private readonly AliDdnsOption _aliDDNSOption; + private readonly DdnsOption _ddnsOption; + private readonly IMapper _mapper; + + public AliDdnsProvider(IOptions aliDDNSOption, IMapper mapper,IOptions ddnsOption) + { + _aliDDNSOption = aliDDNSOption.Value; + _ddnsOption = ddnsOption.Value; + _mapper = mapper; + + + _client = new Client(new Config() + { + // 您的 AccessKey ID + AccessKeyId = _aliDDNSOption.Id, + // 您的 AccessKey Secret + AccessKeySecret = _aliDDNSOption.Key, + Endpoint = _aliDDNSOption.Endpoint,//alidns.cn-beijing.aliyuncs.com + }); + } + + /// + /// 获取解析记录列表 + /// + /// + public async Task?> GetRecordListAsync() + { + var record = (await _client.DescribeDomainRecordsAsync(new DescribeDomainRecordsRequest() + { + DomainName = _ddnsOption.Domain + })).Body.DomainRecords.Record; + + return _mapper.Map>(record); + } + + /// + /// 变更解析记录列表 + /// + /// + /// + /// + public async Task> ModifyRecordListAsync(string newIp, IEnumerable records) + { + foreach (var aliDomainRecord in records) + { + await _client.UpdateDomainRecordAsync(_mapper.Map(aliDomainRecord)); + } + + return records; + } + } +} diff --git a/Hua.DDNS/Common/Config/Options/DomainOption.cs b/Hua.DDNS/DDNSProviders/DDNSOption.cs similarity index 50% rename from Hua.DDNS/Common/Config/Options/DomainOption.cs rename to Hua.DDNS/DDNSProviders/DDNSOption.cs index 7d74405..37b5ad6 100644 --- a/Hua.DDNS/Common/Config/Options/DomainOption.cs +++ b/Hua.DDNS/DDNSProviders/DDNSOption.cs @@ -3,38 +3,30 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Hua.DDNS.Common.Config.Options; +using Hua.DDNS.DDNSProviders.Namesilo; -namespace Hua.DDNS.Common.Config.Options +namespace Hua.DDNS.DDNSProviders { /// /// domain configuration class /// - public class DomainOption + public class DdnsOption { /// - /// platform from 1 Ali 2 Tencent + /// platform from 1 Ali 2 Tencent 3 /// public PlatformEnum Platform { get; set; } - /// - /// Id, the id and key from AliCould or DnsPod - /// - public string Id { get; set; } - - /// - /// Key - /// - public string Key { get; set; } - /// /// domain /// - public string domain { get; set; } + public string Domain { get; set; } /// /// sub domain, eg. www,git /// - public string[] subDomainArray { get; set; } + public string[] SubDomainArray { get; set; } } diff --git a/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs b/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs new file mode 100644 index 0000000..cd73b5f --- /dev/null +++ b/Hua.DDNS/DDNSProviders/Dnspod/DnspodDDNSProvider.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Hua.DDNS.DDNSProviders.Ali; +using Hua.DDNS.Models; +using Microsoft.Extensions.Options; +using TencentCloud.Common.Profile; +using TencentCloud.Common; +using TencentCloud.Dnspod.V20210323; +using System.Net; +using TencentCloud.Dnspod.V20210323.Models; + +namespace Hua.DDNS.DDNSProviders.Dnspod +{ + + /// + /// DdnsProvider for Dnspod + /// + public class DnspodDdnsProvider : IDdnsProvider + { + + private readonly DnspodClient _client; + private readonly DnspodOption _dnspodOption; + private readonly DdnsOption _ddnsOption; + private readonly IMapper _mapper; + + public DnspodDdnsProvider(IMapper mapper, IOptions dnspodOption, IOptions ddnsOption) + { + _mapper = mapper; + _dnspodOption = dnspodOption.Value; + _ddnsOption = ddnsOption.Value; + + _client = new DnspodClient( + // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密 + // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取 + new Credential { SecretId = _dnspodOption.Id, SecretKey = _dnspodOption.Key }, + "", + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + new ClientProfile() + { + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile = new HttpProfile { Endpoint = (_dnspodOption.Endpoint) }//"dnspod.tencentcloudapi.com" + }); + } + + public async Task?> GetRecordListAsync() + { + var recordList = (await _client.DescribeRecordList(new DescribeRecordListRequest() { Domain = _ddnsOption.Domain })).RecordList; + + return _mapper.Map>(recordList); + } + + public async Task> ModifyRecordListAsync(string newIp, IEnumerable records) + { + var rep = await _client.ModifyRecordBatch(new ModifyRecordBatchRequest() + { + RecordIdList = records.Select(m => (ulong?)Convert.ToUInt64(m.Id)).ToArray(), + Change = "value", + ChangeTo = newIp + }); + return records; + } + } +} diff --git a/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs b/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs new file mode 100644 index 0000000..3911611 --- /dev/null +++ b/Hua.DDNS/DDNSProviders/Dnspod/DnspodOption.cs @@ -0,0 +1,25 @@ +namespace Hua.DDNS.DDNSProviders.Dnspod +{ + /// + /// domain configuration Dnspod + /// + public class DnspodOption + { + + /// + /// Id, the id and key from AliCould or DnsPod + /// + public string Id { get; set; } + + /// + /// Key + /// + public string Key { get; set; } + + /// + /// Endpoint + /// + public string Endpoint { get; set; } + } + +} diff --git a/Hua.DDNS/DDNSProviders/IDDNSProvider.cs b/Hua.DDNS/DDNSProviders/IDDNSProvider.cs new file mode 100644 index 0000000..840c414 --- /dev/null +++ b/Hua.DDNS/DDNSProviders/IDDNSProvider.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Hua.DDNS.Models; + +namespace Hua.DDNS.DDNSProviders +{ + + /// + /// Dynamic domain name resolution provider + /// + public interface IDdnsProvider + { + + /// + /// 获取域名解析记录列表 + /// + /// + + Task?> GetRecordListAsync(); + + /// + /// 修改域名解析记录 + /// + /// + /// + /// + Task> ModifyRecordListAsync(string newIp, IEnumerable records); + + } +} diff --git a/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs new file mode 100644 index 0000000..1ddcd08 --- /dev/null +++ b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs @@ -0,0 +1,95 @@ +using System.Xml; +using AutoMapper; +using Hua.DDNS.Models; +using Microsoft.Extensions.Options; + +namespace Hua.DDNS.DDNSProviders.Namesilo +{ + /// + /// DDNSProvider for namesilo + /// + public class NamesiloDdnsProvider : IDdnsProvider + { + public readonly NamesiloOption _namesiloOption; + public readonly DdnsOption _ddnsOption; + + public NamesiloDdnsProvider(IOptions namesiloOption, IOptions ddnsOption) + { + _ddnsOption = ddnsOption.Value; + _namesiloOption = namesiloOption.Value; + } + + + public async Task?> GetRecordListAsync() + { + var client = new HttpClient(); + var response = + await client.GetAsync($"https://www.namesilo.com/api/dnsListRecords?version=1&type=xml&key={_namesiloOption.ApiKey}&domain={_ddnsOption.Domain}"); + var content = response.Content.ReadAsStringAsync().Result; + + var reply = new XmlDocument(); + reply.LoadXml(content); + var status = reply.SelectSingleNode("/namesilo/reply/code/text()"); + if (status == null) + { + return null; + } + + if (status.Value != "300") + { + throw new Exception($"Failed to retrieve value. Check API key.{status}"); + } + + var records = reply.SelectNodes($"/namesilo/reply/resource_record/host"); + if (records == null) + { + return new List(); + } + + return (from record in records.Cast() + let subDomain = record.ParentNode.SelectSingleNode("host/text()").Value.Replace(_ddnsOption.Domain, "") + where _ddnsOption.SubDomainArray.Contains(subDomain) + select new DnsRecord + { + Id = record.ParentNode.SelectSingleNode("record_id/text()").Value, + Ip = record.ParentNode.SelectSingleNode("value/text()").Value, + Host = record.ParentNode.SelectSingleNode("host/text()").Value, + Domain = _ddnsOption.Domain, + TTL = record.ParentNode.SelectSingleNode("ttl/text()").Value, + SubDomain = subDomain, + }).ToList(); + } + + public async Task> ModifyRecordListAsync(string newIp, IEnumerable records) + { + foreach (var dnsRecord in records) + { + using var client = new HttpClient(); + { + var host = dnsRecord.Host[..(dnsRecord.Host.Length - dnsRecord.Domain.Length - 1)]; + var request = + $"https://www.namesilo.com/api/dnsUpdateRecord?version=1&type=xml&key={_namesiloOption.ApiKey}&domain={dnsRecord.Domain}&rrid={dnsRecord.Id}&rrhost={host}&rrvalue={newIp}&rrttl={dnsRecord.TTL}"; + //Console.WriteLine(request); + var response = await client.GetAsync(request); + var content = await response.Content.ReadAsStringAsync(); + + var reply = new XmlDocument(); + reply.LoadXml(content); + var status = reply.SelectSingleNode("/namesilo/reply/code/text()"); + if (status == null) + { + await Console.Error.WriteLineAsync($"Failed to update record: '{dnsRecord.Id}' with Ip: '{newIp}'."); + continue; //return false; + } + + if (status.Value == "300") continue; + } + + await Console.Error.WriteLineAsync($"Failed to update record: '{dnsRecord.Id}' with Ip: '{newIp}'."); + continue; //return false; + } + + return records; + } + } +} \ No newline at end of file diff --git a/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs new file mode 100644 index 0000000..1f116e1 --- /dev/null +++ b/Hua.DDNS/DDNSProviders/Namesilo/NamesiloOption.cs @@ -0,0 +1,16 @@ +namespace Hua.DDNS.DDNSProviders.Namesilo +{ + + /// + /// Namesilo Option + /// + public class NamesiloOption + { + + /// + /// API key + /// + public string ApiKey { get; set; } + + } +} \ No newline at end of file diff --git a/Hua.DDNS/Hua.DDNS.csproj b/Hua.DDNS/Hua.DDNS.csproj index b67525a..efbf6b7 100644 --- a/Hua.DDNS/Hua.DDNS.csproj +++ b/Hua.DDNS/Hua.DDNS.csproj @@ -1,41 +1,45 @@ - - net6.0 - enable - enable - dotnet-Hua.DDNS-C4DADDFF-6D5B-4BD5-AB11-02F07B517CAC - Windows - + + net6.0 + enable + enable + dotnet-Hua.DDNS-C4DADDFF-6D5B-4BD5-AB11-02F07B517CAC + Windows + true + true + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - PreserveNewest - - - PreserveNewest - - + + + PreserveNewest + + + PreserveNewest + + diff --git a/Hua.DDNS/Jobs/AppJob.cs b/Hua.DDNS/Jobs/AppJob.cs index 01cc666..f805200 100644 --- a/Hua.DDNS/Jobs/AppJob.cs +++ b/Hua.DDNS/Jobs/AppJob.cs @@ -1,136 +1,138 @@ -using Hua.DDNS.Common; -using Hua.DDNS.Common.Config; -using Hua.DDNS.Common.Config.Options; -using Hua.DDNS.Common.Http; -using Hua.DDNS.Start; -using Quartz; -using System.Net; -using AlibabaCloud.OpenApiClient.Models; -using AlibabaCloud.SDK.Alidns20150109.Models; -using Hua.DotNet.Code.Extension; -using TencentCloud.Common; -using TencentCloud.Common.Profile; -using TencentCloud.Dnspod.V20210323; -using TencentCloud.Dnspod.V20210323.Models; +//using Hua.DDNS.Common; +//using Hua.DDNS.Common.Config; +//using Hua.DDNS.Common.Config.Options; +//using Hua.DDNS.Common.Http; +//using Hua.DDNS.Start; +//using Quartz; +//using System.Net; +//using AlibabaCloud.OpenApiClient.Models; +//using AlibabaCloud.SDK.Alidns20150109.Models; +//using Hua.DotNet.Code.Extension; +//using TencentCloud.Common; +//using TencentCloud.Common.Profile; +//using TencentCloud.Dnspod.V20210323; +//using TencentCloud.Dnspod.V20210323.Models; -using Tea; -using Tea.Utils; +//using Tea; +//using Tea.Utils; +//using Hua.DDNS.DDNSProviders; -namespace Hua.DDNS.Jobs -{ - [DisallowConcurrentExecution] - public class AppJob : IJob, IDisposable - { - private readonly ILogger _logger; - private readonly SettingProvider _settingProvider; - private readonly DomainOption _domainOption; - private readonly IHttpHelper _httpHelper; - public string CurrentIpv4Address; +//namespace Hua.DDNS.Jobs +//{ +// [DisallowConcurrentExecution] +// public class AppJob : IJob, IDisposable +// { +// private readonly ILogger _logger; +// private readonly SettingProvider _settingProvider; +// private readonly DdnsOption _ddnsOption; +// private readonly IHttpHelper _httpHelper; +// public string CurrentIpv4Address; - public AppJob(ILogger logger,SettingProvider settingProvider, IHttpHelper httpHelper) - { - _logger = logger; - _settingProvider = settingProvider; - _httpHelper = httpHelper; - _domainOption = _settingProvider.App.Domain; +// public AppJob(ILogger logger,SettingProvider settingProvider, IHttpHelper httpHelper) +// { +// _logger = logger; +// _settingProvider = settingProvider; +// _httpHelper = httpHelper; +// _ddnsOption = _settingProvider.App.DDNS; - } - public async Task Execute(IJobExecutionContext context) - { - _logger.LogInformation("开始任务执行"); - try - { - var oldIp = (await Dns.GetHostEntryAsync($"{_domainOption.subDomainArray.First()}.{_domainOption.domain}")).AddressList.First(); - CurrentIpv4Address = await _httpHelper.GetCurrentPublicIpv4(); +// } +// public async Task Execute(IJobExecutionContext context) +// { +// _logger.LogInformation("开始任务执行"); +// try +// { +// var oldIp = (await Dns.GetHostEntryAsync($"{_ddnsOption.SubDomainArray.First()}.{_ddnsOption.Domain}")).AddressList.First(); +// CurrentIpv4Address = await _httpHelper.GetCurrentPublicIpv4(); - if (CurrentIpv4Address!=oldIp.ToString()) - { - await UpdateDns(); - } - } - catch (Exception e) - { - _logger.LogError(e,e.Message); - } - finally - { - _logger.LogInformation("任务执行完成"); - } - } +// if (CurrentIpv4Address!=oldIp.ToString()) +// { +// await UpdateDns(); +// } +// } +// catch (Exception e) +// { +// _logger.LogError(e,e.Message); +// } +// finally +// { +// _logger.LogInformation("任务执行完成"); +// } +// } - private async Task UpdateDns() - { - //更新Ip记录 - switch (_domainOption.Platform) - { - case PlatformEnum.Tencent: - var _dnspodClient = new DnspodClient( - // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密 - // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取 - new Credential { SecretId = _domainOption.Id, SecretKey = _domainOption.Key }, - "", - // 实例化一个client选项,可选的,没有特殊需求可以跳过 - new ClientProfile() - { - // 实例化一个http选项,可选的,没有特殊需求可以跳过 - HttpProfile = new HttpProfile { Endpoint = ("dnspod.tencentcloudapi.com") } - }); +// private async Task UpdateDns() +// { +// //更新Ip记录 +// switch (_ddnsOption.Platform) +// { +// case PlatformEnum.Namesilo: +// case PlatformEnum.Tencent: +// var _dnspodClient = new DnspodClient( +// // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密 +// // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取 +// new Credential { SecretId = _ddnsOption.Id, SecretKey = _ddnsOption.Key }, +// "", +// // 实例化一个client选项,可选的,没有特殊需求可以跳过 +// new ClientProfile() +// { +// // 实例化一个http选项,可选的,没有特殊需求可以跳过 +// HttpProfile = new HttpProfile { Endpoint = ("dnspod.tencentcloudapi.com") } +// }); - //获取域名解析记录 - var describeRecordList = await _dnspodClient.DescribeRecordList(new DescribeRecordListRequest() { Domain = _domainOption.domain }); - var record = describeRecordList.RecordList.FirstOrDefault(m => - m.Value == CurrentIpv4Address && _domainOption.subDomainArray.Any(n => m.Name == n)); - if (record!=null && record.Value == CurrentIpv4Address) return;//如果记录已经变更,不调用更新接口 +// //获取域名解析记录 +// var describeRecordList = await _dnspodClient.DescribeRecordList(new DescribeRecordListRequest() { Domain = _ddnsOption.Domain }); +// var record = describeRecordList.RecordList.FirstOrDefault(m => +// m.Value == CurrentIpv4Address && _ddnsOption.SubDomainArray.Any(n => m.Name == n)); +// if (record!=null && record.Value == CurrentIpv4Address) return;//如果记录已经变更,不调用更新接口 - await _dnspodClient.ModifyRecordBatch(new ModifyRecordBatchRequest() - { - RecordIdList = - describeRecordList.RecordList - .Where(m => m.Value != CurrentIpv4Address && _domainOption.subDomainArray.Any(n => m.Name == n)) - .Select(m => m.RecordId) - .ToArray(), - Change = "value", - ChangeTo = CurrentIpv4Address - }); +// await _dnspodClient.ModifyRecordBatch(new ModifyRecordBatchRequest() +// { +// RecordIdList = +// describeRecordList.RecordList +// .Where(m => m.Value != CurrentIpv4Address && _ddnsOption.SubDomainArray.Any(n => m.Name == n)) +// .Select(m => m.RecordId) +// .ToArray(), +// Change = "value", +// ChangeTo = CurrentIpv4Address +// }); - break; - case PlatformEnum.Ali: - var aliClient = new AlibabaCloud.SDK.Alidns20150109.Client(new Config() - { - // 您的 AccessKey ID - AccessKeyId = _domainOption.Id, - // 您的 AccessKey Secret - AccessKeySecret = _domainOption.Key, - Endpoint = "alidns.cn-beijing.aliyuncs.com", - }); +// break; +// case PlatformEnum.Ali: +// var aliClient = new AlibabaCloud.SDK.Alidns20150109.Client(new Config() +// { +// // 您的 AccessKey ID +// AccessKeyId = _ddnsOption.Id, +// // 您的 AccessKey Secret +// AccessKeySecret = _ddnsOption.Key, +// Endpoint = "alidns.cn-beijing.aliyuncs.com", +// }); - var aliDescribeRecordList = (await aliClient.DescribeDomainRecordsAsync(new DescribeDomainRecordsRequest() - { - DomainName = _domainOption.domain - })).Body.DomainRecords.Record; +// var aliDescribeRecordList = (await aliClient.DescribeDomainRecordsAsync(new DescribeDomainRecordsRequest() +// { +// DomainName = _ddnsOption.Domain +// })).Body.DomainRecords.Record; - foreach (var aliDomainRecord in aliDescribeRecordList - .Where(m => m.Value != CurrentIpv4Address && _domainOption.subDomainArray.Any(n => m.RR == n))) - { - await aliClient.UpdateDomainRecordAsync(new UpdateDomainRecordRequest() - { - RecordId = aliDomainRecord.RecordId, - RR = aliDomainRecord.RR, - Type = aliDomainRecord.Type, - Value = CurrentIpv4Address, - }); - _logger.LogInformation($"Update SubDomain[{aliDomainRecord.RR}.{aliDomainRecord.DomainName}] Value {aliDomainRecord.Value} To {CurrentIpv4Address}"); - } - break; - } - } +// foreach (var aliDomainRecord in aliDescribeRecordList +// .Where(m => m.Value != CurrentIpv4Address && _ddnsOption.SubDomainArray.Any(n => m.RR == n))) +// { +// await aliClient.UpdateDomainRecordAsync(new UpdateDomainRecordRequest() +// { +// RecordId = aliDomainRecord.RecordId, +// RR = aliDomainRecord.RR, +// Type = aliDomainRecord.Type, +// Value = CurrentIpv4Address, +// }); +// _logger.LogInformation($"Update SubDomain[{aliDomainRecord.RR}.{aliDomainRecord.DomainName}] Value {aliDomainRecord.Value} To {CurrentIpv4Address}"); +// } +// break; +// } +// } - public void Dispose() - { - _logger.LogInformation("AppJob已销毁"); - } - } -} \ No newline at end of file +// public void Dispose() +// { +// _logger.LogInformation("AppJob已销毁"); +// } +// } +//} \ No newline at end of file diff --git a/Hua.DDNS/Jobs/NewJob.cs b/Hua.DDNS/Jobs/NewJob.cs new file mode 100644 index 0000000..974ead1 --- /dev/null +++ b/Hua.DDNS/Jobs/NewJob.cs @@ -0,0 +1,88 @@ +using Hua.DDNS.Common; +using Hua.DDNS.Common.Config; +using Hua.DDNS.Common.Config.Options; +using Hua.DDNS.Common.Http; +using Hua.DDNS.Start; +using Quartz; +using System.Net; +using AlibabaCloud.OpenApiClient.Models; +using AlibabaCloud.SDK.Alidns20150109.Models; +using Hua.DDNS.DDNSProviders; +using Hua.DDNS.DDNSProviders.Ali; +using Hua.DDNS.DDNSProviders.Dnspod; +using Hua.DDNS.DDNSProviders.Namesilo; +using Hua.DDNS.Models; +using Hua.DotNet.Code.Extension; +using Microsoft.Extensions.Options; +using TencentCloud.Common; +using TencentCloud.Common.Profile; +using TencentCloud.Dnspod.V20210323; +using TencentCloud.Dnspod.V20210323.Models; + +using Tea; +using Tea.Utils; + +namespace Hua.DDNS.Jobs +{ + [DisallowConcurrentExecution] + public class NewJob : IJob, IDisposable + { + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; + private readonly DdnsOption _ddnsOption; + private readonly IHttpHelper _httpHelper; + public string newIp; + + + + public NewJob(ILogger logger,SettingProvider settingProvider, IHttpHelper httpHelper,IOptions ddnsOption) + { + _logger = logger; + _httpHelper = httpHelper; + _ddnsOption = ddnsOption.Value; + } + public async Task Execute(IJobExecutionContext context) + { + + + try + { + //1. 获取当前机器ip + var domain = $"{_ddnsOption.SubDomainArray.First()}.{_ddnsOption.Domain}"; + var oldIp = (await Dns.GetHostEntryAsync(domain)).AddressList.First(); + newIp = await _httpHelper.GetCurrentPublicIpv4(); + //1.1 如果当前dns记录与实际dns记录一致,跳出本次执行 + if (newIp == oldIp.ToString()) return; + + //2.获取DNS记录 + IDdnsProvider? ddnsProvider = _ddnsOption.Platform switch + { + PlatformEnum.Namesilo => _serviceProvider.GetRequiredService(), + PlatformEnum.Tencent => _serviceProvider.GetRequiredService(), + PlatformEnum.Ali => _serviceProvider.GetRequiredService(), + _ => null + }; + + var dnsRecordList = await ddnsProvider!.GetRecordListAsync(); + var record = dnsRecordList.FirstOrDefault(m => m.Ip == newIp && _ddnsOption.SubDomainArray.Any(n => m.SubDomain == n)); + if (record != null && record.Ip == newIp) return;//如果记录已经变更,不调用更新接口 + + //3.比较并更新 + await ddnsProvider.ModifyRecordListAsync(newIp, dnsRecordList.Where(m => m.Ip != newIp && _ddnsOption.SubDomainArray.Any(n => m.SubDomain == n))); + } + catch (Exception e) + { + _logger.LogError(e,e.Message); + } + finally + { + _logger.LogInformation("任务执行完成"); + } + } + + public void Dispose() + { + _logger.LogInformation("AppJob已销毁"); + } + } +} \ No newline at end of file diff --git a/Hua.DDNS/Models/DnsRecord.cs b/Hua.DDNS/Models/DnsRecord.cs new file mode 100644 index 0000000..27691d1 --- /dev/null +++ b/Hua.DDNS/Models/DnsRecord.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Hua.DDNS.Models; + +public class DnsRecord +{ + public string Id { get; set; } + public string Ip { get; set; } + public string Host { get; set; } + public string SubDomain { get; set; } + public string Domain { get; set; } + public string TTL { get; set; } + public string RecordType { get; set; } +} \ No newline at end of file diff --git a/Hua.DDNS/Models/MappingProfile.cs b/Hua.DDNS/Models/MappingProfile.cs new file mode 100644 index 0000000..588ac8c --- /dev/null +++ b/Hua.DDNS/Models/MappingProfile.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AlibabaCloud.SDK.Alidns20150109.Models; +using AutoMapper; +using TencentCloud.Dnspod.V20210323.Models; + + +namespace Hua.DDNS.Models +{ + public class MappingProfile : Profile + { + public MappingProfile() + { + CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.RecordId)) + .ForMember(dest => dest.RecordType, opt => opt.MapFrom(src => src.Type)) + .ForMember(dest => dest.Ip, opt => opt.MapFrom(src => src.Value)) + .ForMember(dest => dest.SubDomain, opt => opt.MapFrom(src => src.RR)) + ; + CreateMap () + .ForMember(dest => dest.RecordId, opt => opt.MapFrom(src => src.Id)) + .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src.RecordType)) + .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.Ip)) + .ForMember(dest => dest.RR, opt => opt.MapFrom(src => src.SubDomain)) + ; + + + CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.RecordId)) + .ForMember(dest => dest.RecordType, opt => opt.MapFrom(src => src.Type)) + .ForMember(dest => dest.Ip, opt => opt.MapFrom(src => src.Value)) + .ForMember(dest => dest.SubDomain, opt => opt.MapFrom(src => src.Name)) + ; + } + } +} diff --git a/Hua.DDNS/Start/Cache.cs b/Hua.DDNS/Start/Cache.cs deleted file mode 100644 index d06fe11..0000000 --- a/Hua.DDNS/Start/Cache.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Hua.DDNS.Start -{ - public class Cache - { - /// - /// Token - /// - public static string? Token { get; set; } = null; - - } -} diff --git a/Hua.DDNS/Start/Program.cs b/Hua.DDNS/Start/Program.cs index 1527f42..989c718 100644 --- a/Hua.DDNS/Start/Program.cs +++ b/Hua.DDNS/Start/Program.cs @@ -1,8 +1,14 @@ using System.Configuration; +using System.Reflection; using Hua.DDNS.Common; using Hua.DDNS.Common.Config; using Hua.DDNS.Common.Http; +using Hua.DDNS.DDNSProviders; +using Hua.DDNS.DDNSProviders.Ali; +using Hua.DDNS.DDNSProviders.Dnspod; +using Hua.DDNS.DDNSProviders.Namesilo; using Hua.DDNS.Jobs; +using Microsoft.Extensions.DependencyInjection; using Quartz; using Serilog; using Serilog.Extensions.Logging; @@ -34,10 +40,16 @@ namespace Hua.DDNS.Start config.Sources.Clear(); config .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, + reloadOnChange: true); }) .ConfigureServices((hostContext, services) => { + services.AddAutoMapper(Assembly.GetExecutingAssembly()); + services.Configure(hostContext.Configuration.GetSection("DDNS")); + services.Configure(hostContext.Configuration.GetSection("Namesilo")); + services.Configure(hostContext.Configuration.GetSection("Dnspod")); + services.Configure(hostContext.Configuration.GetSection("Ali")); ConfigDi(hostContext, services); ConfigQuartz(hostContext, services); }); @@ -45,10 +57,12 @@ namespace Hua.DDNS.Start public static IServiceProvider ConfigDi(HostBuilderContext hostContext, IServiceCollection services) { services.AddSingleton(); - //services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); return services.BuildServiceProvider(); } @@ -75,18 +89,18 @@ namespace Hua.DDNS.Start q.UseDefaultThreadPool(tp => { tp.MaxConcurrency = 10; }); //configure jobs with code - var appJobKey = new JobKey("AppJob", "AppJobGroup"); - q.AddJob(j => j + var appJobKey = new JobKey("NewJob", "NewJobGroup"); + q.AddJob(j => j .StoreDurably() .WithIdentity(appJobKey) - .WithDescription("AppJob") + .WithDescription("NewJob") ); q.AddTrigger(t => t - .WithIdentity("AppJob Trigger") + .WithIdentity("NewJob Trigger") .ForJob(appJobKey) .WithCronSchedule(hostContext.Configuration.GetSection("App:AppJob:Corn").Value) - .WithDescription("AppJob trigger") + .WithDescription("NewJob trigger") .StartNow() ); }); diff --git a/Hua.DDNS/appsettings.Development.json b/Hua.DDNS/appsettings.Development.json index 0d47edc..c02604b 100644 --- a/Hua.DDNS/appsettings.Development.json +++ b/Hua.DDNS/appsettings.Development.json @@ -11,22 +11,30 @@ "App": { "AppJob": { "Corn": "* * * * * ?" //https://cron.qqe2.com/ - }, - - "Domain": { - "Platform": "Ali", - // Access Id/Secret Id - "Id": "Id", - // Access Key/Secret Key - "Key": "Key", - // 主域名 - "domain": "demo.cn", - // 子域名前缀 - "subDomainArray": [ "bjb", "git"], - // 记录类型 - "type": "A", - //间隔时间 秒 - "time": "30" } + }, + "DDNS": { + "Platform": 3, //1 Ali 2 Tencent 3 Namesilo + // 主域名 + "Domain": "we965.com", + // 子域名前缀 + "SubDomainArray": [ "git", "webutil", "dev" ], + // 记录类型 + "type": "A", + //间隔时间 秒 + "time": "30" + }, + "Namesilo": { + "ApiKey": "1111" + }, + "Dnspod": { + "Id": "1111", + "Key": "1111", + "Endpoint": "1111" + }, + "Ali": { + "Id": "1111", + "Key": "1111", + "Endpoint": "1111" } } \ No newline at end of file diff --git a/Hua.DDNS/appsettings.json b/Hua.DDNS/appsettings.json index de273e0..c02604b 100644 --- a/Hua.DDNS/appsettings.json +++ b/Hua.DDNS/appsettings.json @@ -11,22 +11,30 @@ "App": { "AppJob": { "Corn": "* * * * * ?" //https://cron.qqe2.com/ - }, - - "Domain": { - "Platform": 1, //1 Ali 2 Tencent - // Access Id/Secret Id - "Id": "Id", - // Access Key/Secret Key - "Key": "Key", - // 主域名 - "domain": "demo.cn", - // 子域名前缀 - "subDomainArray": [ "bjb", "git" ], - // 记录类型 - "type": "A", - //间隔时间 秒 - "time": "30" } + }, + "DDNS": { + "Platform": 3, //1 Ali 2 Tencent 3 Namesilo + // 主域名 + "Domain": "we965.com", + // 子域名前缀 + "SubDomainArray": [ "git", "webutil", "dev" ], + // 记录类型 + "type": "A", + //间隔时间 秒 + "time": "30" + }, + "Namesilo": { + "ApiKey": "1111" + }, + "Dnspod": { + "Id": "1111", + "Key": "1111", + "Endpoint": "1111" + }, + "Ali": { + "Id": "1111", + "Key": "1111", + "Endpoint": "1111" } } \ No newline at end of file