anipy-cli 3.4.8__py3-none-any.whl → 3.8.2__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.
- anipy_cli/__init__.py +1 -1
- anipy_cli/anilist_proxy.py +229 -0
- anipy_cli/arg_parser.py +57 -0
- anipy_cli/cli.py +25 -2
- anipy_cli/clis/__init__.py +2 -0
- anipy_cli/clis/anilist_cli.py +62 -0
- anipy_cli/clis/base_cli.py +1 -1
- anipy_cli/clis/binge_cli.py +4 -1
- anipy_cli/clis/default_cli.py +10 -8
- anipy_cli/clis/download_cli.py +6 -2
- anipy_cli/clis/mal_cli.py +1 -1
- anipy_cli/colors.py +7 -4
- anipy_cli/config.py +55 -40
- anipy_cli/download_component.py +42 -16
- anipy_cli/logger.py +200 -0
- anipy_cli/mal_proxy.py +15 -9
- anipy_cli/menus/__init__.py +2 -1
- anipy_cli/menus/anilist_menu.py +671 -0
- anipy_cli/menus/base_menu.py +4 -5
- anipy_cli/menus/mal_menu.py +23 -15
- anipy_cli/menus/menu.py +24 -5
- anipy_cli/menus/seasonal_menu.py +15 -11
- anipy_cli/prompts.py +3 -3
- anipy_cli/util.py +37 -18
- {anipy_cli-3.4.8.dist-info → anipy_cli-3.8.2.dist-info}/METADATA +5 -5
- anipy_cli-3.8.2.dist-info/RECORD +31 -0
- {anipy_cli-3.4.8.dist-info → anipy_cli-3.8.2.dist-info}/WHEEL +1 -1
- anipy_cli-3.4.8.dist-info/RECORD +0 -27
- {anipy_cli-3.4.8.dist-info → anipy_cli-3.8.2.dist-info}/entry_points.txt +0 -0
anipy_cli/menus/mal_menu.py
CHANGED
|
@@ -189,19 +189,19 @@ class MALMenu(MenuBase):
|
|
|
189
189
|
config = Config()
|
|
190
190
|
|
|
191
191
|
choices = []
|
|
192
|
-
if config.
|
|
192
|
+
if config.tracker_dub_tag:
|
|
193
193
|
choices.append(
|
|
194
194
|
Choice(
|
|
195
|
-
value=config.
|
|
196
|
-
name=f"{config.
|
|
195
|
+
value=config.tracker_dub_tag,
|
|
196
|
+
name=f"{config.tracker_dub_tag} (sets wheter you prefer to watch a particular anime in dub)",
|
|
197
197
|
)
|
|
198
198
|
)
|
|
199
199
|
|
|
200
|
-
if config.
|
|
200
|
+
if config.tracker_ignore_tag:
|
|
201
201
|
choices.append(
|
|
202
202
|
Choice(
|
|
203
|
-
value=config.
|
|
204
|
-
name=f"{config.
|
|
203
|
+
value=config.tracker_ignore_tag,
|
|
204
|
+
name=f"{config.tracker_ignore_tag} (sets wheter anipy-cli will ignore a particular anime)",
|
|
205
205
|
)
|
|
206
206
|
)
|
|
207
207
|
|
|
@@ -275,7 +275,7 @@ class MALMenu(MenuBase):
|
|
|
275
275
|
)
|
|
276
276
|
DownloadComponent.serve_download_errors(errors)
|
|
277
277
|
|
|
278
|
-
self.print_options(
|
|
278
|
+
self.print_options(should_clear_screen=len(errors) == 0)
|
|
279
279
|
|
|
280
280
|
def binge_latest(self):
|
|
281
281
|
picked = self._choose_latest()
|
|
@@ -300,6 +300,8 @@ class MALMenu(MenuBase):
|
|
|
300
300
|
stream = anime.get_video(
|
|
301
301
|
ep, lang, preferred_quality=self.options.quality
|
|
302
302
|
)
|
|
303
|
+
if stream is None:
|
|
304
|
+
error("Could not find stream for requested episode, skipping")
|
|
303
305
|
s.ok("✔")
|
|
304
306
|
|
|
305
307
|
self.player.play_title(anime, stream)
|
|
@@ -320,12 +322,12 @@ class MALMenu(MenuBase):
|
|
|
320
322
|
with DotSpinner("Syncing Seasonals into MyAnimeList") as s:
|
|
321
323
|
for k, v in mappings.items():
|
|
322
324
|
tags = set()
|
|
323
|
-
if config.
|
|
325
|
+
if config.tracker_dub_tag:
|
|
324
326
|
if k.language == LanguageTypeEnum.DUB:
|
|
325
|
-
tags.add(config.
|
|
327
|
+
tags.add(config.tracker_dub_tag)
|
|
326
328
|
|
|
327
329
|
if v.my_list_status:
|
|
328
|
-
if config.
|
|
330
|
+
if config.tracker_ignore_tag in v.my_list_status.tags:
|
|
329
331
|
continue
|
|
330
332
|
tags |= set(v.my_list_status.tags)
|
|
331
333
|
|
|
@@ -343,8 +345,11 @@ class MALMenu(MenuBase):
|
|
|
343
345
|
mappings = self._create_maps_mal(mylist)
|
|
344
346
|
with DotSpinner("Syncing MyAnimeList into Seasonals") as s:
|
|
345
347
|
for k, v in mappings.items():
|
|
346
|
-
if config.
|
|
347
|
-
if
|
|
348
|
+
if config.tracker_dub_tag:
|
|
349
|
+
if (
|
|
350
|
+
k.my_list_status
|
|
351
|
+
and config.tracker_dub_tag in k.my_list_status.tags
|
|
352
|
+
):
|
|
348
353
|
pref_lang = LanguageTypeEnum.DUB
|
|
349
354
|
else:
|
|
350
355
|
pref_lang = LanguageTypeEnum.SUB
|
|
@@ -444,8 +449,11 @@ class MALMenu(MenuBase):
|
|
|
444
449
|
)
|
|
445
450
|
continue
|
|
446
451
|
|
|
447
|
-
if config.
|
|
448
|
-
if
|
|
452
|
+
if config.tracker_dub_tag:
|
|
453
|
+
if (
|
|
454
|
+
e.my_list_status
|
|
455
|
+
and config.tracker_dub_tag in e.my_list_status.tags
|
|
456
|
+
):
|
|
449
457
|
pref_lang = LanguageTypeEnum.DUB
|
|
450
458
|
else:
|
|
451
459
|
pref_lang = LanguageTypeEnum.SUB
|
|
@@ -629,7 +637,7 @@ class MALMenu(MenuBase):
|
|
|
629
637
|
def _format_mal_anime(anime: MALAnime) -> str:
|
|
630
638
|
config = Config()
|
|
631
639
|
dub = (
|
|
632
|
-
config.
|
|
640
|
+
config.tracker_dub_tag in anime.my_list_status.tags
|
|
633
641
|
if anime.my_list_status
|
|
634
642
|
else False
|
|
635
643
|
)
|
anipy_cli/menus/menu.py
CHANGED
|
@@ -6,11 +6,18 @@ from InquirerPy.base.control import Choice
|
|
|
6
6
|
from anipy_api.download import Downloader
|
|
7
7
|
from anipy_api.provider import LanguageTypeEnum, ProviderStream
|
|
8
8
|
from anipy_api.locallist import LocalList
|
|
9
|
+
import anipy_cli.logger as logger
|
|
9
10
|
|
|
10
11
|
from anipy_cli.colors import colors, cprint
|
|
11
12
|
from anipy_cli.config import Config
|
|
12
13
|
from anipy_cli.menus.base_menu import MenuBase, MenuOption
|
|
13
|
-
from anipy_cli.util import
|
|
14
|
+
from anipy_cli.util import (
|
|
15
|
+
DotSpinner,
|
|
16
|
+
error,
|
|
17
|
+
get_download_path,
|
|
18
|
+
get_post_download_scripts_hook,
|
|
19
|
+
migrate_locallist,
|
|
20
|
+
)
|
|
14
21
|
from anipy_cli.prompts import pick_episode_prompt, search_show_prompt
|
|
15
22
|
|
|
16
23
|
|
|
@@ -85,6 +92,9 @@ class Menu(MenuBase):
|
|
|
85
92
|
self.stream = self.anime.get_video(
|
|
86
93
|
episode, self.lang, preferred_quality=self.options.quality
|
|
87
94
|
)
|
|
95
|
+
if self.stream is None:
|
|
96
|
+
error("Could not find stream for requested Episode!")
|
|
97
|
+
return
|
|
88
98
|
|
|
89
99
|
self.history_list.update(self.anime, episode=episode, language=self.lang)
|
|
90
100
|
self.player.play_title(self.anime, self.stream)
|
|
@@ -164,6 +174,13 @@ class Menu(MenuBase):
|
|
|
164
174
|
print(f"Provider: {self.anime.provider.NAME}")
|
|
165
175
|
print(f"Stream Url: {self.stream.url}")
|
|
166
176
|
print(f"Quality: {self.stream.resolution}p")
|
|
177
|
+
if self.stream.referrer:
|
|
178
|
+
print(f"Referer: {self.stream.referrer}")
|
|
179
|
+
|
|
180
|
+
if self.stream.subtitle:
|
|
181
|
+
print("Subtitles:")
|
|
182
|
+
for name, sub in self.stream.subtitle.items():
|
|
183
|
+
print(f" {name} - {sub.url}")
|
|
167
184
|
|
|
168
185
|
def add_seasonal(self):
|
|
169
186
|
self.seasonal_list.update(
|
|
@@ -195,7 +212,7 @@ class Menu(MenuBase):
|
|
|
195
212
|
if stream is None:
|
|
196
213
|
return
|
|
197
214
|
|
|
198
|
-
stream =
|
|
215
|
+
stream = next(filter(lambda x: x.url == stream["url"], streams))
|
|
199
216
|
self.options.quality = stream.resolution
|
|
200
217
|
self.stream = stream
|
|
201
218
|
self.player.play_title(self.anime, self.stream)
|
|
@@ -208,10 +225,12 @@ class Menu(MenuBase):
|
|
|
208
225
|
def progress_indicator(percentage: float):
|
|
209
226
|
s.set_text(f"Downloading ({percentage:.1f}%)")
|
|
210
227
|
|
|
211
|
-
def info_display(message: str):
|
|
228
|
+
def info_display(message: str, exc_info: BaseException | None = None):
|
|
229
|
+
logger.info(message, exc_info, exc_info is not None)
|
|
212
230
|
s.write(f"> {message}")
|
|
213
231
|
|
|
214
|
-
def error_display(message: str):
|
|
232
|
+
def error_display(message: str, exc_info: BaseException | None = None):
|
|
233
|
+
logger.error(message, exc_info)
|
|
215
234
|
s.write(f"{colors.RED}! {message}{colors.END}")
|
|
216
235
|
|
|
217
236
|
downloader = Downloader(progress_indicator, info_display, error_display)
|
|
@@ -233,7 +252,7 @@ class Menu(MenuBase):
|
|
|
233
252
|
get_download_path(self.anime, self.stream),
|
|
234
253
|
container=config.remux_to,
|
|
235
254
|
ffmpeg=self.options.ffmpeg or config.ffmpeg_hls,
|
|
236
|
-
post_dl_cb=get_post_download_scripts_hook("default", self.anime, s)
|
|
255
|
+
post_dl_cb=get_post_download_scripts_hook("default", self.anime, s),
|
|
237
256
|
)
|
|
238
257
|
|
|
239
258
|
if Config().auto_open_dl_defaultcli:
|
anipy_cli/menus/seasonal_menu.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from typing import TYPE_CHECKING, List, Tuple
|
|
3
3
|
|
|
4
|
-
from anipy_api.mal import MyAnimeListAdapter
|
|
5
4
|
|
|
6
5
|
from anipy_cli.download_component import DownloadComponent
|
|
7
6
|
|
|
@@ -9,7 +8,7 @@ from anipy_api.anime import Anime
|
|
|
9
8
|
from anipy_api.provider import LanguageTypeEnum
|
|
10
9
|
from anipy_api.provider.base import Episode
|
|
11
10
|
from anipy_api.locallist import LocalList, LocalListEntry
|
|
12
|
-
from anipy_api.error import
|
|
11
|
+
from anipy_api.error import ProviderNotAvailableError
|
|
13
12
|
from InquirerPy import inquirer
|
|
14
13
|
from InquirerPy.base.control import Choice
|
|
15
14
|
from InquirerPy.utils import get_style
|
|
@@ -20,12 +19,15 @@ from anipy_cli.menus.base_menu import MenuBase, MenuOption
|
|
|
20
19
|
from anipy_cli.util import (
|
|
21
20
|
DotSpinner,
|
|
22
21
|
error,
|
|
23
|
-
find_closest,
|
|
24
22
|
get_configured_player,
|
|
25
|
-
get_prefered_providers,
|
|
26
23
|
migrate_locallist,
|
|
27
24
|
)
|
|
28
|
-
from anipy_cli.prompts import
|
|
25
|
+
from anipy_cli.prompts import (
|
|
26
|
+
pick_episode_prompt,
|
|
27
|
+
search_show_prompt,
|
|
28
|
+
lang_prompt,
|
|
29
|
+
migrate_provider,
|
|
30
|
+
)
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
if TYPE_CHECKING:
|
|
@@ -65,7 +67,7 @@ class SeasonalMenu(MenuBase):
|
|
|
65
67
|
for s in self.seasonal_list.get_all():
|
|
66
68
|
try:
|
|
67
69
|
anime = Anime.from_local_list_entry(s)
|
|
68
|
-
except
|
|
70
|
+
except ProviderNotAvailableError:
|
|
69
71
|
error(
|
|
70
72
|
f"Can not load '{s.name}' because the configured provider"
|
|
71
73
|
f" '{s.provider}' was not found, maybe try to migrate"
|
|
@@ -210,7 +212,7 @@ class SeasonalMenu(MenuBase):
|
|
|
210
212
|
|
|
211
213
|
def migrate_provider(self):
|
|
212
214
|
migrate_provider("seasonal", self.seasonal_list)
|
|
213
|
-
self.print_options(
|
|
215
|
+
self.print_options(should_clear_screen=True)
|
|
214
216
|
|
|
215
217
|
def download_latest(self):
|
|
216
218
|
picked = self._choose_latest()
|
|
@@ -224,13 +226,13 @@ class SeasonalMenu(MenuBase):
|
|
|
224
226
|
def on_successful_download(anime: Anime, ep: Episode, lang: LanguageTypeEnum):
|
|
225
227
|
self.seasonal_list.update(anime, episode=ep, language=lang)
|
|
226
228
|
|
|
227
|
-
failed_series = DownloadComponent(
|
|
228
|
-
|
|
229
|
-
)
|
|
229
|
+
failed_series = DownloadComponent(
|
|
230
|
+
self.options, self.dl_path, "seasonal"
|
|
231
|
+
).download_anime(picked, on_successful_download)
|
|
230
232
|
|
|
231
233
|
if not self.options.auto_update:
|
|
232
234
|
# Clear screen only if there were no issues
|
|
233
|
-
self.print_options(
|
|
235
|
+
self.print_options(should_clear_screen=len(failed_series) == 0)
|
|
234
236
|
|
|
235
237
|
def binge_latest(self):
|
|
236
238
|
picked = self._choose_latest()
|
|
@@ -254,6 +256,8 @@ class SeasonalMenu(MenuBase):
|
|
|
254
256
|
stream = anime.get_video(
|
|
255
257
|
ep, lang, preferred_quality=self.options.quality
|
|
256
258
|
)
|
|
259
|
+
if stream is None:
|
|
260
|
+
error("Could not find stream for requested episode, skipping")
|
|
257
261
|
s.ok("✔")
|
|
258
262
|
|
|
259
263
|
self.player.play_title(anime, stream)
|
anipy_cli/prompts.py
CHANGED
|
@@ -44,7 +44,7 @@ def search_show_prompt(
|
|
|
44
44
|
mandatory=False,
|
|
45
45
|
).execute()
|
|
46
46
|
|
|
47
|
-
if query
|
|
47
|
+
if not (query and query.strip()):
|
|
48
48
|
return None
|
|
49
49
|
|
|
50
50
|
with DotSpinner("Searching for ", colors.BLUE, query, "..."):
|
|
@@ -132,7 +132,7 @@ def season_search_prompt(
|
|
|
132
132
|
mandatory=False,
|
|
133
133
|
).execute()
|
|
134
134
|
|
|
135
|
-
if year
|
|
135
|
+
if not year or not str(year).strip():
|
|
136
136
|
return
|
|
137
137
|
|
|
138
138
|
if season is None:
|
|
@@ -336,6 +336,7 @@ def parse_auto_search(
|
|
|
336
336
|
|
|
337
337
|
return result, lang, chosen
|
|
338
338
|
|
|
339
|
+
|
|
339
340
|
def migrate_provider(mode: str, local_list: "LocalList"):
|
|
340
341
|
config = Config()
|
|
341
342
|
all_entries = local_list.get_all()
|
|
@@ -384,4 +385,3 @@ def migrate_provider(mode: str, local_list: "LocalList"):
|
|
|
384
385
|
|
|
385
386
|
episode = find_closest(best_anime.get_episodes(s.language), s.episode)
|
|
386
387
|
local_list.update(best_anime, language=s.language, episode=episode)
|
|
387
|
-
|
anipy_cli/util.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
1
3
|
import sys
|
|
2
|
-
import time
|
|
3
4
|
import subprocess as sp
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import (
|
|
6
7
|
TYPE_CHECKING,
|
|
7
|
-
|
|
8
|
+
Any,
|
|
8
9
|
Iterator,
|
|
9
10
|
List,
|
|
10
11
|
Literal,
|
|
@@ -14,12 +15,13 @@ from typing import (
|
|
|
14
15
|
overload,
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
import anipy_cli.logger as logger
|
|
19
|
+
|
|
17
20
|
from anipy_api.anime import Anime
|
|
18
21
|
from anipy_api.download import Downloader, PostDownloadCallback
|
|
19
|
-
from anipy_api.
|
|
20
|
-
from anipy_api.locallist import LocalListData, LocalListEntry
|
|
22
|
+
from anipy_api.locallist import LocalListData
|
|
21
23
|
from anipy_api.player import get_player
|
|
22
|
-
from anipy_api.provider import
|
|
24
|
+
from anipy_api.provider import list_providers
|
|
23
25
|
from InquirerPy import inquirer
|
|
24
26
|
from yaspin.core import Yaspin
|
|
25
27
|
from yaspin.spinners import Spinners
|
|
@@ -34,7 +36,7 @@ if TYPE_CHECKING:
|
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
class DotSpinner(Yaspin):
|
|
37
|
-
def __init__(self, *text_and_colors, **spinner_args):
|
|
39
|
+
def __init__(self, *text_and_colors: Any, **spinner_args: Any):
|
|
38
40
|
super().__init__(
|
|
39
41
|
text=color(*text_and_colors),
|
|
40
42
|
color="cyan",
|
|
@@ -46,21 +48,26 @@ class DotSpinner(Yaspin):
|
|
|
46
48
|
self.start()
|
|
47
49
|
return self
|
|
48
50
|
|
|
49
|
-
def set_text(self, *text_and_colors):
|
|
51
|
+
def set_text(self, *text_and_colors: Any):
|
|
50
52
|
self.text = color(*text_and_colors)
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
@overload
|
|
54
56
|
def error(error: str, fatal: Literal[True]) -> NoReturn: ...
|
|
55
57
|
@overload
|
|
56
|
-
def error(
|
|
58
|
+
def error(
|
|
59
|
+
error: str, fatal: Literal[False] = ..., log_level: int = logging.INFO
|
|
60
|
+
) -> None: ...
|
|
57
61
|
|
|
58
62
|
|
|
59
|
-
def error(
|
|
63
|
+
def error(
|
|
64
|
+
error: str, fatal: bool = False, log_level: int = logging.INFO
|
|
65
|
+
) -> Union[NoReturn, None]:
|
|
60
66
|
if not fatal:
|
|
61
67
|
sys.stderr.write(
|
|
62
68
|
color(colors.RED, "anipy-cli: error: ", colors.END, f"{error}\n")
|
|
63
69
|
)
|
|
70
|
+
logger.log(log_level, error)
|
|
64
71
|
return
|
|
65
72
|
|
|
66
73
|
sys.stderr.write(
|
|
@@ -71,9 +78,16 @@ def error(error: str, fatal: bool = False) -> Union[NoReturn, None]:
|
|
|
71
78
|
f"{error}, exiting\n",
|
|
72
79
|
)
|
|
73
80
|
)
|
|
81
|
+
logger.warn(error)
|
|
74
82
|
sys.exit(1)
|
|
75
83
|
|
|
76
84
|
|
|
85
|
+
def clear_screen():
|
|
86
|
+
if logger.get_console_log_level() < 60:
|
|
87
|
+
return
|
|
88
|
+
os.system("cls" if os.name == "nt" else "clear")
|
|
89
|
+
|
|
90
|
+
|
|
77
91
|
def get_prefered_providers(mode: str) -> Iterator["BaseProvider"]:
|
|
78
92
|
config = Config()
|
|
79
93
|
preferred_providers = config.providers[mode]
|
|
@@ -121,7 +135,10 @@ def get_download_path(
|
|
|
121
135
|
|
|
122
136
|
return download_folder / anime_name / filename
|
|
123
137
|
|
|
124
|
-
|
|
138
|
+
|
|
139
|
+
def get_post_download_scripts_hook(
|
|
140
|
+
mode: str, anime: "Anime", spinner: DotSpinner
|
|
141
|
+
) -> PostDownloadCallback:
|
|
125
142
|
config = Config()
|
|
126
143
|
scripts = config.post_download_scripts[mode]
|
|
127
144
|
timeout = config.post_download_scripts["timeout"]
|
|
@@ -129,17 +146,21 @@ def get_post_download_scripts_hook(mode: str, anime: "Anime", spinner: DotSpinne
|
|
|
129
146
|
def hook(path: Path, stream: "ProviderStream"):
|
|
130
147
|
spinner.hide()
|
|
131
148
|
arguments = [
|
|
132
|
-
str(path),
|
|
133
|
-
|
|
134
|
-
str(stream.
|
|
149
|
+
str(path),
|
|
150
|
+
anime.name,
|
|
151
|
+
str(stream.episode),
|
|
152
|
+
anime.provider.NAME,
|
|
153
|
+
str(stream.resolution),
|
|
154
|
+
stream.language.name,
|
|
135
155
|
]
|
|
136
156
|
for s in scripts:
|
|
137
157
|
sub_proc = sp.Popen([s, *arguments])
|
|
138
|
-
sub_proc.wait(timeout)
|
|
158
|
+
sub_proc.wait(timeout) # type: ignore
|
|
139
159
|
spinner.show()
|
|
140
160
|
|
|
141
161
|
return hook
|
|
142
162
|
|
|
163
|
+
|
|
143
164
|
def parse_episode_ranges(ranges: str, episodes: List["Episode"]) -> List["Episode"]:
|
|
144
165
|
picked = set()
|
|
145
166
|
for r in ranges.split():
|
|
@@ -202,7 +223,7 @@ def get_configured_player(player_override: Optional[str] = None) -> "PlayerBase"
|
|
|
202
223
|
return get_player(player, args, discord_cb)
|
|
203
224
|
|
|
204
225
|
|
|
205
|
-
def get_anime_season(month):
|
|
226
|
+
def get_anime_season(month: int):
|
|
206
227
|
if 1 <= month <= 3:
|
|
207
228
|
return "Winter"
|
|
208
229
|
elif 4 <= month <= 6:
|
|
@@ -233,9 +254,7 @@ def convert_letter_to_season(letter: str) -> Optional[str]:
|
|
|
233
254
|
|
|
234
255
|
|
|
235
256
|
def migrate_locallist(file: Path) -> LocalListData:
|
|
236
|
-
error(
|
|
237
|
-
f"{file} is in an unsuported format..."
|
|
238
|
-
)
|
|
257
|
+
error(f"{file} is in an unsuported format...")
|
|
239
258
|
|
|
240
259
|
new_list = LocalListData({})
|
|
241
260
|
choice = inquirer.confirm( # type: ignore
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: anipy-cli
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.2
|
|
4
4
|
Summary: Watch and Download anime from the comfort of your Terminal
|
|
5
5
|
License: GPL-3.0
|
|
6
6
|
Keywords: anime,cli
|
|
7
7
|
Author: sdaqo
|
|
8
8
|
Author-email: sdaqo.dev@protonmail.com
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.10,<4.0
|
|
10
10
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
-
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Requires-Dist: anipy-api (>=3.8.2,<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)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
anipy_cli/__init__.py,sha256=ALlLvJfemYvNnVZxVP67VmiMhE3KeaLKxoGq0YSF1bA,48
|
|
2
|
+
anipy_cli/anilist_proxy.py,sha256=tUTQvjxGHMlB0Ci9q-vJwx3R1k1Y9PXhKWiB4s0ZvtI,7441
|
|
3
|
+
anipy_cli/arg_parser.py,sha256=NPswRQ3e0Fs7H3DeJOnOKLj51tC4Muw-9MW280EhD9w,7740
|
|
4
|
+
anipy_cli/cli.py,sha256=_UK-k3sMFFrSCKZV2tby83xfjsR-881p_nhxP4-aOus,2916
|
|
5
|
+
anipy_cli/clis/__init__.py,sha256=zJrVQnb9E1sDsZKdFT1aoD9zNKrWxa291ZR0sPjBbRY,479
|
|
6
|
+
anipy_cli/clis/anilist_cli.py,sha256=XuDmEnAwOpXn3AtH2M3I7SHH_o0btOmEIaGh_jDHa3A,1857
|
|
7
|
+
anipy_cli/clis/base_cli.py,sha256=JfS7mnxNgTK4_Pqeg4IyjHluhfVyO_YLL_TqdyTtyiQ,803
|
|
8
|
+
anipy_cli/clis/binge_cli.py,sha256=rqTRJe8Wmsibkj6sKNogyun0xciffdDmsz6laPP-9-g,2705
|
|
9
|
+
anipy_cli/clis/default_cli.py,sha256=8y0P99K-aoyv7HdzYHF77NbVTptZxfGkUWl4HtPgH8o,3284
|
|
10
|
+
anipy_cli/clis/download_cli.py,sha256=sREoLhgiPk5nQ7eFzbbGznyt80_uaE4VhiOCxrg4ce0,2400
|
|
11
|
+
anipy_cli/clis/history_cli.py,sha256=2ccv6BpQQpUhY4K-KM7lO9qxVLXBrmCY5lec6czipSE,2863
|
|
12
|
+
anipy_cli/clis/mal_cli.py,sha256=s-9wOh1DkWHt3QPDQMVWAr2GcTXcTVLiXmVTR_LwDqg,2283
|
|
13
|
+
anipy_cli/clis/seasonal_cli.py,sha256=GV2TQNm9UotG1cxfYbrFFgg7Jmy8SFa7w_GlFtPdRVE,616
|
|
14
|
+
anipy_cli/colors.py,sha256=MaUeHk6Ad0xSWsii_xph4zzV0Xgr_SixRstYP9eDQPQ,975
|
|
15
|
+
anipy_cli/config.py,sha256=_9dRk6is-Umn9sqtl7DMobnM5GhgEtH6iNdcxU3OsGc,18516
|
|
16
|
+
anipy_cli/discord.py,sha256=c6mdqnEdblzZBYs3cGP66oDeS4ySm59OfTRP-R-Duls,1160
|
|
17
|
+
anipy_cli/download_component.py,sha256=D7PUZPoeP695mHlrSGBeXDFBWQBiCdAbp2VDK4opr0I,6437
|
|
18
|
+
anipy_cli/logger.py,sha256=tXsckOYeewnEyx1GBpv4WrB-icy3Z083xwb8fmnxJ9E,5195
|
|
19
|
+
anipy_cli/mal_proxy.py,sha256=Xns2BQU950zDR5pLOmzDKUCIrqDCoySUNsIvAhAAMX8,7252
|
|
20
|
+
anipy_cli/menus/__init__.py,sha256=U9RLQ61ulY3MpHvz3Q02my_q61LoM3KY1SLd9v3JhnY,253
|
|
21
|
+
anipy_cli/menus/anilist_menu.py,sha256=ukhKe1vYrH_O9y7J6UFoUhfVEZH4Ww9qoQqFrwVKBQQ,24625
|
|
22
|
+
anipy_cli/menus/base_menu.py,sha256=vDvPI36grmk0Dklthj3d_3yE_vG9oyHWNrWwVvJLxpg,1132
|
|
23
|
+
anipy_cli/menus/mal_menu.py,sha256=P0f1yQ1kG1KrQvBnS8zU4rFYh60o2y_HkLR6lVhTxBA,24030
|
|
24
|
+
anipy_cli/menus/menu.py,sha256=8-GykCW6WWLq5C2DJomxFL4MM8ZfnvXHTkKgCbw1QfA,8774
|
|
25
|
+
anipy_cli/menus/seasonal_menu.py,sha256=ACP_V-rexESd_GhkGmbIge3ZND-SN_FAsOIxFlHfGuE,9075
|
|
26
|
+
anipy_cli/prompts.py,sha256=839gD7o4yfEJTQpaz7E3qWqefZwW2lW3W0d1QUWOZDc,11946
|
|
27
|
+
anipy_cli/util.py,sha256=D-eSkUakEk6WMT-eHfTdzfM8THdIrdQUV8z-wnEMtq8,7102
|
|
28
|
+
anipy_cli-3.8.2.dist-info/METADATA,sha256=daocZ1W4jbbUMKlwkm-O1s2ahvMMWzdqzMqWtLAJRkA,3483
|
|
29
|
+
anipy_cli-3.8.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
30
|
+
anipy_cli-3.8.2.dist-info/entry_points.txt,sha256=86iXpcm_ECFndrt0JAI2mqYfXC2Ar7mGi0iOaxCrNP0,51
|
|
31
|
+
anipy_cli-3.8.2.dist-info/RECORD,,
|
anipy_cli-3.4.8.dist-info/RECORD
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
anipy_cli/__init__.py,sha256=zjXWAOAxRpnYzcXe_Lvx-Q68uFakPzNp9AA6rM-2G0Q,48
|
|
2
|
-
anipy_cli/arg_parser.py,sha256=0L2ZamTMVp5jFF9gdrFXRNwm1E5WznwY8PbYjiV_LRE,6244
|
|
3
|
-
anipy_cli/cli.py,sha256=Bk2H15VRF34yKLbGgKVq0A2vdByMJj-JTyx7Ep-JbH0,2238
|
|
4
|
-
anipy_cli/clis/__init__.py,sha256=Y00uiPWiMvvRImxJMvfLA55BOkMUOrrx5vJUNvquNsY,411
|
|
5
|
-
anipy_cli/clis/base_cli.py,sha256=xPr_J8hKs7LkDLvmK6zyL1ZTZRpyC2IuFss8KsaDstU,817
|
|
6
|
-
anipy_cli/clis/binge_cli.py,sha256=ioZ-V0WfGYBqETFkd8epGrT9dPHwsRJ1qvIdqf4waIs,2551
|
|
7
|
-
anipy_cli/clis/default_cli.py,sha256=aJrJwtwdD7l-Z3dMjSHlvMvgTVnwA3_OXwS-9DZQIy8,3078
|
|
8
|
-
anipy_cli/clis/download_cli.py,sha256=K8hqkxTeQ5Ao5LR2rimxX099IWf2I_KDGySIZzuIIVI,2320
|
|
9
|
-
anipy_cli/clis/history_cli.py,sha256=2ccv6BpQQpUhY4K-KM7lO9qxVLXBrmCY5lec6czipSE,2863
|
|
10
|
-
anipy_cli/clis/mal_cli.py,sha256=_tSLgDUOa6GOZNyCncSSzaVj088y5GAKkHVRSndLLxk,2258
|
|
11
|
-
anipy_cli/clis/seasonal_cli.py,sha256=GV2TQNm9UotG1cxfYbrFFgg7Jmy8SFa7w_GlFtPdRVE,616
|
|
12
|
-
anipy_cli/colors.py,sha256=voXC7z1Fs9tHg4zzNTNMIrt9k-EVgJ3_xEf5KiW2xgo,916
|
|
13
|
-
anipy_cli/config.py,sha256=x9u5UHbPMewsA2q7XMHs6pvfFfTGzTxgROER2LEZESI,17746
|
|
14
|
-
anipy_cli/discord.py,sha256=c6mdqnEdblzZBYs3cGP66oDeS4ySm59OfTRP-R-Duls,1160
|
|
15
|
-
anipy_cli/download_component.py,sha256=3GCPoWIEjhN1rBtOt8NQg9lqBTI4OHV3gG2RZ3NMzcA,5248
|
|
16
|
-
anipy_cli/mal_proxy.py,sha256=me2ESB442pYeNEpHY8mqrOEb477UA0uAg2LprKcp8sM,7098
|
|
17
|
-
anipy_cli/menus/__init__.py,sha256=aIzbphxAW-QGfZwR1DIegFZuTJp1O3tSUnai0f0f4lY,185
|
|
18
|
-
anipy_cli/menus/base_menu.py,sha256=g5b9Z7SpvCxcq_vqObcPzxLwcXeGPltLgSwa0sEzyfk,1140
|
|
19
|
-
anipy_cli/menus/mal_menu.py,sha256=jAVJh7K5d0BCnoT4qUIZ7CavrnrctXj-eg9k8E90ulE,23697
|
|
20
|
-
anipy_cli/menus/menu.py,sha256=ejTOGVG8fFJhTT7t23kA_uBbF5pkNcdvj4cGAIPvdt8,8101
|
|
21
|
-
anipy_cli/menus/seasonal_menu.py,sha256=NT9dfQUdN1DFu6wAf9hdWOfVBB7EfFiUECAcW6fqHgs,8995
|
|
22
|
-
anipy_cli/prompts.py,sha256=RW1jqNq6RQY7BqV77vrCtEuyfyc8ArtdwCH73S3-c-k,11909
|
|
23
|
-
anipy_cli/util.py,sha256=8AzEeoSPXMGTdTrArhE0COhSuYP_MCvYIeGHv5X7haU,6841
|
|
24
|
-
anipy_cli-3.4.8.dist-info/METADATA,sha256=gOWjpN276iuw2JJOx4g3i8GCQWKbnqLBglKFJDe0o9Y,3481
|
|
25
|
-
anipy_cli-3.4.8.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
26
|
-
anipy_cli-3.4.8.dist-info/entry_points.txt,sha256=86iXpcm_ECFndrt0JAI2mqYfXC2Ar7mGi0iOaxCrNP0,51
|
|
27
|
-
anipy_cli-3.4.8.dist-info/RECORD,,
|
|
File without changes
|