aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_tmdb_language_gate.py
blob: cd43fef4412435be8324e2cb14bd281af76924c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""
The node does not query TMDB until a language is configured (§9.7).

Browsing the Videos tab is what triggers the lazy `media_meta_req`, and it
routinely happens before the operator has opened the settings and chosen a
language. Querying then would fetch the whole library in TMDB's English default
and throw it away the moment a language was picked — double the requests against
TMDB's rate limit, for a result nobody asked for (found live 2026-09-26: a whole
library indexed in English before "Français" was chosen). So an unset language
answers confidence 0 and makes no call; a set language fetches once, in it.
"""

import pytest
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from meshbay_common.protocol import IndexEntry
from meshbay_node.indexer.group_index import GroupIndex
from meshbay_node.media_cache import MediaCache
from meshbay_node.transport.webrtc_server import WebRTCPeerSession

pytestmark = pytest.mark.asyncio


class CountingTmdbClient:
    def __init__(self):
        self.calls = 0

    async def search_movie(self, title, year=None):
        self.calls += 1
        return {"id": 42, "title": title, "release_date": "2001-01-01"}, 1.0

    async def search_tv(self, title, year=None):
        self.calls += 1
        return {"id": 43, "name": title, "first_air_date": "2001-01-01"}, 1.0

    async def movie_details(self, tmdb_id, language=None):
        self.calls += 1
        return {"title": "A Film", "genres": [{"name": "Drama"}],
                "poster_path": "/p.jpg", "overview": "x"}

    async def movie_credits(self, tmdb_id):
        return {"cast": [], "crew": []}

    async def fetch_image(self, url):
        return b"img"

    @staticmethod
    def poster_url(path):
        return f"https://image.tmdb.org/t/p/w500{path}"


@pytest.fixture
async def media_cache(tmp_path):
    c = MediaCache(db_path=tmp_path / "media_cache.db")
    await c.open()
    yield c
    await c.close()


def _session(media_cache, tmdb_client, language):
    index = GroupIndex(group_id="g" * 32, sk_node=Ed25519PrivateKey.generate())
    entry = IndexEntry(id="f1", name="Some.Film.2001.mkv", path="movies", size=1,
                       type="video", added_at=0, display_title="Some Film")
    index.add_entry(entry)
    session = WebRTCPeerSession.__new__(WebRTCPeerSession)
    session._ctx = {
        "index": index,
        "media_cache": media_cache,
        "tmdb_client": tmdb_client,
        "tmdb_enabled": True,
        "daemon_state": {"tmdb_language": language},
    }
    session._group_id = None
    session.sent = []
    session._send = session.sent.append
    return session, entry


async def test_no_language_makes_no_tmdb_call(media_cache):
    client = CountingTmdbClient()
    session, entry = _session(media_cache, client, language="")

    await session._do_media_meta_request({"file_id": entry.id})

    assert client.calls == 0
    assert session.sent[-1]["confidence"] == 0
    # Nothing cached, so a later request in a real language still starts clean.
    assert await media_cache.get_file_tmdb(entry.id) is None


async def test_a_configured_language_fetches(media_cache):
    client = CountingTmdbClient()
    session, entry = _session(media_cache, client, language="fr-FR")

    await session._do_media_meta_request({"file_id": entry.id})

    assert client.calls > 0
    assert session.sent[-1].get("tmdb_id") == "42"