chore: viu media is better

This commit is contained in:
Benexl
2025-08-18 01:07:36 +03:00
parent 43be7a52cf
commit eddaad64e7
32 changed files with 112 additions and 112 deletions

View File

@@ -20,8 +20,8 @@
</p>
<div align="center">
[![PyPI - Version](https://img.shields.io/pypi/v/viu_cli)](https://pypi.org/project/viu_cli/)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/viu_cli)](https://pypi.org/project/viu_cli/)
[![PyPI - Version](https://img.shields.io/pypi/v/viu-media)](https://pypi.org/project/viu-media/)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/viu-media)](https://pypi.org/project/viu-media/)
[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Benexl/Viu/test.yml?label=Tests)](https://github.com/Benexl/Viu/actions)
[![Discord](https://img.shields.io/discord/1250887070906323096?label=Discord&logo=discord)](https://discord.gg/HBEmAwvbHV)
[![GitHub Issues](https://img.shields.io/github/issues/Benexl/Viu)](https://github.com/Benexl/Viu/issues)
@@ -69,13 +69,13 @@ The best way to install Viu is with [**uv**](https://github.com/astral-sh/uv), a
```bash
# Install with all optional features for the full experience
uv tool install "viu_cli[standard]"
uv tool install "viu-media[standard]"
# Or, pick and choose the extras you need:
uv tool install viu_cli # Core functionality only
uv tool install "viu_cli[download]" # For advanced downloading with yt-dlp
uv tool install "viu_cli[discord]" # For Discord Rich Presence
uv tool install "viu_cli[notifications]" # For desktop notifications
uv tool install viu-media # Core functionality only
uv tool install "viu-media[download]" # For advanced downloading with yt-dlp
uv tool install "viu-media[discord]" # For Discord Rich Presence
uv tool install "viu-media[notifications]" # For desktop notifications
```
### Other Installation Methods
@@ -100,12 +100,12 @@ uv tool install "viu_cli[notifications]" # For desktop notifications
#### Using pipx (for isolated environments)
```bash
pipx install "viu_cli[standard]"
pipx install "viu-media[standard]"
```
#### Using pip
```bash
pip install "viu_cli[standard]"
pip install "viu-media[standard]"
```
</details>

View File

@@ -1,5 +1,5 @@
[project]
name = "viu_cli"
name = "viu-media"
version = "3.2.6"
description = "A browser anime site experience from the terminal"
license = "UNLICENSE"
@@ -14,7 +14,7 @@ dependencies = [
]
[project.scripts]
viu = 'viu_cli:Cli'
viu = 'viu_media:Cli'
[project.optional-dependencies]
standard = [

2
viu Executable file → Normal file
View File

@@ -3,4 +3,4 @@ provider_type=$1
provider_name=$2
[ -z "$provider_type" ] && echo "Please specify provider type" && exit
[ -z "$provider_name" ] && echo "Please specify provider type" && exit
uv run python -m viu_cli.libs.provider.${provider_type}.${provider_name}.provider
uv run python -m viu_media.libs.provider.${provider_type}.${provider_name}.provider

View File

@@ -44,7 +44,7 @@ commands = {
@click.group(
cls=LazyGroup,
root="viu_cli.cli.commands",
root="viu_media.cli.commands",
invoke_without_command=True,
lazy_subcommands=commands,
context_settings=dict(auto_envvar_prefix=PROJECT_NAME),

View File

@@ -18,7 +18,7 @@ commands = {
@click.group(
cls=LazyGroup,
name="anilist",
root="viu_cli.cli.commands.anilist.commands",
root="viu_media.cli.commands.anilist.commands",
invoke_without_command=True,
help="A beautiful interface that gives you access to a commplete streaming experience",
short_help="Access all streaming options",

View File

@@ -1,10 +1,10 @@
from typing import TYPE_CHECKING, Dict, List
import click
from viu_cli.cli.utils.completion import anime_titles_shell_complete
from viu_cli.core.config import AppConfig
from viu_cli.core.exceptions import ViuError
from viu_cli.libs.media_api.types import (
from viu_media.cli.utils.completion import anime_titles_shell_complete
from viu_media.core.config import AppConfig
from viu_media.core.exceptions import ViuError
from viu_media.libs.media_api.types import (
MediaFormat,
MediaGenre,
MediaItem,
@@ -112,15 +112,15 @@ if TYPE_CHECKING:
)
@click.pass_obj
def download(config: AppConfig, **options: "Unpack[DownloadOptions]"):
from viu_cli.cli.service.download.service import DownloadService
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.cli.service.watch_history import WatchHistoryService
from viu_cli.cli.utils.parser import parse_episode_range
from viu_cli.libs.media_api.api import create_api_client
from viu_cli.libs.media_api.params import MediaSearchParams
from viu_cli.libs.provider.anime.provider import create_provider
from viu_cli.libs.selectors import create_selector
from viu_media.cli.service.download.service import DownloadService
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.cli.service.watch_history import WatchHistoryService
from viu_media.cli.utils.parser import parse_episode_range
from viu_media.libs.media_api.api import create_api_client
from viu_media.libs.media_api.params import MediaSearchParams
from viu_media.libs.provider.anime.provider import create_provider
from viu_media.libs.selectors import create_selector
from rich.progress import Progress
feedback = FeedbackService(config)

View File

@@ -1,5 +1,5 @@
import click
from viu_cli.core.config import AppConfig
from viu_media.core.config import AppConfig
from rich.console import Console
from rich.table import Table
@@ -11,8 +11,8 @@ def notifications(config: AppConfig):
Displays unread notifications from AniList.
Running this command will also mark the notifications as read on the AniList website.
"""
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.libs.media_api.api import create_api_client
from viu_media.cli.service.feedback import FeedbackService
from viu_media.libs.media_api.api import create_api_client
from ....service.auth import AuthService

View File

@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
import click
if TYPE_CHECKING:
from viu_cli.core.config import AppConfig
from viu_media.core.config import AppConfig
@click.command(help="Print out your anilist stats")

View File

@@ -11,7 +11,7 @@ if TYPE_CHECKING:
from pathlib import Path
from typing import TypedDict
from viu_cli.cli.service.feedback.service import FeedbackService
from viu_media.cli.service.feedback.service import FeedbackService
from typing_extensions import Unpack
from ...libs.provider.anime.base import BaseAnimeProvider
@@ -103,7 +103,7 @@ if TYPE_CHECKING:
)
@click.pass_obj
def download(config: AppConfig, **options: "Unpack[Options]"):
from viu_cli.cli.service.feedback.service import FeedbackService
from viu_media.cli.service.feedback.service import FeedbackService
from ...core.exceptions import ViuError
from ...libs.provider.anime.params import (

View File

@@ -1,7 +1,7 @@
import click
from viu_cli.core.config import AppConfig
from viu_cli.core.exceptions import ViuError
from viu_cli.libs.media_api.types import (
from viu_media.core.config import AppConfig
from viu_media.core.exceptions import ViuError
from viu_media.libs.media_api.types import (
MediaFormat,
MediaGenre,
MediaItem,
@@ -76,14 +76,14 @@ def queue(config: AppConfig, **options):
and queue the specified episode range for background download.
The background worker should be running to process the queue.
"""
from viu_cli.cli.service.download.service import DownloadService
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.cli.utils.parser import parse_episode_range
from viu_cli.libs.media_api.params import MediaSearchParams
from viu_cli.libs.media_api.api import create_api_client
from viu_cli.libs.provider.anime.provider import create_provider
from viu_cli.libs.selectors import create_selector
from viu_media.cli.service.download.service import DownloadService
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.cli.utils.parser import parse_episode_range
from viu_media.libs.media_api.params import MediaSearchParams
from viu_media.libs.media_api.api import create_api_client
from viu_media.libs.provider.anime.provider import create_provider
from viu_media.libs.selectors import create_selector
from rich.progress import Progress
feedback = FeedbackService(config)

View File

@@ -13,7 +13,7 @@ commands = {
@click.group(
cls=LazyGroup,
name="queue",
root="viu_cli.cli.commands.queue.commands",
root="viu_media.cli.commands.queue.commands",
invoke_without_command=False,
help="Manage the download queue (add, list, resume, clear).",
short_help="Manage the download queue.",

View File

@@ -1,7 +1,7 @@
import click
from viu_cli.core.config import AppConfig
from viu_cli.core.exceptions import ViuError
from viu_cli.libs.media_api.types import (
from viu_media.core.config import AppConfig
from viu_media.core.exceptions import ViuError
from viu_media.libs.media_api.types import (
MediaFormat,
MediaGenre,
MediaItem,
@@ -70,14 +70,14 @@ from viu_cli.libs.media_api.types import (
)
@click.pass_obj
def add(config: AppConfig, **options):
from viu_cli.cli.service.download import DownloadService
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.cli.utils.parser import parse_episode_range
from viu_cli.libs.media_api.api import create_api_client
from viu_cli.libs.media_api.params import MediaSearchParams
from viu_cli.libs.provider.anime.provider import create_provider
from viu_cli.libs.selectors import create_selector
from viu_media.cli.service.download import DownloadService
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.cli.utils.parser import parse_episode_range
from viu_media.libs.media_api.api import create_api_client
from viu_media.libs.media_api.params import MediaSearchParams
from viu_media.libs.provider.anime.provider import create_provider
from viu_media.libs.selectors import create_selector
from rich.progress import Progress
feedback = FeedbackService(config)
@@ -149,7 +149,7 @@ def add(config: AppConfig, **options):
}
preview_command = None
if config.general.preview != "none":
from viu_cli.cli.utils.preview import create_preview_context
from viu_media.cli.utils.preview import create_preview_context
with create_preview_context() as preview_ctx:
preview_command = preview_ctx.get_anime_preview(

View File

@@ -1,5 +1,5 @@
import click
from viu_cli.core.config import AppConfig
from viu_media.core.config import AppConfig
@click.command(
@@ -9,9 +9,9 @@ from viu_cli.core.config import AppConfig
@click.option("--force", is_flag=True, help="Do not prompt for confirmation.")
@click.pass_obj
def clear_cmd(config: AppConfig, force: bool):
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.cli.service.registry.models import DownloadStatus
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.cli.service.registry.models import DownloadStatus
feedback = FeedbackService(config)
registry = MediaRegistryService(config.general.media_api, config.media_registry)

View File

@@ -1,5 +1,5 @@
import click
from viu_cli.core.config import AppConfig
from viu_media.core.config import AppConfig
@click.command(name="list", help="List items in the download queue and their statuses.")
@@ -10,9 +10,9 @@ from viu_cli.core.config import AppConfig
@click.option("--detailed", is_flag=True)
@click.pass_obj
def list_cmd(config: AppConfig, status: str | None, detailed: bool | None):
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.cli.service.registry.models import DownloadStatus
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.cli.service.registry.models import DownloadStatus
feedback = FeedbackService(config)
registry = MediaRegistryService(config.general.media_api, config.media_registry)

View File

@@ -1,5 +1,5 @@
import click
from viu_cli.core.config import AppConfig
from viu_media.core.config import AppConfig
@click.command(
@@ -7,11 +7,11 @@ from viu_cli.core.config import AppConfig
)
@click.pass_obj
def resume(config: AppConfig):
from viu_cli.cli.service.download.service import DownloadService
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.libs.media_api.api import create_api_client
from viu_cli.libs.provider.anime.provider import create_provider
from viu_media.cli.service.download.service import DownloadService
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.libs.media_api.api import create_api_client
from viu_media.libs.provider.anime.provider import create_provider
feedback = FeedbackService(config)
media_api = create_api_client(config.general.media_api, config)

View File

@@ -19,7 +19,7 @@ commands = {
@click.group(
cls=LazyGroup,
name="registry",
root="viu_cli.cli.commands.registry.commands",
root="viu_media.cli.commands.registry.commands",
invoke_without_command=True,
help="Manage your local media registry - sync, search, backup and maintain your anime database",
short_help="Local media registry management",

View File

@@ -3,8 +3,8 @@ Registry sync command - synchronize local registry with remote media API
"""
import click
from viu_cli.cli.service.feedback.service import FeedbackService
from viu_cli.cli.service.registry.service import MediaRegistryService
from viu_media.cli.service.feedback.service import FeedbackService
from viu_media.cli.service.registry.service import MediaRegistryService
from .....core.config import AppConfig

View File

@@ -10,7 +10,7 @@ from . import examples
if TYPE_CHECKING:
from typing import TypedDict
from viu_cli.cli.service.feedback.service import FeedbackService
from viu_media.cli.service.feedback.service import FeedbackService
from typing_extensions import Unpack
from ...libs.provider.anime.base import BaseAnimeProvider
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
)
@click.pass_obj
def search(config: AppConfig, **options: "Unpack[Options]"):
from viu_cli.cli.service.feedback.service import FeedbackService
from viu_media.cli.service.feedback.service import FeedbackService
from ...core.exceptions import ViuError
from ...libs.provider.anime.params import (
@@ -134,7 +134,7 @@ def stream_anime(
episode: str,
anime_title: str,
):
from viu_cli.cli.service.player.service import PlayerService
from viu_media.cli.service.player.service import PlayerService
from ...libs.player.params import PlayerParams
from ...libs.provider.anime.params import EpisodeStreamsParams

View File

@@ -1,5 +1,5 @@
import click
from viu_cli.core.config import AppConfig
from viu_media.core.config import AppConfig
@click.command(help="Run the background worker for notifications and downloads.")
@@ -11,14 +11,14 @@ def worker(config: AppConfig):
process any queued downloads. It's recommended to run this in the
background (e.g., 'viu worker &') or as a system service.
"""
from viu_cli.cli.service.auth import AuthService
from viu_cli.cli.service.download.service import DownloadService
from viu_cli.cli.service.feedback import FeedbackService
from viu_cli.cli.service.notification.service import NotificationService
from viu_cli.cli.service.registry.service import MediaRegistryService
from viu_cli.cli.service.worker.service import BackgroundWorkerService
from viu_cli.libs.media_api.api import create_api_client
from viu_cli.libs.provider.anime.provider import create_provider
from viu_media.cli.service.auth import AuthService
from viu_media.cli.service.download.service import DownloadService
from viu_media.cli.service.feedback import FeedbackService
from viu_media.cli.service.notification.service import NotificationService
from viu_media.cli.service.registry.service import MediaRegistryService
from viu_media.cli.service.worker.service import BackgroundWorkerService
from viu_media.libs.media_api.api import create_api_client
from viu_media.libs.provider.anime.provider import create_provider
feedback = FeedbackService(config)
if not config.worker.enabled:

View File

@@ -6,7 +6,7 @@ from ...state import InternalDirective, State
@session.menu
def download_episodes(ctx: Context, state: State) -> State | InternalDirective:
"""Menu to select and download episodes synchronously."""
from viu_cli.cli.utils.search import find_best_match_title
from viu_media.cli.utils.search import find_best_match_title
from .....core.utils.normalizer import normalize_title
from ....service.download.service import DownloadService

View File

@@ -6,7 +6,7 @@ from ...state import InternalDirective, MenuName, ProviderState, State
@session.menu
def provider_search(ctx: Context, state: State) -> State | InternalDirective:
from viu_cli.cli.utils.search import find_best_match_title
from viu_media.cli.utils.search import find_best_match_title
from .....core.utils.normalizer import normalize_title, update_user_normalizer_json

View File

@@ -317,7 +317,7 @@ class Session:
if filename.endswith(".py") and not filename.startswith("__"):
module_name = filename[:-3]
full_module_name = (
f"viu_cli.cli.interactive.menu.{package_name}.{module_name}"
f"viu_media.cli.interactive.menu.{package_name}.{module_name}"
)
file_path = package_path / filename

View File

@@ -2,7 +2,7 @@ import logging
from pathlib import Path
from typing import TYPE_CHECKING, List
from viu_cli.cli.utils.search import find_best_match_title
from viu_media.cli.utils.search import find_best_match_title
from ....core.config.model import AppConfig
from ....core.constants import APP_CACHE_DIR

View File

@@ -3,12 +3,12 @@ from pathlib import Path
from typing import Optional
import httpx
from viu_cli.cli.service.registry import MediaRegistryService
from viu_cli.cli.service.registry.models import DownloadStatus
from viu_cli.core.config.model import AppConfig
from viu_cli.core.constants import APP_CACHE_DIR
from viu_cli.libs.media_api.base import BaseApiClient
from viu_cli.libs.media_api.types import MediaItem, Notification
from viu_media.cli.service.registry import MediaRegistryService
from viu_media.cli.service.registry.models import DownloadStatus
from viu_media.core.config.model import AppConfig
from viu_media.core.constants import APP_CACHE_DIR
from viu_media.libs.media_api.base import BaseApiClient
from viu_media.libs.media_api.types import MediaItem, Notification
try:
from plyer import notification as plyer_notification

View File

@@ -4,9 +4,9 @@ import threading
import time
from typing import Optional
from viu_cli.cli.service.download.service import DownloadService
from viu_cli.cli.service.notification.service import NotificationService
from viu_cli.core.config.model import WorkerConfig
from viu_media.cli.service.download.service import DownloadService
from viu_media.cli.service.notification.service import NotificationService
from viu_media.core.config.model import WorkerConfig
logger = logging.getLogger(__name__)

View File

@@ -1,9 +1,9 @@
"""Search functionality."""
from viu_cli.core.utils.fuzzy import fuzz
from viu_cli.core.utils.normalizer import normalize_title
from viu_cli.libs.provider.anime.types import SearchResult, ProviderName
from viu_cli.libs.media_api.types import MediaItem
from viu_media.core.utils.fuzzy import fuzz
from viu_media.core.utils.normalizer import normalize_title
from viu_media.libs.provider.anime.types import SearchResult, ProviderName
from viu_media.libs.media_api.types import MediaItem
def find_best_match_title(

View File

@@ -10,7 +10,7 @@ APP_NAME = os.environ.get(f"{PROJECT_NAME}_APP_NAME", PROJECT_NAME_LOWER)
USER_NAME = os.environ.get("USERNAME", "User")
__version__ = metadata.version("viu_cli")
__version__ = metadata.version("viu_media")
AUTHOR = "Benexl"
GIT_REPO = "github.com"

View File

@@ -7,7 +7,7 @@ otherwise falls back to a pure Python implementation with the same API.
Usage:
Basic usage with the convenience functions:
>>> from viu_cli.core.utils.fuzzy import fuzz
>>> from viu_media.core.utils.fuzzy import fuzz
>>> fuzz.ratio("hello world", "hello")
62
>>> fuzz.partial_ratio("hello world", "hello")
@@ -15,7 +15,7 @@ Usage:
Using the FuzzyMatcher class directly:
>>> from viu_cli.core.utils.fuzzy import FuzzyMatcher
>>> from viu_media.core.utils.fuzzy import FuzzyMatcher
>>> matcher = FuzzyMatcher()
>>> matcher.backend
'thefuzz' # or 'pure_python' if thefuzz is not available
@@ -24,7 +24,7 @@ Usage:
For drop-in replacement of thefuzz.fuzz:
>>> from viu_cli.core.utils.fuzzy import ratio, partial_ratio
>>> from viu_media.core.utils.fuzzy import ratio, partial_ratio
>>> ratio("test", "best")
75
"""

View File

@@ -16,8 +16,8 @@ logger = logging.getLogger(__name__)
# Map the client name to its import path AND the config section it needs.
API_CLIENTS = {
"anilist": ("viu_cli.libs.media_api.anilist.api.AniListApi", "anilist"),
"jikan": ("viu_cli.libs.media_api.jikan.api.JikanApi", "jikan"), # For the future
"anilist": ("viu_media.libs.media_api.anilist.api.AniListApi", "anilist"),
"jikan": ("viu_media.libs.media_api.jikan.api.JikanApi", "jikan"), # For the future
}

View File

@@ -25,7 +25,7 @@ def test_media_api(api_client: BaseApiClient):
api_client: An instance of AniListApi to test
Usage:
Run this module directly: python -m viu_cli.libs.media_api.anilist.api
Run this module directly: python -m viu_media.libs.media_api.anilist.api
Or import and call: test_media_api(AniListApi(config, client))
"""
from ....core.constants import APP_ASCII_ART

View File

@@ -45,7 +45,7 @@ class AnimeProviderFactory:
module_name, class_name = import_path.split(".", 1)
# Construct the full package path for dynamic import
package_path = f"viu_cli.libs.provider.anime.{provider_name.value.lower()}"
package_path = f"viu_media.libs.provider.anime.{provider_name.value.lower()}"
try:
provider_module = importlib.import_module(f".{module_name}", package_path)

View File

@@ -39,7 +39,7 @@ class MangaProvider:
def lazyload_provider(self, provider):
"""updates the current provider being used"""
_, anime_provider_cls_name = manga_sources[provider].split(".", 1)
package = f"viu_cli.libs.manga_provider.{provider}"
package = f"viu_media.libs.manga_provider.{provider}"
provider_api = importlib.import_module(".api", package)
manga_provider = getattr(provider_api, anime_provider_cls_name)
self.manga_provider = manga_provider()