pymecli 0.5.0__tar.gz → 0.5.1__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.5.0 → pymecli-0.5.1}/PKG-INFO +1 -1
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/dst.py +111 -41
- {pymecli-0.5.0 → pymecli-0.5.1}/pyproject.toml +2 -2
- pymecli-0.5.0/cli/baidu.py +0 -93
- {pymecli-0.5.0 → pymecli-0.5.1}/.gitignore +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/README.md +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/api/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/api/v1/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/api/v1/clash.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/api/v1/redis.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/bitget.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/example.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/fast.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/gate.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/redis_csv.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/cli/util.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/core/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/core/clash.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/core/config.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/core/redis_client.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/crypto/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/crypto/bitget.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/crypto/gate.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/data/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/data/dou_dict.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/data/dou_list.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/data/main.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/data/template.yaml +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/models/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/models/douzero_model.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/models/ocr_model.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/models/response.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/__init__.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/elapsed.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/helper.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/logger.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/mysql.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/path.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/pd.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/pyredis.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/sleep.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/text.py +0 -0
- {pymecli-0.5.0 → pymecli-0.5.1}/utils/toml.py +0 -0
|
@@ -25,7 +25,7 @@ def get_mod_versions(workshop_ids: List[str]) -> Dict[str, Dict[str, Optional[st
|
|
|
25
25
|
response.raise_for_status()
|
|
26
26
|
result = response.json()
|
|
27
27
|
except Exception as e:
|
|
28
|
-
typer.secho(f"
|
|
28
|
+
typer.secho(f"✗ Steam API 请求失败: {e}", fg=typer.colors.RED)
|
|
29
29
|
return {}
|
|
30
30
|
|
|
31
31
|
versions: Dict[str, Dict[str, Optional[str]]] = {}
|
|
@@ -65,48 +65,46 @@ def write_lua_file(file_path: str, data: dict):
|
|
|
65
65
|
f.write("return " + lua.encode(data) + "\n")
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def
|
|
68
|
+
def get_client_mods(file_path: str, mod_id: str) -> Optional[tuple[dict, dict]]:
|
|
69
69
|
"""
|
|
70
|
-
解析 lua 文件,返回 (data,
|
|
71
|
-
失败返回 None
|
|
70
|
+
解析 lua 文件,返回 (data, client_mods)。
|
|
71
|
+
失败返回 None(错误信息已由函数自行打印)。
|
|
72
72
|
"""
|
|
73
73
|
try:
|
|
74
74
|
data = parse_lua_file(file_path)
|
|
75
75
|
except FileNotFoundError:
|
|
76
|
-
typer.secho(f"
|
|
76
|
+
typer.secho(f"✗ 文件不存在: {file_path}", fg=typer.colors.RED)
|
|
77
77
|
return None
|
|
78
78
|
except Exception as e:
|
|
79
|
-
typer.secho(f"
|
|
79
|
+
typer.secho(f"✗ 解析 Lua 文件失败: {e}", fg=typer.colors.RED)
|
|
80
80
|
return None
|
|
81
81
|
|
|
82
82
|
main_mod_key = f"workshop-{mod_id}"
|
|
83
83
|
main_mod = data.get(main_mod_key)
|
|
84
84
|
if not main_mod:
|
|
85
|
-
typer.secho(f"
|
|
86
|
-
return
|
|
85
|
+
typer.secho(f"✗ 未找到 {main_mod_key}", fg=typer.colors.RED)
|
|
86
|
+
return data, {}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
typer.secho("❌ 未找到 client_mods_list", fg=typer.colors.RED)
|
|
93
|
-
return None
|
|
88
|
+
client_mods = main_mod.get("configuration_options", {}).get("client_mods_list", {})
|
|
89
|
+
if not client_mods:
|
|
90
|
+
typer.secho("✗ 未找到 client_mods", fg=typer.colors.RED)
|
|
91
|
+
return data, {}
|
|
94
92
|
|
|
95
|
-
return data,
|
|
93
|
+
return data, client_mods
|
|
96
94
|
|
|
97
95
|
|
|
98
96
|
# update_client_mods
|
|
99
97
|
@app.command()
|
|
100
|
-
def
|
|
98
|
+
def convert_update(
|
|
101
99
|
file_path: str = typer.Argument(
|
|
102
|
-
"d
|
|
100
|
+
"d:/github/meme2046/docker/dst/modoverrides.lua",
|
|
103
101
|
help="modoverrides.lua 文件路径",
|
|
104
102
|
),
|
|
105
103
|
mod_id: str = typer.Option(
|
|
106
104
|
"3486375086",
|
|
107
105
|
"--mod-id",
|
|
108
106
|
"-m",
|
|
109
|
-
help="
|
|
107
|
+
help="模组: 客户端Mod转为服务器Mod<3486375086>的ID, 固定值",
|
|
110
108
|
),
|
|
111
109
|
output: List[str] = typer.Option(
|
|
112
110
|
None,
|
|
@@ -115,34 +113,37 @@ def cmu(
|
|
|
115
113
|
help="额外的输出路径,可多次指定",
|
|
116
114
|
),
|
|
117
115
|
):
|
|
118
|
-
|
|
116
|
+
"""
|
|
117
|
+
更新modoverrides.lua中<3486375086>的mods的版本信息
|
|
118
|
+
"""
|
|
119
|
+
result = get_client_mods(file_path, mod_id)
|
|
119
120
|
if result is None:
|
|
120
121
|
raise typer.Exit(code=1)
|
|
121
|
-
data,
|
|
122
|
+
data, client_mods = result
|
|
122
123
|
|
|
123
124
|
workshop_ids = []
|
|
124
|
-
for key in
|
|
125
|
+
for key in client_mods.keys():
|
|
125
126
|
wid = extract_workshop_id(key)
|
|
126
127
|
if wid:
|
|
127
128
|
workshop_ids.append(wid)
|
|
128
129
|
|
|
129
130
|
if not workshop_ids:
|
|
130
|
-
typer.secho("
|
|
131
|
+
typer.secho("✗ 未找到任何 client_mods", fg=typer.colors.RED)
|
|
131
132
|
raise typer.Exit(code=1)
|
|
132
133
|
|
|
133
134
|
typer.secho(
|
|
134
|
-
f"🔍 发现 {len(workshop_ids)} 个 client mods
|
|
135
|
+
f"🔍 发现 {len(workshop_ids)} 个 client mods, 正在查询 Steam API...",
|
|
135
136
|
fg=typer.colors.BLUE,
|
|
136
137
|
)
|
|
137
138
|
versions = get_mod_versions(workshop_ids)
|
|
138
139
|
|
|
139
140
|
if not versions:
|
|
140
|
-
typer.secho("
|
|
141
|
+
typer.secho("✗ 未能获取steam版本信息", fg=typer.colors.RED)
|
|
141
142
|
raise typer.Exit(code=1)
|
|
142
143
|
|
|
143
144
|
typer.secho("📝 正在更新版本号...", fg=typer.colors.BLUE)
|
|
144
145
|
updated_count = 0
|
|
145
|
-
for mod_key, mod_info in
|
|
146
|
+
for mod_key, mod_info in client_mods.items():
|
|
146
147
|
wid = extract_workshop_id(mod_key)
|
|
147
148
|
if not wid:
|
|
148
149
|
continue
|
|
@@ -167,7 +168,7 @@ def cmu(
|
|
|
167
168
|
)
|
|
168
169
|
else:
|
|
169
170
|
typer.secho(
|
|
170
|
-
f"
|
|
171
|
+
f"{mod_key} ({title}): 已是最新版本 {old_version}",
|
|
171
172
|
fg=typer.colors.WHITE,
|
|
172
173
|
)
|
|
173
174
|
|
|
@@ -180,43 +181,112 @@ def cmu(
|
|
|
180
181
|
write_lua_file(p, data)
|
|
181
182
|
typer.secho(f"💾 已保存到: {p}", fg=typer.colors.CYAN)
|
|
182
183
|
except Exception as e:
|
|
183
|
-
typer.secho(f"
|
|
184
|
+
typer.secho(f"✗ 写入文件失败: {e}", fg=typer.colors.RED)
|
|
184
185
|
raise typer.Exit(code=1)
|
|
185
186
|
|
|
186
187
|
if updated_count > 0:
|
|
187
188
|
typer.secho(f"\n🎉 成功更新 {updated_count} 个 mod 版本", fg=typer.colors.GREEN)
|
|
188
189
|
else:
|
|
189
|
-
typer.secho("\n
|
|
190
|
+
typer.secho("\n✅ 所有 mod 已是最新版本", fg=typer.colors.YELLOW)
|
|
190
191
|
|
|
191
192
|
|
|
192
|
-
# list_client_mods
|
|
193
193
|
@app.command()
|
|
194
|
-
def
|
|
194
|
+
def mod_setup(
|
|
195
195
|
file_path: str = typer.Argument(
|
|
196
|
-
"d
|
|
196
|
+
"d:/github/meme2046/docker/dst/modoverrides.lua",
|
|
197
197
|
help="modoverrides.lua 文件路径",
|
|
198
198
|
),
|
|
199
199
|
mod_id: str = typer.Option(
|
|
200
200
|
"3486375086",
|
|
201
201
|
"--mod-id",
|
|
202
202
|
"-m",
|
|
203
|
-
help="
|
|
203
|
+
help="模组: 客户端Mod转为服务器Mod<3486375086>的ID, 固定值",
|
|
204
|
+
),
|
|
205
|
+
output: List[str] = typer.Option(
|
|
206
|
+
["dedicated_server_mods_setup.lua"],
|
|
207
|
+
"--output",
|
|
208
|
+
"-o",
|
|
209
|
+
help="mods_setup输出路径,可多次指定",
|
|
204
210
|
),
|
|
205
211
|
):
|
|
206
212
|
"""
|
|
207
|
-
|
|
213
|
+
列出所有 mod, 并以<dedicated_server_mods_setup>格式保存到指定文件
|
|
208
214
|
"""
|
|
209
|
-
result =
|
|
215
|
+
result = get_client_mods(file_path, mod_id)
|
|
210
216
|
if result is None:
|
|
211
217
|
raise typer.Exit(code=1)
|
|
212
|
-
|
|
218
|
+
data, client_mods = result
|
|
219
|
+
|
|
220
|
+
client_ids = []
|
|
221
|
+
for key in client_mods.keys():
|
|
222
|
+
wid = extract_workshop_id(key)
|
|
223
|
+
if wid:
|
|
224
|
+
client_ids.append(wid)
|
|
225
|
+
|
|
226
|
+
server_ids = []
|
|
227
|
+
for key in data.keys():
|
|
228
|
+
wid = extract_workshop_id(key)
|
|
229
|
+
if wid:
|
|
230
|
+
server_ids.append(wid)
|
|
231
|
+
|
|
232
|
+
versions = get_mod_versions(server_ids + client_ids)
|
|
233
|
+
|
|
234
|
+
if not versions:
|
|
235
|
+
typer.secho("✗ 未能获取steam版本信息", fg=typer.colors.RED)
|
|
236
|
+
raise typer.Exit(code=1)
|
|
237
|
+
|
|
238
|
+
setup_list = []
|
|
239
|
+
|
|
240
|
+
typer.secho(
|
|
241
|
+
f"📢 server_mods({len(server_ids)}):",
|
|
242
|
+
fg=typer.colors.GREEN,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
for item in server_ids:
|
|
246
|
+
mod_data = versions.get(item)
|
|
247
|
+
|
|
248
|
+
if mod_data is None:
|
|
249
|
+
typer.secho(f"✗ {item}: 未获取到版本信息", fg=typer.colors.YELLOW)
|
|
250
|
+
raise typer.Exit(code=1)
|
|
251
|
+
|
|
252
|
+
setup_list.append(f'ServerModSetup("{item}")')
|
|
253
|
+
|
|
254
|
+
new_version = mod_data.get("version")
|
|
255
|
+
title = mod_data.get("title", "")
|
|
256
|
+
|
|
257
|
+
typer.secho(
|
|
258
|
+
f"✅ {item} ({title}): {new_version}",
|
|
259
|
+
fg=typer.colors.WHITE,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
typer.secho(
|
|
263
|
+
f"\n📋 client_mods({len(client_ids)}):",
|
|
264
|
+
fg=typer.colors.GREEN,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
for item in client_ids:
|
|
268
|
+
mod_data = versions.get(item)
|
|
269
|
+
|
|
270
|
+
if mod_data is None:
|
|
271
|
+
typer.secho(f"✗ {item}: 未获取到版本信息", fg=typer.colors.YELLOW)
|
|
272
|
+
raise typer.Exit(code=1)
|
|
273
|
+
|
|
274
|
+
setup_list.append(f'ServerModSetup("{item}")')
|
|
275
|
+
|
|
276
|
+
new_version = mod_data.get("version")
|
|
277
|
+
title = mod_data.get("title", "")
|
|
278
|
+
|
|
279
|
+
typer.secho(
|
|
280
|
+
f"✅ {item} ({title}): {new_version}",
|
|
281
|
+
fg=typer.colors.WHITE,
|
|
282
|
+
)
|
|
213
283
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
typer.secho(f"
|
|
284
|
+
for p in output:
|
|
285
|
+
with open(p, "w", encoding="utf-8") as f:
|
|
286
|
+
f.write("\n".join(setup_list))
|
|
287
|
+
typer.secho(f"\n💾 <setup_list>已保存到: {p}", fg=typer.colors.CYAN)
|
|
218
288
|
|
|
219
289
|
|
|
220
290
|
if __name__ == "__main__":
|
|
221
|
-
# cmu("d
|
|
222
|
-
|
|
291
|
+
# cmu("d:/github/meme2046/docker/dst/modoverrides.lua", "3486375086")
|
|
292
|
+
convert_update("d:/github/meme2046/docker/dst/modoverrides.lua", "3486375086")
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
name = "pymecli"
|
|
36
36
|
readme = "README.md"
|
|
37
37
|
requires-python = ">=3.10"
|
|
38
|
-
version = "0.5.
|
|
38
|
+
version = "0.5.1"
|
|
39
39
|
|
|
40
40
|
[project.urls]
|
|
41
41
|
Homepage = "https://pypi.org/project/pymecli"
|
|
42
42
|
Repository = "https://github.com/meme2046/pymecli"
|
|
43
43
|
|
|
44
44
|
[project.scripts]
|
|
45
|
-
baidu = "cli.baidu:app"
|
|
45
|
+
# baidu = "cli.baidu:app"
|
|
46
46
|
bitget = "cli.bitget:app"
|
|
47
47
|
dst = "cli.dst:app"
|
|
48
48
|
example = "cli.example:app"
|
pymecli-0.5.0/cli/baidu.py
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
import typer
|
|
4
|
-
from selenium import webdriver
|
|
5
|
-
from selenium.webdriver.chrome.options import Options
|
|
6
|
-
from selenium.webdriver.chrome.service import Service
|
|
7
|
-
from webdriver_manager.chrome import ChromeDriverManager
|
|
8
|
-
|
|
9
|
-
from utils.pyredis import get_redis_client_sync
|
|
10
|
-
|
|
11
|
-
app = typer.Typer()
|
|
12
|
-
|
|
13
|
-
r = get_redis_client_sync()
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@app.command()
|
|
17
|
-
def acsToken(
|
|
18
|
-
url: str = typer.Argument(
|
|
19
|
-
"https://finance.baidu.com/index/ab-000001?name=%25E4%25B8%258A%25E8%25AF%2581%25E6%258C%2587%25E6%2595%25B0",
|
|
20
|
-
help="request url",
|
|
21
|
-
),
|
|
22
|
-
timeout: int = typer.Option(
|
|
23
|
-
10,
|
|
24
|
-
"--timeout",
|
|
25
|
-
"-t",
|
|
26
|
-
help="timeout内如果没有请求完整,会强制中断,然后从已有的请求中获取数据",
|
|
27
|
-
),
|
|
28
|
-
):
|
|
29
|
-
"""通过selenium获取百度股事通Acs-Token
|
|
30
|
-
|
|
31
|
-
Args:
|
|
32
|
-
url (str, optional): 请求的『URL』地址. Defaults to typer.Argument( "https://finance.baidu.com/", help="request url", ).
|
|
33
|
-
timeout (int, optional): _description_. Defaults to typer.Option( 3, "--timeout", "-t", help="timeout内如果没有请求完整,会强制中断,然后从已有的请求中获取数据", ).
|
|
34
|
-
|
|
35
|
-
Returns:
|
|
36
|
-
str: 『Acs-Token』字符串
|
|
37
|
-
"""
|
|
38
|
-
# 配置 Chrome 浏览器以启用 Performance API
|
|
39
|
-
chrome_options = Options()
|
|
40
|
-
chrome_options.add_argument("--enable-logging")
|
|
41
|
-
chrome_options.add_argument("--v=1")
|
|
42
|
-
chrome_options.add_argument("--headless") # 启用无头模式
|
|
43
|
-
chrome_options.add_argument("--disable-gpu") # 禁用 GPU 加速
|
|
44
|
-
chrome_options.add_argument("--window-size=1920,1080") # 设置窗口大小
|
|
45
|
-
chrome_options.add_argument("--no-sandbox") # 禁用沙盒模式
|
|
46
|
-
chrome_options.add_argument("--disable-dev-shm-usage") # 禁用 /dev/shm 使用
|
|
47
|
-
chrome_options.set_capability("goog:loggingPrefs", {"performance": "ALL"})
|
|
48
|
-
|
|
49
|
-
driver = webdriver.Chrome(
|
|
50
|
-
service=Service(ChromeDriverManager().install()), options=chrome_options
|
|
51
|
-
)
|
|
52
|
-
driver.set_page_load_timeout(timeout)
|
|
53
|
-
|
|
54
|
-
try:
|
|
55
|
-
driver.get(url)
|
|
56
|
-
except Exception:
|
|
57
|
-
driver.execute_script("window.stop();")
|
|
58
|
-
|
|
59
|
-
# 从网络请求中提取 Acs-Token
|
|
60
|
-
acs_token = get_acs_token_from_requests(driver)
|
|
61
|
-
|
|
62
|
-
driver.quit()
|
|
63
|
-
|
|
64
|
-
if acs_token:
|
|
65
|
-
print(f"Acs-Token:『{acs_token}』")
|
|
66
|
-
r.set("baidu.Acs-Token", acs_token)
|
|
67
|
-
|
|
68
|
-
return acs_token
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def get_acs_token_from_requests(driver):
|
|
72
|
-
"""从网络请求中提取 Acs-Token"""
|
|
73
|
-
# 获取性能日志
|
|
74
|
-
|
|
75
|
-
logs = driver.get_log("performance")
|
|
76
|
-
|
|
77
|
-
for entry in logs:
|
|
78
|
-
log = json.loads(entry["message"])["message"]
|
|
79
|
-
|
|
80
|
-
# 检查是否是网络请求
|
|
81
|
-
if log["method"] == "Network.requestWillBeSent":
|
|
82
|
-
request = log["params"].get("request", {})
|
|
83
|
-
headers = request.get("headers", {})
|
|
84
|
-
|
|
85
|
-
# 检查请求头中是否包含 Acs-Token
|
|
86
|
-
if "Acs-Token" in headers:
|
|
87
|
-
return headers["Acs-Token"]
|
|
88
|
-
|
|
89
|
-
return ""
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if __name__ == "__main__":
|
|
93
|
-
app()
|
|
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
|