mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-14 07:59:40 +00:00
fix(ingest): rewrite only the host when normalizing a tweet URL for oEmbed
_fetch_tweet did url.replace("x.com", "twitter.com") over the whole URL,
so "x.com" in the path or query was rewritten too (a ?next= link, or a
handle like dropbox.com_fan becoming dropbotwitter.com_fan), and an
uppercase X.COM host was missed. Match and rewrite the host only, the
same way _detect_url_type classifies it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 3ec4fdcfca)
This commit is contained in:
1 parent
4c21b15e9b
commit
c2fb556919
2 files changed
+46
-2
No files matched your search
+9
-2
@@ -109,8 +109,15 @@ def _html_to_markdown(html: str, url: str) -> str:
|
||||
|
||||
def _fetch_tweet(url: str, author: str | None, contributor: str | None) -> tuple[str, str]:
|
||||
"""Fetch a tweet URL. Returns (content, filename)."""
|
||||
# Normalize to twitter.com for oEmbed
|
||||
oembed_url = url.replace("x.com", "twitter.com")
|
||||
# Normalize to twitter.com for oEmbed. Rewrite the host only: a plain
|
||||
# text replace also rewrote "x.com" wherever it appeared in the path or query.
|
||||
parts = urllib.parse.urlsplit(url)
|
||||
host = (parts.hostname or "").rstrip(".")
|
||||
if _host_is(host, "x.com"):
|
||||
host = host[: -len("x.com")] + "twitter.com"
|
||||
netloc = f"{host}:{parts.port}" if parts.port else host
|
||||
parts = parts._replace(netloc=netloc)
|
||||
oembed_url = urllib.parse.urlunsplit(parts)
|
||||
oembed_api = f"https://publish.twitter.com/oembed?url={urllib.parse.quote(oembed_url)}&omit_script=true"
|
||||
try:
|
||||
data = json.loads(safe_fetch_text(oembed_api))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Tests for how graphify.ingest classifies and routes a URL."""
|
||||
from __future__ import annotations
|
||||
|
||||
import urllib.parse
|
||||
|
||||
import pytest
|
||||
|
||||
import graphify.ingest as ingest_mod
|
||||
@@ -66,3 +68,38 @@ def test_a_dropbox_pdf_is_downloaded_not_saved_as_a_tweet_stub(tmp_path, monkeyp
|
||||
assert fetched == [url]
|
||||
assert out.suffix == ".pdf"
|
||||
assert out.read_bytes() == b"%PDF-1.7 test"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("url", "expected"),
|
||||
[
|
||||
("https://x.com/user/status/1", "https://twitter.com/user/status/1"),
|
||||
("https://mobile.x.com/user/status/1", "https://mobile.twitter.com/user/status/1"),
|
||||
("https://X.COM/user/status/1", "https://twitter.com/user/status/1"),
|
||||
# "x.com" outside the host must survive untouched.
|
||||
(
|
||||
"https://x.com/user/status/1?next=https://x.com/home",
|
||||
"https://twitter.com/user/status/1?next=https://x.com/home",
|
||||
),
|
||||
(
|
||||
"https://twitter.com/dropbox.com_fan/status/1",
|
||||
"https://twitter.com/dropbox.com_fan/status/1",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_tweet_oembed_rewrites_only_the_host(url, expected, monkeypatch):
|
||||
"""The x.com -> twitter.com rewrite for oEmbed was a replace over the whole
|
||||
URL, so "x.com" inside the path or query (e.g. a dropbox.com handle, a
|
||||
?next= link) was rewritten too, sending oEmbed a different URL."""
|
||||
requested = []
|
||||
|
||||
def fake_fetch_text(u):
|
||||
requested.append(u)
|
||||
return '{"html": "<p>hi</p>", "author_name": "someone"}'
|
||||
|
||||
monkeypatch.setattr(ingest_mod, "safe_fetch_text", fake_fetch_text)
|
||||
|
||||
ingest_mod._fetch_tweet(url, None, None)
|
||||
|
||||
query = urllib.parse.parse_qs(urllib.parse.urlsplit(requested[0]).query)
|
||||
assert query["url"] == [expected]
|
||||
Reference in new issue
Block a user