mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-11-10 12:28:27 +00:00
Download to Browser only ever sent the first file of a multi-file release (audiobook chapters, packs): the folder output returned final_paths[0] and /api/localdownload served that one path. The folder output now keeps every final path on the in-memory task (download_paths), and /api/localdownload streams them as one uncompressed ZIP named after the book when there is more than one. The archive is never staged on disk or held in memory, and ZIP64 covers large audiobooks. History still stores only the first path, so a re-download from history after a dismiss or restart serves a single file, as before. Also brings every linter back to green on all files: - pre-commit: bump the ruff hook to v0.17.1 to match uv.lock; ruff-format the Python examples in docs/dev and skills - ruff: fix the remaining issues in skills/shelfmark/download_books.py; format base_handler.py - basedpyright: Optional and attrs errors in databazeknih.py - knip: drop 31 unused exports, reuse ColumnColorHint in colorMaps - oxfmt 0.72: styles.css - direct download: fix the "Welib, mirrors" typo and the test that still expected the pre-OceanofPDF message Fixes #1467
116 lines
4.0 KiB
Python
116 lines
4.0 KiB
Python
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from shelfmark.core import mirrors
|
|
from shelfmark.core.config import config
|
|
from shelfmark.release_sources.direct_download import DirectDownloadSource, SearchUnavailableError
|
|
from shelfmark.release_sources.direct_download import annas_archive as aa
|
|
|
|
|
|
def _fake_config_get(values: dict[str, object]):
|
|
def _get(key: str, default=None, user_id=None):
|
|
del user_id
|
|
return values.get(key, default)
|
|
|
|
return _get
|
|
|
|
|
|
def test_direct_download_source_is_unavailable_when_disabled(monkeypatch):
|
|
|
|
monkeypatch.setattr(config, "get", _fake_config_get({"DIRECT_DOWNLOAD_ENABLED": False}))
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_aa_mirror_configuration", lambda: True)
|
|
|
|
source = DirectDownloadSource()
|
|
|
|
assert source.is_available() is False
|
|
|
|
with pytest.raises(SearchUnavailableError, match="Direct Download is disabled"):
|
|
source.search(SimpleNamespace(), SimpleNamespace())
|
|
|
|
|
|
def test_direct_download_source_is_unavailable_without_aa_mirrors(monkeypatch):
|
|
|
|
monkeypatch.setattr(config, "get", _fake_config_get({"DIRECT_DOWNLOAD_ENABLED": True}))
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_aa_mirror_configuration", lambda: False)
|
|
|
|
source = DirectDownloadSource()
|
|
|
|
assert source.is_available() is False
|
|
|
|
with pytest.raises(SearchUnavailableError, match="not configured"):
|
|
source.get_record("md5-abc")
|
|
|
|
|
|
def test_direct_download_explains_aa_requirement_when_only_zlib_is_configured(monkeypatch):
|
|
monkeypatch.setattr(config, "get", _fake_config_get({"DIRECT_DOWNLOAD_ENABLED": True}))
|
|
monkeypatch.setattr(
|
|
mirrors,
|
|
"_get_config",
|
|
lambda: {"AA_BASE_URL": "auto", "ZLIB_MIRROR_URLS": ["https://z-library.sk"]},
|
|
)
|
|
|
|
assert mirrors.has_zlib_mirror_configuration() is True
|
|
assert mirrors.has_aa_mirror_configuration() is False
|
|
|
|
source = DirectDownloadSource()
|
|
|
|
with pytest.raises(
|
|
SearchUnavailableError,
|
|
match="Anna's Archive or OceanofPDF mirror URL.*only download results found through",
|
|
):
|
|
source.search(SimpleNamespace(), SimpleNamespace())
|
|
|
|
|
|
def test_direct_download_source_is_available_when_enabled_and_configured(monkeypatch):
|
|
|
|
monkeypatch.setattr(config, "get", _fake_config_get({"DIRECT_DOWNLOAD_ENABLED": True}))
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_aa_mirror_configuration", lambda: True)
|
|
|
|
source = DirectDownloadSource()
|
|
|
|
assert source.is_available() is True
|
|
|
|
|
|
def test_get_source_priority_disables_entries_without_required_mirrors(monkeypatch):
|
|
|
|
monkeypatch.setattr(
|
|
config,
|
|
"get",
|
|
_fake_config_get(
|
|
{
|
|
"AA_DONATOR_KEY": "donator-key",
|
|
"FAST_SOURCES_DISPLAY": [
|
|
{"id": "aa-fast", "enabled": True},
|
|
{"id": "libgen", "enabled": True},
|
|
],
|
|
"SOURCE_PRIORITY": [
|
|
{"id": "welib", "enabled": True},
|
|
{"id": "zlib", "enabled": True},
|
|
],
|
|
}
|
|
),
|
|
)
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_aa_mirror_configuration", lambda: False)
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_libgen_mirror_configuration", lambda: True)
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_welib_mirror_configuration", lambda: False)
|
|
monkeypatch.setattr("shelfmark.core.mirrors.has_zlib_mirror_configuration", lambda: True)
|
|
|
|
priority = {item["id"]: item["enabled"] for item in aa._get_source_priority()}
|
|
|
|
assert priority["aa-fast"] is False
|
|
assert priority["libgen"] is True
|
|
assert priority["welib"] is False
|
|
assert priority["zlib"] is True
|
|
|
|
|
|
def test_is_configured_zlib_link_uses_configured_mirror_domains(monkeypatch):
|
|
|
|
monkeypatch.setattr(
|
|
"shelfmark.core.mirrors.get_zlib_cookie_domains",
|
|
lambda: {"custom-zlib.example"},
|
|
)
|
|
|
|
assert aa._is_configured_zlib_link("https://custom-zlib.example/books/example") is True
|
|
assert aa._is_configured_zlib_link("https://other-zlib.example/books/example") is False
|