diff --git a/pyproject.toml b/pyproject.toml index bd06807..cb8c75c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "streamrip" -version = "2.0.2" +version = "2.0.3" description = "A fast, all-in-one music ripper for Qobuz, Deezer, Tidal, and SoundCloud" authors = ["nathom "] license = "GPL-3.0-only" diff --git a/streamrip/__init__.py b/streamrip/__init__.py index 5aeed46..ea02de1 100644 --- a/streamrip/__init__.py +++ b/streamrip/__init__.py @@ -2,4 +2,4 @@ from . import converter, db, exceptions, media, metadata from .config import Config __all__ = ["Config", "media", "metadata", "converter", "db", "exceptions"] -__version__ = "2.0.2" +__version__ = "2.0.3" diff --git a/streamrip/config.py b/streamrip/config.py index 7ee2f57..1ed3ce2 100644 --- a/streamrip/config.py +++ b/streamrip/config.py @@ -15,7 +15,7 @@ logger = logging.getLogger("streamrip") APP_DIR = click.get_app_dir("streamrip") os.makedirs(APP_DIR, exist_ok=True) DEFAULT_CONFIG_PATH = os.path.join(APP_DIR, "config.toml") -CURRENT_CONFIG_VERSION = "2.0" +CURRENT_CONFIG_VERSION = "2.0.3" @dataclass(slots=True) @@ -214,6 +214,7 @@ class CliConfig: @dataclass(slots=True) class MiscConfig: version: str + check_for_updates: bool HOME = Path.home() diff --git a/streamrip/config.toml b/streamrip/config.toml index a9aeeb9..cfbf72e 100644 --- a/streamrip/config.toml +++ b/streamrip/config.toml @@ -186,4 +186,6 @@ max_search_results = 100 [misc] # Metadata to identify this config file. Do not change. -version = "2.0" +version = "2.0.3" +# Print a message if a new version of streamrip is available +check_for_updates = true diff --git a/streamrip/rip/cli.py b/streamrip/rip/cli.py index 1e46718..cde7c09 100644 --- a/streamrip/rip/cli.py +++ b/streamrip/rip/cli.py @@ -8,13 +8,15 @@ from functools import wraps from typing import Any import aiofiles +import aiohttp import click from click_help_colors import HelpColorsGroup # type: ignore from rich.logging import RichHandler +from rich.markdown import Markdown from rich.prompt import Confirm from rich.traceback import install -from .. import db +from .. import __version__, db from ..config import DEFAULT_CONFIG_PATH, Config, set_user_defaults from ..console import console from .main import Main @@ -33,7 +35,7 @@ def coro(f): help_headers_color="yellow", help_options_color="green", ) -@click.version_option(version="2.0.2") +@click.version_option(version=__version__) @click.option( "--config-path", default=DEFAULT_CONFIG_PATH, @@ -152,11 +154,30 @@ def rip(ctx, config_path, folder, no_db, quality, codec, no_progress, verbose): async def url(ctx, urls): """Download content from URLs.""" with ctx.obj["config"] as cfg: + cfg: Config + updates = cfg.session.misc.check_for_updates + if updates: + # Run in background + version_coro = asyncio.create_task(latest_streamrip_version()) + else: + version_coro = None + async with Main(cfg) as main: await main.add_all(urls) await main.resolve() await main.rip() + if version_coro is not None: + latest_version, notes = await version_coro + if latest_version != __version__: + console.print( + f"\n[green]A new version of streamrip [cyan]v{latest_version}[/cyan]" + " is available! Run [white][bold]pip3 install streamrip --upgrade[/bold][/white]" + " to update.[/green]\n" + ) + + console.print(Markdown(notes)) + @rip.command() @click.argument( @@ -390,5 +411,22 @@ async def id(ctx, source, media_type, id): await main.rip() +async def latest_streamrip_version() -> tuple[str, str | None]: + async with aiohttp.ClientSession() as s: + async with s.get("https://pypi.org/pypi/streamrip/json") as resp: + data = await resp.json() + version = data["info"]["version"] + + if version == __version__: + return version, None + + async with s.get( + "https://api.github.com/repos/nathom/streamrip/releases/latest" + ) as resp: + json = await resp.json() + notes = json["body"] + return version, notes + + if __name__ == "__main__": rip() diff --git a/tests/silence.flac b/tests/silence.flac index 449ff2e..108c437 100644 Binary files a/tests/silence.flac and b/tests/silence.flac differ diff --git a/tests/test_config.py b/tests/test_config.py index e37623c..2d154c7 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -127,7 +127,7 @@ def test_sample_config_data_fields(sample_config_data): bit_depth=24, lossy_bitrate=320, ), - misc=MiscConfig(version="2.0"), + misc=MiscConfig(version="2.0", check_for_updates=True), _modified=False, ) assert sample_config_data.downloads == test_config.downloads diff --git a/tests/test_config.toml b/tests/test_config.toml index 95e5e91..91e17df 100644 --- a/tests/test_config.toml +++ b/tests/test_config.toml @@ -185,4 +185,5 @@ max_search_results = 100 [misc] # Metadata to identify this config file. Do not change. -version = "2.0" +version = "2.0.3" +check_for_updates = true diff --git a/tests/test_versions.py b/tests/test_versions.py index 1a6fdfe..3a01813 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -24,19 +24,9 @@ def config_version() -> str | None: return m.group(1) -@pytest.fixture -def click_version() -> str | None: - r = re.compile(r'\@click\.version_option\(version="([\d\.]+)"\)') - with open("streamrip/rip/cli.py") as f: - m = r.search(f.read()) - assert m is not None - return m.group(1) - - def test_config_versions_match(config_version): assert config_version == CURRENT_CONFIG_VERSION -def test_streamrip_versions_match(pyproject_version, click_version): - assert pyproject_version == click_version - assert click_version == init_version +def test_streamrip_versions_match(pyproject_version): + assert pyproject_version == init_version