pymecli 0.6.2__tar.gz → 0.6.3__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.
Files changed (52) hide show
  1. {pymecli-0.6.2 → pymecli-0.6.3}/PKG-INFO +10 -2
  2. {pymecli-0.6.2 → pymecli-0.6.3}/README.md +9 -1
  3. {pymecli-0.6.2 → pymecli-0.6.3}/cli/etcd_sync.py +35 -6
  4. {pymecli-0.6.2 → pymecli-0.6.3}/pyproject.toml +1 -1
  5. {pymecli-0.6.2 → pymecli-0.6.3}/.gitignore +0 -0
  6. {pymecli-0.6.2 → pymecli-0.6.3}/api/__init__.py +0 -0
  7. {pymecli-0.6.2 → pymecli-0.6.3}/api/v1/__init__.py +0 -0
  8. {pymecli-0.6.2 → pymecli-0.6.3}/api/v1/clash.py +0 -0
  9. {pymecli-0.6.2 → pymecli-0.6.3}/api/v1/redis.py +0 -0
  10. {pymecli-0.6.2 → pymecli-0.6.3}/cli/__init__.py +0 -0
  11. {pymecli-0.6.2 → pymecli-0.6.3}/cli/bitget.py +0 -0
  12. {pymecli-0.6.2 → pymecli-0.6.3}/cli/dnspod.py +0 -0
  13. {pymecli-0.6.2 → pymecli-0.6.3}/cli/dst.py +0 -0
  14. {pymecli-0.6.2 → pymecli-0.6.3}/cli/example.py +0 -0
  15. {pymecli-0.6.2 → pymecli-0.6.3}/cli/fast.py +0 -0
  16. {pymecli-0.6.2 → pymecli-0.6.3}/cli/gate.py +0 -0
  17. {pymecli-0.6.2 → pymecli-0.6.3}/cli/okx.py +0 -0
  18. {pymecli-0.6.2 → pymecli-0.6.3}/cli/quark.py +0 -0
  19. {pymecli-0.6.2 → pymecli-0.6.3}/cli/redis_csv.py +0 -0
  20. {pymecli-0.6.2 → pymecli-0.6.3}/cli/tele.py +0 -0
  21. {pymecli-0.6.2 → pymecli-0.6.3}/cli/util.py +0 -0
  22. {pymecli-0.6.2 → pymecli-0.6.3}/core/__init__.py +0 -0
  23. {pymecli-0.6.2 → pymecli-0.6.3}/core/clash.py +0 -0
  24. {pymecli-0.6.2 → pymecli-0.6.3}/core/config.py +0 -0
  25. {pymecli-0.6.2 → pymecli-0.6.3}/core/redis_client.py +0 -0
  26. {pymecli-0.6.2 → pymecli-0.6.3}/crypto/__init__.py +0 -0
  27. {pymecli-0.6.2 → pymecli-0.6.3}/crypto/bitget.py +0 -0
  28. {pymecli-0.6.2 → pymecli-0.6.3}/crypto/gate.py +0 -0
  29. {pymecli-0.6.2 → pymecli-0.6.3}/crypto/okx.py +0 -0
  30. {pymecli-0.6.2 → pymecli-0.6.3}/data/__init__.py +0 -0
  31. {pymecli-0.6.2 → pymecli-0.6.3}/data/dou_dict.py +0 -0
  32. {pymecli-0.6.2 → pymecli-0.6.3}/data/dou_list.py +0 -0
  33. {pymecli-0.6.2 → pymecli-0.6.3}/data/main.py +0 -0
  34. {pymecli-0.6.2 → pymecli-0.6.3}/data/template.yaml +0 -0
  35. {pymecli-0.6.2 → pymecli-0.6.3}/models/__init__.py +0 -0
  36. {pymecli-0.6.2 → pymecli-0.6.3}/models/douzero_model.py +0 -0
  37. {pymecli-0.6.2 → pymecli-0.6.3}/models/ocr_model.py +0 -0
  38. {pymecli-0.6.2 → pymecli-0.6.3}/models/response.py +0 -0
  39. {pymecli-0.6.2 → pymecli-0.6.3}/utils/__init__.py +0 -0
  40. {pymecli-0.6.2 → pymecli-0.6.3}/utils/elapsed.py +0 -0
  41. {pymecli-0.6.2 → pymecli-0.6.3}/utils/etcd.py +0 -0
  42. {pymecli-0.6.2 → pymecli-0.6.3}/utils/helper.py +0 -0
  43. {pymecli-0.6.2 → pymecli-0.6.3}/utils/logger.py +0 -0
  44. {pymecli-0.6.2 → pymecli-0.6.3}/utils/mysql.py +0 -0
  45. {pymecli-0.6.2 → pymecli-0.6.3}/utils/notify.py +0 -0
  46. {pymecli-0.6.2 → pymecli-0.6.3}/utils/path.py +0 -0
  47. {pymecli-0.6.2 → pymecli-0.6.3}/utils/pd.py +0 -0
  48. {pymecli-0.6.2 → pymecli-0.6.3}/utils/pyredis.py +0 -0
  49. {pymecli-0.6.2 → pymecli-0.6.3}/utils/sendNotify.py +0 -0
  50. {pymecli-0.6.2 → pymecli-0.6.3}/utils/sleep.py +0 -0
  51. {pymecli-0.6.2 → pymecli-0.6.3}/utils/text.py +0 -0
  52. {pymecli-0.6.2 → pymecli-0.6.3}/utils/toml.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pymecli
3
- Version: 0.6.2
3
+ Version: 0.6.3
4
4
  Summary: My CLI
5
5
  Project-URL: Homepage, https://pypi.org/project/pymecli
6
6
  Project-URL: Repository, https://github.com/meme2046/pymecli
@@ -88,6 +88,15 @@ uv run quark check
88
88
  ```
89
89
 
90
90
  # dnspod
91
+ ## 环境变量说明
92
+ - `DP_ID`: DNSPod 登录 ID
93
+ - `DP_TOKEN`: DNSPod 登录 Token
94
+ - `DP_DOMAIN`: 域名 (如 cursor.email)
95
+ - `DP_RECORD_ID`: IPv4 A 记录 ID
96
+ - `DP_RECORD_ID_IPV6`: IPv6 AAAA 记录 ID
97
+ - `DP_SUB_DOMAIN`: 子域名前缀 (默认 "api")
98
+ - `DP_RECORD_LINE`: 记录线路 (默认 "默认")
99
+ ## 示例
91
100
  ```shell
92
101
  # 列出域名下所有记录(先跑这个查 record_id)
93
102
  uv run dnspod list
@@ -97,6 +106,5 @@ uv run dnspod ddns
97
106
  uv run dnspod ddns --force
98
107
  # 更新 IPv6 AAAA 记录(从 Redis 读 local.IPv6)
99
108
  uv run dnspod ddns6
100
-
101
109
  uv run dnspod ddns6 --force
102
110
  ```
@@ -49,6 +49,15 @@ uv run quark check
49
49
  ```
50
50
 
51
51
  # dnspod
52
+ ## 环境变量说明
53
+ - `DP_ID`: DNSPod 登录 ID
54
+ - `DP_TOKEN`: DNSPod 登录 Token
55
+ - `DP_DOMAIN`: 域名 (如 cursor.email)
56
+ - `DP_RECORD_ID`: IPv4 A 记录 ID
57
+ - `DP_RECORD_ID_IPV6`: IPv6 AAAA 记录 ID
58
+ - `DP_SUB_DOMAIN`: 子域名前缀 (默认 "api")
59
+ - `DP_RECORD_LINE`: 记录线路 (默认 "默认")
60
+ ## 示例
52
61
  ```shell
53
62
  # 列出域名下所有记录(先跑这个查 record_id)
54
63
  uv run dnspod list
@@ -58,6 +67,5 @@ uv run dnspod ddns
58
67
  uv run dnspod ddns --force
59
68
  # 更新 IPv6 AAAA 记录(从 Redis 读 local.IPv6)
60
69
  uv run dnspod ddns6
61
-
62
70
  uv run dnspod ddns6 --force
63
71
  ```
@@ -25,6 +25,32 @@ logger = get_logger(__name__, level=logging.INFO)
25
25
  DEFAULT_TABLE = "kvs"
26
26
 
27
27
 
28
+ # ---------------------------------------------------------------------------
29
+ # 智能 JSON 转换(etcd ↔ 文件)
30
+ # ---------------------------------------------------------------------------
31
+
32
+ def _try_json_loads(s: str):
33
+ """尝试把字符串当 JSON 解析,成功返回对象,失败返回原字符串。
34
+
35
+ 只接受以 { / [ 开头的内容,避免把 "123" "true" 这类普通值也误解析。
36
+ """
37
+ s = s.strip()
38
+ if not s or s[0] not in "{[":
39
+ return s
40
+ try:
41
+ return json.loads(s)
42
+ except (json.JSONDecodeError, TypeError):
43
+ return s
44
+
45
+
46
+ def _json_or_str(v) -> str:
47
+ """dict/list → 紧凑 JSON 字符串;其他 → str(v)。"""
48
+ if isinstance(v, (dict, list)):
49
+ # separators=(",", ":") 去掉空格,保持 etcd 里原样
50
+ return json.dumps(v, ensure_ascii=False, separators=(",", ":"))
51
+ return str(v)
52
+
53
+
28
54
  @app.command("mysql2etcd")
29
55
  def mysql_to_etcd(
30
56
  prefix: str = typer.Argument(
@@ -182,17 +208,19 @@ def etcd_to_json(
182
208
  ):
183
209
  """将 etcd 中指定前缀的 key/value 导出为 JSON 文件。
184
210
 
185
- JSON 格式为简单的 {key: value} 对象,value 均为字符串。
211
+ 智能转换:如果 etcd value 是 JSON 字符串(以 { 或 [ 开头),
212
+ 会自动解析为真正的 JSON 对象写入文件,编辑更方便;
213
+ 普通字符串保持原样。
186
214
  """
187
215
  etcd = get_etcd_client(env_path)
188
216
 
189
217
  try:
190
- data: dict[str, str] = {}
218
+ data: dict = {}
191
219
  iterator = etcd.get_all() if not prefix else etcd.get_prefix(prefix)
192
220
  for value, meta in iterator:
193
221
  k = meta.key.decode("utf-8")
194
- v = value.decode("utf-8") if isinstance(value, bytes) else value
195
- data[k] = v
222
+ raw = value.decode("utf-8") if isinstance(value, bytes) else value
223
+ data[k] = _try_json_loads(raw)
196
224
 
197
225
  with open(file_path, "w", encoding="utf-8") as f:
198
226
  json.dump(data, f, ensure_ascii=False, indent=2)
@@ -226,7 +254,8 @@ def json_to_etcd(
226
254
  ):
227
255
  """将 JSON 文件中的 key/value 写入 etcd。
228
256
 
229
- JSON 格式应为 {key: value} 对象,value 会被转为字符串。
257
+ 智能转换:dict/list 会自动序列化为紧凑 JSON 字符串写入 etcd;
258
+ 字符串/数字/布尔保持 str() 转换。
230
259
  --prefix 会加到每个 key 前面(如果 key 本身已带该前缀则不重复加)。
231
260
  """
232
261
  etcd = get_etcd_client(env_path)
@@ -253,7 +282,7 @@ def json_to_etcd(
253
282
  if prefix and not k.startswith(prefix):
254
283
  full_key = prefix.rstrip("/") + "/" + k.lstrip("/")
255
284
 
256
- etcd.put(full_key, str(v))
285
+ etcd.put(full_key, _json_or_str(v))
257
286
  logger.debug("put: %s -> %s", full_key, v)
258
287
  count += 1
259
288
 
@@ -38,7 +38,7 @@
38
38
  name = "pymecli"
39
39
  readme = "README.md"
40
40
  requires-python = ">=3.10"
41
- version = "0.6.2"
41
+ version = "0.6.3"
42
42
 
43
43
  [project.urls]
44
44
  Homepage = "https://pypi.org/project/pymecli"
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
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
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
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