ddns 4.0.1__py2.py3-none-any.whl → 4.1.0__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.

Potentially problematic release.


This version of ddns might be problematic. Click here for more details.

ddns/provider/dnscom.py CHANGED
@@ -1,180 +1,103 @@
1
1
  # coding=utf-8
2
2
  """
3
- DNSCOM API
4
- DNS.COM 接口解析操作库
5
- http://open.dns.com/
6
- @author: Bigjin
7
- @mailto: i@bigjin.com
3
+ DNSCOM/51dns API 接口解析操作库
4
+ www.51dns.com (原dns.com)
5
+ @author: Bigjin<i@bigjin.com>, NewFuture
8
6
  """
9
7
 
10
8
  from hashlib import md5
11
- from json import loads as jsondecode
12
- from logging import debug, info, warning
13
- from time import mktime
14
- from datetime import datetime
9
+ from time import time
15
10
 
16
- try: # python 3
17
- from http.client import HTTPSConnection
18
- from urllib.parse import urlencode
19
- except ImportError: # python 2
20
- from httplib import HTTPSConnection
21
- from urllib import urlencode
11
+ from ._base import TYPE_FORM, BaseProvider, encode_params
22
12
 
23
- __author__ = 'Bigjin'
24
- # __all__ = ["request", "ID", "TOKEN", "PROXY"]
25
13
 
26
-
27
- class Config:
28
- ID = "id"
29
- TOKEN = "TOKEN"
30
- PROXY = None # 代理设置
31
- TTL = None
32
-
33
-
34
- class API:
35
- # API 配置
36
- SITE = "www.dns.com" # API endpoint
37
- METHOD = "POST" # 请求方法
38
-
39
-
40
- def signature(params):
41
- """
42
- 计算签名,返回签名后的查询参数
43
- """
44
- params.update({
45
- 'apiKey': Config.ID,
46
- 'timestamp': mktime(datetime.now().timetuple()),
47
- })
48
- query = urlencode(sorted(params.items()))
49
- debug(query)
50
- sign = query
51
- debug("signString: %s", sign)
52
-
53
- sign = md5((sign + Config.TOKEN).encode('utf-8')).hexdigest()
54
- params["hash"] = sign
55
-
56
- return params
57
-
58
-
59
- def request(action, param=None, **params):
60
- """
61
- 发送请求数据
62
- """
63
- if param:
64
- params.update(param)
65
- params = dict((k, params[k]) for k in params if params[k] is not None)
66
- params = signature(params)
67
- info("%s/api/%s/ : params:%s", API.SITE, action, params)
68
-
69
- if Config.PROXY:
70
- conn = HTTPSConnection(Config.PROXY)
71
- conn.set_tunnel(API.SITE, 443)
72
- else:
73
- conn = HTTPSConnection(API.SITE)
74
-
75
- conn.request(API.METHOD, '/api/' + action + '/', urlencode(params),
76
- {"Content-type": "application/x-www-form-urlencoded"})
77
- response = conn.getresponse()
78
- result = response.read().decode('utf8')
79
- conn.close()
80
-
81
- if response.status < 200 or response.status >= 300:
82
- warning('%s : error[%d]:%s', action, response.status, result)
83
- raise Exception(result)
84
- else:
85
- data = jsondecode(result)
86
- debug('%s : result:%s', action, data)
87
- if data.get('code') != 0:
88
- raise Exception("api error:", data.get('message'))
89
- data = data.get('data')
90
- if data is None:
91
- raise Exception('response data is none')
92
- return data
93
-
94
-
95
- def get_domain_info(domain):
96
- """
97
- 切割域名获取主域名和对应ID
98
- """
99
- if len(domain.split('.')) > 2:
100
- domains = domain.split('.', 1)
101
- sub = domains[0]
102
- main = domains[1]
103
- else:
104
- sub = '' # 接口有bug 不能传 @ * 作为主机头,但是如果为空,默认为 @
105
- main = domain
106
-
107
- res = request("domain/getsingle", domainID=main)
108
- domain_id = res.get('domainID')
109
- return sub, main, domain_id
110
-
111
-
112
- def get_records(domain, domain_id, **conditions):
113
- """
114
- 获取记录ID
115
- 返回满足条件的所有记录[]
116
- TODO 大于500翻页
14
+ class DnscomProvider(BaseProvider):
117
15
  """
118
- if not hasattr(get_records, "records"):
119
- get_records.records = {} # "静态变量"存储已查询过的id
120
- get_records.keys = ("recordID", "record", "type", "viewID",
121
- "TTL", "state", "value")
122
-
123
- if domain not in get_records.records:
124
- get_records.records[domain] = {}
125
- data = request("record/list",
126
- domainID=domain_id, pageSize=500)
127
- if data.get('data'):
128
- for record in data.get('data'):
129
- get_records.records[domain][record["recordID"]] = {
130
- k: v for (k, v) in record.items() if k in get_records.keys}
131
- records = {}
132
- for (rid, record) in get_records.records[domain].items():
133
- for (k, value) in conditions.items():
134
- if record.get(k) != value:
135
- break
136
- else: # for else push
137
- records[rid] = record
138
- return records
139
-
140
-
141
- def update_record(domain, value, record_type='A'):
142
- """
143
- 更新记录
16
+ DNSCOM/51dns API Provider
17
+ https://www.51dns.com/document/api/index.html
144
18
  """
145
- info(">>>>>%s(%s)", domain, record_type)
146
- sub, main, domain_id = get_domain_info(domain)
147
19
 
148
- records = get_records(main, domain_id, record=sub, type=record_type)
149
- result = {}
150
-
151
- if records:
152
- for (rid, record) in records.items():
153
- if record["value"] != value:
154
- debug(sub, record)
155
- res = request("record/modify", domainID=domain_id,
156
- recordID=rid, newvalue=value, newTTL=Config.TTL)
157
- if res:
158
- # update records
159
- get_records.records[main][rid]["value"] = value
160
- result[rid] = res
161
- else:
162
- result[rid] = "update fail!\n" + str(res)
163
- else:
164
- result[rid] = domain
165
- else:
166
- res = request("record/create", domainID=domain_id,
167
- value=value, host=sub, type=record_type, TTL=Config.TTL)
168
- if res:
169
- # update records INFO
170
- rid = res.get('recordID')
171
- get_records.records[main][rid] = {
172
- 'value': value,
173
- "recordID": rid,
174
- "record": sub,
175
- "type": record_type
20
+ endpoint = "https://www.51dns.com"
21
+ content_type = TYPE_FORM
22
+
23
+ def _validate(self):
24
+ self.logger.warning(
25
+ "DNS.COM 缺少充分的真实环境测试,请及时在 GitHub Issues 中反馈: %s",
26
+ "https://github.com/NewFuture/DDNS/issues",
27
+ )
28
+ super(DnscomProvider, self)._validate()
29
+
30
+ def _signature(self, params):
31
+ """https://www.51dns.com/document/api/70/72.html"""
32
+ params = {k: v for k, v in params.items() if v is not None}
33
+ params.update(
34
+ {
35
+ "apiKey": self.id,
36
+ "timestamp": time(), # 时间戳
176
37
  }
177
- result = res
178
- else:
179
- result = domain + " created fail!"
180
- return result
38
+ )
39
+ query = encode_params(params)
40
+ sign = md5((query + self.token).encode("utf-8")).hexdigest()
41
+ params["hash"] = sign
42
+ return params
43
+
44
+ def _request(self, action, **params):
45
+ params = self._signature(params)
46
+ data = self._http("POST", "/api/{}/".format(action), body=params)
47
+ if data is None or not isinstance(data, dict):
48
+ raise Exception("response data is none")
49
+ if data.get("code", 0) != 0:
50
+ raise Exception("api error: " + str(data.get("message")))
51
+ return data.get("data")
52
+
53
+ def _query_zone_id(self, domain):
54
+ """https://www.51dns.com/document/api/74/31.html"""
55
+ res = self._request("domain/getsingle", domainID=domain)
56
+ self.logger.debug("Queried domain: %s", res)
57
+ if res:
58
+ return res.get("domainID")
59
+ return None
60
+
61
+ def _query_record(self, zone_id, subdomain, main_domain, record_type, line, extra):
62
+ """https://www.51dns.com/document/api/4/47.html"""
63
+ records = self._request("record/list", domainID=zone_id, host=subdomain, pageSize=500)
64
+ records = records.get("data", []) if records else []
65
+ for record in records:
66
+ if (
67
+ record.get("record") == subdomain
68
+ and record.get("type") == record_type
69
+ and (line is None or record.get("viewID") == line)
70
+ ):
71
+ return record
72
+ return None
73
+
74
+ def _create_record(self, zone_id, subdomain, main_domain, value, record_type, ttl, line, extra):
75
+ """https://www.51dns.com/document/api/4/12.html"""
76
+ extra["remark"] = extra.get("remark", self.remark)
77
+ res = self._request(
78
+ "record/create",
79
+ domainID=zone_id,
80
+ value=value,
81
+ host=subdomain,
82
+ type=record_type,
83
+ TTL=ttl,
84
+ viewID=line,
85
+ **extra
86
+ ) # fmt: skip
87
+ if res and res.get("recordID"):
88
+ self.logger.info("Record created: %s", res)
89
+ return True
90
+ self.logger.error("Failed to create record: %s", res)
91
+ return False
92
+
93
+ def _update_record(self, zone_id, old_record, value, record_type, ttl, line, extra):
94
+ """https://www.51dns.com/document/api/4/45.html"""
95
+ extra["remark"] = extra.get("remark", self.remark)
96
+ res = self._request(
97
+ "record/modify", domainID=zone_id, recordID=old_record.get("recordID"), newvalue=value, newTTL=ttl
98
+ )
99
+ if res:
100
+ self.logger.info("Record updated: %s", res)
101
+ return True
102
+ self.logger.error("Failed to update record: %s", res)
103
+ return False
ddns/provider/dnspod.py CHANGED
@@ -1,186 +1,114 @@
1
1
  # coding=utf-8
2
2
  """
3
3
  DNSPOD API
4
- DNSPOD 接口解析操作库
5
- http://www.dnspod.cn/docs/domains.html
6
- @author: New Future
4
+ @doc: https://docs.dnspod.cn/api/
5
+ @author: NewFuture
7
6
  """
8
7
 
9
- from json import loads as jsondecode
10
- from logging import debug, info, warning
11
- from os import environ
8
+ from ._base import BaseProvider, TYPE_FORM
12
9
 
13
- try: # python 3
14
- from http.client import HTTPSConnection
15
- from urllib.parse import urlencode
16
- except ImportError: # python 2
17
- from httplib import HTTPSConnection
18
- from urllib import urlencode
19
10
 
20
- __author__ = 'New Future'
21
-
22
-
23
- class Config:
24
- ID = "token id"
25
- TOKEN = "token key"
26
- PROXY = None # 代理设置
27
- TTL = None
28
-
29
-
30
- class API:
31
- # API 配置
32
- SITE = "dnsapi.cn" # API endpoint
33
- METHOD = "POST" # 请求方法
34
- TOKEN_PARAM = "login_token" # token参数
35
- DEFAULT = "默认" # 默认线路名
36
- LENGTH = "length" # 添加参数
37
-
38
-
39
- def request(action, param=None, **params):
11
+ class DnspodProvider(BaseProvider):
40
12
  """
41
- 发送请求数据
13
+ DNSPOD API
14
+ DNSPOD 接口解析操作库
42
15
  """
43
- if param:
44
- params.update(param)
45
- params = dict((k, params[k]) for k in params if params[k] is not None)
46
- params.update({API.TOKEN_PARAM: '***', 'format': 'json'})
47
- info("%s/%s : %s", API.SITE, action, params)
48
- params[API.TOKEN_PARAM] = "%s,%s" % (Config.ID, Config.TOKEN)
49
- params[API.LENGTH] = "3000" # 添加参数
50
- if Config.PROXY:
51
- conn = HTTPSConnection(Config.PROXY)
52
- conn.set_tunnel(API.SITE, 443)
53
- else:
54
- conn = HTTPSConnection(API.SITE)
55
-
56
- conn.request(API.METHOD, '/' + action, urlencode(params), {
57
- "Content-type": "application/x-www-form-urlencoded",
58
- "User-Agent": "DDNS/%s (ddns@newfuture.cc)" % environ.get("DDNS_VERSION", "1.0.0")
59
- })
60
- response = conn.getresponse()
61
- res = response.read().decode('utf8')
62
- conn.close()
63
16
 
64
- if response.status < 200 or response.status >= 300:
65
- warning('%s : error[%d]:%s', action, response.status, res)
66
- raise Exception(res)
67
- else:
68
- data = jsondecode(res)
69
- debug('%s : result:%s', action, data)
70
- if not data:
71
- raise Exception("empty response")
72
- elif data.get("status", {}).get("code") == "1":
17
+ endpoint = "https://dnsapi.cn"
18
+ content_type = TYPE_FORM
19
+
20
+ DefaultLine = "默认"
21
+
22
+ def _request(self, action, extra=None, **params):
23
+ # type: (str, dict | None, **(str | int | bytes | bool | None)) -> dict
24
+ """
25
+ 发送请求数据
26
+
27
+ Send request to DNSPod API.
28
+ Args:
29
+ action (str): API 动作/Action
30
+ extra (dict|None): 额外参数/Extra params
31
+ params (dict): 其它参数/Other params
32
+ Returns:
33
+ dict: 响应数据/Response data
34
+ """
35
+ # 过滤掉None参数
36
+ if extra:
37
+ params.update(extra)
38
+ params = {k: v for k, v in params.items() if v is not None}
39
+ params.update({"login_token": "{0},{1}".format(self.id, self.token), "format": "json"})
40
+ data = self._http("POST", "/" + action, body=params)
41
+ if data and data.get("status", {}).get("code") == "1": # 请求成功
42
+ return data
43
+ else: # 请求失败
44
+ error_msg = "Unknown error"
45
+ if data and isinstance(data, dict):
46
+ error_msg = data.get("status", {}).get("message", "Unknown error")
47
+ self.logger.warning("DNSPod API error: %s", error_msg)
73
48
  return data
74
- else:
75
- raise Exception(data.get('status', {}))
76
-
77
-
78
- def get_domain_info(domain):
79
- """
80
- 切割域名获取主域名和对应ID
81
- """
82
- domain_split = domain.split('.')
83
- sub, did = None, None
84
- main = domain_split.pop()
85
- while domain_split: # 通过API判断,最后两个,三个递增
86
- main = domain_split.pop() + '.' + main
87
- did = get_domain_id(main)
88
- if did:
89
- sub = ".".join(domain_split) or '@'
90
- # root domain根域名https://github.com/NewFuture/DDNS/issues/9
91
- break
92
- info('domain_id: %s, sub: %s', did, sub)
93
- return did, sub
94
-
95
-
96
- def get_domain_id(domain):
97
- """
98
- 获取域名ID
99
- http://www.dnspod.cn/docs/domains.html#domain-info
100
- """
101
- if not hasattr(get_domain_id, "domain_list"):
102
- get_domain_id.domain_list = {} # "静态变量"存储已查询过的id
103
-
104
- if domain in get_domain_id.domain_list:
105
- # 如果已经存在直接返回防止再次请求
106
- return get_domain_id.domain_list[domain]
107
- else:
108
- try:
109
- d_info = request('Domain.Info', domain=domain)
110
- except Exception as e:
111
- info("get_domain_id(%s) error: %s", domain, e)
112
- return
113
- did = d_info.get("domain", {}).get("id")
114
- if did:
115
- get_domain_id.domain_list[domain] = did
116
- return did
117
-
118
-
119
- def get_records(did, **conditions):
120
- """
121
- 获取记录ID
122
- 返回满足条件的所有记录[]
123
- TODO 大于3000翻页
124
- http://www.dnspod.cn/docs/records.html#record-list
125
- """
126
- if not hasattr(get_records, "records"):
127
- get_records.records = {} # "静态变量"存储已查询过的id
128
- get_records.keys = ("id", "name", "type", "line",
129
- "line_id", "enabled", "mx", "value")
130
-
131
- if did not in get_records.records:
132
- get_records.records[did] = {}
133
- data = request('Record.List', domain_id=did)
134
- if data:
135
- for record in data.get('records'):
136
- get_records.records[did][record["id"]] = {
137
- k: v for (k, v) in record.items() if k in get_records.keys}
138
-
139
- records = {}
140
- for (did, record) in get_records.records[did].items():
141
- for (k, value) in conditions.items():
142
- if record.get(k) != value:
143
- break
144
- else: # for else push
145
- records[did] = record
146
- return records
147
-
148
-
149
- def update_record(domain, value, record_type="A"):
150
- """
151
- 更新记录
152
- """
153
- info(">>>>>%s(%s)", domain, record_type)
154
- domainid, sub = get_domain_info(domain)
155
- if not domainid:
156
- raise Exception("invalid domain: [ %s ] " % domain)
157
49
 
158
- records = get_records(domainid, name=sub, type=record_type)
159
- result = {}
160
- if records: # update
161
- # http://www.dnspod.cn/docs/records.html#record-modify
162
- for (did, record) in records.items():
163
- if record["value"] != value:
164
- debug(sub, record)
165
- res = request('Record.Modify', record_id=did, record_line=record["line"].replace("Default", "default").encode(
166
- "utf-8"), value=value, sub_domain=sub, domain_id=domainid, record_type=record_type, ttl=Config.TTL)
167
- if res:
168
- get_records.records[domainid][did]["value"] = value
169
- result[did] = res.get("record")
170
- else:
171
- result[did] = "update fail!\n" + str(res)
172
- else:
173
- result[did] = domain
174
- else: # create
175
- # http://www.dnspod.cn/docs/records.html#record-create
176
- res = request("Record.Create", domain_id=domainid, value=value,
177
- sub_domain=sub, record_type=record_type, record_line=API.DEFAULT, ttl=Config.TTL)
178
- if res:
179
- did = res.get("record")["id"]
180
- get_records.records[domainid][did] = res.get("record")
181
- get_records.records[domainid][did].update(
182
- value=value, sub_domain=sub, record_type=record_type)
183
- result = res.get("record")
184
- else:
185
- result = domain + " created fail!"
186
- return result
50
+ def _create_record(self, zone_id, subdomain, main_domain, value, record_type, ttl, line, extra):
51
+ # type: (str, str, str, str, str, int | str | None, str | None, dict) -> bool
52
+ """https://docs.dnspod.cn/api/add-record/"""
53
+ res = self._request(
54
+ "Record.Create",
55
+ extra=extra,
56
+ domain_id=zone_id,
57
+ sub_domain=subdomain,
58
+ value=value,
59
+ record_type=record_type,
60
+ record_line=line or self.DefaultLine,
61
+ ttl=ttl,
62
+ )
63
+ record = res and res.get("record")
64
+ if record: # 记录创建成功
65
+ self.logger.info("Record created: %s", record)
66
+ return True
67
+ else: # 记录创建失败
68
+ self.logger.error("Failed to create record: %s", res)
69
+ return False
70
+
71
+ def _update_record(self, zone_id, old_record, value, record_type, ttl, line, extra):
72
+ # type: (str, dict, str, str, int | str | None, str | None, dict) -> bool
73
+ """https://docs.dnspod.cn/api/modify-records/"""
74
+ record_line = (line or old_record.get("line") or self.DefaultLine).replace("Default", "default")
75
+ res = self._request(
76
+ "Record.Modify",
77
+ domain_id=zone_id,
78
+ record_id=old_record.get("id"),
79
+ sub_domain=old_record.get("name"),
80
+ record_type=record_type,
81
+ value=value,
82
+ record_line=record_line,
83
+ extra=extra,
84
+ )
85
+ record = res and res.get("record")
86
+ if record: # 记录更新成功
87
+ self.logger.debug("Record updated: %s", record)
88
+ return True
89
+ else: # 记录更新失败
90
+ self.logger.error("Failed to update record: %s", res)
91
+ return False
92
+
93
+ def _query_zone_id(self, domain):
94
+ # type: (str) -> str | None
95
+ """查询域名信息 https://docs.dnspod.cn/api/domain-info/"""
96
+ res = self._request("Domain.Info", domain=domain)
97
+ if res and isinstance(res, dict):
98
+ return res.get("domain", {}).get("id")
99
+ return None
100
+
101
+ def _query_record(self, zone_id, subdomain, main_domain, record_type, line, extra):
102
+ # type: (str, str, str, str, str | None, dict) -> dict | None
103
+ """查询记录 list 然后逐个查找 https://docs.dnspod.cn/api/record-list/"""
104
+ res = self._request("Record.List", domain_id=zone_id, sub_domain=subdomain, record_type=record_type, line=line)
105
+ # length="3000"
106
+ records = res.get("records", [])
107
+ n = len(records)
108
+ if not n:
109
+ self.logger.warning("No record found for [%s] %s<%s>(line: %s)", zone_id, subdomain, record_type, line)
110
+ return None
111
+ if n > 1:
112
+ self.logger.warning("%d records found for %s<%s>(%s):\n %s", n, subdomain, record_type, line, records)
113
+ return next((r for r in records if r.get("name") == subdomain), None)
114
+ return records[0]
@@ -1,15 +1,18 @@
1
1
  # coding=utf-8
2
2
  """
3
- DNSPOD API
4
- DNSPOD 接口解析操作库
3
+ DNSPOD Global (国际版) API
5
4
  http://www.dnspod.com/docs/domains.html
6
- @author: New Future
5
+ @author: NewFuture
7
6
  """
8
7
 
9
- from .dnspod import * # noqa: F403
8
+ from .dnspod import DnspodProvider # noqa: F401
10
9
 
11
- API.SITE = "api.dnspod.com" # noqa: F405
12
- API.DEFAULT = "default" # noqa: F405
13
10
 
14
- # https://github.com/NewFuture/DDNS/issues/286
15
- # API.TOKEN_PARAM = "user_token" # noqa: F405
11
+ class DnspodComProvider(DnspodProvider):
12
+ """
13
+ DNSPOD.com Provider (国际版)
14
+ This class extends the DnspodProvider to use the global DNSPOD API.
15
+ """
16
+
17
+ endpoint = "https://api.dnspod.com"
18
+ DefaultLine = "default"
@@ -0,0 +1,83 @@
1
+ # coding=utf-8
2
+ """
3
+ Tencent Cloud EdgeOne API
4
+ 腾讯云 EdgeOne (边缘安全速平台) API
5
+ API Documentation: https://cloud.tencent.com/document/api/1552/80731
6
+ @author: NewFuture
7
+ """
8
+
9
+ from ddns.provider._base import join_domain
10
+ from .tencentcloud import TencentCloudProvider
11
+
12
+
13
+ class EdgeOneProvider(TencentCloudProvider):
14
+ """
15
+ 腾讯云 EdgeOne API 提供商
16
+ Tencent Cloud EdgeOne API Provider
17
+ """
18
+
19
+ endpoint = "https://teo.tencentcloudapi.com"
20
+ # 腾讯云 EdgeOne API 配置
21
+ service = "teo"
22
+ version_date = "2022-09-01"
23
+
24
+ def _query_zone_id(self, domain):
25
+ # type: (str) -> str | None
26
+ """查询域名的加速域名信息获取 ZoneId https://cloud.tencent.com/document/api/1552/80713"""
27
+ # 首先尝试直接查找域名
28
+ filters = [{"Name": "zone-name", "Values": [domain], "Fuzzy": False}] # type: Any
29
+ response = self._request("DescribeZones", Filters=filters)
30
+
31
+ if response and "Zones" in response:
32
+ for zone in response.get("Zones", []):
33
+ if zone.get("ZoneName") == domain:
34
+ zone_id = zone.get("ZoneId")
35
+ if zone_id:
36
+ self.logger.debug("Found acceleration domain %s with Zone ID: %s", domain, zone_id)
37
+ return zone_id
38
+
39
+ self.logger.debug("Acceleration domain not found for: %s", domain)
40
+ return None
41
+
42
+ def _query_record(self, zone_id, subdomain, main_domain, record_type, line, extra):
43
+ # type: (str, str, str, str, str | None, dict) -> dict | None
44
+ """查询加速域名信息 https://cloud.tencent.com/document/api/1552/86336"""
45
+ domain = join_domain(subdomain, main_domain)
46
+ filters = [{"Name": "domain-name", "Values": [domain], "Fuzzy": False}] # type: Any
47
+ response = self._request("DescribeAccelerationDomains", ZoneId=zone_id, Filters=filters)
48
+
49
+ if response and "AccelerationDomains" in response:
50
+ for domain_info in response.get("AccelerationDomains", []):
51
+ if domain_info.get("DomainName") == domain:
52
+ self.logger.debug("Found acceleration domain: %s", domain_info)
53
+ return domain_info
54
+
55
+ self.logger.warning("No acceleration domain found for: %s, response: %s", domain, response)
56
+ return None
57
+
58
+ def _create_record(self, zone_id, subdomain, main_domain, value, record_type, ttl, line, extra):
59
+ # type: (str, str, str, str, str, int, str | None, dict) -> bool
60
+ """创建新的加速域名记录 https://cloud.tencent.com/document/api/1552/86338"""
61
+ domain = join_domain(subdomain, main_domain)
62
+ origin = {"OriginType": "IP_DOMAIN", "Origin": value} # type: Any
63
+ res = self._request("CreateAccelerationDomain", ZoneId=zone_id, DomainName=domain, OriginInfo=origin, **extra)
64
+ if res:
65
+ self.logger.info("Acceleration domain created (%s)", res.get("RequestId"))
66
+ return True
67
+
68
+ self.logger.error("Failed to create acceleration domain, response: %s", res)
69
+ return False
70
+
71
+ def _update_record(self, zone_id, old_record, value, record_type, ttl, line, extra):
72
+ """更新加速域名的源站 IP 地址 https://cloud.tencent.com/document/api/1552/86335"""
73
+ domain = old_record.get("DomainName")
74
+ # 构建源站信息
75
+ backup = old_record.get("OriginDetail", {}).get("BackupOrigin", "")
76
+ origin = {"OriginType": "IP_DOMAIN", "Origin": value, "BackupOrigin": backup} # type: Any
77
+ response = self._request("ModifyAccelerationDomain", ZoneId=zone_id, DomainName=domain, OriginInfo=origin)
78
+
79
+ if response:
80
+ self.logger.info("Acceleration domain updated (%s)", response.get("RequestId"))
81
+ return True
82
+ self.logger.error("Failed to update acceleration domain origin, response: %s", response)
83
+ return False