anipy-cli 2.7.27__tar.gz → 2.7.28__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.

Potentially problematic release.


This version of anipy-cli might be problematic. Click here for more details.

Files changed (50) hide show
  1. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/PKG-INFO +2 -1
  2. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/menus/menu.py +8 -2
  3. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/menus/seasonal_menu.py +5 -2
  4. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/util.py +11 -4
  5. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/colors.py +3 -0
  6. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/download.py +11 -3
  7. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/mal.py +14 -8
  8. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/player.py +5 -9
  9. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/query.py +13 -5
  10. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/seasonal.py +2 -3
  11. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/url_handler.py +36 -8
  12. anipy_cli-2.7.28/anipy_cli/version.py +1 -0
  13. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli.egg-info/PKG-INFO +3 -2
  14. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli.egg-info/requires.txt +1 -0
  15. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/setup.py +1 -0
  16. anipy_cli-2.7.27/anipy_cli/version.py +0 -1
  17. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/LICENSE +0 -0
  18. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/README.md +0 -0
  19. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/__init__.py +0 -0
  20. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/arg_parser.py +0 -0
  21. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/__init__.py +0 -0
  22. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/cli.py +0 -0
  23. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/__init__.py +0 -0
  24. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/base_cli.py +0 -0
  25. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/binge_cli.py +0 -0
  26. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/default_cli.py +0 -0
  27. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/download_cli.py +0 -0
  28. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/history_cli.py +0 -0
  29. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/mal_cli.py +0 -0
  30. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/clis/seasonal_cli.py +0 -0
  31. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/menus/__init__.py +0 -0
  32. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/menus/base_menu.py +0 -0
  33. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/cli/menus/mal_menu.py +0 -0
  34. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/config.py +0 -0
  35. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/history.py +0 -0
  36. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/misc.py +0 -0
  37. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/__init__.py +0 -0
  38. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/players/__init__.py +0 -0
  39. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/players/base.py +0 -0
  40. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/players/mpv.py +0 -0
  41. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/players/mpv_contrl.py +0 -0
  42. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/players/syncplay.py +0 -0
  43. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/player/players/vlc.py +0 -0
  44. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli/run_anipy_cli.py +0 -0
  45. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli.egg-info/SOURCES.txt +0 -0
  46. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli.egg-info/dependency_links.txt +0 -0
  47. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli.egg-info/entry_points.txt +0 -0
  48. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/anipy_cli.egg-info/top_level.txt +0 -0
  49. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/pyproject.toml +0 -0
  50. {anipy_cli-2.7.27 → anipy_cli-2.7.28}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: anipy_cli
3
- Version: 2.7.27
3
+ Version: 2.7.28
4
4
  Summary: Little tool in python to watch anime from the terminal (the better way to watch anime)
5
5
  Home-page: https://github.com/sdaqo/anipy-cli
6
6
  Author: sdaqo
@@ -21,6 +21,7 @@ Requires-Dist: tqdm
21
21
  Requires-Dist: moviepy
22
22
  Requires-Dist: pyyaml
23
23
  Requires-Dist: python-mpv
24
+ Requires-Dist: yaspin
24
25
 
25
26
  ![waving](https://capsule-render.vercel.app/api?type=waving&height=200&text=sdaqo/anipy-cli&fontAlign=60&fontAlignY=40&color=021224&fontColor=b0b8b2&animation=fadeIn)
26
27
 
@@ -1,9 +1,10 @@
1
1
  import sys
2
+ import os
2
3
  from typing import List
3
4
 
4
5
  from anipy_cli.arg_parser import CliArgs
5
6
  from anipy_cli.colors import colors, cprint
6
- from anipy_cli.misc import Entry, error
7
+ from anipy_cli.misc import Entry, error, clear_console
7
8
  from anipy_cli.player import PlayerBaseType
8
9
  from anipy_cli.url_handler import videourl, epHandler
9
10
  from anipy_cli.query import query
@@ -37,7 +38,11 @@ class Menu(MenuBase):
37
38
  def print_header(self):
38
39
  cprint(
39
40
  colors.GREEN,
40
- f"Playing: {self.entry.show_name} {self.entry.quality} | ",
41
+ "Playing: ",
42
+ colors.BLUE,
43
+ self.entry.show_name,
44
+ colors.GREEN,
45
+ f" | {self.entry.quality} | ",
41
46
  colors.RED,
42
47
  f"{self.entry.ep}/{self.entry.latest_ep}",
43
48
  )
@@ -71,6 +76,7 @@ class Menu(MenuBase):
71
76
  self.print_options()
72
77
 
73
78
  def search(self):
79
+ clear_console()
74
80
  query_class = query(input("Search: "), self.entry)
75
81
  if query_class.get_links() == 0:
76
82
  error("no search results")
@@ -1,9 +1,12 @@
1
1
  import sys
2
2
  from typing import List
3
+ from yaspin import yaspin
4
+ from yaspin.spinners import Spinners
5
+
3
6
 
4
7
  from anipy_cli.arg_parser import CliArgs
5
8
  from anipy_cli.colors import colors, cprint, cinput
6
- from anipy_cli.misc import Entry, print_names, error
9
+ from anipy_cli.misc import Entry, print_names, error, clear_console
7
10
  from anipy_cli.player import get_player
8
11
  from anipy_cli.url_handler import videourl, epHandler
9
12
  from anipy_cli.query import query
@@ -59,7 +62,7 @@ class SeasonalMenu(MenuBase, Seasonal):
59
62
  links = [search["category_url"]]
60
63
 
61
64
  else:
62
- print("\nCurrent: ", search)
65
+ clear_console()
63
66
  query_class = query(search, show_entry)
64
67
  query_class.get_pages()
65
68
  links = query_class.get_links()
@@ -1,3 +1,5 @@
1
+ from yaspin import yaspin
2
+ from yaspin.spinners import Spinners
1
3
  from anipy_cli.colors import cprint, colors, cinput
2
4
  from anipy_cli.misc import Entry, search_in_season_on_gogo, print_names
3
5
  from anipy_cli.url_handler import epHandler, videourl
@@ -75,11 +77,16 @@ def get_season_searches(gogo=True):
75
77
  else:
76
78
  cprint(colors.YELLOW, "Please enter a valid season name.\n")
77
79
 
78
- if gogo:
79
- anime_in_season = search_in_season_on_gogo(season_year, season_name)
80
+ with yaspin(
81
+ text="Fetching seasonals...", spinner=Spinners.dots, color="cyan"
82
+ ) as spinner:
83
+ if gogo:
84
+ anime_in_season = search_in_season_on_gogo(season_year, season_name)
80
85
 
81
- else:
82
- anime_in_season = MAL().get_seasonal_anime(season_year, season_name)
86
+ else:
87
+ anime_in_season = MAL().get_seasonal_anime(season_year, season_name)
88
+
89
+ spinner.ok("✔")
83
90
 
84
91
  cprint("Anime found in {} {} Season: ".format(season_year, season_name))
85
92
  cprint(
@@ -11,6 +11,9 @@ class colors:
11
11
  CYAN = "\u001b[36m"
12
12
  RED = "\u001b[31m"
13
13
  END = "\x1b[0m"
14
+ BOLD = "\033[1m"
15
+ UNDERLINE = "\033[4m"
16
+ RESET = "\033[0m"
14
17
 
15
18
 
16
19
  def color(*values, sep: str = "") -> str:
@@ -24,7 +24,9 @@ class download:
24
24
  A entry with all fields is required.
25
25
  """
26
26
 
27
- def __init__(self, entry, quality, ffmpeg=False, dl_path: Path = None, file_name_format="") -> None:
27
+ def __init__(
28
+ self, entry, quality, ffmpeg=False, dl_path: Path = None, file_name_format=""
29
+ ) -> None:
28
30
  try:
29
31
  self.quality = int(quality)
30
32
  except ValueError:
@@ -426,7 +428,11 @@ class download:
426
428
 
427
429
  show_name = self._get_valid_pathname(self.entry.show_name)
428
430
 
429
- file_format = self.file_name_format if self.file_name_format else Config().download_name_format
431
+ file_format = (
432
+ self.file_name_format
433
+ if self.file_name_format
434
+ else Config().download_name_format
435
+ )
430
436
 
431
437
  return file_format.format(
432
438
  show_name=show_name,
@@ -441,7 +447,9 @@ class download:
441
447
  if sys.platform == "win32":
442
448
  name = "".join(["" if x in WIN_INVALID_CHARS else x for x in name])
443
449
 
444
- name = "".join([i for i in name if i.isascii()]) # Verify all chars are ascii (eject if not)
450
+ name = "".join(
451
+ [i for i in name if i.isascii()]
452
+ ) # Verify all chars are ascii (eject if not)
445
453
  name = "-".join(name.split()) # Clean all white spaces, including tabs and such
446
454
 
447
455
  return name
@@ -97,10 +97,9 @@ class MAL:
97
97
  def auto_map_all_without_map(self):
98
98
  with Pool(processes=None) as pool:
99
99
  mal_entries = self.local_mal_list_json["data"]
100
- # apply the search function to each search value in parallel
100
+ # apply the search function to each search value in parallel
101
101
  results = pool.map(self.auto_map_gogo_mal, mal_entries, True)
102
102
 
103
-
104
103
  new_mal_entries = list()
105
104
  for result in results:
106
105
  if type(result) is dict:
@@ -562,7 +561,9 @@ class MAL:
562
561
  if "gogo_map" in mal_entry and len(mal_entry["gogo_map"]) > 0:
563
562
  return {"failed_to_map": False, "mal_entry": mal_entry}
564
563
  failed_to_map = True
565
- cprint(colors.GREEN, "Auto mapping: ", colors.BLUE, mal_entry["node"]["title"])
564
+ cprint(
565
+ colors.GREEN, "Auto mapping: ", colors.BLUE, mal_entry["node"]["title"]
566
+ )
566
567
 
567
568
  search_values = [
568
569
  mal_entry["node"]["title"],
@@ -582,7 +583,10 @@ class MAL:
582
583
  mal_entry["gogo_map"] = []
583
584
  for i, anime in enumerate(found["search"][1]):
584
585
  if any(
585
- anime.lower().rstrip("(dub)").rstrip("(japanese dub)").strip(" ")
586
+ anime.lower()
587
+ .rstrip("(dub)")
588
+ .rstrip("(japanese dub)")
589
+ .strip(" ")
586
590
  in show.lower()
587
591
  for show in [search_values[0], search_values[1]]
588
592
  ):
@@ -592,13 +596,15 @@ class MAL:
592
596
  self.update_gogo_map_list(gogo_map, current_map)
593
597
  failed_to_map = False
594
598
  if not mp:
595
- self.shows_failed_automap.discard(mal_entry["node"]["title"])
599
+ self.shows_failed_automap.discard(
600
+ mal_entry["node"]["title"]
601
+ )
596
602
  self.update_anime_list(
597
603
  mal_entry["node"]["id"],
598
604
  {
599
- "num_watched_episodes": mal_entry["node"]["my_list_status"][
600
- "num_episodes_watched"
601
- ],
605
+ "num_watched_episodes": mal_entry["node"][
606
+ "my_list_status"
607
+ ]["num_episodes_watched"],
602
608
  "tags": "anipy-cli",
603
609
  },
604
610
  )
@@ -17,22 +17,18 @@ def get_player(rpc_client=None, player_override="") -> PlayerBaseType:
17
17
 
18
18
  if not player_override:
19
19
  player = cfg.player_path
20
-
20
+
21
21
  player = Path(player)
22
-
22
+
23
23
  if player.name == "mpv" and cfg.reuse_mpv_window:
24
24
  from anipy_cli.player.players.mpv_contrl import MpvControllable
25
+
25
26
  return MpvControllable(rpc_client=rpc_client)
26
27
 
27
- player_dict = {
28
- "mpv": Mpv,
29
- "mpvnet": Mpv,
30
- "vlc": Vlc,
31
- "syncplay": Syncplay
32
- }
28
+ player_dict = {"mpv": Mpv, "mpvnet": Mpv, "vlc": Vlc, "syncplay": Syncplay}
33
29
 
34
30
  player_class = player_dict.get(player.name, None)
35
-
31
+
36
32
  if player_class:
37
33
  return player_class(str(player), rpc_client=rpc_client)
38
34
  else:
@@ -1,6 +1,9 @@
1
1
  import requests
2
2
  import re
3
3
  from bs4 import BeautifulSoup
4
+ from yaspin import yaspin
5
+ from yaspin.spinners import Spinners
6
+
4
7
 
5
8
  from anipy_cli.misc import loc_err, response_err, error, print_names
6
9
  from anipy_cli.colors import colors, cinput
@@ -18,11 +21,16 @@ class query:
18
21
  """
19
22
 
20
23
  def __init__(self, search_param, entry) -> None:
21
- self.entry = entry
22
- self.search_url = base_url + f"/search.html?keyword={search_param}"
23
- r = requests.get(self.search_url)
24
- response_err(r, self.search_url)
25
- self.soup = BeautifulSoup(r.content, "html.parser")
24
+ with yaspin() as spinner:
25
+ spinner.text = f"Searching for {colors.BLUE}{search_param}{colors.END}"
26
+ spinner.spinner = Spinners.dots
27
+ spinner.color = "cyan"
28
+ self.entry = entry
29
+ self.search_url = base_url + f"/search.html?keyword={search_param}"
30
+ r = requests.get(self.search_url)
31
+ response_err(r, self.search_url)
32
+ self.soup = BeautifulSoup(r.content, "html.parser")
33
+ spinner.ok("✓")
26
34
 
27
35
  def get_pages(self):
28
36
  """Get count of result pages of query"""
@@ -36,14 +36,13 @@ class Seasonal:
36
36
  for i, e, n in zip(categ_urls, user_eps, names):
37
37
  self.entry.category_url = i
38
38
  ep_class = epHandler(self.entry)
39
-
39
+
40
40
  eps_range = ep_class._load_eps_list()
41
41
  for j in eps_range:
42
42
  if parsenum(j["ep"]) == e:
43
- eps_range = eps_range[eps_range.index(j) + 1:]
43
+ eps_range = eps_range[eps_range.index(j) + 1 :]
44
44
  break
45
45
 
46
-
47
46
  ep_urls = []
48
47
  for j in eps_range:
49
48
  self.entry.ep = parsenum(j["ep"])
@@ -5,14 +5,16 @@ import re
5
5
  import base64
6
6
  import functools
7
7
  import m3u8
8
+ from yaspin import yaspin
9
+ from yaspin.spinners import Spinners
8
10
  from pathlib import Path
9
11
  from urllib.parse import urlparse, parse_qsl, urlencode, urljoin
10
12
  from bs4 import BeautifulSoup
11
13
  from requests.adapters import HTTPAdapter, Retry
12
14
  from Cryptodome.Cipher import AES
13
15
 
14
- from anipy_cli.misc import response_err, error, loc_err, parsenum, Entry
15
- from anipy_cli.colors import cinput, color, colors
16
+ from anipy_cli.misc import response_err, error, loc_err, parsenum, Entry, clear_console
17
+ from anipy_cli.colors import cinput, color, colors, cprint
16
18
  from anipy_cli.config import Config
17
19
 
18
20
 
@@ -119,7 +121,16 @@ class epHandler:
119
121
  else:
120
122
  return ep_list[0]["ep"]
121
123
 
122
- def _do_prompt(self, prompt="Episode"):
124
+ def _do_prompt(self, prompt="Select Episode"):
125
+ clear_console()
126
+ cprint(
127
+ colors.BLUE,
128
+ colors.BOLD,
129
+ colors.UNDERLINE,
130
+ (self.entry.show_name),
131
+ colors.END,
132
+ colors.RESET,
133
+ )
123
134
  ep_range = f" [{self.get_first()}-{self.get_latest()}]"
124
135
 
125
136
  specials = self.get_special_list()
@@ -127,7 +138,9 @@ class epHandler:
127
138
  ep_range += " Special Eps: "
128
139
  ep_range += ", ".join([x["ep"] for x in specials])
129
140
 
130
- return cinput(prompt, colors.GREEN, ep_range, colors.END, "\n>> ", input_color=colors.CYAN)
141
+ return cinput(
142
+ prompt, colors.GREEN, ep_range, colors.END, "\n>> ", input_color=colors.CYAN
143
+ )
131
144
 
132
145
  def _validate_ep(self, ep: str):
133
146
  """
@@ -147,8 +160,13 @@ class epHandler:
147
160
  Cli function to pick an episode from 1 to
148
161
  the latest available.
149
162
  """
150
-
151
- self.get_latest()
163
+ with yaspin(
164
+ text=f"Fetching episode list for {colors.BLUE}{self.entry.show_name}..."
165
+ ) as spinner:
166
+ spinner.color = "cyan"
167
+ spinner.spinner = Spinners.dots
168
+ self.get_latest()
169
+ spinner.hide()
152
170
 
153
171
  while True:
154
172
  which_episode = self._do_prompt()
@@ -171,7 +189,13 @@ class epHandler:
171
189
  the latest available.
172
190
  """
173
191
 
174
- self.get_latest()
192
+ with yaspin(
193
+ text=f"Fetching episode list for {colors.BLUE}{self.entry.show_name}..."
194
+ ) as spinner:
195
+ spinner.color = "cyan"
196
+ spinner.spinner = Spinners.dots
197
+ self.get_latest()
198
+ spinner.hide()
175
199
 
176
200
  while True:
177
201
  which_episode = self._do_prompt(
@@ -298,7 +322,11 @@ class videourl:
298
322
  soup = BeautifulSoup(r.content, "html.parser")
299
323
  link = soup.find("a", {"class": "active", "rel": "1"})
300
324
  loc_err(link, self.entry.ep_url, "embed-url")
301
- self.entry.embed_url = f'https:{link["data-video"]}' if not link["data-video"].startswith("https:") else link["data-video"]
325
+ self.entry.embed_url = (
326
+ f'https:{link["data-video"]}'
327
+ if not link["data-video"].startswith("https:")
328
+ else link["data-video"]
329
+ )
302
330
 
303
331
  @functools.lru_cache()
304
332
  def get_enc_keys(self):
@@ -0,0 +1 @@
1
+ __version__ = "2.7.28"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
- Name: anipy-cli
3
- Version: 2.7.27
2
+ Name: anipy_cli
3
+ Version: 2.7.28
4
4
  Summary: Little tool in python to watch anime from the terminal (the better way to watch anime)
5
5
  Home-page: https://github.com/sdaqo/anipy-cli
6
6
  Author: sdaqo
@@ -21,6 +21,7 @@ Requires-Dist: tqdm
21
21
  Requires-Dist: moviepy
22
22
  Requires-Dist: pyyaml
23
23
  Requires-Dist: python-mpv
24
+ Requires-Dist: yaspin
24
25
 
25
26
  ![waving](https://capsule-render.vercel.app/api?type=waving&height=200&text=sdaqo/anipy-cli&fontAlign=60&fontAlignY=40&color=021224&fontColor=b0b8b2&animation=fadeIn)
26
27
 
@@ -10,3 +10,4 @@ tqdm
10
10
  moviepy
11
11
  pyyaml
12
12
  python-mpv
13
+ yaspin
@@ -38,6 +38,7 @@ setup(
38
38
  "moviepy",
39
39
  "pyyaml",
40
40
  "python-mpv",
41
+ "yaspin"
41
42
  ],
42
43
  entry_points="[console_scripts]\nanipy-cli=anipy_cli.run_anipy_cli:main",
43
44
  )
@@ -1 +0,0 @@
1
- __version__ = "2.7.27"
File without changes
File without changes
File without changes
File without changes
File without changes