From 91a82eb244c2d9ed06294506e022e3d4686489f8 Mon Sep 17 00:00:00 2001 From: New Future Date: Mon, 14 Jun 2021 08:39:04 +0000 Subject: [PATCH] feat(config): cli argument supports to set config --- run.py | 63 +++------------------------ util/config.py | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 56 deletions(-) create mode 100644 util/config.py diff --git a/run.py b/run.py index 84d2ba8d..31e1b374 100755 --- a/run.py +++ b/run.py @@ -6,10 +6,8 @@ @modified: rufengsuixing """ from __future__ import print_function -from argparse import ArgumentParser, RawTextHelpFormatter -from json import load as loadjson, dump as dumpjson from time import ctime -from os import path, environ, stat, name as os_name +from os import path, environ, name as os_name from tempfile import gettempdir from logging import DEBUG, basicConfig, info, warning, error, debug from subprocess import check_output @@ -18,6 +16,7 @@ from util import ip from util.cache import Cache +from util.config import init_config, get_config __version__ = "${BUILD_SOURCEBRANCHNAME}@${BUILD_DATE}" # CI 时会被Tag替换 __description__ = "automatically update DNS records to dynamic local IP [自动更新DNS记录指向本地IP]" @@ -38,48 +37,6 @@ CACHE_FILE = path.join(gettempdir(), 'ddns.cache') -def get_config(key=None, default=None, path="config.json"): - """ - 读取配置 - """ - if not hasattr(get_config, "config"): - try: - with open(path) as configfile: - get_config.config = loadjson(configfile) - get_config.time = stat(path).st_mtime - except IOError: - error(' Config file `%s` does not exist!' % path) - with open(path, 'w') as configfile: - configure = { - "$schema": "https://ddns.newfuture.cc/schema/v2.8.json", - "id": "YOUR ID or EMAIL for DNS Provider", - "token": "YOUR TOKEN or KEY for DNS Provider", - "dns": "dnspod", - "ipv4": [ - "newfuture.cc", - "ddns.newfuture.cc" - ], - "ipv6": [ - "newfuture.cc", - "ipv6.ddns.newfuture.cc" - ], - "index4": "default", - "index6": "default", - "ttl": None, - "proxy": None, - "debug": False, - } - dumpjson(configure, configfile, indent=2, sort_keys=True) - sys.stdout.write("New template configure file `%s` is generated.\n" % path) - sys.exit(1) - except: - sys.exit('fail to load config from file: %s' % path) - if key: - return get_config.config.get(key, default) - else: - return get_config.config - - def get_ip(ip_type, index="default"): """ get IP address @@ -138,7 +95,7 @@ def update_ip(ip_type, cache, dns, proxy_list): index_rule = get_config('index' + ip_type, "default") # 从配置中获取index配置 address = get_ip(ip_type, index_rule) if not address: - error('Fail to get %s address!' ,ipname) + error('Fail to get %s address!', ipname) return False elif cache and (address == cache[ipname]): print('.', end=" ") # 缓存命中 @@ -157,14 +114,7 @@ def main(): """ 更新 """ - parser = ArgumentParser(description=__description__, - epilog=__doc__, formatter_class=RawTextHelpFormatter) - parser.add_argument('-v', '--version', - action='version', version=__version__) - parser.add_argument('-c', '--config', - default="config.json", help="run with config file [配置文件路径]") - config_file = parser.parse_args().config - get_config(path=config_file) + init_config(__description__, __doc__, __version__) # Dynamicly import the dns module as configuration dns_provider = str(get_config('dns', 'dnspod').lower()) dns = getattr(__import__('dns', fromlist=[dns_provider]), dns_provider) @@ -177,7 +127,8 @@ def main(): level=DEBUG, 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("Configuration was loaded from <==", + path.abspath(get_config("config"))) print("=" * 25, ctime(), "=" * 25, sep=' ') proxy = get_config('proxy') or 'DIRECT' @@ -186,7 +137,7 @@ def main(): cache = get_config('cache', True) and Cache(CACHE_FILE) if cache is False: info("Cache is disabled!") - elif get_config.time >= cache.time: + elif get_config("config_modified_time") is None or get_config("config_modified_time") >= cache.time: warning("Cache file is out of dated.") cache.clear() elif not cache: diff --git a/util/config.py b/util/config.py new file mode 100644 index 00000000..7dda8d40 --- /dev/null +++ b/util/config.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +from argparse import ArgumentParser, ArgumentTypeError, Namespace, RawTextHelpFormatter +from json import load as loadjson, dump as dumpjson +from logging import error +from os import stat +from time import time + +import sys + +__cli_args = {} # type: Namespace +__config = {} # type: dict + + +def str2bool(v): + if isinstance(v, bool): + return v + if v.lower() in ('yes', 'true', 't', 'y', '1'): + return True + elif v.lower() in ('no', 'false', 'f', 'n', '0'): + return False + else: + raise ArgumentTypeError('Boolean value expected.') + + +def init_config(description, doc, version): + global __cli_args + """ + 配置 + """ + parser = ArgumentParser(description=description, + epilog=doc, formatter_class=RawTextHelpFormatter) + parser.add_argument('-v', '--version', + action='version', version=version) + parser.add_argument('-c', '--config', help="run with config file [配置文件路径]") + + # 参数定义 + parser.add_argument('--dns', help="DNS Provider [DNS服务提供商]", choices=[ + 'alidns', 'cloudflare', 'dnscom', 'dnspod', 'dnspod_com', 'he', 'huaweidns', 'callback']) + parser.add_argument('--id', help="api ID [授权账户]") + parser.add_argument('--token', help="api token or Secret key [授权访问凭证或密钥]") + parser.add_argument('--ipv4', nargs="*", + help="ipv4 domain list [IPV4域名列表]") + parser.add_argument('--ipv6', nargs="*", + help="ipv6 domain list [IPV6域名列表]") + parser.add_argument('--index4', help="the way to get ipv4 [IPV4 获取方式]") + parser.add_argument('--index6', help="the way to get ipv6 [IPV6获取方式]") + parser.add_argument('--ttl', type=int, help="ttl for DNS [DNS 解析 TTL 时间]") + parser.add_argument('--proxy', nargs="*", + help="https proxy [设置http 代理,多代理逐个尝试直到成功]") + parser.add_argument('--debug', type=str2bool, nargs='?', + const=True, help="debug mode [是否开启调试,默认否]", ) + parser.add_argument('--cache', type=str2bool, nargs='?', + const=True, help="eusing cache [是否缓存记录,默认是]") + + __cli_args = parser.parse_args() + has_cli_config = __cli_args.token or __cli_args.id + __load_config(__cli_args.config or "config.json", has_cli_config) + if __cli_args.config is None: + __cli_args.config = "config.json" + + +def __load_config(path="config.json", skip_auto_generation=False): + """ + 加载配置 + """ + global __config, config_modified_time + try: + with open(path) as configfile: + __config = loadjson(configfile) + __config["config_modified_time"] = stat(path).st_mtime + except IOError: + if skip_auto_generation: + __config["config_modified_time"] = time() + return + error(' Config file `%s` does not exist!' % path) + with open(path, 'w') as configfile: + configure = { + "$schema": "https://ddns.newfuture.cc/schema/v2.8.json", + "id": "YOUR ID or EMAIL for DNS Provider", + "token": "YOUR TOKEN or KEY for DNS Provider", + "dns": "dnspod", + "ipv4": [ + "newfuture.cc", + "ddns.newfuture.cc" + ], + "ipv6": [ + "newfuture.cc", + "ipv6.ddns.newfuture.cc" + ], + "index4": "default", + "index6": "default", + "ttl": None, + "proxy": None, + "debug": False, + } + dumpjson(configure, configfile, indent=2, sort_keys=True) + sys.stdout.write( + "New template configure file `%s` is generated.\n" % path) + sys.exit(1) + except: + sys.exit('fail to load config from file: %s' % path) + + +def get_config(key, default=None): + """ + 读取配置 + """ + if hasattr(__cli_args, key) and getattr(__cli_args, key) is not None: + return getattr(__cli_args, key) + if key in __config: + return __config.get(key) + return default