DDNS icon indicating copy to clipboard operation
DDNS copied to clipboard

[dns] 希望能支持name.com

Open Seifon opened this issue 1 month ago • 2 comments

DNS 服务商信息

  • 官网 (Website): name.com
  • 中文名称 (Chinese Name): name
  • 英文名称 (English Name): name
  • 标准DNS服务商 (Standard DNS Provider): Yes

DNS 服务商文档链接

请提供以下相关文档的链接(如有):

  • [ ] API 认证与签名 (Authorization & Signature):
  • [ ] 查询/列出域名 (Query/List Domains):
  • [ ] 查询/列出解析记录 (Query/List DNS Records):
  • [ ] 创建解析记录 (Create DNS Record):
  • [ ] 修改解析记录 (Update DNS Record):
  • [ ] 其它配置或使用文档 (Other Configuration/Usage Docs, 可选):
  • [ ] 官方或第三方Python SDK (Official or Third-party Python SDK, 可选):

其他补充信息(可选)

请补充任何有助于集成该 DNS 服务商的信息,例如常见问题、注意事项、特殊限制等。

Seifon avatar Dec 03 '25 16:12 Seifon

感谢反馈,已确认这是一个“新增DNS服务商”需求。我们可以为 Name.com 实现一个标准的 BaseProvider 适配器,支持查询/创建/更新 A 和 AAAA 等记录。

下面是可行性评估、实现方案和需要您补充的资料。


结论

  • 可实现:基于现有架构(BaseProvider + 内置 HTTP 工具),Name.com 的 REST API(推测为 v4)通常使用 Basic Auth,记录接口完整(列出/创建/更新)。实现难度中等。
  • 预计 Provider 名称:建议使用 namecom,并兼容别名 namename_com

我们需要您提供的官方文档链接(Issue 模板的勾选项)

为确保实现细节准确,请补全以下官方文档链接:

  • API 认证与签名(Authorization & Signature)
  • 查询/列出域名(List Domains)
  • 查询/列出解析记录(List DNS Records)
  • 创建解析记录(Create DNS Record)
  • 修改解析记录(Update DNS Record)
  • 其它配置或使用文档(可选)
  • 官方或第三方 Python SDK(可选)

并附上 1~2 个实际响应样例(JSON),尤其是:

  • 列出记录返回对象的字段名(例如 hostnameanswervalue、是否有 id
  • 创建和更新请求体的字段(是否用 host/name + type + answer + ttl
  • 认证方式(是否为 Basic Auth:用户名 + API Token;或专用 Header)

说明:我们已有 Namesilo/No-IP/Cloudflare 等实现示例。Name.com 若为 Basic Auth,可复用 No-IP 的“在 endpoint 中嵌入认证信息”的做法,或者使用 Header 形式。请以官方文档为准。


实现方案(拟定)

参考现有 Provider 结构:

  • Base 类:ddns/provider/_base.py
  • HTTP 工具:ddns/util/http.py(支持 Basic Auth,当 URL 中包含 https://user:pass@host 时自动注入认证)
  • 参考:Cloudflare(JSON + Bearer)、Namesilo(GET + query token)、No-IP(Basic Auth)

新增文件:ddns/provider/namecom.py

拟采用 BaseProvider,支持完整 CRUD:

# coding=utf-8
from ._base import BaseProvider, TYPE_JSON, quote, join_domain

class NameComProvider(BaseProvider):
    endpoint = "https://api.name.com"
    content_type = TYPE_JSON

    def _validate(self):
        # Name.com 通常需要用户名 + API token(Basic Auth)
        if not self.id:
            raise ValueError("Name.com requires 'id' (username)")
        if not self.token:
            raise ValueError("Name.com requires 'token' (API token)")
        # 将认证信息嵌入 endpoint,复用内置 BasicAuth 机制
        protocol, domain = self.endpoint.split("://", 1)
        self.endpoint = "{0}://{1}:{2}@{3}".format(
            protocol, quote(self.id, safe=""), quote(self.token, safe=""), domain
        )

    def _request(self, method, path, **params):
        # 过滤 None
        params = {k: v for k, v in params.items() if v is not None}
        # Name.com API 通常是 JSON body + JSON response
        return self._http(method, path, body=params)

    def _query_zone_id(self, domain):
        # 方案A:查询单域名信息(若文档提供 /v4/domains/{domain})
        # 方案B:列出域名并匹配(若仅提供 /v4/domains 列表)
        # 若返回200且域名存在,则以主域名作为 zone_id
        try:
            res = self._http("GET", "/v4/domains/{}".format(domain))
            if isinstance(res, dict):
                return domain
        except Exception:
            pass
        return None

    def _query_record(self, zone_id, subdomain, main_domain, record_type, line, extra):
        # 列出记录并匹配
        data = self._http("GET", "/v4/domains/{}/records".format(main_domain))
        if isinstance(data, dict):
            records = data.get("records") or data.get("resource_record") or data.get("data") or []
            name = join_domain(subdomain, main_domain)
            # Name.com 可能使用 host/name + answer/value 字段,兼容性匹配
            for r in records:
                host = r.get("host") or r.get("name") or r.get("hostname")
                if host in (subdomain, name) and r.get("type") == record_type:
                    return r
        return None

    def _create_record(self, zone_id, subdomain, main_domain, value, record_type, ttl, line, extra):
        payload = {
            # 字段名以官方文档为准,这里兼容常见命名
            "host": subdomain if subdomain != "@" else "@",
            "type": record_type,
            "answer": value,
            "ttl": ttl
        }
        res = self._http("POST", "/v4/domains/{}/records".format(main_domain), body=payload)
        return bool(res)

    def _update_record(self, zone_id, old_record, value, record_type, ttl, line, extra):
        record_id = old_record.get("id") or old_record.get("record_id")
        if not record_id:
            self.logger.error("record id not found: %s", old_record)
            return False
        payload = {
            "host": old_record.get("host") or old_record.get("name"),
            "type": record_type,
            "answer": value,
            "ttl": ttl or old_record.get("ttl")
        }
        res = self._http("PUT", "/v4/domains/{}/records/{}".format(zone_id, record_id), body=payload)
        return bool(res)

以上代码是骨架示例,最终字段名需以官方文档为准(常见为 host/nameanswer)。我们会根据您提供的文档和样例调整。

注册 Provider 映射

文件:ddns/provider/__init__.py

from .namecom import NameComProvider
# ...
    mapping = {
        # ...
        "namecom": NameComProvider,
        "name": NameComProvider,      # 兼容
        "name_com": NameComProvider,  # 兼容
    }

更新 JSON Schema(v4.1)枚举

文件:schema/v4.1.jsonenum 处增加:

  • 在顶层 dns 的 enum 中加入:"namecom"
  • providers[].provider 的 enum 中加入:"namecom"

文档

新增:doc/providers/namecom.mddoc/providers/namecom.en.md(用法、字段、示例)。

测试

新增:tests/test_provider_namecom.py

  • 初始化校验(需要 id+token)
  • 列出记录并匹配
  • 创建与更新(用 MagicMock 模拟 _http 返回)
  • 错误处理(认证失败、无记录、参数错误)

配置示例

  • 命令行:
ddns --dns namecom --id your_username --token your_api_token --ipv4 host.example.com
  • 多 Provider JSON:
{
  "$schema": "https://ddns.newfuture.cc/schema/v4.1.json",
  "providers": [
    {
      "provider": "namecom",
      "id": "your_username",
      "token": "your_api_token",
      "ipv4": ["ddns.example.com"],
      "ttl": 300
    }
  ]
}

说明:若 Name.com 不支持自动创建记录(以官方文档为准),则需在控制台预先创建记录;否则 BaseProvider 会自动创建。


约束与注意事项

  • 项目为 Python stdlib-only(不依赖第三方库),HTTP 通过 urllib 封装实现,已支持:代理、SSL、重试、BasicAuth。
  • Basic Auth 两种方式:
    • 在 URL 中嵌入(https://user:[email protected]),我们的 http.request 会自动处理。
    • 或直接设置 Authorization: Basic ... 头。但当前 _http 没有 auth 参数,采用 URL 方式更简单。
  • 主域名作为 zone_id:若 Name.com API 没有“zone id”,可像 Namesilo 一样使用主域名字符串作为 ID。
  • 字段名差异:请以官方文档为准,我们会适配 host/nameanswer/value、以及 id/record_id 等别名。

下一步

  1. 请在此 Issue 补充上述官方文档链接与若干响应样例。
  2. 我们基于文档完善实现(字段与路径),提交 PR 与文档。
  3. 您可在本地通过 ddns --debug 验证并反馈(日志会输出请求/响应,敏感信息已打码)。

参考文档:

感谢支持,我们随时跟进!

github-actions[bot] avatar Dec 04 '25 01:12 github-actions[bot]

@Seifon 确认一下API对吗?或者补充一下链接

NewFuture avatar Dec 04 '25 01:12 NewFuture