anipy-cli 3.1.0__py3-none-any.whl → 3.1.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.
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 +1 -1
- anipy_cli/clis/base_cli.py +13 -11
- anipy_cli/clis/default_cli.py +2 -3
- anipy_cli/clis/download_cli.py +1 -2
- anipy_cli/clis/history_cli.py +9 -6
- anipy_cli/menus/mal_menu.py +2 -2
- anipy_cli/menus/menu.py +50 -2
- anipy_cli/prompts.py +13 -3
- {anipy_cli-3.1.0.dist-info → anipy_cli-3.1.2.dist-info}/METADATA +2 -2
- {anipy_cli-3.1.0.dist-info → anipy_cli-3.1.2.dist-info}/RECORD +13 -13
- {anipy_cli-3.1.0.dist-info → anipy_cli-3.1.2.dist-info}/WHEEL +0 -0
- {anipy_cli-3.1.0.dist-info → anipy_cli-3.1.2.dist-info}/entry_points.txt +0 -0
anipy_cli/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__appname__ = "anipy-cli"
|
|
2
|
-
__version__ = "3.1.
|
|
2
|
+
__version__ = "3.1.2"
|
anipy_cli/arg_parser.py
CHANGED
anipy_cli/clis/base_cli.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
3
|
|
|
4
4
|
if TYPE_CHECKING:
|
|
5
5
|
from anipy_cli.arg_parser import CliArgs
|
|
@@ -10,23 +10,25 @@ class CliBase(ABC):
|
|
|
10
10
|
self.options = options
|
|
11
11
|
|
|
12
12
|
@abstractmethod
|
|
13
|
-
def print_header(self): ...
|
|
13
|
+
def print_header(self) -> Optional[bool]: ...
|
|
14
14
|
|
|
15
15
|
@abstractmethod
|
|
16
|
-
def take_input(self): ...
|
|
16
|
+
def take_input(self) -> Optional[bool]: ...
|
|
17
17
|
|
|
18
18
|
@abstractmethod
|
|
19
|
-
def process(self): ...
|
|
19
|
+
def process(self) -> Optional[bool]: ...
|
|
20
20
|
|
|
21
21
|
@abstractmethod
|
|
22
|
-
def show(self): ...
|
|
22
|
+
def show(self) -> Optional[bool]: ...
|
|
23
23
|
|
|
24
24
|
@abstractmethod
|
|
25
|
-
def post(self): ...
|
|
25
|
+
def post(self) -> Optional[bool]: ...
|
|
26
26
|
|
|
27
27
|
def run(self):
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
funcs = ["print_header", "take_input", "process", "show", "post"]
|
|
29
|
+
for f in funcs:
|
|
30
|
+
func = getattr(self, f)
|
|
31
|
+
ret = func()
|
|
32
|
+
|
|
33
|
+
if ret == False: # noqa: E712
|
|
34
|
+
break
|
anipy_cli/clis/default_cli.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import sys
|
|
2
1
|
from typing import TYPE_CHECKING, Optional
|
|
3
2
|
|
|
4
3
|
from anipy_api.locallist import LocalList
|
|
@@ -54,14 +53,14 @@ class DefaultCli(CliBase):
|
|
|
54
53
|
anime = search_show_prompt("default")
|
|
55
54
|
|
|
56
55
|
if anime is None:
|
|
57
|
-
|
|
56
|
+
return False
|
|
58
57
|
|
|
59
58
|
self.lang = lang_prompt(anime)
|
|
60
59
|
|
|
61
60
|
episode = pick_episode_prompt(anime, self.lang)
|
|
62
61
|
|
|
63
62
|
if episode is None:
|
|
64
|
-
|
|
63
|
+
return False
|
|
65
64
|
|
|
66
65
|
self.anime = anime
|
|
67
66
|
self.epsiode = episode
|
anipy_cli/clis/download_cli.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import sys
|
|
2
1
|
from typing import TYPE_CHECKING, Optional, List
|
|
3
2
|
|
|
4
3
|
from anipy_api.download import Downloader
|
|
@@ -50,7 +49,7 @@ class DownloadCli(CliBase):
|
|
|
50
49
|
anime = search_show_prompt("download")
|
|
51
50
|
|
|
52
51
|
if anime is None:
|
|
53
|
-
|
|
52
|
+
return False
|
|
54
53
|
|
|
55
54
|
self.lang = lang_prompt(anime)
|
|
56
55
|
|
anipy_cli/clis/history_cli.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import sys
|
|
2
1
|
from typing import TYPE_CHECKING, Optional
|
|
3
2
|
|
|
3
|
+
from InquirerPy.base.control import Choice
|
|
4
4
|
from anipy_api.anime import Anime
|
|
5
5
|
from anipy_api.locallist import LocalList, LocalListEntry
|
|
6
6
|
from InquirerPy import inquirer
|
|
@@ -39,20 +39,23 @@ class HistoryCli(CliBase):
|
|
|
39
39
|
|
|
40
40
|
if not history:
|
|
41
41
|
print("You have no History, exiting")
|
|
42
|
-
|
|
42
|
+
return False
|
|
43
43
|
|
|
44
44
|
entry = inquirer.fuzzy( # type: ignore
|
|
45
45
|
message="Select History Entry:",
|
|
46
|
-
choices=
|
|
46
|
+
choices=[
|
|
47
|
+
Choice(value=h, name=f"{n + 1}. {repr(h)}")
|
|
48
|
+
for n, h in enumerate(history)
|
|
49
|
+
],
|
|
47
50
|
long_instruction="To cancel this prompt press ctrl+z",
|
|
48
51
|
mandatory=False,
|
|
49
52
|
).execute()
|
|
50
53
|
|
|
51
54
|
if entry is None:
|
|
52
|
-
|
|
55
|
+
return False
|
|
53
56
|
|
|
54
|
-
self.history_entry = entry
|
|
55
|
-
self.anime = Anime.from_local_list_entry(
|
|
57
|
+
self.history_entry = LocalListEntry.from_dict(entry)
|
|
58
|
+
self.anime = Anime.from_local_list_entry(self.history_entry)
|
|
56
59
|
|
|
57
60
|
def process(self):
|
|
58
61
|
assert self.anime is not None
|
anipy_cli/menus/mal_menu.py
CHANGED
|
@@ -528,7 +528,7 @@ class MALMenu(MenuBase):
|
|
|
528
528
|
|
|
529
529
|
counter += 1
|
|
530
530
|
s.set_text(f"Progress: {counter / to_map_length * 100:.1f}%")
|
|
531
|
-
except:
|
|
531
|
+
except: # noqa: E722
|
|
532
532
|
failed.append(anime)
|
|
533
533
|
|
|
534
534
|
with ThreadPoolExecutor(max_workers=5) as pool:
|
|
@@ -582,7 +582,7 @@ class MALMenu(MenuBase):
|
|
|
582
582
|
|
|
583
583
|
counter += 1
|
|
584
584
|
s.set_text(f"Progress: {counter / to_map_length * 100}%")
|
|
585
|
-
except:
|
|
585
|
+
except: # noqa: E722
|
|
586
586
|
failed.append(entry)
|
|
587
587
|
|
|
588
588
|
with ThreadPoolExecutor(max_workers=5) as pool:
|
anipy_cli/menus/menu.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from typing import TYPE_CHECKING, List
|
|
3
3
|
|
|
4
|
+
from InquirerPy import inquirer
|
|
5
|
+
from InquirerPy.base.control import Choice
|
|
4
6
|
from anipy_api.download import Downloader
|
|
5
|
-
from anipy_api.provider import LanguageTypeEnum
|
|
7
|
+
from anipy_api.provider import LanguageTypeEnum, ProviderStream
|
|
6
8
|
from anipy_api.locallist import LocalList
|
|
7
9
|
|
|
8
10
|
from anipy_cli.colors import colors, cprint
|
|
@@ -15,7 +17,7 @@ from anipy_cli.prompts import pick_episode_prompt, search_show_prompt
|
|
|
15
17
|
if TYPE_CHECKING:
|
|
16
18
|
from anipy_api.anime import Anime
|
|
17
19
|
from anipy_api.player import PlayerBase
|
|
18
|
-
from anipy_api.provider import Episode
|
|
20
|
+
from anipy_api.provider import Episode
|
|
19
21
|
|
|
20
22
|
from anipy_cli.arg_parser import CliArgs
|
|
21
23
|
|
|
@@ -36,6 +38,7 @@ class Menu(MenuBase):
|
|
|
36
38
|
self.history_list = LocalList(
|
|
37
39
|
Config()._history_file_path, migrate_cb=migrate_locallist
|
|
38
40
|
)
|
|
41
|
+
self.seasonal_list = LocalList(Config()._seasonal_file_path, migrate_locallist)
|
|
39
42
|
|
|
40
43
|
@property
|
|
41
44
|
def menu_options(self) -> List["MenuOption"]:
|
|
@@ -49,7 +52,10 @@ class Menu(MenuBase):
|
|
|
49
52
|
"c",
|
|
50
53
|
),
|
|
51
54
|
MenuOption("Select episode", self.selec_ep, "s"),
|
|
55
|
+
MenuOption("Select from history", self.selec_hist, "h"),
|
|
52
56
|
MenuOption("Search for Anime", self.search, "a"),
|
|
57
|
+
MenuOption("Add to seasonals", self.add_seasonal, "t"),
|
|
58
|
+
MenuOption("Change video quality", self.change_quality, "v"),
|
|
53
59
|
MenuOption("Print Video Info", self.video_info, "i"),
|
|
54
60
|
MenuOption("Download Episode", self.download_video, "d"),
|
|
55
61
|
MenuOption("Quit", self.quit, "q"),
|
|
@@ -136,6 +142,12 @@ class Menu(MenuBase):
|
|
|
136
142
|
self._start_episode(episode)
|
|
137
143
|
self.print_options()
|
|
138
144
|
|
|
145
|
+
def selec_hist(self):
|
|
146
|
+
from anipy_cli.clis.history_cli import HistoryCli
|
|
147
|
+
|
|
148
|
+
hist_cli = HistoryCli(self.options)
|
|
149
|
+
hist_cli.run()
|
|
150
|
+
|
|
139
151
|
def search(self):
|
|
140
152
|
search_result = search_show_prompt("default")
|
|
141
153
|
if search_result is None:
|
|
@@ -153,6 +165,42 @@ class Menu(MenuBase):
|
|
|
153
165
|
print(f"Stream Url: {self.stream.url}")
|
|
154
166
|
print(f"Quality: {self.stream.resolution}p")
|
|
155
167
|
|
|
168
|
+
def add_seasonal(self):
|
|
169
|
+
self.seasonal_list.update(
|
|
170
|
+
self.anime, episode=self.stream.episode, language=self.stream.language
|
|
171
|
+
)
|
|
172
|
+
cprint(colors.GREEN, "Anime added to seasonals!")
|
|
173
|
+
|
|
174
|
+
def change_quality(self):
|
|
175
|
+
with DotSpinner(
|
|
176
|
+
"Extracting streams for ",
|
|
177
|
+
colors.BLUE,
|
|
178
|
+
f"{self.anime.name} ({self.lang})",
|
|
179
|
+
" Episode ",
|
|
180
|
+
self.stream.episode,
|
|
181
|
+
"...",
|
|
182
|
+
):
|
|
183
|
+
streams = self.anime.get_videos(self.stream.episode, self.lang)
|
|
184
|
+
streams.reverse()
|
|
185
|
+
|
|
186
|
+
stream = inquirer.select( # type: ignore
|
|
187
|
+
message="Select Stream:",
|
|
188
|
+
choices=[
|
|
189
|
+
Choice(value=s, name=f"{s.resolution}p - {s.url}") for s in streams
|
|
190
|
+
],
|
|
191
|
+
long_instruction="To skip this prompt press ctrl+z",
|
|
192
|
+
mandatory=False,
|
|
193
|
+
).execute()
|
|
194
|
+
|
|
195
|
+
if stream is None:
|
|
196
|
+
return
|
|
197
|
+
|
|
198
|
+
stream = ProviderStream(**stream)
|
|
199
|
+
self.options.quality = stream.resolution
|
|
200
|
+
self.stream = stream
|
|
201
|
+
self.player.play_title(self.anime, self.stream)
|
|
202
|
+
self.print_options()
|
|
203
|
+
|
|
156
204
|
def download_video(self):
|
|
157
205
|
config = Config()
|
|
158
206
|
with DotSpinner("Starting Download...") as s:
|
anipy_cli/prompts.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from typing import TYPE_CHECKING, Optional, List, Tuple
|
|
3
3
|
from InquirerPy import inquirer
|
|
4
|
+
from InquirerPy.base.control import Choice
|
|
4
5
|
from anipy_api.provider import (
|
|
5
6
|
BaseProvider,
|
|
6
7
|
FilterCapabilities,
|
|
@@ -72,7 +73,9 @@ def search_show_prompt(
|
|
|
72
73
|
|
|
73
74
|
anime = inquirer.fuzzy( # type: ignore
|
|
74
75
|
message="Select Show:",
|
|
75
|
-
choices=
|
|
76
|
+
choices=[
|
|
77
|
+
Choice(value=r, name=f"{n + 1}. {repr(r)}") for n, r in enumerate(results)
|
|
78
|
+
],
|
|
76
79
|
long_instruction=(
|
|
77
80
|
"\nS = Anime is available in sub\n"
|
|
78
81
|
"D = Anime is available in dub\n"
|
|
@@ -118,8 +121,15 @@ def season_search_prompt(provider: "BaseProvider") -> Optional["Anime"]:
|
|
|
118
121
|
|
|
119
122
|
anime = inquirer.fuzzy( # type: ignore
|
|
120
123
|
message="Select Show:",
|
|
121
|
-
choices=
|
|
122
|
-
|
|
124
|
+
choices=[
|
|
125
|
+
Choice(value=r, name=f"{n + 1}. {repr(r)}") for n, r in enumerate(results)
|
|
126
|
+
],
|
|
127
|
+
long_instruction=(
|
|
128
|
+
"\nS = Anime is available in sub\n"
|
|
129
|
+
"D = Anime is available in dub\n"
|
|
130
|
+
"First two letters indicate the provider\n"
|
|
131
|
+
"To skip this prompt press ctrl+z"
|
|
132
|
+
),
|
|
123
133
|
mandatory=False,
|
|
124
134
|
).execute()
|
|
125
135
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: anipy-cli
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: Watch and Download anime from the comfort of your Terminal
|
|
5
5
|
Home-page: https://sdaqo.github.io/anipy-cli
|
|
6
6
|
License: GPL-3.0
|
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Requires-Dist: anipy-api (>=3.1.
|
|
17
|
+
Requires-Dist: anipy-api (>=3.1.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)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
anipy_cli/__init__.py,sha256=
|
|
2
|
-
anipy_cli/arg_parser.py,sha256=
|
|
1
|
+
anipy_cli/__init__.py,sha256=kyWUdgJH0tIsytyrRITwExQDe8Nf8IINcUErSv0JXJQ,48
|
|
2
|
+
anipy_cli/arg_parser.py,sha256=r2lroeHRyOA5_4RfNngClEsY9NXpNA96voOQDetuU7Y,5288
|
|
3
3
|
anipy_cli/cli.py,sha256=Ah5BE-u_SjcuzU5dQ5cSHtUloVRApCWwTK5i49yQtH8,1922
|
|
4
4
|
anipy_cli/clis/__init__.py,sha256=Y00uiPWiMvvRImxJMvfLA55BOkMUOrrx5vJUNvquNsY,411
|
|
5
|
-
anipy_cli/clis/base_cli.py,sha256=
|
|
5
|
+
anipy_cli/clis/base_cli.py,sha256=xPr_J8hKs7LkDLvmK6zyL1ZTZRpyC2IuFss8KsaDstU,817
|
|
6
6
|
anipy_cli/clis/binge_cli.py,sha256=eSvdOo_BRSb8-Xp48ZDcelqUBlDPdyQqu8OV0vc4szo,2281
|
|
7
|
-
anipy_cli/clis/default_cli.py,sha256=
|
|
8
|
-
anipy_cli/clis/download_cli.py,sha256=
|
|
9
|
-
anipy_cli/clis/history_cli.py,sha256=
|
|
7
|
+
anipy_cli/clis/default_cli.py,sha256=yuHyDqTgnq84I522mUkY1An5c114qqIYW-Xbm1SsDl4,2806
|
|
8
|
+
anipy_cli/clis/download_cli.py,sha256=y_8Txs6SSi60BvPCUcKDZg6zlN-w-eatM_O5ld0pzcQ,3187
|
|
9
|
+
anipy_cli/clis/history_cli.py,sha256=2ccv6BpQQpUhY4K-KM7lO9qxVLXBrmCY5lec6czipSE,2863
|
|
10
10
|
anipy_cli/clis/mal_cli.py,sha256=_tSLgDUOa6GOZNyCncSSzaVj088y5GAKkHVRSndLLxk,2258
|
|
11
11
|
anipy_cli/clis/seasonal_cli.py,sha256=GV2TQNm9UotG1cxfYbrFFgg7Jmy8SFa7w_GlFtPdRVE,616
|
|
12
12
|
anipy_cli/colors.py,sha256=voXC7z1Fs9tHg4zzNTNMIrt9k-EVgJ3_xEf5KiW2xgo,916
|
|
@@ -15,12 +15,12 @@ anipy_cli/discord.py,sha256=c6mdqnEdblzZBYs3cGP66oDeS4ySm59OfTRP-R-Duls,1160
|
|
|
15
15
|
anipy_cli/mal_proxy.py,sha256=wIsku2_dl8vKD2K99L63OlzA3L5fl-VmyeiXC9VrxI4,6981
|
|
16
16
|
anipy_cli/menus/__init__.py,sha256=aIzbphxAW-QGfZwR1DIegFZuTJp1O3tSUnai0f0f4lY,185
|
|
17
17
|
anipy_cli/menus/base_menu.py,sha256=g5b9Z7SpvCxcq_vqObcPzxLwcXeGPltLgSwa0sEzyfk,1140
|
|
18
|
-
anipy_cli/menus/mal_menu.py,sha256=
|
|
19
|
-
anipy_cli/menus/menu.py,sha256=
|
|
18
|
+
anipy_cli/menus/mal_menu.py,sha256=tJYq5J3k89_0BKFiWavn9Gqh5Z7uXtoUFqJaa3fT4o4,24105
|
|
19
|
+
anipy_cli/menus/menu.py,sha256=UQJ1hpyDT0i03ecIjBbFRp4PFh6FTNHDhSwSBSAhQEI,7860
|
|
20
20
|
anipy_cli/menus/seasonal_menu.py,sha256=VBmeXanJb-vS5TXiK79KgtJ5vPW87gIOdpN_EijAG_U,9097
|
|
21
|
-
anipy_cli/prompts.py,sha256=
|
|
21
|
+
anipy_cli/prompts.py,sha256=seNeErTP1om1wpRUN-rbUUI8bAGRmu48ScQjztzKkeE,7564
|
|
22
22
|
anipy_cli/util.py,sha256=e9k29kGOi_h4RPrQfKMsg-8xNZHO-fLfBSma6SjGfYg,7684
|
|
23
|
-
anipy_cli-3.1.
|
|
24
|
-
anipy_cli-3.1.
|
|
25
|
-
anipy_cli-3.1.
|
|
26
|
-
anipy_cli-3.1.
|
|
23
|
+
anipy_cli-3.1.2.dist-info/METADATA,sha256=WXn2iN7p2kcBUZO_cgX3MiAa7QHl_HY_ZJn4n6lmSOA,3418
|
|
24
|
+
anipy_cli-3.1.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
25
|
+
anipy_cli-3.1.2.dist-info/entry_points.txt,sha256=86iXpcm_ECFndrt0JAI2mqYfXC2Ar7mGi0iOaxCrNP0,51
|
|
26
|
+
anipy_cli-3.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|