easyrip 3.13.2__py3-none-any.whl → 4.9.1__py3-none-any.whl
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.
- easyrip/__init__.py +5 -1
- easyrip/__main__.py +124 -15
- easyrip/easyrip_command.py +457 -148
- easyrip/easyrip_config/config.py +269 -0
- easyrip/easyrip_config/config_key.py +28 -0
- easyrip/easyrip_log.py +120 -42
- easyrip/easyrip_main.py +509 -259
- easyrip/easyrip_mlang/__init__.py +20 -45
- easyrip/easyrip_mlang/global_lang_val.py +18 -16
- easyrip/easyrip_mlang/lang_en.py +1 -1
- easyrip/easyrip_mlang/lang_zh_Hans_CN.py +101 -77
- easyrip/easyrip_mlang/translator.py +12 -10
- easyrip/easyrip_prompt.py +73 -0
- easyrip/easyrip_web/__init__.py +2 -1
- easyrip/easyrip_web/http_server.py +56 -42
- easyrip/easyrip_web/third_party_api.py +60 -8
- easyrip/global_val.py +21 -1
- easyrip/ripper/media_info.py +10 -3
- easyrip/ripper/param.py +482 -0
- easyrip/ripper/ripper.py +260 -574
- easyrip/ripper/sub_and_font/__init__.py +10 -0
- easyrip/ripper/{font_subset → sub_and_font}/ass.py +95 -84
- easyrip/ripper/{font_subset → sub_and_font}/font.py +72 -79
- easyrip/ripper/{font_subset → sub_and_font}/subset.py +122 -81
- easyrip/utils.py +129 -27
- easyrip-4.9.1.dist-info/METADATA +92 -0
- easyrip-4.9.1.dist-info/RECORD +31 -0
- easyrip/easyrip_config.py +0 -198
- easyrip/ripper/__init__.py +0 -10
- easyrip/ripper/font_subset/__init__.py +0 -7
- easyrip-3.13.2.dist-info/METADATA +0 -89
- easyrip-3.13.2.dist-info/RECORD +0 -29
- {easyrip-3.13.2.dist-info → easyrip-4.9.1.dist-info}/WHEEL +0 -0
- {easyrip-3.13.2.dist-info → easyrip-4.9.1.dist-info}/entry_points.txt +0 -0
- {easyrip-3.13.2.dist-info → easyrip-4.9.1.dist-info}/licenses/LICENSE +0 -0
- {easyrip-3.13.2.dist-info → easyrip-4.9.1.dist-info}/top_level.txt +0 -0
easyrip/easyrip_main.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import ast
|
|
1
2
|
import ctypes
|
|
2
3
|
import itertools
|
|
3
4
|
import json
|
|
@@ -7,19 +8,23 @@ import shlex
|
|
|
7
8
|
import shutil
|
|
8
9
|
import subprocess
|
|
9
10
|
import sys
|
|
11
|
+
import textwrap
|
|
12
|
+
import threading
|
|
10
13
|
import tkinter as tk
|
|
14
|
+
import tomllib
|
|
15
|
+
from collections.abc import Callable, Iterable
|
|
16
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
11
17
|
from datetime import datetime
|
|
12
18
|
from multiprocessing import shared_memory
|
|
13
19
|
from pathlib import Path
|
|
14
20
|
from threading import Thread
|
|
15
21
|
from time import sleep
|
|
16
22
|
from tkinter import filedialog
|
|
17
|
-
|
|
18
|
-
import tomllib
|
|
23
|
+
from typing import Final, Literal
|
|
19
24
|
|
|
20
25
|
from . import easyrip_mlang, easyrip_web, global_val
|
|
21
26
|
from .easyrip_command import Cmd_type, Opt_type, get_help_doc
|
|
22
|
-
from .easyrip_config import config
|
|
27
|
+
from .easyrip_config.config import Config_key, config
|
|
23
28
|
from .easyrip_log import Event as LogEvent
|
|
24
29
|
from .easyrip_log import log
|
|
25
30
|
from .easyrip_mlang import (
|
|
@@ -30,7 +35,11 @@ from .easyrip_mlang import (
|
|
|
30
35
|
gettext,
|
|
31
36
|
translate_subtitles,
|
|
32
37
|
)
|
|
33
|
-
from .
|
|
38
|
+
from .easyrip_prompt import easyrip_prompt
|
|
39
|
+
from .ripper.media_info import Media_info
|
|
40
|
+
from .ripper.param import DEFAULT_PRESET_PARAMS, PRESET_OPT_NAME
|
|
41
|
+
from .ripper.ripper import Ripper
|
|
42
|
+
from .ripper.sub_and_font import load_fonts
|
|
34
43
|
from .utils import change_title, check_ver, read_text
|
|
35
44
|
|
|
36
45
|
__all__ = ["init", "run_command"]
|
|
@@ -42,40 +51,44 @@ PROJECT_TITLE = global_val.PROJECT_TITLE
|
|
|
42
51
|
PROJECT_URL = global_val.PROJECT_URL
|
|
43
52
|
|
|
44
53
|
|
|
45
|
-
def log_new_ver(
|
|
54
|
+
def log_new_ver(
|
|
55
|
+
new_ver: str | None, old_ver: str, program_name: str, dl_url: str
|
|
56
|
+
) -> None:
|
|
46
57
|
if new_ver is None:
|
|
47
58
|
return
|
|
48
59
|
try:
|
|
49
60
|
if check_ver(new_ver, old_ver):
|
|
50
|
-
print()
|
|
51
61
|
log.info(
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
"\n"
|
|
63
|
+
+ gettext(
|
|
64
|
+
"{} has new version ({} -> {}). Suggest upgrading it: {}",
|
|
65
|
+
program_name,
|
|
66
|
+
old_ver,
|
|
67
|
+
new_ver,
|
|
68
|
+
dl_url,
|
|
69
|
+
)
|
|
56
70
|
)
|
|
57
|
-
print(get_input_prompt(True), end="")
|
|
58
71
|
except Exception as e:
|
|
59
|
-
|
|
60
|
-
log.warning(e, deep=True)
|
|
61
|
-
print(get_input_prompt(True), end="")
|
|
72
|
+
log.warning(f"\n{e}", is_format=False, deep=True)
|
|
62
73
|
|
|
63
74
|
|
|
64
|
-
def check_env():
|
|
75
|
+
def check_env() -> None:
|
|
65
76
|
try:
|
|
66
77
|
change_title(f"{gettext('Check env...')} {PROJECT_TITLE}")
|
|
67
78
|
|
|
68
|
-
if config.get_user_profile(
|
|
79
|
+
if config.get_user_profile(Config_key.check_dependent):
|
|
69
80
|
_url = "https://ffmpeg.org/download.html"
|
|
70
81
|
for _name in ("FFmpeg", "FFprobe"):
|
|
71
82
|
if not shutil.which(_name):
|
|
72
|
-
print()
|
|
73
83
|
log.error(
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
"\n"
|
|
85
|
+
+ gettext(
|
|
86
|
+
"{} not found, download it: {}",
|
|
87
|
+
_name,
|
|
88
|
+
f"(full build ver) {_url}",
|
|
89
|
+
)
|
|
77
90
|
)
|
|
78
|
-
print(get_input_prompt(True), end="")
|
|
91
|
+
log.print(get_input_prompt(True), end="")
|
|
79
92
|
else:
|
|
80
93
|
_new_ver = (
|
|
81
94
|
subprocess.run(
|
|
@@ -86,19 +99,21 @@ def check_env():
|
|
|
86
99
|
)
|
|
87
100
|
|
|
88
101
|
if "." in _new_ver:
|
|
89
|
-
log_new_ver("8.0", _new_ver.split("-")[0], _name, _url)
|
|
102
|
+
log_new_ver("8.0.1", _new_ver.split("-")[0], _name, _url)
|
|
90
103
|
else:
|
|
91
104
|
log_new_ver(
|
|
92
|
-
"2025.
|
|
105
|
+
"2025.11.20", ".".join(_new_ver.split("-")[:3]), _name, _url
|
|
93
106
|
)
|
|
94
107
|
|
|
95
108
|
_name, _url = "flac", "https://github.com/xiph/flac/releases"
|
|
96
109
|
if not shutil.which(_name):
|
|
97
|
-
print()
|
|
98
110
|
log.warning(
|
|
99
|
-
"
|
|
111
|
+
"\n"
|
|
112
|
+
+ gettext(
|
|
113
|
+
"{} not found, download it: {}", _name, f"(ver >= 1.5.0) {_url}"
|
|
114
|
+
)
|
|
100
115
|
)
|
|
101
|
-
print(get_input_prompt(True), end="")
|
|
116
|
+
log.print(get_input_prompt(True), end="")
|
|
102
117
|
|
|
103
118
|
elif check_ver(
|
|
104
119
|
"1.5.0",
|
|
@@ -112,7 +127,7 @@ def check_env():
|
|
|
112
127
|
|
|
113
128
|
else:
|
|
114
129
|
log_new_ver(
|
|
115
|
-
easyrip_web.github.
|
|
130
|
+
easyrip_web.github.get_latest_release_ver(
|
|
116
131
|
"https://api.github.com/repos/xiph/flac/releases/latest"
|
|
117
132
|
),
|
|
118
133
|
old_ver_str,
|
|
@@ -122,12 +137,13 @@ def check_env():
|
|
|
122
137
|
|
|
123
138
|
_name, _url = "mp4fpsmod", "https://github.com/nu774/mp4fpsmod/releases"
|
|
124
139
|
if not shutil.which(_name):
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
log.warning(
|
|
141
|
+
"\n" + gettext("{} not found, download it: {}", _name, _url)
|
|
142
|
+
)
|
|
143
|
+
log.print(get_input_prompt(True), end="")
|
|
128
144
|
else:
|
|
129
145
|
log_new_ver(
|
|
130
|
-
easyrip_web.github.
|
|
146
|
+
easyrip_web.github.get_latest_release_ver(
|
|
131
147
|
"https://api.github.com/repos/nu774/mp4fpsmod/releases/latest"
|
|
132
148
|
),
|
|
133
149
|
subprocess.run(_name, capture_output=True, text=True).stderr.split(
|
|
@@ -139,9 +155,10 @@ def check_env():
|
|
|
139
155
|
|
|
140
156
|
_name, _url = "MP4Box", "https://gpac.io/downloads/gpac-nightly-builds/"
|
|
141
157
|
if not shutil.which(_name):
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
log.warning(
|
|
159
|
+
"\n" + gettext("{} not found, download it: {}", _name, _url)
|
|
160
|
+
)
|
|
161
|
+
log.print(get_input_prompt(True), end="")
|
|
145
162
|
else:
|
|
146
163
|
log_new_ver(
|
|
147
164
|
"2.5",
|
|
@@ -156,12 +173,13 @@ def check_env():
|
|
|
156
173
|
_url = "https://mkvtoolnix.download/downloads.html"
|
|
157
174
|
for _name in ("mkvpropedit", "mkvmerge"):
|
|
158
175
|
if not shutil.which(_name):
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
176
|
+
log.warning(
|
|
177
|
+
"\n" + gettext("{} not found, download it: {}", _name, _url)
|
|
178
|
+
)
|
|
179
|
+
log.print(get_input_prompt(True), end="")
|
|
162
180
|
else:
|
|
163
181
|
log_new_ver(
|
|
164
|
-
|
|
182
|
+
easyrip_web.mkvtoolnix.get_latest_release_ver(),
|
|
165
183
|
subprocess.run(
|
|
166
184
|
f"{_name} --version", capture_output=True, text=True
|
|
167
185
|
).stdout.split(maxsplit=2)[1],
|
|
@@ -169,28 +187,29 @@ def check_env():
|
|
|
169
187
|
_url,
|
|
170
188
|
)
|
|
171
189
|
|
|
172
|
-
|
|
173
|
-
# if not shutil.which(_name):
|
|
174
|
-
# print()
|
|
175
|
-
# log.warning('{} not found, download it: {}', _name, f'(CLI ver) {_url}')
|
|
176
|
-
# print(get_input_prompt(), end='')
|
|
177
|
-
# elif not subprocess.run('mediainfo --version', capture_output=True, text=True).stdout:
|
|
178
|
-
# log.error("The MediaInfo must be CLI ver")
|
|
179
|
-
|
|
180
|
-
if config.get_user_profile("check_update"):
|
|
190
|
+
if config.get_user_profile(Config_key.check_update):
|
|
181
191
|
log_new_ver(
|
|
182
|
-
easyrip_web.github.
|
|
192
|
+
easyrip_web.github.get_latest_release_ver(
|
|
193
|
+
global_val.PROJECT_RELEASE_API
|
|
194
|
+
),
|
|
183
195
|
PROJECT_VERSION,
|
|
184
196
|
PROJECT_NAME,
|
|
185
|
-
f"{global_val.PROJECT_URL}
|
|
197
|
+
f"{global_val.PROJECT_URL}\n{
|
|
198
|
+
gettext(
|
|
199
|
+
'Suggest running the following command to upgrade using pip: {}',
|
|
200
|
+
f'{f'"{sys.executable}" -m ' if sys.executable.lower().endswith("python.exe") else ""}pip install -U easyrip',
|
|
201
|
+
)
|
|
202
|
+
}",
|
|
186
203
|
)
|
|
187
204
|
|
|
188
|
-
sys.stdout.flush()
|
|
189
|
-
sys.stderr.flush()
|
|
190
205
|
change_title(PROJECT_TITLE)
|
|
191
206
|
|
|
192
207
|
except Exception as e:
|
|
193
|
-
log.error(
|
|
208
|
+
log.error(
|
|
209
|
+
f"The function {check_env.__name__} error: {e!r} {e}",
|
|
210
|
+
is_format=False,
|
|
211
|
+
deep=True,
|
|
212
|
+
)
|
|
194
213
|
|
|
195
214
|
|
|
196
215
|
def get_input_prompt(is_color: bool = False) -> str:
|
|
@@ -209,17 +228,29 @@ if os.name == "nt":
|
|
|
209
228
|
log.warning("Windows DPI Aware failed")
|
|
210
229
|
|
|
211
230
|
|
|
212
|
-
def file_dialog(
|
|
231
|
+
def file_dialog(
|
|
232
|
+
*,
|
|
233
|
+
is_askdir: bool = False,
|
|
234
|
+
initialdir=None,
|
|
235
|
+
) -> tuple[str, ...]:
|
|
213
236
|
tkRoot = tk.Tk()
|
|
237
|
+
|
|
214
238
|
tkRoot.withdraw()
|
|
215
|
-
|
|
239
|
+
if is_askdir:
|
|
240
|
+
file_paths = (filedialog.askdirectory(initialdir=initialdir),)
|
|
241
|
+
else:
|
|
242
|
+
file_paths = filedialog.askopenfilenames(initialdir=initialdir)
|
|
243
|
+
|
|
216
244
|
tkRoot.destroy()
|
|
217
|
-
return file_paths
|
|
245
|
+
return file_paths if file_paths else ()
|
|
218
246
|
|
|
219
247
|
|
|
220
248
|
def run_ripper_list(
|
|
221
|
-
|
|
222
|
-
|
|
249
|
+
*,
|
|
250
|
+
is_exit_when_run_finished: bool = False,
|
|
251
|
+
shutdow_sec_str: str | None = None,
|
|
252
|
+
enable_multithreading: bool = False,
|
|
253
|
+
) -> None:
|
|
223
254
|
shutdown_sec: int | None = None
|
|
224
255
|
if shutdow_sec_str is not None:
|
|
225
256
|
try:
|
|
@@ -236,8 +267,10 @@ def run_ripper_list(
|
|
|
236
267
|
create=True,
|
|
237
268
|
size=_size,
|
|
238
269
|
)
|
|
270
|
+
assert path_lock_shm.buf is not None
|
|
239
271
|
except FileExistsError:
|
|
240
272
|
_shm = shared_memory.SharedMemory(name=_name)
|
|
273
|
+
assert _shm.buf is not None
|
|
241
274
|
_res: dict = json.loads(
|
|
242
275
|
bytes(_shm.buf[: len(_shm.buf)]).decode("utf-8").rstrip("\0")
|
|
243
276
|
)
|
|
@@ -258,27 +291,55 @@ def run_ripper_list(
|
|
|
258
291
|
).encode("utf-8")
|
|
259
292
|
path_lock_shm.buf[: len(_data)] = _data
|
|
260
293
|
|
|
261
|
-
total = len(Ripper.ripper_list)
|
|
262
|
-
warning_num = log.warning_num
|
|
263
|
-
error_num = log.error_num
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
294
|
+
total: Final[int] = len(Ripper.ripper_list)
|
|
295
|
+
warning_num: Final[int] = log.warning_num
|
|
296
|
+
error_num: Final[int] = log.error_num
|
|
297
|
+
|
|
298
|
+
if enable_multithreading:
|
|
299
|
+
threading_lock = threading.Lock()
|
|
300
|
+
progress_num: int = 0
|
|
301
|
+
|
|
302
|
+
def _executor_submit_ripper_run(ripper: Ripper) -> None:
|
|
303
|
+
nonlocal progress_num
|
|
304
|
+
with threading_lock:
|
|
305
|
+
progress_num += 1
|
|
306
|
+
|
|
307
|
+
progress = f"{progress_num} / {total} - {PROJECT_TITLE}"
|
|
308
|
+
log.info(progress)
|
|
309
|
+
change_title(progress)
|
|
310
|
+
|
|
311
|
+
try:
|
|
312
|
+
if ripper.run() is False:
|
|
313
|
+
log.error("Run {} failed", "Ripper")
|
|
314
|
+
except Exception as e:
|
|
315
|
+
log.error(e, deep=True)
|
|
316
|
+
log.warning("Stop run Ripper")
|
|
317
|
+
|
|
318
|
+
with ThreadPoolExecutor() as executor:
|
|
319
|
+
for ripper in Ripper.ripper_list:
|
|
320
|
+
executor.submit(_executor_submit_ripper_run, ripper)
|
|
321
|
+
sleep(0.1)
|
|
322
|
+
|
|
323
|
+
else:
|
|
324
|
+
for i, ripper in enumerate(Ripper.ripper_list, 1):
|
|
325
|
+
progress = f"{i} / {total} - {PROJECT_TITLE}"
|
|
326
|
+
log.info(progress)
|
|
327
|
+
change_title(progress)
|
|
328
|
+
try:
|
|
329
|
+
if ripper.run() is False:
|
|
330
|
+
log.error("Run {} failed", "Ripper")
|
|
331
|
+
except Exception as e:
|
|
332
|
+
log.error(e, deep=True)
|
|
333
|
+
log.warning("Stop run Ripper")
|
|
334
|
+
sleep(0.5)
|
|
335
|
+
|
|
275
336
|
if log.warning_num > warning_num:
|
|
276
337
|
log.warning(
|
|
277
338
|
"There are {} {} during run", log.warning_num - warning_num, "warning"
|
|
278
339
|
)
|
|
279
340
|
if log.error_num > error_num:
|
|
280
341
|
log.error("There are {} {} during run", log.error_num - error_num, "error")
|
|
281
|
-
Ripper.ripper_list
|
|
342
|
+
Ripper.ripper_list.clear()
|
|
282
343
|
path_lock_shm.close()
|
|
283
344
|
|
|
284
345
|
if shutdown_sec:
|
|
@@ -293,25 +354,52 @@ def run_ripper_list(
|
|
|
293
354
|
os.system(_cmd[0])
|
|
294
355
|
|
|
295
356
|
if is_exit_when_run_finished:
|
|
296
|
-
sys.exit()
|
|
357
|
+
sys.exit(0)
|
|
297
358
|
|
|
298
359
|
change_title(f"End - {PROJECT_TITLE}")
|
|
299
360
|
log.info("Run completed")
|
|
300
361
|
|
|
301
362
|
|
|
302
|
-
def
|
|
303
|
-
|
|
304
|
-
|
|
363
|
+
def get_web_server_params(
|
|
364
|
+
opt: str,
|
|
365
|
+
) -> Literal[False] | tuple[str, int, str | None]:
|
|
366
|
+
"""[<address>]:[<port>]@[<password>]"""
|
|
367
|
+
if easyrip_web.http_server.Event.is_run_command:
|
|
368
|
+
log.error("Can not start multiple services")
|
|
369
|
+
return False
|
|
305
370
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
371
|
+
if ":" not in opt:
|
|
372
|
+
log.error("{} param illegal", f"':' not in '{opt}':")
|
|
373
|
+
return False
|
|
374
|
+
|
|
375
|
+
opt_list: list[str] = opt.split(":")
|
|
376
|
+
opt_list = [opt_list[0], *opt_list[1].split("@")]
|
|
377
|
+
|
|
378
|
+
if len(opt_list) != 3:
|
|
379
|
+
log.error("{} param illegal", f"len('{opt}') != 3:")
|
|
380
|
+
return False
|
|
381
|
+
|
|
382
|
+
host, port, password = opt_list
|
|
383
|
+
|
|
384
|
+
port = port or "0"
|
|
385
|
+
|
|
386
|
+
if not port.isdigit():
|
|
387
|
+
log.error("{} param illegal", f"The port in '{opt}' not a digit:")
|
|
388
|
+
return False
|
|
389
|
+
|
|
390
|
+
return (host or "", int(port), password)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def run_command(command: Iterable[str] | str) -> bool:
|
|
394
|
+
try:
|
|
395
|
+
cmd_list: list[str] = (
|
|
396
|
+
shlex.split(command.replace("\\", "\\\\") if os.name == "nt" else command)
|
|
397
|
+
if isinstance(command, str)
|
|
398
|
+
else list(command)
|
|
399
|
+
)
|
|
400
|
+
except ValueError as e:
|
|
401
|
+
log.error(e)
|
|
402
|
+
return False
|
|
315
403
|
|
|
316
404
|
if len(cmd_list) == 0:
|
|
317
405
|
return True
|
|
@@ -321,7 +409,7 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
321
409
|
cmd_list.append("")
|
|
322
410
|
|
|
323
411
|
cmd_type: Cmd_type | None = None
|
|
324
|
-
if cmd_list[0] in Cmd_type._member_map_
|
|
412
|
+
if cmd_list[0] in Cmd_type._member_map_:
|
|
325
413
|
cmd_type = Cmd_type[cmd_list[0]]
|
|
326
414
|
elif len(cmd_list[0]) > 0 and cmd_list[0].startswith("$"):
|
|
327
415
|
cmd_type = Cmd_type._run_any
|
|
@@ -332,10 +420,54 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
332
420
|
_want_doc_cmd_type: Cmd_type | Opt_type | None = Cmd_type.from_str(
|
|
333
421
|
cmd_list[1]
|
|
334
422
|
) or Opt_type.from_str(cmd_list[1])
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
423
|
+
match _want_doc_cmd_type:
|
|
424
|
+
case Opt_type._preset:
|
|
425
|
+
if not cmd_list[2]:
|
|
426
|
+
log.send(_want_doc_cmd_type.value.to_doc(), is_format=False)
|
|
427
|
+
elif cmd_list[2] in Ripper.Preset_name._value2member_map_:
|
|
428
|
+
_preset = Ripper.Preset_name(cmd_list[2])
|
|
429
|
+
if (
|
|
430
|
+
_preset in DEFAULT_PRESET_PARAMS
|
|
431
|
+
or _preset in PRESET_OPT_NAME
|
|
432
|
+
):
|
|
433
|
+
if _preset in PRESET_OPT_NAME:
|
|
434
|
+
log.send(
|
|
435
|
+
"Params that can be directly used:\n{}",
|
|
436
|
+
textwrap.indent(
|
|
437
|
+
"\n".join(
|
|
438
|
+
f"-{n}"
|
|
439
|
+
for n in PRESET_OPT_NAME[_preset]
|
|
440
|
+
),
|
|
441
|
+
prefix=" ",
|
|
442
|
+
),
|
|
443
|
+
)
|
|
444
|
+
if _preset in DEFAULT_PRESET_PARAMS:
|
|
445
|
+
_default_params = DEFAULT_PRESET_PARAMS[_preset]
|
|
446
|
+
max_name_len = (
|
|
447
|
+
max(len(str(n)) for n in _default_params) + 1
|
|
448
|
+
)
|
|
449
|
+
log.send(
|
|
450
|
+
"Default val:\n{}",
|
|
451
|
+
textwrap.indent(
|
|
452
|
+
"\n".join(
|
|
453
|
+
f"{f'-{n}':>{max_name_len}} {v}"
|
|
454
|
+
for n, v in _default_params.items()
|
|
455
|
+
),
|
|
456
|
+
prefix=" ",
|
|
457
|
+
),
|
|
458
|
+
)
|
|
459
|
+
else:
|
|
460
|
+
log.send(
|
|
461
|
+
"The preset '{}' has no separate help", cmd_list[2]
|
|
462
|
+
)
|
|
463
|
+
else:
|
|
464
|
+
log.error("'{}' is not a member of preset", cmd_list[2])
|
|
465
|
+
|
|
466
|
+
case None:
|
|
467
|
+
log.error("'{}' does not exist", cmd_list[1])
|
|
468
|
+
|
|
469
|
+
case _:
|
|
470
|
+
log.send(_want_doc_cmd_type.value.to_doc(), is_format=False)
|
|
339
471
|
else:
|
|
340
472
|
log.send(get_help_doc(), is_format=False)
|
|
341
473
|
|
|
@@ -368,35 +500,52 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
368
500
|
log.error("Your input command has error:\n{}", e)
|
|
369
501
|
|
|
370
502
|
case Cmd_type.exit:
|
|
371
|
-
sys.exit()
|
|
503
|
+
sys.exit(0)
|
|
372
504
|
|
|
373
|
-
case Cmd_type.cd | Cmd_type.mediainfo:
|
|
374
|
-
|
|
505
|
+
case Cmd_type.cd | Cmd_type.mediainfo | Cmd_type.fontinfo:
|
|
506
|
+
_path_tuple: tuple[str, ...] | None = None
|
|
375
507
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
508
|
+
match cmd_list[1]:
|
|
509
|
+
case "fd" | "cfd" as fd_param:
|
|
510
|
+
if easyrip_web.http_server.Event.is_run_command:
|
|
511
|
+
log.error("Disable the use of '{}' on the web", fd_param)
|
|
512
|
+
return False
|
|
513
|
+
_path_tuple = file_dialog(
|
|
514
|
+
is_askdir=cmd_type is Cmd_type.cd,
|
|
515
|
+
initialdir=os.getcwd() if fd_param == "cfd" else None,
|
|
516
|
+
)
|
|
517
|
+
case _:
|
|
518
|
+
if isinstance(command, str):
|
|
519
|
+
_path = command.split(None, maxsplit=1)
|
|
520
|
+
_path_tuple = (
|
|
521
|
+
None
|
|
522
|
+
if len(_path) <= 1
|
|
523
|
+
else tuple(_path[1].strip('"').strip("'").split("?"))
|
|
524
|
+
)
|
|
382
525
|
|
|
383
|
-
|
|
384
|
-
|
|
526
|
+
if _path_tuple is None:
|
|
527
|
+
_path_tuple = tuple(cmd_list[1].split("?"))
|
|
385
528
|
|
|
386
529
|
match cmd_type:
|
|
387
530
|
case Cmd_type.cd:
|
|
388
531
|
try:
|
|
389
|
-
os.chdir(
|
|
532
|
+
os.chdir(_path_tuple[0])
|
|
390
533
|
except OSError as e:
|
|
391
534
|
log.error(e)
|
|
392
535
|
case Cmd_type.mediainfo:
|
|
393
|
-
|
|
394
|
-
|
|
536
|
+
for _path in _path_tuple:
|
|
537
|
+
log.send(f"{_path}: {Media_info.from_path(_path)}")
|
|
538
|
+
case Cmd_type.fontinfo:
|
|
539
|
+
for _font in itertools.chain.from_iterable(
|
|
540
|
+
load_fonts(_path) for _path in _path_tuple
|
|
541
|
+
):
|
|
542
|
+
log.send(
|
|
543
|
+
f"{_font.pathname}: {_font.familys} / {_font.font_type.name}"
|
|
544
|
+
)
|
|
395
545
|
|
|
396
546
|
case Cmd_type.dir:
|
|
397
547
|
files = os.listdir(os.getcwd())
|
|
398
|
-
|
|
399
|
-
print(f_and_s)
|
|
548
|
+
log.print("\n".join(files))
|
|
400
549
|
log.send(" | ".join(files))
|
|
401
550
|
|
|
402
551
|
case Cmd_type.mkdir:
|
|
@@ -407,11 +556,12 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
407
556
|
|
|
408
557
|
case Cmd_type.cls:
|
|
409
558
|
os.system("cls") if os.name == "nt" else os.system("clear")
|
|
559
|
+
easyrip_web.http_server.Event.log_queue.clear()
|
|
410
560
|
|
|
411
561
|
case Cmd_type.list:
|
|
412
562
|
match cmd_list[1]:
|
|
413
563
|
case "clear" | "clean":
|
|
414
|
-
Ripper.ripper_list
|
|
564
|
+
Ripper.ripper_list.clear()
|
|
415
565
|
case "del" | "pop":
|
|
416
566
|
try:
|
|
417
567
|
del Ripper.ripper_list[int(cmd_list[2]) - 1]
|
|
@@ -437,15 +587,14 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
437
587
|
reverse=reverse,
|
|
438
588
|
)
|
|
439
589
|
case "":
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
log.send(msg, is_format=False)
|
|
590
|
+
log.send(
|
|
591
|
+
f"Ripper list ({len(Ripper.ripper_list)}):"
|
|
592
|
+
+ f"\n {'─' * (shutil.get_terminal_size().columns - 2)}".join(
|
|
593
|
+
f"\n {i}.\n {ripper}"
|
|
594
|
+
for i, ripper in enumerate(Ripper.ripper_list, 1)
|
|
595
|
+
),
|
|
596
|
+
is_format=False,
|
|
597
|
+
)
|
|
449
598
|
case _:
|
|
450
599
|
try:
|
|
451
600
|
i1, i2 = int(cmd_list[1]), int(cmd_list[2])
|
|
@@ -457,109 +606,138 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
457
606
|
Ripper.ripper_list[i2],
|
|
458
607
|
Ripper.ripper_list[i1],
|
|
459
608
|
)
|
|
460
|
-
except
|
|
461
|
-
log.error(
|
|
609
|
+
except ValueError:
|
|
610
|
+
log.error("2 int must be inputed")
|
|
611
|
+
except IndexError:
|
|
612
|
+
log.error("list index out of range")
|
|
462
613
|
|
|
463
614
|
case Cmd_type.run:
|
|
464
|
-
is_run_exit = False
|
|
465
|
-
match cmd_list[1]:
|
|
466
|
-
case "":
|
|
467
|
-
pass
|
|
468
|
-
case "exit":
|
|
469
|
-
is_run_exit = True
|
|
470
|
-
case "shutdown":
|
|
471
|
-
if _shutdown_sec_str := cmd_list[2] or "60":
|
|
472
|
-
log.info(
|
|
473
|
-
"Will shutdown in {}s after run finished", _shutdown_sec_str
|
|
474
|
-
)
|
|
475
|
-
case _ as param:
|
|
476
|
-
log.error("Unsupported param: {}", param)
|
|
477
|
-
return False
|
|
615
|
+
is_run_exit: bool = False
|
|
478
616
|
|
|
479
|
-
|
|
617
|
+
_web_server_params = None
|
|
480
618
|
|
|
481
|
-
|
|
482
|
-
if easyrip_web.http_server.Event.is_run_command:
|
|
483
|
-
log.error("Can not start multiple services")
|
|
484
|
-
return False
|
|
619
|
+
_enable_multithreading: bool = False
|
|
485
620
|
|
|
486
|
-
|
|
621
|
+
_shutdown_sec_str: str | None = None
|
|
487
622
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
623
|
+
_skip_run_param: int = 0
|
|
624
|
+
|
|
625
|
+
for i, cmd in enumerate(cmd_list[1:]):
|
|
626
|
+
if _skip_run_param:
|
|
627
|
+
_skip_run_param -= 1
|
|
628
|
+
continue
|
|
629
|
+
|
|
630
|
+
match cmd:
|
|
631
|
+
case "":
|
|
632
|
+
pass
|
|
633
|
+
|
|
634
|
+
case "exit":
|
|
635
|
+
is_run_exit = True
|
|
636
|
+
|
|
637
|
+
case "shutdown":
|
|
638
|
+
_skip_run_param += 1
|
|
639
|
+
if i + 1 < len(cmd_list[1:]):
|
|
640
|
+
_shutdown_sec_str = cmd_list[i + 1] or "60"
|
|
641
|
+
log.info(
|
|
642
|
+
"Will shutdown in {}s after run finished",
|
|
643
|
+
_shutdown_sec_str,
|
|
644
|
+
)
|
|
645
|
+
else:
|
|
646
|
+
log.error("{} need param", cmd)
|
|
647
|
+
return False
|
|
648
|
+
|
|
649
|
+
case "server":
|
|
650
|
+
_skip_run_param += 1
|
|
651
|
+
if (
|
|
652
|
+
_web_server_params := get_web_server_params(cmd_list[2])
|
|
653
|
+
) is False:
|
|
654
|
+
return False
|
|
655
|
+
|
|
656
|
+
case "-multithreading":
|
|
657
|
+
_skip_run_param += 1
|
|
658
|
+
if i + 1 < len(cmd_list[1:]):
|
|
659
|
+
_enable_multithreading = cmd_list[i + 1] != "0"
|
|
660
|
+
else:
|
|
661
|
+
log.error("{} need param", cmd)
|
|
662
|
+
return False
|
|
663
|
+
|
|
664
|
+
case _ as param:
|
|
665
|
+
log.error("Unsupported param: {}", param)
|
|
666
|
+
return False
|
|
667
|
+
|
|
668
|
+
if _web_server_params is None:
|
|
669
|
+
run_ripper_list(
|
|
670
|
+
is_exit_when_run_finished=is_run_exit,
|
|
671
|
+
shutdow_sec_str=_shutdown_sec_str,
|
|
672
|
+
enable_multithreading=_enable_multithreading,
|
|
503
673
|
)
|
|
504
|
-
if res:
|
|
505
|
-
host = res.group(1)
|
|
506
|
-
port = res.group(2)
|
|
507
|
-
if port:
|
|
508
|
-
port = int(port.lstrip(":"))
|
|
509
|
-
elif host.isdigit():
|
|
510
|
-
port = int(host)
|
|
511
|
-
host = None
|
|
512
|
-
else:
|
|
513
|
-
port = None
|
|
514
|
-
host = None
|
|
515
|
-
else:
|
|
516
|
-
host, port = "localhost", 0
|
|
517
674
|
else:
|
|
518
|
-
|
|
675
|
+
easyrip_web.run_server(
|
|
676
|
+
*_web_server_params,
|
|
677
|
+
after_start_server_hook=lambda: run_ripper_list(
|
|
678
|
+
is_exit_when_run_finished=is_run_exit,
|
|
679
|
+
shutdow_sec_str=_shutdown_sec_str,
|
|
680
|
+
enable_multithreading=_enable_multithreading,
|
|
681
|
+
),
|
|
682
|
+
)
|
|
519
683
|
|
|
520
|
-
|
|
684
|
+
case Cmd_type.server:
|
|
685
|
+
if (_params := get_web_server_params(cmd_list[1])) is False:
|
|
686
|
+
return False
|
|
687
|
+
easyrip_web.run_server(*_params)
|
|
521
688
|
|
|
522
689
|
case Cmd_type.config:
|
|
523
690
|
match cmd_list[1]:
|
|
524
|
-
case "
|
|
691
|
+
case "list" | "":
|
|
692
|
+
config.show_config_list()
|
|
693
|
+
case "regenerate" | "clear" | "clean":
|
|
525
694
|
config.regenerate_config()
|
|
526
695
|
init()
|
|
527
696
|
case "open":
|
|
528
697
|
config.open_config_dir()
|
|
529
698
|
case "set":
|
|
699
|
+
_key = cmd_list[2]
|
|
530
700
|
_val = cmd_list[3]
|
|
701
|
+
|
|
702
|
+
if (_old_val := config.get_user_profile(_key)) is None:
|
|
703
|
+
return False
|
|
704
|
+
|
|
531
705
|
try:
|
|
532
|
-
_val =
|
|
533
|
-
except ValueError:
|
|
706
|
+
_val = ast.literal_eval(_val)
|
|
707
|
+
except (ValueError, SyntaxError):
|
|
534
708
|
pass
|
|
535
|
-
try:
|
|
536
|
-
_val = float(_val)
|
|
537
|
-
except ValueError:
|
|
538
|
-
pass
|
|
539
|
-
match _val:
|
|
540
|
-
case "true" | "True":
|
|
541
|
-
_val = True
|
|
542
|
-
case "false" | "False":
|
|
543
|
-
_val = False
|
|
544
709
|
|
|
545
|
-
if
|
|
710
|
+
if _old_val == _val:
|
|
546
711
|
log.info(
|
|
547
712
|
"The new value is the same as the old value, cancel the modification",
|
|
548
713
|
)
|
|
549
|
-
elif config.set_user_profile(
|
|
714
|
+
elif config.set_user_profile(_key, _val):
|
|
550
715
|
init()
|
|
551
716
|
log.info(
|
|
552
|
-
"'
|
|
553
|
-
|
|
554
|
-
_old_val,
|
|
555
|
-
|
|
717
|
+
"'{}' successfully: {}",
|
|
718
|
+
f"config set {_key}",
|
|
719
|
+
f"{f'"{_old_val}"' if isinstance(_old_val, str) else _old_val} -> {f'"{_val}"' if isinstance(_val, str) else _val}"
|
|
720
|
+
+ (
|
|
721
|
+
""
|
|
722
|
+
if type(_old_val) is type(_val)
|
|
723
|
+
else f" ({type(_old_val).__name__} -> {type(_val).__name__})"
|
|
724
|
+
),
|
|
556
725
|
)
|
|
557
|
-
case "list":
|
|
558
|
-
config.show_config_list()
|
|
559
726
|
case _ as param:
|
|
560
727
|
log.error("Unsupported param: {}", param)
|
|
561
728
|
return False
|
|
562
729
|
|
|
730
|
+
case Cmd_type.prompt:
|
|
731
|
+
match cmd_list[1]:
|
|
732
|
+
case "history":
|
|
733
|
+
with easyrip_prompt.PROMPT_HISTORY_FILE.open(
|
|
734
|
+
"rt", encoding="utf-8"
|
|
735
|
+
) as f:
|
|
736
|
+
for line in f.read().splitlines():
|
|
737
|
+
log.send(line, is_format=False)
|
|
738
|
+
case "clear" | "clean":
|
|
739
|
+
easyrip_prompt.clear()
|
|
740
|
+
|
|
563
741
|
case Cmd_type.translate:
|
|
564
742
|
if not (_infix := cmd_list[1]):
|
|
565
743
|
log.error("Need target infix")
|
|
@@ -604,22 +782,32 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
604
782
|
return True
|
|
605
783
|
|
|
606
784
|
case _:
|
|
785
|
+
if shutil.which(cmd_list[0]):
|
|
786
|
+
if easyrip_web.http_server.Event.is_run_command:
|
|
787
|
+
log.error("Disable the use of '{}' on the web", cmd_list[0])
|
|
788
|
+
return False
|
|
789
|
+
|
|
790
|
+
os.system(command if isinstance(command, str) else " ".join(command))
|
|
791
|
+
return True
|
|
792
|
+
|
|
607
793
|
input_pathname_org_list: list[str] = []
|
|
608
|
-
output_basename = None
|
|
609
|
-
output_dir = None
|
|
610
|
-
preset_name = None
|
|
794
|
+
output_basename: str | None = None
|
|
795
|
+
output_dir: str | None = None
|
|
796
|
+
preset_name: str | Ripper.Preset_name | None = None
|
|
611
797
|
option_map: dict[str, str] = {}
|
|
612
|
-
is_run = False
|
|
613
|
-
|
|
798
|
+
is_run: bool = False
|
|
799
|
+
web_server_params = None
|
|
800
|
+
is_exit_when_run_finished: bool = False
|
|
614
801
|
shutdown_sec_str: str | None = None
|
|
802
|
+
enable_multithreading: bool = False
|
|
615
803
|
|
|
616
|
-
_skip:
|
|
804
|
+
_skip: int = 0
|
|
617
805
|
for i in range(len(cmd_list)):
|
|
618
806
|
if _skip:
|
|
619
|
-
_skip
|
|
807
|
+
_skip -= 1
|
|
620
808
|
continue
|
|
621
809
|
|
|
622
|
-
_skip
|
|
810
|
+
_skip += 1
|
|
623
811
|
|
|
624
812
|
match cmd_list[i]:
|
|
625
813
|
case "-i":
|
|
@@ -631,7 +819,9 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
631
819
|
)
|
|
632
820
|
return False
|
|
633
821
|
input_pathname_org_list += file_dialog(
|
|
634
|
-
|
|
822
|
+
initialdir=(
|
|
823
|
+
os.getcwd() if fd_param == "cfd" else None
|
|
824
|
+
)
|
|
635
825
|
)
|
|
636
826
|
case _:
|
|
637
827
|
input_pathname_org_list += [
|
|
@@ -674,18 +864,51 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
674
864
|
is_exit_when_run_finished = True
|
|
675
865
|
case "shutdown":
|
|
676
866
|
shutdown_sec_str = cmd_list[i + 2] or "60"
|
|
867
|
+
_skip += 1
|
|
868
|
+
case "server":
|
|
869
|
+
web_server_params = get_web_server_params(
|
|
870
|
+
cmd_list[i + 2]
|
|
871
|
+
)
|
|
872
|
+
if web_server_params is False:
|
|
873
|
+
return False
|
|
874
|
+
_skip += 1
|
|
875
|
+
case _:
|
|
876
|
+
_skip -= 1
|
|
877
|
+
|
|
878
|
+
case "-multithreading":
|
|
879
|
+
match cmd_list[i + 1]:
|
|
880
|
+
case "0":
|
|
881
|
+
enable_multithreading = False
|
|
882
|
+
case "1":
|
|
883
|
+
enable_multithreading = True
|
|
677
884
|
case _:
|
|
678
|
-
|
|
885
|
+
log.error("Unsupported param: {}", cmd_list[i + 1])
|
|
886
|
+
return False
|
|
679
887
|
|
|
680
888
|
case str() as s if len(s) > 1 and s.startswith("-"):
|
|
681
889
|
option_map[s[1:]] = cmd_list[i + 1]
|
|
682
890
|
|
|
683
891
|
case _:
|
|
684
|
-
_skip
|
|
892
|
+
_skip -= 1
|
|
685
893
|
|
|
686
894
|
if not preset_name:
|
|
687
895
|
log.warning("Missing '-preset' option, set to default value 'custom'")
|
|
688
896
|
preset_name = "custom"
|
|
897
|
+
if preset_name not in Ripper.Preset_name._value2member_map_:
|
|
898
|
+
log.error("'{}' is not a member of preset", preset_name)
|
|
899
|
+
return False
|
|
900
|
+
|
|
901
|
+
preset_name = Ripper.Preset_name(preset_name)
|
|
902
|
+
|
|
903
|
+
if (
|
|
904
|
+
preset_name is Ripper.Preset_name.custom
|
|
905
|
+
and easyrip_web.http_server.Event.is_run_command
|
|
906
|
+
):
|
|
907
|
+
log.error(
|
|
908
|
+
"Disable the use of '{}' on the web",
|
|
909
|
+
f"-preset {Ripper.Preset_name.custom}",
|
|
910
|
+
)
|
|
911
|
+
return False
|
|
689
912
|
|
|
690
913
|
try:
|
|
691
914
|
if len(input_pathname_org_list) == 0:
|
|
@@ -695,17 +918,21 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
695
918
|
for i, input_pathname in enumerate(input_pathname_org_list):
|
|
696
919
|
new_option_map = option_map.copy()
|
|
697
920
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
921
|
+
fmt_time = datetime.now()
|
|
922
|
+
|
|
923
|
+
def _create_iterator_fmt_replace(
|
|
924
|
+
time: datetime, num: int
|
|
925
|
+
) -> Callable[[re.Match[str]], str]:
|
|
926
|
+
def _iterator_fmt_replace(match: re.Match[str]) -> str:
|
|
927
|
+
s = match.group(1)
|
|
928
|
+
match s:
|
|
929
|
+
case str() as s if s.startswith("time:"):
|
|
930
|
+
try:
|
|
931
|
+
return time.strftime(s[5:])
|
|
932
|
+
except Exception as e:
|
|
933
|
+
log.error(f"{e!r} {e}", deep=True)
|
|
934
|
+
return ""
|
|
935
|
+
case _:
|
|
709
936
|
d = {
|
|
710
937
|
k: v
|
|
711
938
|
for s1 in s.split(",")
|
|
@@ -714,35 +941,38 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
714
941
|
start = int(d.get("start", 0))
|
|
715
942
|
padding = int(d.get("padding", 0))
|
|
716
943
|
increment = int(d.get("increment", 1))
|
|
717
|
-
return str(start +
|
|
718
|
-
except Exception as e:
|
|
719
|
-
log.error(f"{e!r} {e}", deep=True)
|
|
720
|
-
return ""
|
|
944
|
+
return str(start + num * increment).zfill(padding)
|
|
721
945
|
|
|
722
|
-
|
|
723
|
-
new_output_basename = None
|
|
724
|
-
else:
|
|
725
|
-
_time = datetime.now()
|
|
946
|
+
return _iterator_fmt_replace
|
|
726
947
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
output_basename
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
_iterator_fmt_replace,
|
|
737
|
-
chapters,
|
|
948
|
+
try:
|
|
949
|
+
new_output_basename = (
|
|
950
|
+
None
|
|
951
|
+
if output_basename is None
|
|
952
|
+
else re.sub(
|
|
953
|
+
r"\?\{([^}]*)\}",
|
|
954
|
+
_create_iterator_fmt_replace(fmt_time, i),
|
|
955
|
+
output_basename,
|
|
956
|
+
)
|
|
738
957
|
)
|
|
739
958
|
|
|
740
|
-
if
|
|
741
|
-
|
|
742
|
-
"
|
|
959
|
+
if chapters := option_map.get("chapters"):
|
|
960
|
+
chapters = re.sub(
|
|
961
|
+
r"\?\{([^}]*)\}",
|
|
962
|
+
_create_iterator_fmt_replace(fmt_time, i),
|
|
963
|
+
chapters,
|
|
743
964
|
)
|
|
744
965
|
|
|
745
|
-
|
|
966
|
+
if not Path(chapters).is_file():
|
|
967
|
+
log.warning(
|
|
968
|
+
"The '-chapters' file {} does not exist", chapters
|
|
969
|
+
)
|
|
970
|
+
|
|
971
|
+
new_option_map["chapters"] = chapters
|
|
972
|
+
|
|
973
|
+
except ValueError as e:
|
|
974
|
+
log.error("Unsupported param: {}", e)
|
|
975
|
+
return False
|
|
746
976
|
|
|
747
977
|
input_pathname_list: list[str] = input_pathname.split("?")
|
|
748
978
|
for path in input_pathname_list:
|
|
@@ -801,7 +1031,7 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
801
1031
|
f"{new_output_basename or _input_basename[0]}{_output_base_suffix_name}"
|
|
802
1032
|
],
|
|
803
1033
|
output_dir,
|
|
804
|
-
|
|
1034
|
+
preset_name,
|
|
805
1035
|
new_option_map,
|
|
806
1036
|
)
|
|
807
1037
|
|
|
@@ -818,7 +1048,7 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
818
1048
|
input_pathname_list,
|
|
819
1049
|
[new_output_basename],
|
|
820
1050
|
output_dir,
|
|
821
|
-
|
|
1051
|
+
preset_name,
|
|
822
1052
|
new_option_map,
|
|
823
1053
|
)
|
|
824
1054
|
|
|
@@ -827,7 +1057,7 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
827
1057
|
input_pathname_list,
|
|
828
1058
|
[new_output_basename],
|
|
829
1059
|
output_dir,
|
|
830
|
-
|
|
1060
|
+
preset_name,
|
|
831
1061
|
new_option_map,
|
|
832
1062
|
)
|
|
833
1063
|
|
|
@@ -836,38 +1066,56 @@ def run_command(command: list[str] | str) -> bool:
|
|
|
836
1066
|
return False
|
|
837
1067
|
|
|
838
1068
|
if is_run:
|
|
839
|
-
|
|
1069
|
+
if web_server_params is None:
|
|
1070
|
+
run_ripper_list(
|
|
1071
|
+
is_exit_when_run_finished=is_exit_when_run_finished,
|
|
1072
|
+
shutdow_sec_str=shutdown_sec_str,
|
|
1073
|
+
enable_multithreading=enable_multithreading,
|
|
1074
|
+
)
|
|
1075
|
+
else:
|
|
1076
|
+
easyrip_web.run_server(
|
|
1077
|
+
*web_server_params,
|
|
1078
|
+
after_start_server_hook=lambda: run_ripper_list(
|
|
1079
|
+
is_exit_when_run_finished=is_exit_when_run_finished,
|
|
1080
|
+
shutdow_sec_str=shutdown_sec_str,
|
|
1081
|
+
enable_multithreading=enable_multithreading,
|
|
1082
|
+
),
|
|
1083
|
+
)
|
|
840
1084
|
|
|
841
1085
|
return True
|
|
842
1086
|
|
|
843
1087
|
|
|
844
|
-
def init(is_first_run: bool = False):
|
|
1088
|
+
def init(is_first_run: bool = False) -> None:
|
|
845
1089
|
if is_first_run:
|
|
846
1090
|
# 当前路径添加到环境变量
|
|
847
1091
|
new_path = os.path.realpath(os.getcwd())
|
|
848
|
-
if os.pathsep in (
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
1092
|
+
if os.pathsep in (
|
|
1093
|
+
current_path := os.environ.get("PATH", "")
|
|
1094
|
+
) and new_path not in current_path.split(os.pathsep):
|
|
1095
|
+
updated_path = f"{new_path}{os.pathsep}{current_path}"
|
|
1096
|
+
os.environ["PATH"] = updated_path
|
|
852
1097
|
|
|
853
1098
|
# 设置语言
|
|
854
1099
|
_sys_lang = get_system_language()
|
|
855
1100
|
Global_lang_val.gettext_target_lang = _sys_lang
|
|
856
|
-
if (_lang_config := config.get_user_profile(
|
|
1101
|
+
if (_lang_config := config.get_user_profile(Config_key.language)) not in {
|
|
1102
|
+
"auto",
|
|
1103
|
+
None,
|
|
1104
|
+
}:
|
|
857
1105
|
Global_lang_val.gettext_target_lang = Lang_tag.from_str(str(_lang_config))
|
|
858
1106
|
|
|
859
1107
|
# 设置日志文件路径名
|
|
860
|
-
log.html_filename = gettext(
|
|
861
|
-
if _path := str(config.get_user_profile(
|
|
1108
|
+
log.html_filename = gettext(log.html_filename)
|
|
1109
|
+
if _path := str(config.get_user_profile(Config_key.force_log_file_path) or ""):
|
|
862
1110
|
log.html_filename = os.path.join(_path, log.html_filename)
|
|
863
1111
|
|
|
864
1112
|
# 设置日志级别
|
|
865
1113
|
try:
|
|
866
1114
|
log.print_level = getattr(
|
|
867
|
-
log.LogLevel, str(config.get_user_profile(
|
|
1115
|
+
log.LogLevel, str(config.get_user_profile(Config_key.log_print_level))
|
|
868
1116
|
)
|
|
869
1117
|
log.write_level = getattr(
|
|
870
|
-
log.LogLevel, str(config.get_user_profile(
|
|
1118
|
+
log.LogLevel, str(config.get_user_profile(Config_key.log_write_level))
|
|
871
1119
|
)
|
|
872
1120
|
except Exception as e:
|
|
873
1121
|
log.error(f"{e!r} {e}", deep=True)
|
|
@@ -875,8 +1123,18 @@ def init(is_first_run: bool = False):
|
|
|
875
1123
|
if is_first_run:
|
|
876
1124
|
# 设置启动目录
|
|
877
1125
|
try:
|
|
878
|
-
if
|
|
879
|
-
|
|
1126
|
+
if _startup_dir := config.get_user_profile(Config_key.startup_dir):
|
|
1127
|
+
if _startup_dir_blacklist := config.get_user_profile(
|
|
1128
|
+
Config_key.startup_dir_blacklist
|
|
1129
|
+
):
|
|
1130
|
+
if any(
|
|
1131
|
+
Path.cwd().samefile(d)
|
|
1132
|
+
for d in map(Path, _startup_dir_blacklist)
|
|
1133
|
+
if d.is_dir()
|
|
1134
|
+
):
|
|
1135
|
+
os.chdir(_startup_dir)
|
|
1136
|
+
else:
|
|
1137
|
+
os.chdir(_startup_dir)
|
|
880
1138
|
except Exception as e:
|
|
881
1139
|
log.error(f"{e!r} {e}", deep=True)
|
|
882
1140
|
|
|
@@ -900,9 +1158,7 @@ def init(is_first_run: bool = False):
|
|
|
900
1158
|
if (
|
|
901
1159
|
lang_tag := Lang_tag.from_str(file.stem[5:])
|
|
902
1160
|
).language is not Lang_tag_language.Unknown:
|
|
903
|
-
easyrip_mlang.all_supported_lang_map[lang_tag] =
|
|
904
|
-
k: v for k, v in lang_map.items()
|
|
905
|
-
}
|
|
1161
|
+
easyrip_mlang.all_supported_lang_map[lang_tag] = lang_map
|
|
906
1162
|
|
|
907
1163
|
log.debug("Loading \"{}\" as '{}' language successfully", file, lang_tag)
|
|
908
1164
|
|
|
@@ -911,11 +1167,5 @@ def init(is_first_run: bool = False):
|
|
|
911
1167
|
Thread(target=check_env, daemon=True).start()
|
|
912
1168
|
|
|
913
1169
|
LogEvent.append_http_server_log_queue = (
|
|
914
|
-
|
|
1170
|
+
easyrip_web.http_server.Event.log_queue.append
|
|
915
1171
|
)
|
|
916
|
-
|
|
917
|
-
def _post_run_event(cmd: str):
|
|
918
|
-
run_command(cmd)
|
|
919
|
-
easyrip_web.http_server.Event.is_run_command = False
|
|
920
|
-
|
|
921
|
-
easyrip_web.http_server.Event.post_run_event = _post_run_event
|