"""A Facebook download's title when the signed-in read gives only a placeholder. Measured on prod (2026-11-01): every Facebook download since 2026-10-28 is titled "Facebook" — the signed-in read (the owner's cookie) now gives that placeholder and NO description, so the adapter had no post text to fall back on, and the download name copied the placeholder too. A signed-out read of the same reel (yt-dlp 2026.08.19, as on prod) still carries the post's text in its description. """ from app.config import settings from app.downloads import adapters, backfill, pipeline from app.downloads.models import DownloadJob, MediaAsset _URL = "https://www.facebook.com/reel/1860682468422402/" # The measured signed-out read of that reel. _PUBLIC = { "title": "163K reactions · 14K shares | sorry not helping #workhumor #officelife | Work dot exe", "description": "sorry not helping\n\n#workhumor #officelife", "uploader": "Work dot exe", } def _fake_ydl(monkeypatch, outcome): """yt-dlp faked at its `YoutubeDL` boundary: records each read's options, answers `outcome`.""" seen: list[dict] = [] class FakeYDL: def __init__(self, opts): seen.append(opts) def __enter__(self): return self def __exit__(self, *exc): return False def extract_info(self, url, download): return outcome monkeypatch.setattr(backfill.yt_dlp, "YoutubeDL", FakeYDL) return seen def test_a_placeholder_with_nothing_behind_it_takes_the_signed_out_pages_text(monkeypatch): seen = _fake_ydl(monkeypatch, _PUBLIC) fb = adapters.FacebookAdapter() info = backfill.public_title_info({"title": "Facebook", "description": None}, _URL, fb, 7) assert fb.title(info) == "sorry not helping" # One metadata-only read, and signed out: no cookie goes with it. assert len(seen) == 1 assert seen[0]["skip_download"] is True assert not seen[0].get("cookiefile") def test_a_real_title_reads_nothing_more(monkeypatch): seen = _fake_ydl(monkeypatch, _PUBLIC) info = {"title": "Funny Dark Humor Dad Joke!", "description": None} assert backfill.public_title_info(info, _URL, adapters.FacebookAdapter(), 7) is info assert seen == [] def test_a_placeholder_the_signed_out_page_cannot_better_stays(monkeypatch): _fake_ydl(monkeypatch, {"title": "Facebook", "description": None}) fb = adapters.FacebookAdapter() info = backfill.public_title_info({"title": "Facebook", "description": None}, _URL, fb, 7) assert fb.title(info) == "Facebook" def test_another_source_is_never_read_again(monkeypatch): seen = _fake_ydl(monkeypatch, _PUBLIC) info = {"title": "Video", "description": None} assert backfill.public_title_info(info, _URL, adapters.SourceAdapter(), 7) is info assert seen == [] def test_the_backfill_retitles_a_placeholder_download_and_the_names_that_repeated_it( db, make_user, monkeypatch ): _fake_ydl(monkeypatch, _PUBLIC) owner, other = make_user(), make_user() asset = MediaAsset( source_kind="url", source_ref=_URL, format_sig="fb", status="ready", rel_path="facebook/x.mp4", poster_path="facebook/x.jpg", uploader_url="https://www.facebook.com/1", title="Facebook", ref_count=2, ) db.add(asset) db.flush() copied = DownloadJob( user_id=owner.id, asset_id=asset.id, source_kind="url", source_ref=_URL, status="done", queue_pos=0, profile_snapshot={}, display_name="Facebook", ) renamed = DownloadJob( user_id=other.id, asset_id=asset.id, source_kind="url", source_ref=_URL, status="done", queue_pos=0, profile_snapshot={}, display_name="Office jokes", ) db.add_all([copied, renamed]) db.commit() assert backfill.run()["retitled"] == 1 db.expire_all() assert db.get(MediaAsset, asset.id).title == "sorry not helping" assert db.get(DownloadJob, copied.id).display_name == "sorry not helping" assert db.get(DownloadJob, renamed.id).display_name == "Office jokes" # Run again: nothing left to retitle, and no page read for it. assert backfill.run()["retitled"] == 0 def test_a_download_titled_facebook_is_named_from_the_signed_out_page( db, make_user, monkeypatch, tmp_path ): # The whole download path with yt-dlp and the media tools faked: the signed-in read gives only # the placeholder, and the file and the download's name get the post's text. _fake_ydl(monkeypatch, _PUBLIC) monkeypatch.setattr(settings, "files_root", str(tmp_path)) monkeypatch.setattr(pipeline.urlguard, "check_url", lambda url: None) monkeypatch.setattr(pipeline, "_ensure_phone_safe", lambda _j, produced, *_a: produced) monkeypatch.setattr( pipeline.probe, "resolve_media_facts", lambda produced, info: ("h264", "aac", 720, 1280, 9) ) monkeypatch.setattr(pipeline.editmod, "thumbnail_to_jpg", lambda *a: None) monkeypatch.setattr(pipeline.editmod, "ensure_poster", lambda *a: None) owner = make_user() asset = MediaAsset( source_kind="url", source_ref=_URL, format_sig="fb", status="downloading", ref_count=1 ) db.add(asset) db.flush() job = DownloadJob( user_id=owner.id, asset_id=asset.id, source_kind="url", source_ref=_URL, status="running", queue_pos=0, profile_snapshot={}, ) db.add(job) db.commit() def signed_in_read(job_id, asset_id, url, spec, staging, adapter, **kw): f = staging / "1860682468422402.mp4" f.write_bytes(b"v" * 100) return { "id": "1860682468422402", "title": "Facebook", "uploader": "Work dot exe", "requested_downloads": [{"filepath": str(f)}], } monkeypatch.setattr(pipeline, "_extract_with_fallback", signed_in_read) pipeline._download(job.id, asset.id, "url", _URL, {}, owner.id) db.expire_all() assert db.get(DownloadJob, job.id).status == "done" assert db.get(MediaAsset, asset.id).title == "sorry not helping" assert db.get(DownloadJob, job.id).display_name == "sorry not helping"