ASMRManager 2.9.0__tar.gz → 2.9.2__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.
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/PKG-INFO +3 -3
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/README.md +2 -2
- asmrmanager-2.9.2/asmrmanager/_version.py +1 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/core.py +9 -4
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/dl.py +4 -2
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/file.py +44 -9
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/main.py +3 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/sql.py +15 -3
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/utils.py +5 -3
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/which.py +3 -3
- asmrmanager-2.9.2/asmrmanager/common/__init__.py +11 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/fileconverter.py +4 -2
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/output.py +1 -1
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/config.py +6 -1
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/config.example.toml +10 -1
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/player/pygameplayer.py +1 -1
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/downloader.py +5 -3
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/interface.py +4 -2
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/pyproject.toml +1 -1
- asmrmanager-2.9.0/asmrmanager/_version.py +0 -1
- asmrmanager-2.9.0/asmrmanager/common/__init__.py +0 -1
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/LICENSE +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/__main__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/hold.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/info.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/pl.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/play.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/query.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/review.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/view.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/cli/vote.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/browse_params.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/download_params.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/parse_filter.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/rj_parse.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/select.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/subtitle.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/types.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/common/vtt2lrc.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/__pycache__/database.d.er +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/__pycache__/engine.d.er +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/__pycache__/q_func.d.er +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/database.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/engine.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/manage.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/orm_type.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/q_func.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/utils/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/utils/add2db.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/database/utils/uuid_sqlite.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/appdirs_.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/exceptions.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/file_zipper.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/manager.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/akarin.jpg +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/circle_name.sql +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/score.sql +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/search.sql +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/tags.sql +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/test.sql +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/vas.sql +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/utils.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/logger/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/lrcparse.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/main.css +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/main.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/player/base.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/player/mpdplayer.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/lrcplayer/player/sdplayer.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/__init__.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/asmrapi.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/playlist.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/tag.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/utils/IDMHelper.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/utils/aria2_downloader.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/utils/concurrency.py +0 -0
- {asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/spider/utils/retry.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ASMRManager
|
|
3
|
-
Version: 2.9.
|
|
3
|
+
Version: 2.9.2
|
|
4
4
|
Summary: download, manage and play the voices on asmr.one
|
|
5
5
|
Keywords: asmr,downloader,music,player,manager,cli,tui,commandline,terminal
|
|
6
6
|
Author-Email: SLQY <sqiyel@gmail.com>
|
|
@@ -216,8 +216,8 @@ asmr dl get 300015443 # 本项目存储VJ与BJ所使用的ID("3" + 8位VJ号
|
|
|
216
216
|
检查下载目录下文件是否下载完全(默认会计算hash并向服务器验证,较为耗时。可使用 --offline 跳过)
|
|
217
217
|
|
|
218
218
|
```shell
|
|
219
|
-
asmr file check
|
|
220
|
-
asmr file check --list | xargs asmr dl get --force --replace # 重新下载所有不完整的文件,以bash shell为例
|
|
219
|
+
asmr file check --all
|
|
220
|
+
asmr file check --all --list | xargs asmr dl get --force --replace # 重新下载所有不完整的文件,以bash shell为例
|
|
221
221
|
```
|
|
222
222
|
|
|
223
223
|
将下载的文件转移到存储目录(STORAGE_PATH),并执行相应文件格式转换(详情见config.toml的before_store字段)
|
|
@@ -167,8 +167,8 @@ asmr dl get 300015443 # 本项目存储VJ与BJ所使用的ID("3" + 8位VJ号
|
|
|
167
167
|
检查下载目录下文件是否下载完全(默认会计算hash并向服务器验证,较为耗时。可使用 --offline 跳过)
|
|
168
168
|
|
|
169
169
|
```shell
|
|
170
|
-
asmr file check
|
|
171
|
-
asmr file check --list | xargs asmr dl get --force --replace # 重新下载所有不完整的文件,以bash shell为例
|
|
170
|
+
asmr file check --all
|
|
171
|
+
asmr file check --all --list | xargs asmr dl get --force --replace # 重新下载所有不完整的文件,以bash shell为例
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
将下载的文件转移到存储目录(STORAGE_PATH),并执行相应文件格式转换(详情见config.toml的before_store字段)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.9.2"
|
|
@@ -93,6 +93,7 @@ def create_downloader_and_database(
|
|
|
93
93
|
aria2_config=config.aria2_config,
|
|
94
94
|
limit=config.api_max_concurrent_requests,
|
|
95
95
|
fetch_cover=config.fetch_cover,
|
|
96
|
+
tagger=config.default_tagger,
|
|
96
97
|
),
|
|
97
98
|
db,
|
|
98
99
|
)
|
|
@@ -437,7 +438,9 @@ def multi_rj_argument(convert: Literal[False, "local", "remote"] = False):
|
|
|
437
438
|
SEPARATOR = ":"
|
|
438
439
|
|
|
439
440
|
|
|
440
|
-
def interval_preprocess_cb(
|
|
441
|
+
def interval_preprocess_cb(
|
|
442
|
+
_ctx: click.Context, _opt: click.Parameter, val: str
|
|
443
|
+
):
|
|
441
444
|
"""
|
|
442
445
|
input must be numeric or None,
|
|
443
446
|
and it returns a float/int/str/None value tuple
|
|
@@ -470,9 +473,11 @@ def time_interval_preprocess_cb(
|
|
|
470
473
|
):
|
|
471
474
|
return tuple(
|
|
472
475
|
map(
|
|
473
|
-
lambda x:
|
|
474
|
-
|
|
475
|
-
|
|
476
|
+
lambda x: (
|
|
477
|
+
str(x) + "m"
|
|
478
|
+
if (x is not None) and (not isinstance(x, str))
|
|
479
|
+
else x
|
|
480
|
+
),
|
|
476
481
|
interval_preprocess_cb(ctx, opt, val),
|
|
477
482
|
)
|
|
478
483
|
)
|
|
@@ -283,8 +283,10 @@ def search(
|
|
|
283
283
|
spider.search(
|
|
284
284
|
" ".join(
|
|
285
285
|
map(
|
|
286
|
-
lambda t: (
|
|
287
|
-
|
|
286
|
+
lambda t: (
|
|
287
|
+
(t := t.strip())
|
|
288
|
+
and ("-" + t[1:] if t.startswith("!") else t)
|
|
289
|
+
),
|
|
288
290
|
keywords,
|
|
289
291
|
)
|
|
290
292
|
),
|
|
@@ -153,12 +153,21 @@ def recover(source_id: LocalSourceID, regex: str, ignore_filter: bool):
|
|
|
153
153
|
show_default=True,
|
|
154
154
|
help="check files before storing",
|
|
155
155
|
)
|
|
156
|
+
@click.option(
|
|
157
|
+
"--on-error",
|
|
158
|
+
"-e",
|
|
159
|
+
type=click.Choice(["abort", "skip"], case_sensitive=False),
|
|
160
|
+
default="abort",
|
|
161
|
+
show_default=True,
|
|
162
|
+
help="what to do when a check failed",
|
|
163
|
+
)
|
|
156
164
|
def store(
|
|
157
165
|
source_ids: List[LocalSourceID],
|
|
158
166
|
no_convert: bool,
|
|
159
167
|
replace: bool,
|
|
160
168
|
all_: bool,
|
|
161
169
|
check: Literal["none", "offline", "online"],
|
|
170
|
+
on_error: Literal["abort", "skip"],
|
|
162
171
|
):
|
|
163
172
|
"""
|
|
164
173
|
store the downloaded files to the storage
|
|
@@ -204,8 +213,9 @@ def store(
|
|
|
204
213
|
else:
|
|
205
214
|
src_paths = list(
|
|
206
215
|
filter(
|
|
207
|
-
lambda p:
|
|
208
|
-
|
|
216
|
+
lambda p: (
|
|
217
|
+
not p.is_dir() and p.suffix.lower() != f".{to}"
|
|
218
|
+
),
|
|
209
219
|
path.rglob(f"*.{from_}", case_sensitive=False),
|
|
210
220
|
)
|
|
211
221
|
)
|
|
@@ -269,7 +279,12 @@ def store(
|
|
|
269
279
|
)
|
|
270
280
|
if not success:
|
|
271
281
|
logger.error("Stop storing due to check failed")
|
|
272
|
-
|
|
282
|
+
if on_error == "abort":
|
|
283
|
+
return
|
|
284
|
+
elif on_error == "skip":
|
|
285
|
+
continue
|
|
286
|
+
else:
|
|
287
|
+
assert False
|
|
273
288
|
fm.store(id_, replace=replace, hook=hook)
|
|
274
289
|
|
|
275
290
|
res = db.check_exists(id_)
|
|
@@ -353,15 +368,21 @@ def verify_voices(source_id: LocalSourceID, offline: bool) -> bool:
|
|
|
353
368
|
logger.error(f"failed to load recover for id {source_id}")
|
|
354
369
|
return False
|
|
355
370
|
|
|
356
|
-
|
|
371
|
+
local_files = fm.get_all_files(source_id)
|
|
372
|
+
for p in local_files:
|
|
373
|
+
if p.suffix == ".aria2":
|
|
374
|
+
logger.error(f"Aria2 control file found: {p}")
|
|
375
|
+
return False
|
|
357
376
|
remote_files_should_down = set(
|
|
358
377
|
[Path(i["path"]) for i in recovers if i["should_download"]]
|
|
359
378
|
)
|
|
360
379
|
# should_download_but_missing = remote_files_should_down - local_files
|
|
361
380
|
should_download_but_missing = set(
|
|
362
381
|
filter(
|
|
363
|
-
lambda p:
|
|
364
|
-
|
|
382
|
+
lambda p: (
|
|
383
|
+
not any(
|
|
384
|
+
fm.check_exists(f"{id2source_name(source_id)}/{str(p)}")
|
|
385
|
+
)
|
|
365
386
|
),
|
|
366
387
|
remote_files_should_down,
|
|
367
388
|
)
|
|
@@ -375,6 +396,7 @@ def verify_voices(source_id: LocalSourceID, offline: bool) -> bool:
|
|
|
375
396
|
|
|
376
397
|
if offline:
|
|
377
398
|
return True
|
|
399
|
+
logger.info(f"Start hash verification: {source_id}")
|
|
378
400
|
|
|
379
401
|
remote_files_should_down_list = [
|
|
380
402
|
Path(i["path"]) for i in recovers if i["should_download"]
|
|
@@ -454,12 +476,25 @@ def verify_voices(source_id: LocalSourceID, offline: bool) -> bool:
|
|
|
454
476
|
show_default=True,
|
|
455
477
|
help="only list source id (pipe it to `dl get --force` to redownload them)",
|
|
456
478
|
)
|
|
457
|
-
|
|
479
|
+
@click.option(
|
|
480
|
+
"--all",
|
|
481
|
+
"-a",
|
|
482
|
+
"all_",
|
|
483
|
+
is_flag=True,
|
|
484
|
+
default=False,
|
|
485
|
+
show_default=True,
|
|
486
|
+
help="check all files in download path",
|
|
487
|
+
)
|
|
488
|
+
@multi_rj_argument(convert="local")
|
|
489
|
+
def check(
|
|
490
|
+
source_ids: list[LocalSourceID], list_: bool, offline: bool, all_: bool
|
|
491
|
+
):
|
|
458
492
|
"""
|
|
459
493
|
check for download path for files to be downloaded correctly without missing or fail.
|
|
460
494
|
"""
|
|
461
|
-
|
|
462
|
-
|
|
495
|
+
if all_:
|
|
496
|
+
source_ids = list(fm.list_("download"))
|
|
497
|
+
|
|
463
498
|
for source_id in source_ids:
|
|
464
499
|
success = verify_voices(source_id, offline)
|
|
465
500
|
if not success and list_:
|
|
@@ -46,12 +46,15 @@ try:
|
|
|
46
46
|
import importlib.util
|
|
47
47
|
|
|
48
48
|
if importlib.util.find_spec("trogon"):
|
|
49
|
+
|
|
49
50
|
@click.command("tui", help="Open Textual TUI.")
|
|
50
51
|
@click.pass_context
|
|
51
52
|
def tui(ctx: click.Context):
|
|
52
53
|
from trogon import Trogon # type: ignore
|
|
54
|
+
|
|
53
55
|
if ctx.parent is not None:
|
|
54
56
|
Trogon(ctx.parent.command, click_context=ctx).run()
|
|
57
|
+
|
|
55
58
|
main.add_command(tui)
|
|
56
59
|
except ImportError:
|
|
57
60
|
pass
|
|
@@ -25,8 +25,20 @@ class SQLName(click.ParamType):
|
|
|
25
25
|
|
|
26
26
|
@click.command()
|
|
27
27
|
@click.argument("sql_name", type=SQLName())
|
|
28
|
-
@click.option(
|
|
29
|
-
|
|
28
|
+
@click.option(
|
|
29
|
+
"--edit",
|
|
30
|
+
"-e",
|
|
31
|
+
is_flag=True,
|
|
32
|
+
default=False,
|
|
33
|
+
help="whether to open an editor",
|
|
34
|
+
)
|
|
35
|
+
@click.option(
|
|
36
|
+
"--raw",
|
|
37
|
+
"-r",
|
|
38
|
+
is_flag=True,
|
|
39
|
+
default=False,
|
|
40
|
+
help="output sql results as json",
|
|
41
|
+
)
|
|
30
42
|
@click.option(
|
|
31
43
|
"--save/--no-save",
|
|
32
44
|
"-s/-ns",
|
|
@@ -55,7 +67,7 @@ def sql(sql_name: str, save: bool, edit: bool, raw: bool):
|
|
|
55
67
|
temp_file_path.write_text(
|
|
56
68
|
sql_path.read_text(encoding="utf8"), encoding="utf8"
|
|
57
69
|
)
|
|
58
|
-
if edit:
|
|
70
|
+
if edit:
|
|
59
71
|
run(f'{config.editor} "{temp_file_path}"', shell=True)
|
|
60
72
|
# db_path = temp_file_path.with_name('data.db')
|
|
61
73
|
# print(db_path, temp_file_path)
|
|
@@ -73,9 +73,11 @@ def convert(
|
|
|
73
73
|
|
|
74
74
|
src_paths = list(
|
|
75
75
|
filter(
|
|
76
|
-
lambda p:
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
lambda p: (
|
|
77
|
+
not p.is_dir()
|
|
78
|
+
and p.suffix.lower() in [".flac", ".wav", ".m4a"]
|
|
79
|
+
and p.suffix.lower() != f".{mode}"
|
|
80
|
+
),
|
|
79
81
|
path.rglob("*.*"),
|
|
80
82
|
)
|
|
81
83
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import subprocess
|
|
2
2
|
|
|
3
3
|
import click
|
|
4
4
|
|
|
@@ -22,9 +22,9 @@ def which(source_id: LocalSourceID, show: bool):
|
|
|
22
22
|
import sys
|
|
23
23
|
|
|
24
24
|
if sys.platform == "win32":
|
|
25
|
-
|
|
25
|
+
subprocess.Popen(["explorer.exe", path], start_new_session=True)
|
|
26
26
|
elif sys.platform.startswith("linux"):
|
|
27
|
-
|
|
27
|
+
subprocess.Popen(["xdg-open", path], start_new_session=True)
|
|
28
28
|
else:
|
|
29
29
|
logger.error(
|
|
30
30
|
"option --show is for windows and XDG based linux desktop environment only, if you are using other platform, using"
|
|
@@ -96,6 +96,7 @@ class AudioConverter:
|
|
|
96
96
|
):
|
|
97
97
|
self.tasks_total = len(src)
|
|
98
98
|
self.tasks_done = 0
|
|
99
|
+
self.update_total_progress()
|
|
99
100
|
|
|
100
101
|
match dst.lower():
|
|
101
102
|
case "mp3":
|
|
@@ -122,8 +123,9 @@ class AudioConverter:
|
|
|
122
123
|
x, x.with_suffix(f".{dst}"), convert_args
|
|
123
124
|
),
|
|
124
125
|
filter(
|
|
125
|
-
lambda p:
|
|
126
|
-
|
|
126
|
+
lambda p: (
|
|
127
|
+
not p.is_dir() and p.suffix.lower() != f".{dst}"
|
|
128
|
+
),
|
|
127
129
|
src,
|
|
128
130
|
),
|
|
129
131
|
)
|
|
@@ -19,6 +19,7 @@ class Config:
|
|
|
19
19
|
download_path: str
|
|
20
20
|
storage_path: str
|
|
21
21
|
view_path: str
|
|
22
|
+
default_tagger: Literal["tag", "tagw"]
|
|
22
23
|
tag_strategy: Literal["common_only", "accept_all", "except_rejected"] | str
|
|
23
24
|
tag_filter: List[str]
|
|
24
25
|
fetch_cover: bool
|
|
@@ -30,7 +31,7 @@ class Config:
|
|
|
30
31
|
aria2_config: "Aria2Config"
|
|
31
32
|
subtitle_config: "SubtitleConfig"
|
|
32
33
|
playlist_aliases: Dict[str, str]
|
|
33
|
-
player: Literal["mpd", "pygame"]
|
|
34
|
+
player: Literal["mpd", "pygame", "sounddevice"]
|
|
34
35
|
mpd_config: "MPDConfig"
|
|
35
36
|
before_store: str = ""
|
|
36
37
|
|
|
@@ -101,6 +102,7 @@ config = Config(
|
|
|
101
102
|
download_path=_config["download_path"],
|
|
102
103
|
storage_path=_config["storage_path"],
|
|
103
104
|
view_path=_config["view_path"],
|
|
105
|
+
default_tagger=_config.get("default_tagger", "tag"),
|
|
104
106
|
tag_strategy=_config.get("tag_strategy", "common_only"),
|
|
105
107
|
tag_filter=_config["tag_filter"],
|
|
106
108
|
fetch_cover=_config.get("fetch_cover", False),
|
|
@@ -127,4 +129,7 @@ if env_concurrency_limit := os.getenv("ASMR_CONCURRENCY_LIMIT"):
|
|
|
127
129
|
if os.getenv("ASMR_DISABLE_COVER") == "1":
|
|
128
130
|
config.display_cover = False
|
|
129
131
|
|
|
132
|
+
if (__tagger := os.getenv("ASMR_DEFAULT_TAGGER")) in ("tag", "tagw"):
|
|
133
|
+
config.default_tagger = __tagger
|
|
134
|
+
|
|
130
135
|
logger.debug(f"Config loaded: {config}")
|
{asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/config.example.toml
RENAMED
|
@@ -37,6 +37,13 @@ storage_path = "~/Music/asmr"
|
|
|
37
37
|
# 如不使用 view 方法可以设为空
|
|
38
38
|
view_path = "~/Desktop/asmr"
|
|
39
39
|
|
|
40
|
+
# [可选]
|
|
41
|
+
# 默认标签搜索策略,可选值为 tag 或 tagw
|
|
42
|
+
# 默认 tag 将排除用户添加的低愿力标签
|
|
43
|
+
# 如果你希望搜索它们可以使用 tagw
|
|
44
|
+
# 详见:https://t.me/asmr_one_chan/79
|
|
45
|
+
default_tagger = "tag"
|
|
46
|
+
|
|
40
47
|
# [高级]
|
|
41
48
|
# 标签接受策略,具体说明参考官方频道:https://t.me/asmr_one_chan/73
|
|
42
49
|
# 可选项有:
|
|
@@ -56,6 +63,8 @@ view_path = "~/Desktop/asmr"
|
|
|
56
63
|
# 因此,如果你特别讨厌某个标签,那么对于包含该标签的作品,即使票数并不多,也可以考虑接受该标签,这样在下一步的tag_filter中就可以过滤掉这个作品。
|
|
57
64
|
# 例如下面的设置,将对于特定的标签只需分数大于2即考虑接受,而一般标签需要分数大于5:
|
|
58
65
|
# tag_strategy = "common_only or (voteRank >= 5 or (tag['name'] in ['tagname1', 'tagname2'] and voteRank >= 2))"
|
|
66
|
+
#
|
|
67
|
+
# 请注意当default_tagger = "tag" 时,将不会搜到低愿力标签,即voteStatus != 0
|
|
59
68
|
|
|
60
69
|
# 默认会过滤除普通标签外的所有标签
|
|
61
70
|
tag_strategy = "common_only"
|
|
@@ -83,7 +92,7 @@ display_cover = false
|
|
|
83
92
|
editor = "code --wait"
|
|
84
93
|
|
|
85
94
|
# [可选]
|
|
86
|
-
#
|
|
95
|
+
# 下载所用的工具,可选择idm或aria2,请注意需安装对应的依赖项
|
|
87
96
|
download_method = "idm"
|
|
88
97
|
|
|
89
98
|
# [高级]
|
|
@@ -5,7 +5,7 @@ from .base import BasePlayer, Music
|
|
|
5
5
|
|
|
6
6
|
try:
|
|
7
7
|
with contextlib.redirect_stdout(None):
|
|
8
|
-
from pygame import mixer
|
|
8
|
+
from pygame import mixer # type: ignore
|
|
9
9
|
except ImportError:
|
|
10
10
|
raise ImportError(
|
|
11
11
|
"pygame is not installed, please install asmrmanager with pygame"
|
|
@@ -149,8 +149,10 @@ class ASMRDownloadAPI(ASMRAPI):
|
|
|
149
149
|
)
|
|
150
150
|
if any(
|
|
151
151
|
map(
|
|
152
|
-
lambda f:
|
|
153
|
-
|
|
152
|
+
lambda f: (
|
|
153
|
+
1 <= f.download_order <= download_order
|
|
154
|
+
and f.path.suffix.lower() in MUSIC_SUFFIXES
|
|
155
|
+
),
|
|
154
156
|
file_list_with_order,
|
|
155
157
|
)
|
|
156
158
|
):
|
|
@@ -215,7 +217,7 @@ class ASMRDownloadAPI(ASMRAPI):
|
|
|
215
217
|
logger.debug("final file list: %s", file_list)
|
|
216
218
|
|
|
217
219
|
self.create_recover_file(file_list, voice_path)
|
|
218
|
-
if self.fetch_cover:
|
|
220
|
+
if self.fetch_cover and all(f.path != 'cover.jpg' for f in file_list):
|
|
219
221
|
await self.download_cover(voice_id, voice_path)
|
|
220
222
|
await self.create_dir_and_download(file_list)
|
|
221
223
|
|
|
@@ -97,6 +97,7 @@ class ASMRDownloadManager(AsyncManager):
|
|
|
97
97
|
aria2_config: Aria2Config | None = None,
|
|
98
98
|
limit: int = 4,
|
|
99
99
|
fetch_cover: bool = False,
|
|
100
|
+
tagger: Literal["tag", "tagw"] = "tag",
|
|
100
101
|
):
|
|
101
102
|
self.downloader = ASMRDownloadAPI(
|
|
102
103
|
name=name,
|
|
@@ -112,6 +113,7 @@ class ASMRDownloadManager(AsyncManager):
|
|
|
112
113
|
)
|
|
113
114
|
super().__init__(self.downloader)
|
|
114
115
|
self.id_should_download = id_should_download or (lambda _: True)
|
|
116
|
+
self.tagger = tagger
|
|
115
117
|
|
|
116
118
|
async def get(self, ids: List[RemoteSourceID]):
|
|
117
119
|
tasks = []
|
|
@@ -152,8 +154,8 @@ class ASMRDownloadManager(AsyncManager):
|
|
|
152
154
|
|
|
153
155
|
filters = []
|
|
154
156
|
|
|
155
|
-
filters += [f"$
|
|
156
|
-
filters += [f"$-
|
|
157
|
+
filters += [f"${self.tagger}:{t}$" for t in tags]
|
|
158
|
+
filters += [f"$-{self.tagger}:{nt}$" for nt in no_tags]
|
|
157
159
|
|
|
158
160
|
filters += [f"$va:{va}$" for va in vas]
|
|
159
161
|
filters += [f"$-va:{nva}$" for nva in no_vas]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.9.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
MUSIC_SUFFIXES = (".mp3", ".wav", ".m4a", ".flac")
|
|
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
|
{asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/score.sql
RENAMED
|
File without changes
|
{asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/search.sql
RENAMED
|
File without changes
|
{asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/tags.sql
RENAMED
|
File without changes
|
{asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/test.sql
RENAMED
|
File without changes
|
{asmrmanager-2.9.0 → asmrmanager-2.9.2}/asmrmanager/filemanager/resources/sqls.example/vas.sql
RENAMED
|
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
|