pymecli 0.4.3__tar.gz → 0.4.4__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.
- {pymecli-0.4.3 → pymecli-0.4.4}/PKG-INFO +14 -3
- pymecli-0.4.4/README.md +26 -0
- pymecli-0.4.4/cli/dst.py +222 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/pyproject.toml +4 -1
- pymecli-0.4.3/README.md +0 -16
- {pymecli-0.4.3 → pymecli-0.4.4}/.gitignore +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/api/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/api/v1/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/api/v1/clash.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/api/v1/redis.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/baidu.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/bitget.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/example.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/fast.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/gate.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/redis_csv.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/cli/util.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/core/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/core/clash.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/core/config.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/core/redis_client.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/crypto/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/crypto/bitget.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/crypto/gate.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/data/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/data/dou_dict.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/data/dou_list.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/data/main.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/data/template.yaml +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/models/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/models/douzero_model.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/models/ocr_model.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/models/response.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/__init__.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/elapsed.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/helper.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/logger.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/mysql.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/path.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/pd.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/pyredis.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/sleep.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/text.py +0 -0
- {pymecli-0.4.3 → pymecli-0.4.4}/utils/toml.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymecli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
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
|
|
@@ -22,6 +22,7 @@ Requires-Dist: pyyaml>=6.0.3
|
|
|
22
22
|
Requires-Dist: redis[hiredis]>=7.1.0
|
|
23
23
|
Requires-Dist: requests[socks]>=2.32.5
|
|
24
24
|
Requires-Dist: selenium>=4.40.0
|
|
25
|
+
Requires-Dist: slpp>=1.2.3
|
|
25
26
|
Requires-Dist: sqlalchemy>=2.0.45
|
|
26
27
|
Requires-Dist: tabulate>=0.9.0
|
|
27
28
|
Requires-Dist: toml>=0.10.2
|
|
@@ -42,7 +43,17 @@ uv run example goodbye Xiaoming -f
|
|
|
42
43
|
# fastapi server
|
|
43
44
|
|
|
44
45
|
```shell
|
|
45
|
-
uv run fast --port 8877
|
|
46
|
+
uv run fast --port 8877 # local server
|
|
46
47
|
uv build
|
|
47
|
-
uv publish --token
|
|
48
|
+
uv publish --token < TOKEN > # publish
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
# dontstarvetogether
|
|
52
|
+
|
|
53
|
+
1. 饥荒专服禁client mods使用, 更新client mods version, modoverrides.lua:
|
|
54
|
+
|
|
55
|
+
```shell
|
|
56
|
+
uv run dst cmu d:/.backups/dontstarvetogether/modoverrides.lua -o c:/.dst/save/Cluster_1/Master/modoverrides.lua -o c:/.dst/save/Cluster_1/Caves/modoverrides.lua
|
|
57
|
+
|
|
58
|
+
uv run dst cml d:/.backups/dontstarvetogether/modoverrides.lua -m 3486375086
|
|
48
59
|
```
|
pymecli-0.4.4/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typer example
|
|
2
|
+
|
|
3
|
+
```shell
|
|
4
|
+
uv run example hello Xiaoming
|
|
5
|
+
uv run example hello Xiaoming --from Pymecli
|
|
6
|
+
uv run example goodbye Xiaoming
|
|
7
|
+
uv run example goodbye Xiaoming -f
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
# fastapi server
|
|
11
|
+
|
|
12
|
+
```shell
|
|
13
|
+
uv run fast --port 8877 # local server
|
|
14
|
+
uv build
|
|
15
|
+
uv publish --token < TOKEN > # publish
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
# dontstarvetogether
|
|
19
|
+
|
|
20
|
+
1. 饥荒专服禁client mods使用, 更新client mods version, modoverrides.lua:
|
|
21
|
+
|
|
22
|
+
```shell
|
|
23
|
+
uv run dst cmu d:/.backups/dontstarvetogether/modoverrides.lua -o c:/.dst/save/Cluster_1/Master/modoverrides.lua -o c:/.dst/save/Cluster_1/Caves/modoverrides.lua
|
|
24
|
+
|
|
25
|
+
uv run dst cml d:/.backups/dontstarvetogether/modoverrides.lua -m 3486375086
|
|
26
|
+
```
|
pymecli-0.4.4/cli/dst.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
import typer
|
|
6
|
+
from slpp import slpp as lua
|
|
7
|
+
|
|
8
|
+
app = typer.Typer()
|
|
9
|
+
|
|
10
|
+
STEAM_API_URL = (
|
|
11
|
+
"https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v0001"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_mod_versions(workshop_ids: List[str]) -> Dict[str, Dict[str, Optional[str]]]:
|
|
16
|
+
if not workshop_ids:
|
|
17
|
+
return {}
|
|
18
|
+
|
|
19
|
+
data = {"itemcount": str(len(workshop_ids))}
|
|
20
|
+
for i, wid in enumerate(workshop_ids):
|
|
21
|
+
data[f"publishedfileids[{i}]"] = wid
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
response = requests.post(STEAM_API_URL, data=data, timeout=15)
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
result = response.json()
|
|
27
|
+
except Exception as e:
|
|
28
|
+
typer.secho(f"❌ Steam API 请求失败: {e}", fg=typer.colors.RED)
|
|
29
|
+
return {}
|
|
30
|
+
|
|
31
|
+
versions: Dict[str, Dict[str, Optional[str]]] = {}
|
|
32
|
+
for detail in result["response"].get("publishedfiledetails", []):
|
|
33
|
+
publishedfileid = detail.get("publishedfileid")
|
|
34
|
+
title = detail.get("title")
|
|
35
|
+
tags = detail.get("tags", [])
|
|
36
|
+
version = None
|
|
37
|
+
for tag in tags:
|
|
38
|
+
tag_str = tag.get("tag", "")
|
|
39
|
+
if tag_str.startswith("version:"):
|
|
40
|
+
version = tag_str.replace("version:", "")
|
|
41
|
+
break
|
|
42
|
+
versions[publishedfileid] = {"version": version, "title": title}
|
|
43
|
+
|
|
44
|
+
return versions
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def extract_workshop_id(key: str) -> Optional[str]:
|
|
48
|
+
match = re.match(r"workshop-(\d+)", key)
|
|
49
|
+
return match.group(1) if match else None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def parse_lua_file(file_path: str) -> dict:
|
|
53
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
54
|
+
source = f.read()
|
|
55
|
+
source = source.strip()
|
|
56
|
+
if source.startswith("return"):
|
|
57
|
+
source = source[6:].strip()
|
|
58
|
+
result = lua.decode(source)
|
|
59
|
+
assert isinstance(result, dict)
|
|
60
|
+
return result
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def write_lua_file(file_path: str, data: dict):
|
|
64
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
65
|
+
f.write("return " + lua.encode(data) + "\n")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_client_mods_list(file_path: str, mod_id: str) -> Optional[tuple[dict, dict]]:
|
|
69
|
+
"""
|
|
70
|
+
解析 lua 文件,返回 (data, client_mods_list)。
|
|
71
|
+
失败返回 None(错误信息已由函数自行打印)。
|
|
72
|
+
"""
|
|
73
|
+
try:
|
|
74
|
+
data = parse_lua_file(file_path)
|
|
75
|
+
except FileNotFoundError:
|
|
76
|
+
typer.secho(f"❌ 文件不存在: {file_path}", fg=typer.colors.RED)
|
|
77
|
+
return None
|
|
78
|
+
except Exception as e:
|
|
79
|
+
typer.secho(f"❌ 解析 Lua 文件失败: {e}", fg=typer.colors.RED)
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
main_mod_key = f"workshop-{mod_id}"
|
|
83
|
+
main_mod = data.get(main_mod_key)
|
|
84
|
+
if not main_mod:
|
|
85
|
+
typer.secho(f"❌ 未找到 {main_mod_key}", fg=typer.colors.RED)
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
client_mods_list = main_mod.get("configuration_options", {}).get(
|
|
89
|
+
"client_mods_list", {}
|
|
90
|
+
)
|
|
91
|
+
if not client_mods_list:
|
|
92
|
+
typer.secho("❌ 未找到 client_mods_list", fg=typer.colors.RED)
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
return data, client_mods_list
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# update_client_mods
|
|
99
|
+
@app.command()
|
|
100
|
+
def cmu(
|
|
101
|
+
file_path: str = typer.Argument(
|
|
102
|
+
"d:/.backups/dontstarvetogether/modoverrides.lua",
|
|
103
|
+
help="modoverrides.lua 文件路径",
|
|
104
|
+
),
|
|
105
|
+
mod_id: str = typer.Option(
|
|
106
|
+
"3486375086",
|
|
107
|
+
"--mod-id",
|
|
108
|
+
"-m",
|
|
109
|
+
help="主 mod 的 workshop ID",
|
|
110
|
+
),
|
|
111
|
+
output: List[str] = typer.Option(
|
|
112
|
+
None,
|
|
113
|
+
"--output",
|
|
114
|
+
"-o",
|
|
115
|
+
help="额外的输出路径,可多次指定",
|
|
116
|
+
),
|
|
117
|
+
):
|
|
118
|
+
result = get_client_mods_list(file_path, mod_id)
|
|
119
|
+
if result is None:
|
|
120
|
+
raise typer.Exit(code=1)
|
|
121
|
+
data, client_mods_list = result
|
|
122
|
+
|
|
123
|
+
workshop_ids = []
|
|
124
|
+
for key in client_mods_list.keys():
|
|
125
|
+
wid = extract_workshop_id(key)
|
|
126
|
+
if wid:
|
|
127
|
+
workshop_ids.append(wid)
|
|
128
|
+
|
|
129
|
+
if not workshop_ids:
|
|
130
|
+
typer.secho("❌ 未找到任何 client_mods", fg=typer.colors.RED)
|
|
131
|
+
raise typer.Exit(code=1)
|
|
132
|
+
|
|
133
|
+
typer.secho(
|
|
134
|
+
f"🔍 发现 {len(workshop_ids)} 个 client mods,正在查询 Steam API...",
|
|
135
|
+
fg=typer.colors.BLUE,
|
|
136
|
+
)
|
|
137
|
+
versions = get_mod_versions(workshop_ids)
|
|
138
|
+
|
|
139
|
+
if not versions:
|
|
140
|
+
typer.secho("❌ 未能获取版本信息", fg=typer.colors.RED)
|
|
141
|
+
raise typer.Exit(code=1)
|
|
142
|
+
|
|
143
|
+
typer.secho("📝 正在更新版本号...", fg=typer.colors.BLUE)
|
|
144
|
+
updated_count = 0
|
|
145
|
+
for mod_key, mod_info in client_mods_list.items():
|
|
146
|
+
wid = extract_workshop_id(mod_key)
|
|
147
|
+
if not wid:
|
|
148
|
+
continue
|
|
149
|
+
mod_data = versions.get(wid)
|
|
150
|
+
if mod_data is None:
|
|
151
|
+
typer.secho(f"⚠️ {mod_key}: 未获取到版本信息", fg=typer.colors.YELLOW)
|
|
152
|
+
continue
|
|
153
|
+
new_version = mod_data.get("version")
|
|
154
|
+
title = mod_data.get("title", "")
|
|
155
|
+
if new_version is None:
|
|
156
|
+
typer.secho(
|
|
157
|
+
f"⚠️ {mod_key} ({title}): 未获取到版本信息", fg=typer.colors.YELLOW
|
|
158
|
+
)
|
|
159
|
+
continue
|
|
160
|
+
old_version = mod_info.get("version")
|
|
161
|
+
if old_version != new_version:
|
|
162
|
+
mod_info["version"] = new_version
|
|
163
|
+
updated_count += 1
|
|
164
|
+
typer.secho(
|
|
165
|
+
f"✅ {mod_key} ({title}): {old_version} -> {new_version}",
|
|
166
|
+
fg=typer.colors.GREEN,
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
typer.secho(
|
|
170
|
+
f"ℹ️ {mod_key} ({title}): 已是最新版本 {old_version}",
|
|
171
|
+
fg=typer.colors.WHITE,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
if updated_count > 0:
|
|
176
|
+
write_lua_file(file_path, data)
|
|
177
|
+
typer.secho(f"💾 已保存到: {file_path}", fg=typer.colors.CYAN)
|
|
178
|
+
if output:
|
|
179
|
+
for p in output:
|
|
180
|
+
write_lua_file(p, data)
|
|
181
|
+
typer.secho(f"💾 已保存到: {p}", fg=typer.colors.CYAN)
|
|
182
|
+
except Exception as e:
|
|
183
|
+
typer.secho(f"❌ 写入文件失败: {e}", fg=typer.colors.RED)
|
|
184
|
+
raise typer.Exit(code=1)
|
|
185
|
+
|
|
186
|
+
if updated_count > 0:
|
|
187
|
+
typer.secho(f"\n🎉 成功更新 {updated_count} 个 mod 版本", fg=typer.colors.GREEN)
|
|
188
|
+
else:
|
|
189
|
+
typer.secho("\nℹ️ 所有 mod 已是最新版本", fg=typer.colors.YELLOW)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# list_client_mods
|
|
193
|
+
@app.command()
|
|
194
|
+
def cml(
|
|
195
|
+
file_path: str = typer.Argument(
|
|
196
|
+
"d:/.backups/dontstarvetogether/modoverrides.lua",
|
|
197
|
+
help="modoverrides.lua 文件路径",
|
|
198
|
+
),
|
|
199
|
+
mod_id: str = typer.Option(
|
|
200
|
+
"3486375086",
|
|
201
|
+
"--mod-id",
|
|
202
|
+
"-m",
|
|
203
|
+
help="主 mod 的 workshop ID",
|
|
204
|
+
),
|
|
205
|
+
):
|
|
206
|
+
"""
|
|
207
|
+
列出 client_mods_list 中所有 mod 的当前版本
|
|
208
|
+
"""
|
|
209
|
+
result = get_client_mods_list(file_path, mod_id)
|
|
210
|
+
if result is None:
|
|
211
|
+
raise typer.Exit(code=1)
|
|
212
|
+
_, client_mods_list = result
|
|
213
|
+
|
|
214
|
+
typer.secho("\n📋 client_mods_list 中的 mod 列表:", fg=typer.colors.BLUE)
|
|
215
|
+
for i, (mod_key, mod_info) in enumerate(client_mods_list.items(), 1):
|
|
216
|
+
version = mod_info.get("version", "unknown")
|
|
217
|
+
typer.secho(f"{i}. {mod_key}: {version}", fg=typer.colors.WHITE)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
# cmu("d:/.backups/dontstarvetogether/modoverrides.lua", "3486375086")
|
|
222
|
+
cml("d:/.backups/dontstarvetogether/modoverrides.lua", "3486375086")
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"cowsay>=6.1",
|
|
11
11
|
"dotenv>=0.9.9",
|
|
12
12
|
"fastapi>=0.127.0",
|
|
13
|
+
"SLPP>=1.2.3",
|
|
13
14
|
"numpy<2.0.0",
|
|
14
15
|
"pandas>=2.3.3",
|
|
15
16
|
"pymysql>=1.1.2",
|
|
@@ -18,6 +19,7 @@
|
|
|
18
19
|
"redis[hiredis]>=7.1.0",
|
|
19
20
|
"requests[socks]>=2.32.5",
|
|
20
21
|
"selenium>=4.40.0",
|
|
22
|
+
"slpp>=1.2.3",
|
|
21
23
|
"sqlalchemy>=2.0.45",
|
|
22
24
|
"tabulate>=0.9.0",
|
|
23
25
|
"toml>=0.10.2",
|
|
@@ -30,7 +32,7 @@
|
|
|
30
32
|
name = "pymecli"
|
|
31
33
|
readme = "README.md"
|
|
32
34
|
requires-python = ">=3.10"
|
|
33
|
-
version = "0.4.
|
|
35
|
+
version = "0.4.4"
|
|
34
36
|
|
|
35
37
|
[project.urls]
|
|
36
38
|
Homepage = "https://pypi.org/project/pymecli"
|
|
@@ -39,6 +41,7 @@
|
|
|
39
41
|
[project.scripts]
|
|
40
42
|
baidu = "cli.baidu:app"
|
|
41
43
|
bitget = "cli.bitget:app"
|
|
44
|
+
dst = "cli.dst:app"
|
|
42
45
|
example = "cli.example:app"
|
|
43
46
|
fast = "cli.fast:typer_app"
|
|
44
47
|
gate = "cli.gate:app"
|
pymecli-0.4.3/README.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# typer example
|
|
2
|
-
|
|
3
|
-
```shell
|
|
4
|
-
uv run example hello Xiaoming
|
|
5
|
-
uv run example hello Xiaoming --from Pymecli
|
|
6
|
-
uv run example goodbye Xiaoming
|
|
7
|
-
uv run example goodbye Xiaoming -f
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
# fastapi server
|
|
11
|
-
|
|
12
|
-
```shell
|
|
13
|
-
uv run fast --port 8877
|
|
14
|
-
uv build
|
|
15
|
-
uv publish --token (TOKEN)
|
|
16
|
-
```
|
|
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
|