ddns 4.1.0b1__py2.py3-none-any.whl → 4.1.0b2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ddns/__init__.py +2 -11
- ddns/__main__.py +67 -142
- ddns/{util/cache.py → cache.py} +42 -11
- ddns/{util/ip.py → ip.py} +11 -9
- ddns/provider/__init__.py +24 -4
- ddns/provider/_base.py +78 -198
- ddns/provider/_signature.py +113 -0
- ddns/provider/alidns.py +31 -14
- ddns/provider/aliesa.py +129 -0
- ddns/provider/callback.py +9 -10
- ddns/provider/cloudflare.py +8 -8
- ddns/provider/dnscom.py +5 -5
- ddns/provider/dnspod.py +3 -4
- ddns/provider/dnspod_com.py +1 -1
- ddns/provider/edgeone.py +82 -0
- ddns/provider/he.py +4 -4
- ddns/provider/huaweidns.py +8 -8
- ddns/provider/namesilo.py +159 -0
- ddns/provider/noip.py +103 -0
- ddns/provider/tencentcloud.py +7 -7
- ddns/util/comment.py +88 -0
- ddns/util/http.py +85 -134
- {ddns-4.1.0b1.dist-info → ddns-4.1.0b2.dist-info}/METADATA +22 -13
- ddns-4.1.0b2.dist-info/RECORD +31 -0
- ddns/util/config.py +0 -314
- ddns-4.1.0b1.dist-info/RECORD +0 -26
- {ddns-4.1.0b1.dist-info → ddns-4.1.0b2.dist-info}/WHEEL +0 -0
- {ddns-4.1.0b1.dist-info → ddns-4.1.0b2.dist-info}/entry_points.txt +0 -0
- {ddns-4.1.0b1.dist-info → ddns-4.1.0b2.dist-info}/licenses/LICENSE +0 -0
- {ddns-4.1.0b1.dist-info → ddns-4.1.0b2.dist-info}/top_level.txt +0 -0
ddns/__init__.py
CHANGED
|
@@ -6,16 +6,7 @@ ddns Package
|
|
|
6
6
|
__description__ = "automatically update DNS records to my IP [域名自动指向本机IP]"
|
|
7
7
|
|
|
8
8
|
# 编译时,版本会被替换
|
|
9
|
-
__version__ = "4.1.
|
|
9
|
+
__version__ = "4.1.0b2"
|
|
10
10
|
|
|
11
11
|
# 时间也会被替换掉
|
|
12
|
-
build_date = "2025-07-
|
|
13
|
-
|
|
14
|
-
__doc__ = """
|
|
15
|
-
ddns [v{}@{}]
|
|
16
|
-
(i) homepage or docs [文档主页]: https://ddns.newfuture.cc/
|
|
17
|
-
(?) issues or bugs [问题和反馈]: https://github.com/NewFuture/DDNS/issues
|
|
18
|
-
Copyright (c) NewFuture (MIT License)
|
|
19
|
-
""".format(
|
|
20
|
-
__version__, build_date
|
|
21
|
-
)
|
|
12
|
+
build_date = "2025-07-15T02:27:02Z"
|
ddns/__main__.py
CHANGED
|
@@ -4,189 +4,114 @@ DDNS
|
|
|
4
4
|
@author: NewFuture, rufengsuixing
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from os import path, environ, name as os_name
|
|
8
7
|
from io import TextIOWrapper
|
|
9
8
|
from subprocess import check_output
|
|
10
|
-
from
|
|
11
|
-
from logging import basicConfig, getLogger, info, error, debug, warning, INFO
|
|
12
|
-
|
|
9
|
+
from logging import getLogger
|
|
13
10
|
import sys
|
|
14
11
|
|
|
15
|
-
from .__init__ import __version__, __description__,
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
|
|
21
|
-
environ["DDNS_VERSION"] = __version__
|
|
22
|
-
|
|
12
|
+
from .__init__ import __version__, __description__, build_date
|
|
13
|
+
from .config import load_config, Config # noqa: F401
|
|
14
|
+
from .provider import get_provider_class, SimpleProvider
|
|
15
|
+
from . import ip
|
|
16
|
+
from .cache import Cache
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
字符串 'false', 或者 False, 或者 'none';
|
|
28
|
-
0 不是 False
|
|
29
|
-
"""
|
|
30
|
-
if hasattr(value, "strip"): # 字符串
|
|
31
|
-
return value.strip().lower() in ["false", "none"]
|
|
32
|
-
return value is False
|
|
18
|
+
logger = getLogger()
|
|
19
|
+
# Set user agent for All Providers
|
|
20
|
+
SimpleProvider.user_agent = SimpleProvider.user_agent.format(version=__version__)
|
|
33
21
|
|
|
34
22
|
|
|
35
|
-
def get_ip(ip_type,
|
|
23
|
+
def get_ip(ip_type, rules):
|
|
36
24
|
"""
|
|
37
25
|
get IP address
|
|
38
26
|
"""
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
try:
|
|
43
|
-
debug("get_ip(%s, %s)", ip_type, index)
|
|
44
|
-
if is_false(index): # disabled
|
|
45
|
-
return False
|
|
46
|
-
elif isinstance(index, list): # 如果获取到的规则是列表,则依次判断列表中每一个规则,直到获取到IP
|
|
47
|
-
for i in index:
|
|
48
|
-
value = get_ip(ip_type, i)
|
|
49
|
-
if value:
|
|
50
|
-
break
|
|
51
|
-
elif str(index).isdigit(): # 数字 local eth
|
|
52
|
-
value = getattr(ip, "local_v" + ip_type)(index)
|
|
53
|
-
elif index.startswith("cmd:"): # cmd
|
|
54
|
-
value = str(check_output(index[4:]).strip().decode("utf-8"))
|
|
55
|
-
elif index.startswith("shell:"): # shell
|
|
56
|
-
value = str(check_output(index[6:], shell=True).strip().decode("utf-8"))
|
|
57
|
-
elif index.startswith("url:"): # 自定义 url
|
|
58
|
-
value = getattr(ip, "public_v" + ip_type)(index[4:])
|
|
59
|
-
elif index.startswith("regex:"): # 正则 regex
|
|
60
|
-
value = getattr(ip, "regex_v" + ip_type)(index[6:])
|
|
61
|
-
else:
|
|
62
|
-
value = getattr(ip, index + "_v" + ip_type)()
|
|
63
|
-
except Exception as e:
|
|
64
|
-
error("Failed to get %s address: %s", ip_type, e)
|
|
65
|
-
return value
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def change_dns_record(dns, proxy_list, **kw):
|
|
69
|
-
# type: (SimpleProvider, list, **(str)) -> bool
|
|
70
|
-
for proxy in proxy_list:
|
|
71
|
-
if not proxy or (proxy.upper() in ["DIRECT", "NONE"]):
|
|
72
|
-
dns.set_proxy(None)
|
|
73
|
-
else:
|
|
74
|
-
dns.set_proxy(proxy)
|
|
75
|
-
record_type, domain = kw["record_type"], kw["domain"]
|
|
27
|
+
if rules is False: # disabled
|
|
28
|
+
return False
|
|
29
|
+
for i in rules:
|
|
76
30
|
try:
|
|
77
|
-
|
|
31
|
+
logger.debug("get_ip:(%s, %s)", ip_type, i)
|
|
32
|
+
if str(i).isdigit(): # 数字 local eth
|
|
33
|
+
return getattr(ip, "local_v" + ip_type)(i)
|
|
34
|
+
elif i.startswith("cmd:"): # cmd
|
|
35
|
+
return str(check_output(i[4:]).strip().decode("utf-8"))
|
|
36
|
+
elif i.startswith("shell:"): # shell
|
|
37
|
+
return str(check_output(i[6:], shell=True).strip().decode("utf-8"))
|
|
38
|
+
elif i.startswith("url:"): # 自定义 url
|
|
39
|
+
return getattr(ip, "public_v" + ip_type)(i[4:])
|
|
40
|
+
elif i.startswith("regex:"): # 正则 regex
|
|
41
|
+
return getattr(ip, "regex_v" + ip_type)(i[6:])
|
|
42
|
+
else:
|
|
43
|
+
return getattr(ip, i + "_v" + ip_type)()
|
|
78
44
|
except Exception as e:
|
|
79
|
-
error("Failed to
|
|
80
|
-
return
|
|
45
|
+
logger.error("Failed to get %s address: %s", ip_type, e)
|
|
46
|
+
return None
|
|
81
47
|
|
|
82
48
|
|
|
83
|
-
def update_ip(
|
|
84
|
-
# type: (
|
|
49
|
+
def update_ip(dns, cache, index_rule, domains, record_type, config):
|
|
50
|
+
# type: (SimpleProvider, Cache | None, list[str]|bool, list[str], str, Config) -> bool | None
|
|
85
51
|
"""
|
|
86
|
-
更新IP
|
|
52
|
+
更新IP并变更DNS记录
|
|
87
53
|
"""
|
|
88
|
-
ipname = "ipv" + ip_type
|
|
89
|
-
domains = get_config(ipname)
|
|
90
54
|
if not domains:
|
|
91
55
|
return None
|
|
92
|
-
if not isinstance(domains, list):
|
|
93
|
-
domains = domains.strip("; ").replace(",", ";").replace(" ", ";").split(";")
|
|
94
56
|
|
|
95
|
-
|
|
57
|
+
ip_type = "4" if record_type == "A" else "6"
|
|
96
58
|
address = get_ip(ip_type, index_rule)
|
|
97
59
|
if not address:
|
|
98
|
-
error("Fail to get %s address!",
|
|
60
|
+
logger.error("Fail to get %s address!", ip_type)
|
|
99
61
|
return False
|
|
100
62
|
|
|
101
|
-
record_type = "A" if ip_type == "4" else "AAAA"
|
|
102
63
|
update_success = False
|
|
103
64
|
|
|
104
|
-
# Check cache and update each domain individually
|
|
105
65
|
for domain in domains:
|
|
106
66
|
domain = domain.lower()
|
|
107
67
|
cache_key = "{}:{}".format(domain, record_type)
|
|
108
68
|
if cache and cache.get(cache_key) == address:
|
|
109
|
-
info("%s[%s] address not changed, using cache: %s", domain, record_type, address)
|
|
110
|
-
update_success = True
|
|
69
|
+
logger.info("%s[%s] address not changed, using cache: %s", domain, record_type, address)
|
|
70
|
+
update_success = True
|
|
111
71
|
else:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
72
|
+
try:
|
|
73
|
+
result = dns.set_record(domain, address, record_type=record_type, ttl=config.ttl, line=config.line)
|
|
74
|
+
if result:
|
|
75
|
+
logger.warning("set %s[IPv%s]: %s successfully.", domain, ip_type, address)
|
|
76
|
+
update_success = True
|
|
77
|
+
if isinstance(cache, dict):
|
|
78
|
+
cache[cache_key] = address
|
|
79
|
+
else:
|
|
80
|
+
logger.error("Failed to update %s record for %s", record_type, domain)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
logger.exception("Failed to update %s record for %s: %s", record_type, domain, e)
|
|
120
83
|
return update_success
|
|
121
84
|
|
|
122
85
|
|
|
123
|
-
def
|
|
86
|
+
def run(config):
|
|
87
|
+
# type: (Config) -> bool
|
|
124
88
|
"""
|
|
125
|
-
|
|
89
|
+
Run the DDNS update process
|
|
126
90
|
"""
|
|
91
|
+
# 设置IP模块的SSL验证配置
|
|
92
|
+
ip.ssl_verify = config.ssl
|
|
93
|
+
|
|
94
|
+
# dns provider class
|
|
95
|
+
provider_class = get_provider_class(config.dns)
|
|
96
|
+
dns = provider_class(
|
|
97
|
+
config.id, config.token, endpoint=config.endpoint, logger=logger, proxy=config.proxy, verify_ssl=config.ssl
|
|
98
|
+
)
|
|
99
|
+
cache = Cache.new(config.cache, config.md5(), logger)
|
|
100
|
+
return (
|
|
101
|
+
update_ip(dns, cache, config.index4, config.ipv4, "A", config) is not False
|
|
102
|
+
and update_ip(dns, cache, config.index6, config.ipv6, "AAAA", config) is not False
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def main():
|
|
127
107
|
encode = sys.stdout.encoding
|
|
128
108
|
if encode is not None and encode.lower() != "utf-8" and hasattr(sys.stdout, "buffer"):
|
|
129
109
|
# 兼容windows 和部分ASCII编码的老旧系统
|
|
130
110
|
sys.stdout = TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
|
|
131
111
|
sys.stderr = TextIOWrapper(sys.stderr.buffer, encoding="utf-8")
|
|
132
|
-
init_config(__description__, __doc__, __version__, build_date)
|
|
133
|
-
|
|
134
|
-
log_level = get_config("log.level", INFO) # type: int # type: ignore
|
|
135
|
-
log_format = get_config("log.format") # type: str | None # type: ignore
|
|
136
|
-
if log_format:
|
|
137
|
-
# A custom log format is already set; no further action is required.
|
|
138
|
-
pass
|
|
139
|
-
elif log_level < INFO:
|
|
140
|
-
# Override log format in debug mode to include filename and line number for detailed debugging
|
|
141
|
-
log_format = "%(asctime)s %(levelname)s [%(name)s.%(funcName)s](%(filename)s:%(lineno)d): %(message)s"
|
|
142
|
-
elif log_level > INFO:
|
|
143
|
-
log_format = "%(asctime)s %(levelname)s: %(message)s"
|
|
144
|
-
else:
|
|
145
|
-
log_format = "%(asctime)s %(levelname)s [%(name)s]: %(message)s"
|
|
146
|
-
basicConfig(
|
|
147
|
-
level=log_level,
|
|
148
|
-
format=log_format,
|
|
149
|
-
datefmt=get_config("log.datefmt", "%Y-%m-%dT%H:%M:%S"), # type: ignore
|
|
150
|
-
filename=get_config("log.file"), # type: ignore
|
|
151
|
-
)
|
|
152
|
-
logger = getLogger()
|
|
153
112
|
logger.name = "ddns"
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
# dns provider class
|
|
158
|
-
dns_name = get_config("dns", "debug") # type: str # type: ignore
|
|
159
|
-
provider_class = get_provider_class(dns_name)
|
|
160
|
-
ssl_config = get_config("ssl", "auto") # type: str | bool # type: ignore
|
|
161
|
-
dns = provider_class(get_config("id"), get_config("token"), logger=logger, verify_ssl=ssl_config) # type: ignore
|
|
162
|
-
|
|
163
|
-
if get_config("config"):
|
|
164
|
-
info("loaded Config from: %s", path.abspath(get_config("config"))) # type: ignore
|
|
165
|
-
|
|
166
|
-
proxy = get_config("proxy") or "DIRECT"
|
|
167
|
-
proxy_list = proxy if isinstance(proxy, list) else proxy.strip(";").replace(",", ";").split(";")
|
|
168
|
-
|
|
169
|
-
cache_config = get_config("cache", True) # type: bool | str # type: ignore
|
|
170
|
-
if cache_config is False:
|
|
171
|
-
cache = None
|
|
172
|
-
elif cache_config is True:
|
|
173
|
-
cache = Cache(path.join(gettempdir(), "ddns.cache"), logger)
|
|
174
|
-
else:
|
|
175
|
-
cache = Cache(cache_config, logger)
|
|
176
|
-
|
|
177
|
-
if cache is None:
|
|
178
|
-
info("Cache is disabled!")
|
|
179
|
-
elif get_config("config_modified_time", float("inf")) >= cache.time: # type: ignore
|
|
180
|
-
info("Cache file is outdated.")
|
|
181
|
-
cache.clear()
|
|
182
|
-
elif len(cache) == 0:
|
|
183
|
-
debug("Cache is empty.")
|
|
184
|
-
else:
|
|
185
|
-
debug("Cache loaded with %d entries.", len(cache))
|
|
186
|
-
ttl = get_config("ttl") # type: str # type: ignore
|
|
187
|
-
line = get_config("line") # type: str | None # type: ignore
|
|
188
|
-
update_ip("4", cache, dns, ttl, line, proxy_list)
|
|
189
|
-
update_ip("6", cache, dns, ttl, line, proxy_list)
|
|
113
|
+
config = load_config(__description__, __version__, build_date)
|
|
114
|
+
run(config)
|
|
190
115
|
|
|
191
116
|
|
|
192
117
|
if __name__ == "__main__":
|
ddns/{util/cache.py → cache.py}
RENAMED
|
@@ -4,10 +4,11 @@ cache module
|
|
|
4
4
|
文件缓存
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from logging import getLogger, Logger # noqa: F401
|
|
7
8
|
from os import path, stat
|
|
8
|
-
from
|
|
9
|
+
from json import load, dump
|
|
10
|
+
from tempfile import gettempdir
|
|
9
11
|
from time import time
|
|
10
|
-
from logging import getLogger, Logger # noqa: F401
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class Cache(dict):
|
|
@@ -40,18 +41,20 @@ class Cache(dict):
|
|
|
40
41
|
file = self.__filename
|
|
41
42
|
|
|
42
43
|
self.__logger.debug("load cache data from %s", file)
|
|
43
|
-
if file
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
if file:
|
|
45
|
+
try:
|
|
46
|
+
with open(file, "r") as data:
|
|
46
47
|
loaded_data = load(data)
|
|
47
48
|
self.clear()
|
|
48
49
|
self.update(loaded_data)
|
|
49
50
|
self.__time = stat(file).st_mtime
|
|
50
51
|
return self
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
except (IOError, OSError):
|
|
53
|
+
self.__logger.info("cache file not exist or cannot be opened")
|
|
54
|
+
except ValueError:
|
|
55
|
+
pass
|
|
56
|
+
except Exception as e:
|
|
57
|
+
self.__logger.warning(e)
|
|
55
58
|
else:
|
|
56
59
|
self.__logger.info("cache file not exist")
|
|
57
60
|
|
|
@@ -63,10 +66,10 @@ class Cache(dict):
|
|
|
63
66
|
def sync(self):
|
|
64
67
|
"""Sync the write buffer with the cache files and clear the buffer."""
|
|
65
68
|
if self.__changed and self.__filename:
|
|
66
|
-
with open(self.__filename, "
|
|
69
|
+
with open(self.__filename, "w") as data:
|
|
67
70
|
# 只保存非私有字段(不以__开头的字段)
|
|
68
71
|
filtered_data = {k: v for k, v in super(Cache, self).items() if not k.startswith("__")}
|
|
69
|
-
dump(filtered_data, data)
|
|
72
|
+
dump(filtered_data, data, separators=(",", ":"))
|
|
70
73
|
self.__logger.debug("save cache data to %s", self.__filename)
|
|
71
74
|
self.__time = time()
|
|
72
75
|
self.__changed = False
|
|
@@ -150,3 +153,31 @@ class Cache(dict):
|
|
|
150
153
|
|
|
151
154
|
def __del__(self):
|
|
152
155
|
self.close()
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def new(config_cache, hash, logger):
|
|
159
|
+
# type: (str|bool, str, Logger) -> Cache|None
|
|
160
|
+
"""
|
|
161
|
+
new cache from a file path.
|
|
162
|
+
:param path: Path to the cache file.
|
|
163
|
+
:param logger: Optional logger for debug messages.
|
|
164
|
+
:return: Cache instance with loaded data.
|
|
165
|
+
"""
|
|
166
|
+
if config_cache is False:
|
|
167
|
+
cache = None
|
|
168
|
+
elif config_cache is True:
|
|
169
|
+
cache_path = path.join(gettempdir(), "ddns.%s.cache" % hash)
|
|
170
|
+
cache = Cache(cache_path, logger)
|
|
171
|
+
else:
|
|
172
|
+
cache = Cache(config_cache, logger)
|
|
173
|
+
|
|
174
|
+
if cache is None:
|
|
175
|
+
logger.debug("Cache is disabled!")
|
|
176
|
+
elif cache.time + 72 * 3600 < time(): # 72小时有效期
|
|
177
|
+
logger.info("Cache file is outdated.")
|
|
178
|
+
cache.clear()
|
|
179
|
+
elif len(cache) == 0:
|
|
180
|
+
logger.debug("Cache is empty.")
|
|
181
|
+
else:
|
|
182
|
+
logger.debug("Cache loaded with %d entries.", len(cache))
|
|
183
|
+
return cache
|
ddns/{util/ip.py → ip.py}
RENAMED
|
@@ -5,10 +5,10 @@ from os import name as os_name, popen
|
|
|
5
5
|
from socket import socket, getaddrinfo, gethostname, AF_INET, AF_INET6, SOCK_DGRAM
|
|
6
6
|
from logging import debug, error
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
from .util.http import send_http_request
|
|
9
|
+
|
|
10
|
+
# 模块级别的SSL验证配置,默认使用auto模式
|
|
11
|
+
ssl_verify = "auto"
|
|
12
12
|
|
|
13
13
|
# IPV4正则
|
|
14
14
|
IPV4_REG = r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
|
|
@@ -48,13 +48,15 @@ def local_v4(i=0): # 本地ipv4地址
|
|
|
48
48
|
def _open(url, reg):
|
|
49
49
|
try:
|
|
50
50
|
debug("open: %s", url)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.read()
|
|
54
|
-
.decode("utf8", "ignore")
|
|
51
|
+
response = send_http_request(
|
|
52
|
+
method="GET", url=url, headers={"User-Agent": "Mozilla/5.0 ddns"}, verify_ssl=ssl_verify
|
|
55
53
|
)
|
|
54
|
+
res = response.body
|
|
56
55
|
debug("response: %s", res)
|
|
57
|
-
|
|
56
|
+
match = compile(reg).search(res)
|
|
57
|
+
if match:
|
|
58
|
+
return match.group()
|
|
59
|
+
error("No match found in response: %s", res)
|
|
58
60
|
except Exception as e:
|
|
59
61
|
error(e)
|
|
60
62
|
|
ddns/provider/__init__.py
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
# coding=utf-8
|
|
2
|
-
from ._base import SimpleProvider
|
|
2
|
+
from ._base import SimpleProvider
|
|
3
3
|
from .alidns import AlidnsProvider
|
|
4
|
+
from .aliesa import AliesaProvider
|
|
4
5
|
from .callback import CallbackProvider
|
|
5
6
|
from .cloudflare import CloudflareProvider
|
|
7
|
+
from .debug import DebugProvider
|
|
6
8
|
from .dnscom import DnscomProvider
|
|
7
9
|
from .dnspod import DnspodProvider
|
|
8
10
|
from .dnspod_com import DnspodComProvider
|
|
11
|
+
from .edgeone import EdgeOneProvider
|
|
9
12
|
from .he import HeProvider
|
|
10
13
|
from .huaweidns import HuaweiDNSProvider
|
|
14
|
+
from .namesilo import NamesiloProvider
|
|
15
|
+
from .noip import NoipProvider
|
|
11
16
|
from .tencentcloud import TencentCloudProvider
|
|
12
|
-
|
|
17
|
+
|
|
18
|
+
__all__ = ["SimpleProvider", "get_provider_class"]
|
|
13
19
|
|
|
14
20
|
|
|
15
21
|
def get_provider_class(provider_name):
|
|
@@ -32,15 +38,22 @@ def get_provider_class(provider_name):
|
|
|
32
38
|
"tencentcloud": TencentCloudProvider,
|
|
33
39
|
"tencent": TencentCloudProvider, # 兼容tencent
|
|
34
40
|
"qcloud": TencentCloudProvider, # 兼容qcloud
|
|
41
|
+
# tencent cloud edgeone
|
|
42
|
+
"edgeone": EdgeOneProvider,
|
|
43
|
+
"teo": EdgeOneProvider, # 兼容teo (EdgeOne产品的API名称)
|
|
44
|
+
"tencentedgeone": EdgeOneProvider, # 兼容tencentedgeone
|
|
35
45
|
# cloudflare
|
|
36
46
|
"cloudflare": CloudflareProvider,
|
|
37
47
|
# aliyun alidns
|
|
38
48
|
"alidns": AlidnsProvider,
|
|
39
49
|
"aliyun": AlidnsProvider, # 兼容aliyun
|
|
50
|
+
# aliyun esa
|
|
51
|
+
"aliesa": AliesaProvider,
|
|
52
|
+
"esa": AliesaProvider, # 兼容esa
|
|
40
53
|
# dns.com
|
|
41
54
|
"dnscom": DnscomProvider,
|
|
42
|
-
"51dns": DnscomProvider, #
|
|
43
|
-
"dns_com": DnscomProvider, #
|
|
55
|
+
"51dns": DnscomProvider, # 兼容51dns
|
|
56
|
+
"dns_com": DnscomProvider, # 兼容dns_com
|
|
44
57
|
# he.net
|
|
45
58
|
"he": HeProvider,
|
|
46
59
|
"he_net": HeProvider, # 兼容he.net
|
|
@@ -48,6 +61,13 @@ def get_provider_class(provider_name):
|
|
|
48
61
|
"huaweidns": HuaweiDNSProvider,
|
|
49
62
|
"huawei": HuaweiDNSProvider, # 兼容huawei
|
|
50
63
|
"huaweicloud": HuaweiDNSProvider,
|
|
64
|
+
# namesilo
|
|
65
|
+
"namesilo": NamesiloProvider,
|
|
66
|
+
"namesilo_com": NamesiloProvider, # 兼容namesilo.com
|
|
67
|
+
# no-ip
|
|
68
|
+
"noip": NoipProvider,
|
|
69
|
+
"no-ip": NoipProvider, # 兼容no-ip
|
|
70
|
+
"noip_com": NoipProvider, # 兼容noip.com
|
|
51
71
|
# callback
|
|
52
72
|
"callback": CallbackProvider,
|
|
53
73
|
"webhook": CallbackProvider, # 兼容
|