Bläddra i källkod

feat(config): cli argument supports to set config

New Future 4 år sedan
förälder
incheckning
91a82eb244
2 ändrade filer med 120 tillägg och 56 borttagningar
  1. 7 56
      run.py
  2. 113 0
      util/config.py

+ 7 - 56
run.py

@@ -6,10 +6,8 @@ DDNS
 @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 @@ import sys
 
 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 @@ if getattr(sys, 'frozen', False):
 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:

+ 113 - 0
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