"""Thread root matching via ``e``/``E``/``a``/``A``/``q`` (Jumble-style).""" import tempfile from pathlib import Path from typing import Any, cast from imwald.core.database import Database, thread_root_link_targets from imwald.core.nostr_crypto import build_signed_event, pubkey_hex_from_secret def _sk() -> bytes: return bytes.fromhex("3501454135014541350145413501453fefb02227e449e57cf4d3a3ce05378683") def test_thread_root_link_targets_kind1() -> None: root = cast(dict[str, Any], {"id": "a" * 64, "kind": 1, "pubkey": "b" * 64, "tags": []}) assert thread_root_link_targets(root) == ["a" * 64] def test_thread_root_link_targets_addressable_adds_a_coordinate() -> None: pk = "c" * 64 root = cast( dict[str, Any], {"id": "d" * 64, "kind": 30023, "pubkey": pk, "tags": [["d", "slug-x"]]}, ) t = thread_root_link_targets(root) assert "d" * 64 in t assert f"30023:{pk}:slug-x" in t def test_list_replies_to_matches_q_tag() -> None: sk = _sk() root = build_signed_event(sk, created_at=1, kind=1, tags=[], content="root") rid = root["id"] rep = build_signed_event( sk, created_at=2, kind=1, tags=[["q", rid]], content="quote", ) with tempfile.TemporaryDirectory() as td: db = Database(Path(td) / "t.sqlite") db.connect() db.upsert_event(root) db.upsert_event(rep) got = db.list_replies_to(root, limit=20) assert len(got) == 1 and got[0]["id"] == rep["id"] def test_list_replies_to_nested_reply_tags_only_parent() -> None: """Transitive closure: reply-to-reply often tags only the parent id, not the root.""" sk = _sk() root = build_signed_event(sk, created_at=1, kind=1, tags=[], content="root") rid = root["id"] direct = build_signed_event( sk, created_at=2, kind=1, tags=[["e", rid, "", "root"]], content="direct", ) did = direct["id"] nested = build_signed_event( sk, created_at=3, kind=1, tags=[["e", did, "", "reply"]], content="nested", ) with tempfile.TemporaryDirectory() as td: db = Database(Path(td) / "t3.sqlite") db.connect() db.upsert_event(root) db.upsert_event(direct) db.upsert_event(nested) got = db.list_replies_to(root, limit=20) ids = {str(x["id"]) for x in got} assert ids == {did, nested["id"]} def test_list_replies_to_matches_uppercase_e() -> None: sk = _sk() root = build_signed_event(sk, created_at=1, kind=1, tags=[], content="root") rid = root["id"] rep = build_signed_event( sk, created_at=2, kind=1111, tags=[["E", rid, "", "1" * 64], ["p", pubkey_hex_from_secret(sk)]], content="c", ) with tempfile.TemporaryDirectory() as td: db = Database(Path(td) / "t2.sqlite") db.connect() db.upsert_event(root) db.upsert_event(rep) got = db.list_replies_to(root, limit=20) assert len(got) == 1 and got[0]["id"] == rep["id"]