ddns 4.0.0b3__tar.gz → 4.0.0b5__tar.gz

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ddns
3
- Version: 4.0.0b3
3
+ Version: 4.0.0b5
4
4
  Summary: automatically update DNS records to dynamic local IP [自动更新DNS记录指向本地IP]
5
5
  Home-page: https://ddns.newfuture.cc
6
6
  Author: NewFuture
@@ -57,8 +57,12 @@ Dynamic: summary
57
57
 
58
58
  - 兼容和跨平台:
59
59
  - [Docker (@NN708)](https://hub.docker.com/r/newfuture/ddns) [![Docker Image Size](https://img.shields.io/docker/image-size/newfuture/ddns/latest?logo=docker&style=social)](https://hub.docker.com/r/newfuture/ddns)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?style=social)](https://hub.docker.com/r/newfuture/ddns)
60
- - [PIP 安装 (兼容Python2)](https://pypi.org/project/ddns/) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?logo=pypi&style=social) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social)
61
60
  - [二进制文件](https://github.com/NewFuture/DDNS/releases/latest) ![cross platform](https://img.shields.io/badge/system-windows_%7C%20linux_%7C%20mac-success.svg?style=social)
61
+
62
+ - 配置方式:
63
+ - [命令行参数](#详细配置)
64
+ - [JSON 配置文件](#详细配置)
65
+ - [环境变量配置](doc/env.md) 📖
62
66
 
63
67
  - 域名支持:
64
68
  - 多个域名支持
@@ -157,6 +161,8 @@ Dynamic: summary
157
161
  2. JSON 配置文件(值为 null 认为是有效值,会覆盖环境变量的设置,如果没有对应的 key 则会尝试使用环境变量)
158
162
  3. 环境变量 DDNS_ 前缀加上 key 全大写或者全小写,点转下划线(`${ddns_id}` 或 `${DDNS_ID}`,`${DDNS_LOG_LEVEL}`)
159
163
 
164
+ > 📖 **环境变量详细配置**: 查看 [环境变量配置文档](doc/env.md) 了解所有环境变量的详细用法和示例
165
+
160
166
  <details open>
161
167
  <summary markdown="span">config.json 配置文件</summary>
162
168
 
@@ -16,8 +16,12 @@
16
16
 
17
17
  - 兼容和跨平台:
18
18
  - [Docker (@NN708)](https://hub.docker.com/r/newfuture/ddns) [![Docker Image Size](https://img.shields.io/docker/image-size/newfuture/ddns/latest?logo=docker&style=social)](https://hub.docker.com/r/newfuture/ddns)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?style=social)](https://hub.docker.com/r/newfuture/ddns)
19
- - [PIP 安装 (兼容Python2)](https://pypi.org/project/ddns/) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?logo=pypi&style=social) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social)
20
19
  - [二进制文件](https://github.com/NewFuture/DDNS/releases/latest) ![cross platform](https://img.shields.io/badge/system-windows_%7C%20linux_%7C%20mac-success.svg?style=social)
20
+
21
+ - 配置方式:
22
+ - [命令行参数](#详细配置)
23
+ - [JSON 配置文件](#详细配置)
24
+ - [环境变量配置](doc/env.md) 📖
21
25
 
22
26
  - 域名支持:
23
27
  - 多个域名支持
@@ -116,6 +120,8 @@
116
120
  2. JSON 配置文件(值为 null 认为是有效值,会覆盖环境变量的设置,如果没有对应的 key 则会尝试使用环境变量)
117
121
  3. 环境变量 DDNS_ 前缀加上 key 全大写或者全小写,点转下划线(`${ddns_id}` 或 `${DDNS_ID}`,`${DDNS_LOG_LEVEL}`)
118
122
 
123
+ > 📖 **环境变量详细配置**: 查看 [环境变量配置文档](doc/env.md) 了解所有环境变量的详细用法和示例
124
+
119
125
  <details open>
120
126
  <summary markdown="span">config.json 配置文件</summary>
121
127
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ddns
3
- Version: 4.0.0b3
3
+ Version: 4.0.0b5
4
4
  Summary: automatically update DNS records to dynamic local IP [自动更新DNS记录指向本地IP]
5
5
  Home-page: https://ddns.newfuture.cc
6
6
  Author: NewFuture
@@ -57,8 +57,12 @@ Dynamic: summary
57
57
 
58
58
  - 兼容和跨平台:
59
59
  - [Docker (@NN708)](https://hub.docker.com/r/newfuture/ddns) [![Docker Image Size](https://img.shields.io/docker/image-size/newfuture/ddns/latest?logo=docker&style=social)](https://hub.docker.com/r/newfuture/ddns)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?style=social)](https://hub.docker.com/r/newfuture/ddns)
60
- - [PIP 安装 (兼容Python2)](https://pypi.org/project/ddns/) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?logo=pypi&style=social) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social)
61
60
  - [二进制文件](https://github.com/NewFuture/DDNS/releases/latest) ![cross platform](https://img.shields.io/badge/system-windows_%7C%20linux_%7C%20mac-success.svg?style=social)
61
+
62
+ - 配置方式:
63
+ - [命令行参数](#详细配置)
64
+ - [JSON 配置文件](#详细配置)
65
+ - [环境变量配置](doc/env.md) 📖
62
66
 
63
67
  - 域名支持:
64
68
  - 多个域名支持
@@ -157,6 +161,8 @@ Dynamic: summary
157
161
  2. JSON 配置文件(值为 null 认为是有效值,会覆盖环境变量的设置,如果没有对应的 key 则会尝试使用环境变量)
158
162
  3. 环境变量 DDNS_ 前缀加上 key 全大写或者全小写,点转下划线(`${ddns_id}` 或 `${DDNS_ID}`,`${DDNS_LOG_LEVEL}`)
159
163
 
164
+ > 📖 **环境变量详细配置**: 查看 [环境变量配置文档](doc/env.md) 了解所有环境变量的详细用法和示例
165
+
160
166
  <details open>
161
167
  <summary markdown="span">config.json 配置文件</summary>
162
168
 
@@ -106,10 +106,11 @@ def get_domain_id(domain):
106
106
  return get_domain_id.domain_list[domain]
107
107
  else:
108
108
  try:
109
- info = request('Domain.Info', domain=domain)
110
- except Exception:
109
+ d_info = request('Domain.Info', domain=domain)
110
+ except Exception as e:
111
+ info("get_domain_id(%s) error: %s", domain, e)
111
112
  return
112
- did = info.get("domain", {}).get("id")
113
+ did = d_info.get("domain", {}).get("id")
113
114
  if did:
114
115
  get_domain_id.domain_list[domain] = did
115
116
  return did
@@ -9,9 +9,10 @@ DDNS
9
9
  # nuitka-project: --product-version=0.0.0
10
10
 
11
11
  from os import path, environ, name as os_name
12
+ from io import TextIOWrapper
13
+ from subprocess import check_output
12
14
  from tempfile import gettempdir
13
15
  from logging import basicConfig, info, warning, error, debug
14
- from subprocess import check_output
15
16
 
16
17
  import sys
17
18
 
@@ -19,7 +20,7 @@ from util import ip
19
20
  from util.cache import Cache
20
21
  from util.config import init_config, get_config
21
22
 
22
- __version__ = "v4.0.0-beta3@2025-06-04T17:36:22+00:00" # CI 时会被Tag替换
23
+ __version__ = "v4.0.0-beta5@2025-06-12T01:13:18+00:00" # CI 时会被Tag替换
23
24
  __description__ = "automatically update DNS records to dynamic local IP [自动更新DNS记录指向本地IP]"
24
25
  __doc__ = """
25
26
  ddns[%s]
@@ -28,12 +29,18 @@ ddns[%s]
28
29
  Copyright (c) New Future (MIT License)
29
30
  """ % (__version__)
30
31
 
31
- environ["DDNS_VERSION"] = "v4.0.0-beta3"
32
+ environ["DDNS_VERSION"] = "v4.0.0-beta5"
33
+
32
34
 
33
- if getattr(sys, 'frozen', False):
34
- # https://github.com/pyinstaller/pyinstaller/wiki/Recipe-OpenSSL-Certificate
35
- environ['SSL_CERT_FILE'] = path.join(
36
- getattr(sys, '_MEIPASS'), 'lib', 'cert.pem')
35
+ def is_false(value):
36
+ """
37
+ 判断值是否为 False
38
+ 字符串 'false', 或者 False, 或者 'none';
39
+ 0 不是 False
40
+ """
41
+ if isinstance(value, str):
42
+ return value.strip().lower() in ['false', 'none']
43
+ return value is False
37
44
 
38
45
 
39
46
  def get_ip(ip_type, index="default"):
@@ -45,7 +52,7 @@ def get_ip(ip_type, index="default"):
45
52
  value = None
46
53
  try:
47
54
  debug("get_ip(%s, %s)", ip_type, index)
48
- if index is False: # disabled
55
+ if is_false(index): # disabled
49
56
  return False
50
57
  elif isinstance(index, list): # 如果获取到的规则是列表,则依次判断列表中每一个规则,直到获取到IP
51
58
  for i in index:
@@ -153,7 +160,7 @@ def main():
153
160
  if cache is False:
154
161
  info('Cache is disabled!')
155
162
  elif not get_config('config_modified_time') or get_config('config_modified_time') >= cache.time:
156
- warning('Cache file is out of dated.')
163
+ warning('Cache file is outdated.')
157
164
  cache.clear()
158
165
  else:
159
166
  debug('Cache is empty.')
@@ -162,8 +169,9 @@ def main():
162
169
 
163
170
 
164
171
  if __name__ == '__main__':
165
- if sys.version_info.major == 3 and os_name == 'nt':
166
- from io import TextIOWrapper
167
- sys.stdout = TextIOWrapper(sys.stdout.detach(), encoding='utf-8')
168
- sys.stderr = TextIOWrapper(sys.stderr.detach(), encoding='utf-8')
172
+ encoding = sys.stdout.encoding
173
+ if encoding is not None and encoding.lower() != 'utf-8' and hasattr(sys.stdout, 'buffer'):
174
+ # 兼容windows 和部分ASCII编码的老旧系统
175
+ sys.stdout = TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
176
+ sys.stderr = TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
169
177
  main()
@@ -38,7 +38,7 @@ elif 'BUILD_SOURCEBRANCHNAME' in environ:
38
38
  elif 'GITHUB_REF_NAME' in environ: # github actions
39
39
  ref = environ['GITHUB_REF_NAME']
40
40
  if ref == 'master' or ref == 'main': # CI
41
- version = '0.0.b' + str(int(time()))
41
+ version = '4.0.b' + str(int(time()))
42
42
  elif ref.startswith('v') or ref.startswith('V'): # Tag
43
43
  version = ref
44
44
  else: # PR
@@ -11,10 +11,9 @@ from time import time
11
11
 
12
12
  from logging import info, debug, warning
13
13
 
14
- try:
14
+ try: # python 3
15
15
  from collections.abc import MutableMapping
16
- except ImportError:
17
- # Python 2 imports
16
+ except ImportError: # python 2
18
17
  from collections import MutableMapping
19
18
 
20
19
 
@@ -4,6 +4,7 @@ from argparse import Action, ArgumentParser, Namespace, RawTextHelpFormatter
4
4
  from json import load as loadjson, dump as dumpjson
5
5
  from os import stat, environ, path
6
6
  from logging import error, getLevelName
7
+ from ast import literal_eval
7
8
 
8
9
  import sys
9
10
 
@@ -13,6 +14,11 @@ __config = {} # type: dict
13
14
  log_levels = ['CRITICAL', 'FATAL', 'ERROR',
14
15
  'WARN', 'WARNING', 'INFO', 'DEBUG', 'NOTSET']
15
16
 
17
+ # 支持数组的参数列表
18
+ ARRAY_PARAMS = ['index4', 'index6', 'ipv4', 'ipv6', 'proxy']
19
+ # 简单数组,支持’,’, ‘;’ 分隔的参数列表
20
+ SIMPLE_ARRAY_PARAMS = ['ipv4', 'ipv6', 'proxy']
21
+
16
22
 
17
23
  def str2bool(v):
18
24
  """
@@ -35,6 +41,32 @@ def log_level(value):
35
41
  return getLevelName(value.upper())
36
42
 
37
43
 
44
+ def parse_array_string(value, enable_simple_split):
45
+ """
46
+ 解析数组字符串
47
+ 仅当 trim 之后以 '[' 开头以 ']' 结尾时,才尝试使用 ast.literal_eval 解析
48
+ 默认返回原始字符串
49
+ """
50
+ if not isinstance(value, str):
51
+ return value
52
+
53
+ trimmed = value.strip()
54
+ if trimmed.startswith('[') and trimmed.endswith(']'):
55
+ try:
56
+ # 尝试使用 ast.literal_eval 解析数组
57
+ parsed_value = literal_eval(trimmed)
58
+ # 确保解析结果是列表或元组
59
+ if isinstance(parsed_value, (list, tuple)):
60
+ return list(parsed_value)
61
+ except (ValueError, SyntaxError) as e:
62
+ # 解析失败时返回原始字符串
63
+ error('Failed to parse array string: %s. Exception: %s', value, e)
64
+ elif enable_simple_split and ',' in trimmed:
65
+ # 尝试使用逗号或分号分隔符解析
66
+ return [item.strip() for item in trimmed.split(',') if item.strip()]
67
+ return value
68
+
69
+
38
70
  def init_config(description, doc, version):
39
71
  """
40
72
  配置
@@ -128,14 +160,16 @@ def get_config(key, default=None):
128
160
  return getattr(__cli_args, key)
129
161
  if key in __config:
130
162
  return __config.get(key)
163
+ # 检查环境变量
131
164
  env_name = 'DDNS_' + key.replace('.', '_') # type:str
132
- if env_name in environ: # 环境变量
133
- return environ.get(env_name)
134
- elif env_name.upper() in environ: # 大写环境变量
135
- return environ.get(env_name.upper())
136
- elif env_name.lower() in environ: # 小写环境变量
137
- return environ.get(env_name.lower())
138
- return default
165
+ variations = [env_name, env_name.upper(), env_name.lower()]
166
+ value = next((environ.get(v) for v in variations if v in environ), None)
167
+
168
+ # 如果找到环境变量值且参数支持数组,尝试解析为数组
169
+ if value is not None and key in ARRAY_PARAMS:
170
+ return parse_array_string(value, key in SIMPLE_ARRAY_PARAMS)
171
+
172
+ return value if value is not None else default
139
173
 
140
174
 
141
175
  class ExtendAction(Action):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes