Files
Hua.DDNS/Hua.DDNS/DDNSProviders/Namesilo/NamesiloDDNSProvider.cs
T
ShaoHua 773c230e3d feat: 支持 SSL 证书自动申请并重构 DDNS 任务逻辑
- 实现阿里/腾讯云 SSL 证书的全生命周期自动化管理。
- 重构 NewJob 为 DdnsJob,优化子域名匹配与记录自动创建逻辑。
- 更新项目配置结构,移除冗余的 AppJob 相关代码。
2026-04-08 21:45:36 +08:00

152 lines
6.3 KiB
C#

using System.Xml;
using AutoMapper;
using Hua.DDNS.Models;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace Hua.DDNS.DDNSProviders.Namesilo
{
/// <summary>
/// Namesilo DDNS 解析提供者
/// </summary>
public class NamesiloDdnsProvider : IDdnsProvider
{
public readonly NamesiloOption _namesiloOption;
public readonly DdnsOption _ddnsOption;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="namesiloOption">Namesilo 配置</param>
/// <param name="ddnsOption">DDNS 配置</param>
public NamesiloDdnsProvider(IOptions<NamesiloOption> namesiloOption, IOptions<DdnsOption> ddnsOption)
{
_ddnsOption = ddnsOption.Value;
_namesiloOption = namesiloOption.Value;
}
/// <summary>
/// 异步获取 Namesilo 上的域名解析记录列表
/// </summary>
/// <returns>解析记录列表</returns>
public async Task<IEnumerable<DnsRecord>?> 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<DnsRecord>();
}
return (from record in records.Cast<XmlNode>()
let host = record.ParentNode.SelectSingleNode("host/text()").Value
let subDomain = host.Replace($".{_ddnsOption.Domain}", "").Replace(_ddnsOption.Domain, "")
where _ddnsOption.SubDomainArray.Contains(subDomain) || (subDomain == "" && _ddnsOption.SubDomainArray.Contains("@"))
select new DnsRecord
{
Id = record.ParentNode.SelectSingleNode("record_id/text()").Value,
Ip = record.ParentNode.SelectSingleNode("value/text()").Value,
Host = host,
Domain = _ddnsOption.Domain,
TTL = record.ParentNode.SelectSingleNode("ttl/text()").Value,
SubDomain = subDomain,
}).ToList();
}
/// <summary>
/// 异步在 Namesilo 上创建新的域名解析记录
/// </summary>
/// <param name="dnsRecord">解析记录信息</param>
/// <returns>创建后的解析记录信息</returns>
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord dnsRecord)
{
var host = dnsRecord.SubDomain == "@" ? "" : dnsRecord.SubDomain;
//https://www.namesilo.com/api/dnsAddRecord?version=1&type=xml&key=12345&domain=namesilo.com&rrtype=A&rrhost=test&rrvalue=55.55.55.55&rrttl=7207
var url = $"https://www.namesilo.com/api/dnsAddRecord?version=1&type=xml&key={_namesiloOption.ApiKey}&domain={dnsRecord.Domain}&rrtype={dnsRecord.RecordType}&rrhost={host}&rrvalue={dnsRecord.Ip}&rrttl={dnsRecord.TTL}";
using var client = new HttpClient();
{
var response = await client.GetAsync(url);
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 create record: '{JsonConvert.SerializeObject(dnsRecord)}'");
return null;
}
if (status.Value != "300")
{
await Console.Error.WriteLineAsync($"Failed to create record: '{JsonConvert.SerializeObject(dnsRecord)}', Status: {status.Value}");
return null;
}
}
return dnsRecord;
}
/// <summary>
/// 异步批量修改 Namesilo 上的域名解析记录
/// </summary>
/// <param name="newIp">新的 IP 地址</param>
/// <param name="records">需要修改的解析记录列表</param>
/// <returns>修改后的解析记录列表</returns>
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
{
foreach (var dnsRecord in records)
{
using var client = new HttpClient();
{
var host = dnsRecord.SubDomain == "@" ? "" : dnsRecord.SubDomain;
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 || status.Value != "300")
{
await Console.Error.WriteLineAsync($"Failed to update record: '{dnsRecord.Id}' with Ip: '{newIp}'. Status: {status?.Value}");
continue;
}
}
}
return records;
}
/// <summary>
/// 异步清理无效证书
/// </summary>
/// <returns></returns>
public Task CleanInvalidCertificatesAsync()
{
return Task.CompletedTask;
}
}
}