anipy-cli 3.4.5__py3-none-any.whl → 3.4.7__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.
Potentially problematic release.
This version of anipy-cli might be problematic. Click here for more details.
- anipy_cli/__init__.py +1 -1
- anipy_cli/arg_parser.py +9 -0
- anipy_cli/cli.py +10 -1
- anipy_cli/menus/seasonal_menu.py +2 -48
- anipy_cli/prompts.py +53 -0
- {anipy_cli-3.4.5.dist-info → anipy_cli-3.4.7.dist-info}/METADATA +2 -2
- {anipy_cli-3.4.5.dist-info → anipy_cli-3.4.7.dist-info}/RECORD +9 -9
- {anipy_cli-3.4.5.dist-info → anipy_cli-3.4.7.dist-info}/WHEEL +0 -0
- {anipy_cli-3.4.5.dist-info → anipy_cli-3.4.7.dist-info}/entry_points.txt +0 -0
anipy_cli/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__appname__ = "anipy-cli"
|
|
2
|
-
__version__ = "3.4.
|
|
2
|
+
__version__ = "3.4.7"
|
anipy_cli/arg_parser.py
CHANGED
|
@@ -14,6 +14,7 @@ class CliArgs:
|
|
|
14
14
|
seasonal: bool
|
|
15
15
|
mal: bool
|
|
16
16
|
delete: bool
|
|
17
|
+
migrate_hist: bool
|
|
17
18
|
quality: Optional[Union[str, int]]
|
|
18
19
|
ffmpeg: bool
|
|
19
20
|
auto_update: bool
|
|
@@ -99,6 +100,14 @@ def parse_args(override_args: Optional[list[str]] = None) -> CliArgs:
|
|
|
99
100
|
help="Delete your History.",
|
|
100
101
|
)
|
|
101
102
|
|
|
103
|
+
actions_group.add_argument(
|
|
104
|
+
"--migrate-history",
|
|
105
|
+
required=False,
|
|
106
|
+
dest="migrate_hist",
|
|
107
|
+
action="store_true",
|
|
108
|
+
help="Migrate your history to the current provider.",
|
|
109
|
+
)
|
|
110
|
+
|
|
102
111
|
options_group.add_argument(
|
|
103
112
|
"-s",
|
|
104
113
|
"--search",
|
anipy_cli/cli.py
CHANGED
|
@@ -2,10 +2,13 @@ from typing import Optional
|
|
|
2
2
|
|
|
3
3
|
from pypresence.exceptions import DiscordNotFound
|
|
4
4
|
|
|
5
|
+
from anipy_api.locallist import LocalList
|
|
6
|
+
from anipy_cli.prompts import migrate_provider
|
|
7
|
+
|
|
5
8
|
from anipy_cli.arg_parser import parse_args
|
|
6
9
|
from anipy_cli.clis import *
|
|
7
10
|
from anipy_cli.colors import colors, cprint
|
|
8
|
-
from anipy_cli.util import error, DotSpinner
|
|
11
|
+
from anipy_cli.util import error, DotSpinner, migrate_locallist
|
|
9
12
|
from anipy_cli.config import Config
|
|
10
13
|
from anipy_cli.discord import DiscordPresence
|
|
11
14
|
|
|
@@ -45,6 +48,12 @@ def run_cli(override_args: Optional[list[str]] = None):
|
|
|
45
48
|
except FileNotFoundError:
|
|
46
49
|
error("no history file found")
|
|
47
50
|
return
|
|
51
|
+
elif args.migrate_hist:
|
|
52
|
+
history_list = LocalList(
|
|
53
|
+
Config()._history_file_path, migrate_cb=migrate_locallist
|
|
54
|
+
)
|
|
55
|
+
migrate_provider("default", history_list)
|
|
56
|
+
return
|
|
48
57
|
|
|
49
58
|
clis_dict = {
|
|
50
59
|
args.download: DownloadCli,
|
anipy_cli/menus/seasonal_menu.py
CHANGED
|
@@ -25,7 +25,7 @@ from anipy_cli.util import (
|
|
|
25
25
|
get_prefered_providers,
|
|
26
26
|
migrate_locallist,
|
|
27
27
|
)
|
|
28
|
-
from anipy_cli.prompts import pick_episode_prompt, search_show_prompt, lang_prompt
|
|
28
|
+
from anipy_cli.prompts import pick_episode_prompt, search_show_prompt, lang_prompt, migrate_provider
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
if TYPE_CHECKING:
|
|
@@ -209,53 +209,7 @@ class SeasonalMenu(MenuBase):
|
|
|
209
209
|
print(i)
|
|
210
210
|
|
|
211
211
|
def migrate_provider(self):
|
|
212
|
-
|
|
213
|
-
all_seasonals = self.seasonal_list.get_all()
|
|
214
|
-
current_providers = list(get_prefered_providers("seasonal"))
|
|
215
|
-
print(
|
|
216
|
-
"Migrating to configured providers:",
|
|
217
|
-
", ".join([p.NAME for p in current_providers]),
|
|
218
|
-
)
|
|
219
|
-
for s in all_seasonals:
|
|
220
|
-
if s.provider in [p.NAME for p in current_providers]:
|
|
221
|
-
continue
|
|
222
|
-
|
|
223
|
-
print(f"Mapping: {s.name}")
|
|
224
|
-
|
|
225
|
-
search_results: List[Anime] = []
|
|
226
|
-
for p in current_providers:
|
|
227
|
-
search_results.extend(
|
|
228
|
-
[Anime.from_search_result(p, r) for r in p.get_search(s.name)]
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
best_anime = None
|
|
232
|
-
best_ratio = 0
|
|
233
|
-
for r in search_results:
|
|
234
|
-
titles = {r.name}
|
|
235
|
-
titles |= set(r.get_info().alternative_names or [])
|
|
236
|
-
ratio = MyAnimeListAdapter._find_best_ratio(titles, {s.name})
|
|
237
|
-
|
|
238
|
-
if ratio > best_ratio:
|
|
239
|
-
best_ratio = ratio
|
|
240
|
-
best_anime = r
|
|
241
|
-
|
|
242
|
-
if best_ratio == 1:
|
|
243
|
-
break
|
|
244
|
-
|
|
245
|
-
if best_anime is None:
|
|
246
|
-
continue
|
|
247
|
-
|
|
248
|
-
if best_ratio >= config.mal_mapping_min_similarity:
|
|
249
|
-
self.seasonal_list.delete(s)
|
|
250
|
-
else:
|
|
251
|
-
print(f"Could not autmatically map {s.name}, you can map it manually.")
|
|
252
|
-
best_anime = search_show_prompt("seasonal", skip_season_search=True)
|
|
253
|
-
if best_anime is None:
|
|
254
|
-
continue
|
|
255
|
-
|
|
256
|
-
episode = find_closest(best_anime.get_episodes(s.language), s.episode)
|
|
257
|
-
self.seasonal_list.update(best_anime, language=s.language, episode=episode)
|
|
258
|
-
|
|
212
|
+
migrate_provider("seasonal", self.seasonal_list)
|
|
259
213
|
self.print_options(clear_screen=True)
|
|
260
214
|
|
|
261
215
|
def download_latest(self):
|
anipy_cli/prompts.py
CHANGED
|
@@ -2,6 +2,7 @@ import time
|
|
|
2
2
|
from typing import TYPE_CHECKING, Optional, List, Tuple
|
|
3
3
|
from InquirerPy import inquirer
|
|
4
4
|
from InquirerPy.base.control import Choice
|
|
5
|
+
from anipy_api.mal import MyAnimeListAdapter
|
|
5
6
|
from anipy_api.provider import (
|
|
6
7
|
BaseProvider,
|
|
7
8
|
FilterCapabilities,
|
|
@@ -13,6 +14,7 @@ from anipy_api.anime import Anime
|
|
|
13
14
|
|
|
14
15
|
from anipy_cli.util import (
|
|
15
16
|
DotSpinner,
|
|
17
|
+
find_closest,
|
|
16
18
|
get_anime_season,
|
|
17
19
|
get_prefered_providers,
|
|
18
20
|
error,
|
|
@@ -25,6 +27,7 @@ from anipy_cli.config import Config
|
|
|
25
27
|
|
|
26
28
|
if TYPE_CHECKING:
|
|
27
29
|
from anipy_api.provider import Episode
|
|
30
|
+
from anipy_api.locallist import LocalList
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
def search_show_prompt(
|
|
@@ -332,3 +335,53 @@ def parse_auto_search(
|
|
|
332
335
|
error("could not determine any epiosdes from search parameter", fatal=True)
|
|
333
336
|
|
|
334
337
|
return result, lang, chosen
|
|
338
|
+
|
|
339
|
+
def migrate_provider(mode: str, local_list: "LocalList"):
|
|
340
|
+
config = Config()
|
|
341
|
+
all_entries = local_list.get_all()
|
|
342
|
+
current_providers = list(get_prefered_providers(mode))
|
|
343
|
+
print(
|
|
344
|
+
f"Migrating to configured providers ({mode}):",
|
|
345
|
+
", ".join([p.NAME for p in current_providers]),
|
|
346
|
+
)
|
|
347
|
+
for s in all_entries:
|
|
348
|
+
if s.provider in [p.NAME for p in current_providers]:
|
|
349
|
+
continue
|
|
350
|
+
|
|
351
|
+
print(f"Mapping: {s.name}")
|
|
352
|
+
|
|
353
|
+
search_results: List[Anime] = []
|
|
354
|
+
for p in current_providers:
|
|
355
|
+
search_results.extend(
|
|
356
|
+
[Anime.from_search_result(p, r) for r in p.get_search(s.name)]
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
best_anime = None
|
|
360
|
+
best_ratio = 0
|
|
361
|
+
for r in search_results:
|
|
362
|
+
titles = {r.name}
|
|
363
|
+
titles |= set(r.get_info().alternative_names or [])
|
|
364
|
+
ratio = MyAnimeListAdapter._find_best_ratio(titles, {s.name})
|
|
365
|
+
|
|
366
|
+
if ratio > best_ratio:
|
|
367
|
+
best_ratio = ratio
|
|
368
|
+
best_anime = r
|
|
369
|
+
|
|
370
|
+
if best_ratio == 1:
|
|
371
|
+
break
|
|
372
|
+
|
|
373
|
+
if best_anime is None:
|
|
374
|
+
continue
|
|
375
|
+
|
|
376
|
+
if best_ratio >= config.mal_mapping_min_similarity:
|
|
377
|
+
local_list.delete(s)
|
|
378
|
+
else:
|
|
379
|
+
print(f"Could not autmatically map {s.name}, you can map it manually.")
|
|
380
|
+
best_anime = search_show_prompt("seasonal", skip_season_search=True)
|
|
381
|
+
if best_anime is None:
|
|
382
|
+
continue
|
|
383
|
+
local_list.delete(s)
|
|
384
|
+
|
|
385
|
+
episode = find_closest(best_anime.get_episodes(s.language), s.episode)
|
|
386
|
+
local_list.update(best_anime, language=s.language, episode=episode)
|
|
387
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: anipy-cli
|
|
3
|
-
Version: 3.4.
|
|
3
|
+
Version: 3.4.7
|
|
4
4
|
Summary: Watch and Download anime from the comfort of your Terminal
|
|
5
5
|
License: GPL-3.0
|
|
6
6
|
Keywords: anime,cli
|
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
-
Requires-Dist: anipy-api (>=3.4.
|
|
17
|
+
Requires-Dist: anipy-api (>=3.4.7,<4.0.0)
|
|
18
18
|
Requires-Dist: appdirs (>=1.4.4,<2.0.0)
|
|
19
19
|
Requires-Dist: inquirerpy (>=0.3.4,<0.4.0)
|
|
20
20
|
Requires-Dist: pypresence (>=4.3.0,<5.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
anipy_cli/__init__.py,sha256=
|
|
2
|
-
anipy_cli/arg_parser.py,sha256=
|
|
3
|
-
anipy_cli/cli.py,sha256=
|
|
1
|
+
anipy_cli/__init__.py,sha256=7yueElkuj6z7jrhdWJCQqCFqIqciqJdilpwdy1uTHWo,48
|
|
2
|
+
anipy_cli/arg_parser.py,sha256=0L2ZamTMVp5jFF9gdrFXRNwm1E5WznwY8PbYjiV_LRE,6244
|
|
3
|
+
anipy_cli/cli.py,sha256=Bk2H15VRF34yKLbGgKVq0A2vdByMJj-JTyx7Ep-JbH0,2238
|
|
4
4
|
anipy_cli/clis/__init__.py,sha256=Y00uiPWiMvvRImxJMvfLA55BOkMUOrrx5vJUNvquNsY,411
|
|
5
5
|
anipy_cli/clis/base_cli.py,sha256=xPr_J8hKs7LkDLvmK6zyL1ZTZRpyC2IuFss8KsaDstU,817
|
|
6
6
|
anipy_cli/clis/binge_cli.py,sha256=ioZ-V0WfGYBqETFkd8epGrT9dPHwsRJ1qvIdqf4waIs,2551
|
|
@@ -18,10 +18,10 @@ anipy_cli/menus/__init__.py,sha256=aIzbphxAW-QGfZwR1DIegFZuTJp1O3tSUnai0f0f4lY,1
|
|
|
18
18
|
anipy_cli/menus/base_menu.py,sha256=g5b9Z7SpvCxcq_vqObcPzxLwcXeGPltLgSwa0sEzyfk,1140
|
|
19
19
|
anipy_cli/menus/mal_menu.py,sha256=jAVJh7K5d0BCnoT4qUIZ7CavrnrctXj-eg9k8E90ulE,23697
|
|
20
20
|
anipy_cli/menus/menu.py,sha256=ejTOGVG8fFJhTT7t23kA_uBbF5pkNcdvj4cGAIPvdt8,8101
|
|
21
|
-
anipy_cli/menus/seasonal_menu.py,sha256=
|
|
22
|
-
anipy_cli/prompts.py,sha256=
|
|
21
|
+
anipy_cli/menus/seasonal_menu.py,sha256=NT9dfQUdN1DFu6wAf9hdWOfVBB7EfFiUECAcW6fqHgs,8995
|
|
22
|
+
anipy_cli/prompts.py,sha256=RW1jqNq6RQY7BqV77vrCtEuyfyc8ArtdwCH73S3-c-k,11909
|
|
23
23
|
anipy_cli/util.py,sha256=8AzEeoSPXMGTdTrArhE0COhSuYP_MCvYIeGHv5X7haU,6841
|
|
24
|
-
anipy_cli-3.4.
|
|
25
|
-
anipy_cli-3.4.
|
|
26
|
-
anipy_cli-3.4.
|
|
27
|
-
anipy_cli-3.4.
|
|
24
|
+
anipy_cli-3.4.7.dist-info/METADATA,sha256=7Sv02AJmZtG8lPUYkYtcye6noagFnuWYImioBcjE0Vs,3481
|
|
25
|
+
anipy_cli-3.4.7.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
26
|
+
anipy_cli-3.4.7.dist-info/entry_points.txt,sha256=86iXpcm_ECFndrt0JAI2mqYfXC2Ar7mGi0iOaxCrNP0,51
|
|
27
|
+
anipy_cli-3.4.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|