Compare commits

...

8 Commits

10 changed files with 52 additions and 23 deletions

3
.envrc
View File

@@ -1,5 +1,6 @@
VIU_APP_NAME="viu-dev"
export VIU_APP_NAME
PATH="./.venv/bin/:$PATH"
export PATH VIU_APP_NAME
if command -v nix >/dev/null;then
use flake
fi

View File

@@ -30,7 +30,6 @@ if TYPE_CHECKING:
@click.option(
"--anime-title",
"-t",
required=True,
shell_complete=anime_titles_shell_complete,
multiple=True,
help="Specify which anime to download",
@@ -52,6 +51,10 @@ def search(config: AppConfig, **options: "Unpack[Options]"):
from ...libs.provider.anime.provider import create_provider
from ...libs.selectors.selector import create_selector
if not options["anime_title"]:
raw = click.prompt("What are you in the mood for? (comma-separated)")
options["anime_title"] = [a.strip() for a in raw.split(",") if a.strip()]
feedback = FeedbackService(config)
provider = create_provider(config.general.provider)
selector = create_selector(config)
@@ -173,6 +176,22 @@ def stream_anime(
if not server_name:
raise ViuError("Server not selected")
server = servers[server_name]
quality = [
ep_stream.link
for ep_stream in server.links
if ep_stream.quality == config.stream.quality
]
if not quality:
feedback.warning("Preferred quality not found, selecting quality...")
stream_link = selector.choose(
"Select Quality", [link.quality for link in server.links]
)
if not stream_link:
raise ViuError("Quality not selected")
stream_link = next(
(link.link for link in server.links if link.quality == stream_link), None
)
stream_link = server.links[0].link
if not stream_link:
raise ViuError(

View File

@@ -296,8 +296,7 @@ class DownloadService:
message=message,
app_name="Viu",
app_icon=app_icon,
timeout=self.app_config.general.desktop_notification_duration
* 60,
timeout=self.app_config.general.desktop_notification_duration,
)
except: # noqa: E722
pass
@@ -318,7 +317,7 @@ class DownloadService:
message=message,
app_name="Viu",
app_icon=app_icon,
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
except: # noqa: E722
pass

View File

@@ -41,7 +41,7 @@ class FeedbackService:
message=message,
app_name=CLI_NAME,
app_icon=str(ICON_PATH),
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
return
except: # noqa: E722
@@ -67,7 +67,7 @@ class FeedbackService:
message=message,
app_name=CLI_NAME,
app_icon=str(ICON_PATH),
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
return
except: # noqa: E722
@@ -94,7 +94,7 @@ class FeedbackService:
message=message,
app_name=CLI_NAME,
app_icon=str(ICON_PATH),
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
return
except: # noqa: E722
@@ -120,7 +120,7 @@ class FeedbackService:
message=message,
app_name=CLI_NAME,
app_icon=str(ICON_PATH),
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
return
except: # noqa: E722
@@ -176,7 +176,7 @@ class FeedbackService:
message="No current way to display info in rofi, use fzf and the terminal instead",
app_name=CLI_NAME,
app_icon=str(ICON_PATH),
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
return
except: # noqa: E722

View File

@@ -101,7 +101,7 @@ class NotificationService:
message=message,
app_name="Viu",
app_icon=app_icon, # plyer supports file paths or URLs depending on platform
timeout=self.app_config.general.desktop_notification_duration * 60,
timeout=self.app_config.general.desktop_notification_duration,
)
logger.info(f"Displayed notification: {message}")
self._mark_seen(

View File

@@ -6,7 +6,7 @@ GENERAL_PYGMENT_STYLE = "github-dark"
GENERAL_PREFERRED_SPINNER = "smiley"
GENERAL_API_CLIENT = "anilist"
GENERAL_PREFERRED_TRACKER = "local"
GENERAL_DESKTOP_NOTIFICATION_DURATION = 5
GENERAL_DESKTOP_NOTIFICATION_DURATION = 5 * 60
GENERAL_PROVIDER = "allanime"

View File

@@ -25,7 +25,7 @@ ANILIST_AUTH = (
)
try:
APP_DIR = Path(str(resources.files(CLI_NAME.lower())))
APP_DIR = Path(str(resources.files(PROJECT_NAME.lower())))
except ModuleNotFoundError:
from pathlib import Path

View File

@@ -1,5 +1,3 @@
from typing import Any
from ..types import (
Anime,
AnimeEpisodeInfo,
@@ -87,13 +85,16 @@ def map_to_anime_result(
def map_to_server(
episode: AnimeEpisodeInfo, translation_type: Any, quality: Any, stream_link: Any
episode: AnimeEpisodeInfo,
translation_type: str,
stream_links: list[tuple[str, str]],
) -> Server:
links = [
EpisodeStream(
link=stream_link,
quality=quality,
link=link[1],
quality=link[0] if link[0] in ["360", "480", "720", "1080"] else "1080", # type:ignore
translation_type=translation_type_map[translation_type],
)
for link in stream_links
]
return Server(name="kwik", links=links, episode_title=episode.title)

View File

@@ -131,15 +131,17 @@ class AnimePahe(BaseAnimeProvider):
res_dicts = [extract_attributes(item) for item in resolutionMenuItems]
quality = None
translation_type = None
stream_link = None
stream_links = []
# TODO: better document the scraping process
for res_dict in res_dicts:
# the actual attributes are data attributes in the original html 'prefixed with data-'
embed_url = res_dict["src"]
logger.debug(f"Found embed url: {embed_url}")
data_audio = "dub" if res_dict["audio"] == "eng" else "sub"
if data_audio != params.translation_type:
logger.debug(f"Found {data_audio} but wanted {params.translation_type}")
continue
if not embed_url:
@@ -155,22 +157,26 @@ class AnimePahe(BaseAnimeProvider):
)
embed_response.raise_for_status()
embed_page = embed_response.text
logger.debug("Processing embed page for JS decoding")
decoded_js = process_animepahe_embed_page(embed_page)
if not decoded_js:
logger.error("failed to decode embed page")
continue
logger.debug(f"Decoded JS: {decoded_js[:100]}...")
juicy_stream = JUICY_STREAM_REGEX.search(decoded_js)
if not juicy_stream:
logger.error("failed to find juicy stream")
continue
logger.debug(f"Found juicy stream: {juicy_stream.group(1)}")
juicy_stream = juicy_stream.group(1)
quality = res_dict["resolution"]
logger.debug(f"Found quality: {quality}")
translation_type = data_audio
stream_link = juicy_stream
stream_links.append((quality, juicy_stream))
if translation_type and quality and stream_link:
yield map_to_server(episode, translation_type, quality, stream_link)
if translation_type and stream_links:
yield map_to_server(episode, translation_type, stream_links)
@lru_cache()
def _get_episode_info(

View File

@@ -69,6 +69,9 @@ def test_anime_provider(AnimeProvider: Type[BaseAnimeProvider]):
for i, stream in enumerate(episode_streams):
print(f"{i + 1}: {stream.name}")
stream = episode_streams[int(input("Select your preferred server: ")) - 1]
for i, link in enumerate(stream.links):
print(f"{i + 1}: {link.quality}")
link = stream.links[int(input("Select your preferred quality: ")) - 1]
if executable := shutil.which("mpv"):
cmd = executable
elif executable := shutil.which("xdg-open"):
@@ -84,4 +87,4 @@ def test_anime_provider(AnimeProvider: Type[BaseAnimeProvider]):
"Episode: ",
stream.episode_title if stream.episode_title else episode_number,
)
subprocess.run([cmd, stream.links[0].link])
subprocess.run([cmd, link.link])