ASMRManager 2.2.7__tar.gz → 2.2.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/PKG-INFO +52 -2
  2. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/README.md +51 -1
  3. asmrmanager-2.2.8/asmrmanager/_version.py +1 -0
  4. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/dl.py +1 -1
  5. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/file.py +10 -2
  6. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/utils.py +1 -1
  7. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/manager.py +71 -36
  8. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/pyproject.toml +1 -1
  9. asmrmanager-2.2.7/asmrmanager/_version.py +0 -1
  10. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/LICENSE +0 -0
  11. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/__init__.py +0 -0
  12. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/__main__.py +0 -0
  13. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/core.py +0 -0
  14. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/hold.py +0 -0
  15. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/info.py +0 -0
  16. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/main.py +0 -0
  17. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/pl.py +0 -0
  18. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/play.py +0 -0
  19. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/query.py +0 -0
  20. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/review.py +0 -0
  21. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/sql.py +0 -0
  22. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/view.py +0 -0
  23. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/cli/which.py +0 -0
  24. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/__init__.py +0 -0
  25. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/browse_params.py +0 -0
  26. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/download_params.py +0 -0
  27. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/fileconverter.py +0 -0
  28. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/output.py +0 -0
  29. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/parse_filter.py +0 -0
  30. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/rj_parse.py +0 -0
  31. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/select.py +0 -0
  32. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/types.py +0 -0
  33. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/common/vtt2lrc.py +0 -0
  34. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/config.py +0 -0
  35. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/__init__.py +0 -0
  36. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/database.py +0 -0
  37. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/engine.py +0 -0
  38. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/manage.py +0 -0
  39. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/orm_type.py +0 -0
  40. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/q_func.py +0 -0
  41. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/utils/__init__.py +0 -0
  42. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/utils/add2db.py +0 -0
  43. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/database/utils/uuid_sqlite.py +0 -0
  44. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/__init__.py +0 -0
  45. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/appdirs_.py +0 -0
  46. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/exceptions.py +0 -0
  47. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/file_zipper.py +0 -0
  48. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/config.example.toml +0 -0
  49. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/sqls.example/circle_name.sql +0 -0
  50. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/sqls.example/score.sql +0 -0
  51. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/sqls.example/search.sql +0 -0
  52. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/sqls.example/tags.sql +0 -0
  53. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/sqls.example/test.sql +0 -0
  54. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/resources/sqls.example/vas.sql +0 -0
  55. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/filemanager/utils.py +0 -0
  56. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/logger/__init__.py +0 -0
  57. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/__init__.py +0 -0
  58. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/lrcparse.py +0 -0
  59. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/main.css +0 -0
  60. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/main.py +0 -0
  61. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/player/base.py +0 -0
  62. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/player/mpdplayer.py +0 -0
  63. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/lrcplayer/player/pygameplayer.py +0 -0
  64. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/__init__.py +0 -0
  65. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/asmrapi.py +0 -0
  66. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/downloader.py +0 -0
  67. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/interface.py +0 -0
  68. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/playlist.py +0 -0
  69. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/utils/IDMHelper.py +0 -0
  70. {asmrmanager-2.2.7 → asmrmanager-2.2.8}/asmrmanager/spider/utils/aria2_downloader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ASMRManager
3
- Version: 2.2.7
3
+ Version: 2.2.8
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>
@@ -163,6 +163,8 @@ pip install ASMRManager[依赖]
163
163
  - `pl add` 将某个音声添加到用户的云端播放列表(配合 `pl create` 使用)
164
164
  - `review` 为某个作品评分并评论(本地)
165
165
 
166
+ 更多使用示例可参考[这一小节](#使用示例)。
167
+
166
168
  > 使用命令时,如果不输入 RJID ,将会自动使用上一次命令的RJID。
167
169
 
168
170
  另外本工具提供基于 `trogon` 的可视化命令行界面,在安装`tui`依赖后使用 `asmr tui` 即可打开。
@@ -182,11 +184,59 @@ _ASMR_COMPLETE=zsh_source asmr > ~/.asmr-complete.zsh
182
184
  echo '. ~/.asmr-complete.zsh' >> ~/.zshrc
183
185
  ```
184
186
 
187
+ ## 使用示例
188
+ 搜索最近更新的40个(一页)作品并下载:
189
+ ```shell
190
+ asmr dl search -o release --desc # 选择并下载
191
+ asmr dl search -o release --desc --all # 下载全部
192
+ ```
193
+
194
+ 下载`治愈`标签下销量大于等于5000的全部的作品:
195
+ ```shell
196
+ asmr dl search --tags 治愈 --sell 5000: --page 0 --all # --page 0 会遍历下载所有页,否则默认只会下载第一页
197
+ ```
198
+
199
+ 下载某个社团下的全年龄并包含中文字幕的作品:
200
+ ```shell
201
+ asmr dl search --circle Yostar --age general --subtitle
202
+ ```
203
+
204
+ 根据RJ/VJ/BJ号下载(下述输入格式适用于一切需要输入单个或多个ID的场合):
205
+ ```shell
206
+ asmr dl get RJ299717
207
+ asmr dl get 299717 # RJ可以省略;对于8位RJ号,第一位的0也可以省略
208
+ asmr dl get VJ015443
209
+ asmr dl get 100000029 # 对于BJ与VJ,网站为了兼容RJ所使用的特殊ID
210
+ asmr dl get 300015443 # 本项目存储VJ与BJ所使用的ID("3" + 8位VJ号,BJ则为"4" + 8位BJ号)
211
+ ```
212
+
213
+ 检查下载目录下文件是否下载完全(只验证文件存在,不保证文件完整性)
214
+ ```shell
215
+ asmr file check
216
+ asmr file check --list | xargs asmr dl get --force # 重新下载所有不完整的文件,以linux shell为例
217
+ ```
218
+
219
+ 将下载的文件转移到存储目录(STORAGE_PATH),并执行相应文件格式转换(详情见config.toml的before_store字段)
220
+ ```shell
221
+ asmr file store --all
222
+ ```
223
+
224
+ 比较本地文件与服务器文件的差异:
225
+
226
+ ![diff](./assets/diff.png)
227
+
228
+ 简单的关键词搜索(本地数据库):
229
+ ```shell
230
+ asmr query 治愈 --limit 3 # 搜索字段有:标题,社团名和标签名
231
+ asmr query 治愈 --limit 3 --raw | jq .[].id | xargs -n1 asmr info # 输出为json格式,获取详细信息
232
+ ```
233
+
234
+
185
235
  ## 关于`dl search/get`的使用
186
236
  命令执行过程中会进行如下的检查与过滤操作:
187
237
  1. 开始下载前:检查RJ号是否应该下载,如果本地文件不存在或者数据库无记录都会执行下载操作。可以通过 `--force` 强制执行下载。
188
238
  1. 获取音声信息后:检查音声的tags,如果包含tag_filters里指定的tag,则跳过下载。可以通过 `--ignore-tag` 来强制下载。
189
- 1. 获取下载文件后:检查文件的名称和路径,如果不符合filename_filters里指定的规则,则跳过下载。可以通过`ignore-name`来强制下载。
239
+ 1. 获取下载文件后:检查文件的名称和路径,如果不符合filename_filters里指定的规则,则跳过下载。可以通过`--ignore-name`来强制下载。
190
240
  1. 添加下载任务时:如果检测到本地有同名文件,则跳过该文件的下载。可以通过`--replace`来强制覆盖存在的文件。
191
241
 
192
242
  ## 其他
@@ -121,6 +121,8 @@ pip install ASMRManager[依赖]
121
121
  - `pl add` 将某个音声添加到用户的云端播放列表(配合 `pl create` 使用)
122
122
  - `review` 为某个作品评分并评论(本地)
123
123
 
124
+ 更多使用示例可参考[这一小节](#使用示例)。
125
+
124
126
  > 使用命令时,如果不输入 RJID ,将会自动使用上一次命令的RJID。
125
127
 
126
128
  另外本工具提供基于 `trogon` 的可视化命令行界面,在安装`tui`依赖后使用 `asmr tui` 即可打开。
@@ -140,11 +142,59 @@ _ASMR_COMPLETE=zsh_source asmr > ~/.asmr-complete.zsh
140
142
  echo '. ~/.asmr-complete.zsh' >> ~/.zshrc
141
143
  ```
142
144
 
145
+ ## 使用示例
146
+ 搜索最近更新的40个(一页)作品并下载:
147
+ ```shell
148
+ asmr dl search -o release --desc # 选择并下载
149
+ asmr dl search -o release --desc --all # 下载全部
150
+ ```
151
+
152
+ 下载`治愈`标签下销量大于等于5000的全部的作品:
153
+ ```shell
154
+ asmr dl search --tags 治愈 --sell 5000: --page 0 --all # --page 0 会遍历下载所有页,否则默认只会下载第一页
155
+ ```
156
+
157
+ 下载某个社团下的全年龄并包含中文字幕的作品:
158
+ ```shell
159
+ asmr dl search --circle Yostar --age general --subtitle
160
+ ```
161
+
162
+ 根据RJ/VJ/BJ号下载(下述输入格式适用于一切需要输入单个或多个ID的场合):
163
+ ```shell
164
+ asmr dl get RJ299717
165
+ asmr dl get 299717 # RJ可以省略;对于8位RJ号,第一位的0也可以省略
166
+ asmr dl get VJ015443
167
+ asmr dl get 100000029 # 对于BJ与VJ,网站为了兼容RJ所使用的特殊ID
168
+ asmr dl get 300015443 # 本项目存储VJ与BJ所使用的ID("3" + 8位VJ号,BJ则为"4" + 8位BJ号)
169
+ ```
170
+
171
+ 检查下载目录下文件是否下载完全(只验证文件存在,不保证文件完整性)
172
+ ```shell
173
+ asmr file check
174
+ asmr file check --list | xargs asmr dl get --force # 重新下载所有不完整的文件,以linux shell为例
175
+ ```
176
+
177
+ 将下载的文件转移到存储目录(STORAGE_PATH),并执行相应文件格式转换(详情见config.toml的before_store字段)
178
+ ```shell
179
+ asmr file store --all
180
+ ```
181
+
182
+ 比较本地文件与服务器文件的差异:
183
+
184
+ ![diff](./assets/diff.png)
185
+
186
+ 简单的关键词搜索(本地数据库):
187
+ ```shell
188
+ asmr query 治愈 --limit 3 # 搜索字段有:标题,社团名和标签名
189
+ asmr query 治愈 --limit 3 --raw | jq .[].id | xargs -n1 asmr info # 输出为json格式,获取详细信息
190
+ ```
191
+
192
+
143
193
  ## 关于`dl search/get`的使用
144
194
  命令执行过程中会进行如下的检查与过滤操作:
145
195
  1. 开始下载前:检查RJ号是否应该下载,如果本地文件不存在或者数据库无记录都会执行下载操作。可以通过 `--force` 强制执行下载。
146
196
  1. 获取音声信息后:检查音声的tags,如果包含tag_filters里指定的tag,则跳过下载。可以通过 `--ignore-tag` 来强制下载。
147
- 1. 获取下载文件后:检查文件的名称和路径,如果不符合filename_filters里指定的规则,则跳过下载。可以通过`ignore-name`来强制下载。
197
+ 1. 获取下载文件后:检查文件的名称和路径,如果不符合filename_filters里指定的规则,则跳过下载。可以通过`--ignore-name`来强制下载。
148
198
  1. 添加下载任务时:如果检测到本地有同名文件,则跳过该文件的下载。可以通过`--replace`来强制覆盖存在的文件。
149
199
 
150
200
  ## 其他
@@ -0,0 +1 @@
1
+ __version__ = "2.2.8"
@@ -28,7 +28,7 @@ def dl():
28
28
  @multi_rj_argument("remote")
29
29
  @download_param_options
30
30
  def get(source_ids: List[RemoteSourceID], download_params: DownloadParams):
31
- """get ASMR by RJ ids"""
31
+ """get ASMR by RJ/VJ/BJ ids"""
32
32
  if not source_ids:
33
33
  logger.error("You must give at least one source id!")
34
34
  return
@@ -290,11 +290,19 @@ def check(list_: bool):
290
290
  print(source_id)
291
291
  continue
292
292
 
293
- local_files = fm.get_all_files(source_id)
293
+ # local_files = fm.get_all_files(source_id)
294
294
  remote_files_should_down = set(
295
295
  [Path(i["path"]) for i in recovers if i["should_download"]]
296
296
  )
297
- should_download_but_missing = remote_files_should_down - local_files
297
+ # should_download_but_missing = remote_files_should_down - local_files
298
+ should_download_but_missing = set(
299
+ filter(
300
+ lambda p: not any(
301
+ fm.check_exists(f"{id2source_name(source_id)}/{str(p)}")
302
+ ),
303
+ remote_files_should_down,
304
+ )
305
+ )
298
306
  if len(should_download_but_missing):
299
307
  logger.error(
300
308
  f"source_id {source_id} has missing files:\n"
@@ -51,7 +51,7 @@ def convert(
51
51
 
52
52
  fm = FileManager.get_fm()
53
53
 
54
- path = fm.get_path(source_id, dst)
54
+ path = fm.get_path(source_id, prefer=dst)
55
55
  if path is None:
56
56
  logger.error("Source not found")
57
57
  exit(-1)
@@ -1,7 +1,16 @@
1
1
  import os
2
2
  import shutil
3
3
  from pathlib import Path
4
- from typing import Callable, Iterable, List, Literal, NamedTuple, Set, Tuple
4
+ from typing import (
5
+ Callable,
6
+ Iterable,
7
+ List,
8
+ Literal,
9
+ NamedTuple,
10
+ Set,
11
+ Tuple,
12
+ overload,
13
+ )
5
14
 
6
15
  import toml
7
16
 
@@ -301,20 +310,25 @@ class FileManager:
301
310
  def get_path(
302
311
  self,
303
312
  source_id: LocalSourceID,
313
+ rel: str = "",
304
314
  prefer: Literal["storage", "download"] = "storage",
305
315
  ) -> Path | None:
306
316
  """get rj file path"""
307
- res = self.get_location(source_id, prefer=prefer)
308
-
309
- match res:
310
- case "download":
311
- return self.download_path / id2source_name(source_id)
312
- case "storage":
313
- return self.storage_path / id2source_name(source_id)
314
- case _:
315
- return None
317
+ source_name = id2source_name(source_id)
318
+ path = f"{source_name}/{rel}"
319
+ res = self.check_exists(path)
320
+ # res = self.get_location(source_id, prefer=prefer)
321
+ if not any(res):
322
+ return None
323
+
324
+ return (
325
+ self.download_path / path
326
+ if res.__getattribute__(prefer)
327
+ else self.storage_path / path
328
+ )
316
329
 
317
- def check_exists(self, rel_path: str):
330
+ def check_exists(self, rel_path: str, check_duplicate=True):
331
+ """rel_path = source_name/rel"""
318
332
  download, storage = False, False
319
333
  download_file_path = self.download_path / rel_path
320
334
  storage_file_path = self.storage_path / rel_path
@@ -322,39 +336,63 @@ class FileManager:
322
336
  download = True
323
337
  if storage_file_path.exists():
324
338
  storage = True
325
- if (not download) and self.check_wav_flac_duplicate(
326
- download_file_path
327
- ):
328
- download = True
329
- if (not storage) and self.check_wav_flac_duplicate(storage_file_path):
330
- storage = True
339
+
340
+ if check_duplicate:
341
+ if (not download) and self.check_file_duplicate(
342
+ download_file_path
343
+ ):
344
+ download = True
345
+ if (not storage) and self.check_file_duplicate(storage_file_path):
346
+ storage = True
331
347
 
332
348
  return NamedTuple(
333
349
  "ExistInfo", [("download", bool), ("storage", bool)]
334
350
  )(download, storage)
335
351
 
336
352
  @staticmethod
337
- def check_wav_flac_duplicate(file_path: Path) -> bool:
338
- """if file duplicate or already exists, return True"""
353
+ def check_file_duplicate(file_path: Path) -> bool:
354
+ """if file duplicate or already exists in a different type, return True"""
339
355
  if file_path.exists():
340
- logger.error(
356
+ logger.warning(
341
357
  f"file already exists: {file_path}, please "
342
358
  "check for the existence of the download files first"
343
359
  )
344
360
  return True
345
- match file_path.suffix.lower():
346
- case ".wav":
347
- another_file_path = file_path.with_suffix(".flac")
361
+
362
+ audio_formats = [".wav", ".flac", ".mp3", ".m4a"]
363
+ if file_path.suffix.lower() in audio_formats:
364
+ for audio_format in audio_formats:
365
+ another_file_path = file_path.with_suffix(audio_format)
348
366
  if another_file_path.exists():
349
- logger.info(f"Detected {file_path} for same flac exists")
367
+ logger.debug(
368
+ f"Detected {file_path} duplicated for a same name {audio_format} exists"
369
+ )
350
370
  return True
351
- case ".flac":
352
- another_file_path = file_path.with_suffix(".wav")
371
+
372
+ lyrics_formats = [".lrc", ".vtt", ".mp3.vtt", ".wav.vtt"]
373
+ if file_path.suffix.lower() in lyrics_formats:
374
+ file_name = file_path.stem
375
+ for lyrics_format in lyrics_formats:
376
+ another_file_path = file_path.with_name(
377
+ file_name + lyrics_format
378
+ )
353
379
  if another_file_path.exists():
354
- logger.info(f"Detected {file_path} for same wav exists")
380
+ logger.info(f"Detected {file_path} for same lyrics exists")
355
381
  return True
356
- case _:
357
- pass
382
+
383
+ # match file_path.suffix.lower():
384
+ # case ".wav":
385
+ # another_file_path = file_path.with_suffix(".flac")
386
+ # if another_file_path.exists():
387
+ # logger.info(f"Detected {file_path} for same flac exists")
388
+ # return True
389
+ # case ".flac":
390
+ # another_file_path = file_path.with_suffix(".wav")
391
+ # if another_file_path.exists():
392
+ # logger.info(f"Detected {file_path} for same wav exists")
393
+ # return True
394
+ # case _:
395
+ # pass
358
396
 
359
397
  return False
360
398
 
@@ -362,13 +400,10 @@ class FileManager:
362
400
  self, source_id: LocalSourceID
363
401
  ) -> List[RecoverRecord] | None:
364
402
  """load recover file of source ID(choose download path first)"""
365
- rj_path = self.get_path(source_id, prefer="download")
366
- if rj_path is None:
367
- logger.error(f"item {source_id} does not exist")
368
- return
369
-
370
- recover_path = rj_path / ".recover"
371
- if not recover_path.exists():
403
+ recover_path = self.get_path(
404
+ source_id, rel=".recover", prefer="download"
405
+ )
406
+ if recover_path is None:
372
407
  logger.error(
373
408
  f"item {source_id} does not have recover file, please update this"
374
409
  " rj id first"
@@ -33,7 +33,7 @@ dependencies = [
33
33
  ]
34
34
  requires-python = ">=3.10"
35
35
  readme = "README.md"
36
- version = "2.2.7"
36
+ version = "2.2.8"
37
37
 
38
38
  [project.license]
39
39
  text = "MIT"
@@ -1 +0,0 @@
1
- __version__ = "2.2.7"
File without changes