v1.9.0: filter-recall (meervoud/vervoeging, ProRail/intercity/veerdienst/buurtbus) + vijf fixes (ETag na parse, WhatsApp-check, paywall JSON, start-guard, dedup op posted_at)

This commit is contained in:
Eddy de Vink 2026-09-10 19:04:05 +02:00
commit 59f927b038
4 changed files with 107 additions and 54 deletions

View file

@ -90,12 +90,12 @@ date_fmt_microseconds = "%Y-%m-%d %H:%M:%S.%f"
def normalize_title(title: str) -> str:
"""Genormaliseerde titel-sleutel voor cross-feed duplicate-detectie.
Stript HTML, lowercaset, vouwt whitespace samen en verwijdert rand-interpunctie,
zodat hetzelfde artikel dat door één uitgever onder een andere URL/feed wordt
gepubliceerd (vrijwel) identieke titels matcht. Bewust exacte matching:
terugkerende koppen ("treinstoring", "staking") met écht andere titels
mogen niet als duplicaat worden weggefilterd."""
text = html.unescape(re.sub(r"<[^>]+>", "", title or ""))
Decodeert eerst HTML-entities en stript dan de tags, lowercaset, vouwt whitespace
samen en verwijdert rand-interpunctie, zodat hetzelfde artikel dat door één
uitgever onder een andere URL/feed wordt gepubliceerd (vrijwel) identieke titels
matcht. Bewust exacte matching: terugkerende koppen ("treinstoring", "staking")
met écht andere titels mogen niet als duplicaat worden weggefilterd."""
text = re.sub(r"<[^>]+>", "", html.unescape(title or ""))
text = re.sub(r"\s+", " ", text)
return text.strip(" \t\n.,;:!?…-–—").lower()
@ -170,15 +170,16 @@ class DBManager:
"""Genormaliseerde titels van entries die sinds `since` daadwerkelijk zijn
gebroadcast (posted=true). Dit is de bron voor cross-feed titel-dedup."""
rows = await self.db.fetch(
"SELECT title FROM entry WHERE posted AND date >= $1", since
"SELECT title FROM entry WHERE posted AND posted_at >= $1", since
)
return {normalize_title(row["title"]) for row in rows if row["title"]}
async def mark_entry_posted(self, feed_id: int, entry_id: str) -> None:
await self.db.execute(
"UPDATE entry SET posted = true WHERE feed_id = $1 AND id = $2",
"UPDATE entry SET posted = true, posted_at = $3 WHERE feed_id = $1 AND id = $2",
feed_id,
entry_id,
datetime.now(timezone.utc),
)
async def add_entries(self, entries: list[Entry], override_feed_id: int | None = None) -> None: