From 8f184468f99c60c010e2890088c5dbfdb37205a8 Mon Sep 17 00:00:00 2001 From: NewFututre Date: Sat, 2 Nov 2019 01:49:22 +0800 Subject: [PATCH 1/5] fix(config): fix #104 dnspod.com --- dns/alidns.py | 17 ++++++++++------- dns/cloudflare.py | 17 ++++++++++------- dns/dnscom.py | 17 ++++++++++------- dns/dnspod.py | 18 +++++++++--------- run.py | 11 ++++++----- 5 files changed, 45 insertions(+), 35 deletions(-) diff --git a/dns/alidns.py b/dns/alidns.py index 23dd8157c..28bf1351d 100644 --- a/dns/alidns.py +++ b/dns/alidns.py @@ -26,9 +26,12 @@ __author__ = 'New Future' # __all__ = ["request", "ID", "TOKEN", "PROXY"] -ID = "id" -TOKEN = "TOKEN" -PROXY = None # 代理设置 + +class Config: + ID = "id" + TOKEN = "TOKEN" + PROXY = None # 代理设置 + TTL = 600 class API: @@ -44,7 +47,7 @@ def signature(params): params.update({ 'Format': 'json', 'Version': '2015-01-09', - 'AccessKeyId': ID, + 'AccessKeyId': Config.ID, 'Timestamp': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), 'SignatureMethod': 'HMAC-SHA1', 'SignatureNonce': uuid4(), @@ -55,7 +58,7 @@ def signature(params): sign = API.METHOD + "&" + quote_plus("/") + "&" + quote(query, safe='') debug("signString: %s", sign) - sign = hmac((TOKEN + "&").encode('utf-8'), + sign = hmac((Config.TOKEN + "&").encode('utf-8'), sign.encode('utf-8'), sha1).digest() sign = b64encode(sign).strip() params["Signature"] = sign @@ -71,8 +74,8 @@ def request(param=None, **params): params = signature(params) info("%s: %s", API.SITE, params) - if PROXY: - conn = HTTPSConnection(PROXY) + if Config.PROXY: + conn = HTTPSConnection(Config.PROXY) conn.set_tunnel(API.SITE, 443) else: conn = HTTPSConnection(API.SITE) diff --git a/dns/cloudflare.py b/dns/cloudflare.py index 411f139e2..ce8e53599 100644 --- a/dns/cloudflare.py +++ b/dns/cloudflare.py @@ -20,9 +20,12 @@ __author__ = 'TongYifan' -ID = "AUTH EMAIL" # CloudFlare 验证的是用户Email,等同于其他平台的userID -TOKEN = "API KEY" -PROXY = None # 代理设置 + +class Config: + ID = "AUTH EMAIL" # CloudFlare 验证的是用户Email,等同于其他平台的userID + TOKEN = "API KEY" + PROXY = None # 代理设置 + TTL = 600 class API: @@ -38,8 +41,8 @@ def request(method, action, param=None, **params): params.update(param) info("%s/%s : %s", API.SITE, action, params) - if PROXY: - conn = HTTPSConnection(PROXY) + if Config.PROXY: + conn = HTTPSConnection(Config.PROXY) conn.set_tunnel(API.SITE, 443) else: conn = HTTPSConnection(API.SITE) @@ -54,8 +57,8 @@ def request(method, action, param=None, **params): params = None conn.request(method, '/client/v4/zones' + action, params, {"Content-type": "application/json", - "X-Auth-Email": ID, - "X-Auth-Key": TOKEN}) + "X-Auth-Email": Config.ID, + "X-Auth-Key": Config.TOKEN}) response = conn.getresponse() res = response.read() conn.close() diff --git a/dns/dnscom.py b/dns/dnscom.py index 86fcbd0d8..c075e9b35 100644 --- a/dns/dnscom.py +++ b/dns/dnscom.py @@ -26,9 +26,12 @@ __author__ = 'Bigjin' # __all__ = ["request", "ID", "TOKEN", "PROXY"] -ID = "id" -TOKEN = "TOKEN" -PROXY = None # 代理设置 + +class Config: + ID = "id" + TOKEN = "TOKEN" + PROXY = None # 代理设置 + TTL = 600 class API: @@ -42,7 +45,7 @@ def signature(params): 计算签名,返回签名后的查询参数 """ params.update({ - 'apiKey': ID, + 'apiKey': Config.ID, 'timestamp': mktime(datetime.now().timetuple()), }) query = urlencode(sorted(params.items())) @@ -50,7 +53,7 @@ def signature(params): sign = query debug("signString: %s", sign) - sign = md5((sign + TOKEN).encode('utf-8')).hexdigest() + sign = md5((sign + Config.TOKEN).encode('utf-8')).hexdigest() params["hash"] = sign return params @@ -65,8 +68,8 @@ def request(action, param=None, **params): params = signature(params) info("%s/api/%s/ : params:%s", API.SITE, action, params) - if PROXY: - conn = HTTPSConnection(PROXY) + if Config.PROXY: + conn = HTTPSConnection(Config.PROXY) conn.set_tunnel(API.SITE, 443) else: conn = HTTPSConnection(API.SITE) diff --git a/dns/dnspod.py b/dns/dnspod.py index dfc091ccf..1e52ee888 100644 --- a/dns/dnspod.py +++ b/dns/dnspod.py @@ -20,10 +20,11 @@ __author__ = 'New Future' -ID = "token id" -TOKEN = "token key" -PROXY = None # 代理设置 -TTL = 600 +class Config: + ID = "token id" + TOKEN = "token key" + PROXY = None # 代理设置 + TTL = 600 class API: @@ -43,10 +44,9 @@ def request(action, param=None, **params): params.update({API.TOKEN_PARAM: '***', 'format': 'json'}) info("%s/%s : %s", API.SITE, action, params) - params[API.TOKEN_PARAM] = "%s,%s" % (ID, TOKEN) - - if PROXY: - conn = HTTPSConnection(PROXY) + params[API.TOKEN_PARAM] = "%s,%s" % (Config.ID, Config.TOKEN) + if Config.PROXY: + conn = HTTPSConnection(Config.PROXY) conn.set_tunnel(API.SITE, 443) else: conn = HTTPSConnection(API.SITE) @@ -169,7 +169,7 @@ def update_record(domain, value, record_type="A"): else: # create # http://www.dnspod.cn/docs/records.html#record-create res = request("Record.Create", domain_id=domainid, value=value, - sub_domain=sub, record_type=record_type, record_line=API.DEFAULT, ttl=TTL) + sub_domain=sub, record_type=record_type, record_line=API.DEFAULT, ttl=Config.TTL) if res: did = res.get("record")["id"] get_records.records[domainid][did] = res.get("record") diff --git a/run.py b/run.py index edc092ee8..141aa3d1f 100755 --- a/run.py +++ b/run.py @@ -85,11 +85,12 @@ def get_ip(ip_type): return False elif str(index).isdigit(): # 数字 local eth value = getattr(ip, "local_v" + ip_type)(index) - elif index.startswith('cmd:'): # cmd + elif index.startswith('cmd:'): # cmd value = str(check_output(index[4:]).strip().decode('utf-8')) - elif index.startswith('shell:'): # shell - value = str(check_output(index[6:], shell=True).strip().decode('utf-8')) - elif index.startswith('url:'): # 自定义 url + elif index.startswith('shell:'): # shell + value = str(check_output( + index[6:], shell=True).strip().decode('utf-8')) + elif index.startswith('url:'): # 自定义 url value = getattr(ip, "public_v" + ip_type)(index[4:]) elif index.startswith('regex:'): # 正则 regex value = getattr(ip, "regex_v" + ip_type)(index[6:]) @@ -155,7 +156,7 @@ def main(): # Dynamicly import the dns module as configuration dns_provider = str(get_config('dns', 'dnspod').lower()) dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider) - dns.ID, dns.TOKEN = get_config('id'), get_config('token') + dns.Config.ID, dns.Config.TOKEN = get_config('id'), get_config('token') if get_config('debug'): ip.DEBUG = get_config('debug') basicConfig( From c9fe4028bc22e44c6d7033487d308e9f76e7383a Mon Sep 17 00:00:00 2001 From: NewFututre Date: Sat, 2 Nov 2019 13:54:18 +0800 Subject: [PATCH 2/5] fix(log): decode & error status code --- dns/alidns.py | 6 +++--- dns/cloudflare.py | 7 ++++--- dns/dnscom.py | 7 ++++--- dns/dnspod.py | 6 +++--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/dns/alidns.py b/dns/alidns.py index 28bf1351d..930810d19 100644 --- a/dns/alidns.py +++ b/dns/alidns.py @@ -82,14 +82,14 @@ def request(param=None, **params): conn.request(API.METHOD, '/', urlencode(params), {"Content-type": "application/x-www-form-urlencoded"}) response = conn.getresponse() - data = response.read() + data = response.read().decode('utf8') conn.close() if response.status < 200 or response.status >= 300: - warning('%s : error:%s', params['Action'], data) + warning('%s : error[%d]: %s', params['Action'], response.status, data) raise Exception(data) else: - data = jsondecode(data.decode('utf8')) + data = jsondecode(data) debug('%s : result:%s', params['Action'], data) return data diff --git a/dns/cloudflare.py b/dns/cloudflare.py index ce8e53599..43752b870 100644 --- a/dns/cloudflare.py +++ b/dns/cloudflare.py @@ -7,7 +7,7 @@ """ from json import loads as jsondecode, dumps as jsonencode -from logging import debug, info +from logging import debug, info, warning try: # python 2 @@ -60,12 +60,13 @@ def request(method, action, param=None, **params): "X-Auth-Email": Config.ID, "X-Auth-Key": Config.TOKEN}) response = conn.getresponse() - res = response.read() + res = response.read().decode('utf8') conn.close() if response.status < 200 or response.status >= 300: + warning('%s : error[%d]:%s', action, response.status, res) raise Exception(res) else: - data = jsondecode(res.decode('utf8')) + data = jsondecode(res) debug('%s : result:%s', action, data) if not data: raise Exception("Empty Response") diff --git a/dns/dnscom.py b/dns/dnscom.py index c075e9b35..dced73ce9 100644 --- a/dns/dnscom.py +++ b/dns/dnscom.py @@ -9,7 +9,7 @@ from hashlib import md5 from json import loads as jsondecode -from logging import debug, info +from logging import debug, info, warning from time import mktime from datetime import datetime @@ -77,13 +77,14 @@ def request(action, param=None, **params): conn.request(API.METHOD, '/api/' + action + '/', urlencode(params), {"Content-type": "application/x-www-form-urlencoded"}) response = conn.getresponse() - result = response.read() + result = response.read().decode('utf8') conn.close() if response.status < 200 or response.status >= 300: + warning('%s : error[%d]:%s', action, response.status, result) raise Exception(result) else: - data = jsondecode(result.decode('utf8')) + data = jsondecode(result) debug('%s : result:%s', action, data) if data.get('code') != 0: raise Exception("api error:", data.get('message')) diff --git a/dns/dnspod.py b/dns/dnspod.py index 1e52ee888..262f8af92 100644 --- a/dns/dnspod.py +++ b/dns/dnspod.py @@ -54,14 +54,14 @@ def request(action, param=None, **params): conn.request(API.METHOD, '/' + action, urlencode(params), {"Content-type": "application/x-www-form-urlencoded"}) response = conn.getresponse() - res = response.read() + res = response.read().decode('utf8') conn.close() if response.status < 200 or response.status >= 300: - warning('%s : error:%s', action, res) + warning('%s : error[%d]:%s', action, response.status, res) raise Exception(res) else: - data = jsondecode(res.decode('utf8')) + data = jsondecode(res) debug('%s : result:%s', action, data) if not data: raise Exception("empty response") From 593194fe93ab7fe8e647fbbfb51c20fb166826ed Mon Sep 17 00:00:00 2001 From: NewFututre Date: Sat, 2 Nov 2019 14:49:44 +0800 Subject: [PATCH 3/5] feat(debug): show config path when debug --- run.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index 141aa3d1f..71a2b1ac4 100755 --- a/run.py +++ b/run.py @@ -152,7 +152,8 @@ def main(): action='version', version=__version__) parser.add_argument('-c', '--config', default="config.json", help="run with config file [配置文件路径]") - get_config(path=parser.parse_args().config) + config_file = parser.parse_args().config + get_config(path=config_file) # Dynamicly import the dns module as configuration dns_provider = str(get_config('dns', 'dnspod').lower()) dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider) @@ -162,7 +163,8 @@ def main(): basicConfig( level=DEBUG, format='%(asctime)s <%(module)s.%(funcName)s> %(lineno)d@%(pathname)s \n[%(levelname)s] %(message)s') - info("DDNS[%s] run: %s,%s", __version__, os_name, sys.platform) + print("DDNS[", __version__, "] run:", os_name, sys.platform) + print("Configuration was loaded from <==", path.abspath(config_file)) proxy = get_config('proxy') or 'DIRECT' proxy_list = proxy.strip('; ') .split(';') From 3f2a44b266d4302f5d1f3126829ad7378f0438f8 Mon Sep 17 00:00:00 2001 From: NewFututre Date: Sat, 2 Nov 2019 14:58:49 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat(run):=20=E4=BC=98=E5=8C=96=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index 71a2b1ac4..b3511f76e 100755 --- a/run.py +++ b/run.py @@ -165,16 +165,17 @@ def main(): format='%(asctime)s <%(module)s.%(funcName)s> %(lineno)d@%(pathname)s \n[%(levelname)s] %(message)s') print("DDNS[", __version__, "] run:", os_name, sys.platform) print("Configuration was loaded from <==", path.abspath(config_file)) + print("=" * 25, ctime(), "=" * 25, sep=' ') proxy = get_config('proxy') or 'DIRECT' proxy_list = proxy.strip('; ') .split(';') cache = get_config('cache', True) and Cache(CACHE_FILE) if cache is False: - warning("Cache is disabled!") + info("Cache is disabled!") elif len(cache) < 1 or get_config.time >= cache.time: + warning("Cache file is out of dated.") cache.clear() - print("=" * 25, ctime(), "=" * 25, sep=' ') update_ip('4', cache, dns, proxy_list) update_ip('6', cache, dns, proxy_list) From e360ed61e64aa0522c8147dd2332cdf8c60d0d38 Mon Sep 17 00:00:00 2001 From: NewFututre Date: Sat, 2 Nov 2019 21:18:53 +0800 Subject: [PATCH 5/5] fix(dnspod): UA #104 --- dns/dnspod.py | 7 +++++-- run.py | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/dns/dnspod.py b/dns/dnspod.py index 262f8af92..12e00b3f7 100644 --- a/dns/dnspod.py +++ b/dns/dnspod.py @@ -8,6 +8,7 @@ from json import loads as jsondecode from logging import debug, info, warning +from os import environ try: # python 2 from httplib import HTTPSConnection @@ -51,8 +52,10 @@ def request(action, param=None, **params): else: conn = HTTPSConnection(API.SITE) - conn.request(API.METHOD, '/' + action, urlencode(params), - {"Content-type": "application/x-www-form-urlencoded"}) + conn.request(API.METHOD, '/' + action, urlencode(params), { + "Content-type": "application/x-www-form-urlencoded", + "User-Agent": "DDNS/%s (ddns@newfuture.cc)" % environ.get("DDNS_VERSION", "1.0.0") + }) response = conn.getresponse() res = response.read().decode('utf8') conn.close() diff --git a/run.py b/run.py index b3511f76e..cfd65e140 100755 --- a/run.py +++ b/run.py @@ -28,6 +28,8 @@ Copyright (c) New Future (MIT License) """ % (__version__) +environ["DDNS_VERSION"] = "${BUILD_SOURCEBRANCHNAME}" + if getattr(sys, 'frozen', False): # https://github.com/pyinstaller/pyinstaller/wiki/Recipe-OpenSSL-Certificate environ['SSL_CERT_FILE'] = path.join(