diff --git a/base-config.yaml b/base-config.yaml index f556482..2111378 100644 --- a/base-config.yaml +++ b/base-config.yaml @@ -20,7 +20,7 @@ exclude_paywalled: true # Global match filter (whitelist): applies to ALL feeds in this instance. # A post is ONLY sent when the regex matches the title OR the (HTML-stripped) summary. # Set it live with `!rss set-filter `. Empty = send everything. -match_filter: "(?i)\\b(?:ns|arriva|qbuzz|connexxion|cxx|transdev|keolis|ret|gvb|ebs|htm|syntus|breng|u-ov|allgo|flixbus|blauwnet|r-net|valleilijn|waterbus|eurostar|thalys|randstadrail|gvu|ov)\\b|\\b(?:bus|tram|metro)(?:halte|haltes|lijn|lijnen|station|stations|verkeer|net|staking)?\\b|\\btrein(?:en|verkeer|stel(?:len)?|staking|ongeluk|reizigers?|station|stations)?\\b|\\b(?:spoorweg|spoorbaan|spoorlijn|spoorverkeer|spoorwegovergang|spoorstoring|perron|perrons|overweg|overwegen|seinstoring|wisselstoring|sein|ontsporing|ontspoord|spoorstaking)\\b|\\b(?:openbaar vervoer|dienstregeling|reizigers?|inchecken|uitchecken|pont|ponten|lightrail|pendelbus|shuttlebus)\\b|\\b(?:ov-chipkaart|chipkaart|ovpay|ov-pay|reisproduct|studentenreisproduct|vervoersbewijs|vervoerbewijs|opwaarderen)\\b|\\b(?:ov-staking|conducteursstaking)\\b" +match_filter: "(?i)\\b(?:ns|arriva|qbuzz|connexxion|cxx|transdev|keolis|ret|gvb|ebs|htm|syntus|breng|u-ov|allgo|flixbus|blauwnet|r-net|valleilijn|waterbus|eurostar|thalys|randstadrail|gvu|ov)\\b|\\b(?:bus|tram|metro)(?:halte|haltes|lijn|lijnen|station|stations|verkeer|net|staking|sen)?\\b|\\btrein(?:en|verkeer|stel(?:len)?|staking|ongeluk|reizigers?|station|stations)?\\b|\\b(?:spoorweg|spoorbaan|spoorlijn|spoorverkeer|spoorwegovergang|spoorstoring|perron|perrons|overweg|overwegen|seinstoring|wisselstoring|sein|ontsporing|ontspoord|spoorstaking)\\b|\\b(?:openbaar vervoer|dienstregeling|reizigers?|inchecken|uitchecken|pont|ponten|lightrail|pendelbus|shuttlebus)\\b|\\b(?:ov-chipkaart|chipkaart|ovpay|ov-pay|reisproduct|studentenreisproduct|vervoersbewijs|vervoerbewijs|opwaarderen)\\b|\\b(?:ov-staking|conducteursstaking)\\b" # Users who can bypass room permission checks admins: - "@user:example.com" \ No newline at end of file diff --git a/buzzrss/bot.py b/buzzrss/bot.py index 1068dda..5c6f894 100644 --- a/buzzrss/bot.py +++ b/buzzrss/bot.py @@ -51,7 +51,7 @@ rss_change_level = EventType.find("xyz.maubot.rss", t_class=EventType.Class.STAT DEFAULT_MATCH_FILTER = ( r"(?i)" r"\b(?:ns|arriva|qbuzz|connexxion|cxx|transdev|keolis|ret|gvb|ebs|htm|syntus|breng|u-ov|allgo|flixbus|blauwnet|r-net|valleilijn|waterbus|eurostar|thalys|randstadrail|gvu|ov)\b" - r"|\b(?:bus|tram|metro)(?:halte|haltes|lijn|lijnen|station|stations|verkeer|net|staking)?\b" + r"|\b(?:bus|tram|metro)(?:halte|haltes|lijn|lijnen|station|stations|verkeer|net|staking|sen)?\b" r"|\btrein(?:en|verkeer|stel(?:len)?|staking|ongeluk|reizigers?|station|stations)?\b" r"|\b(?:spoorweg|spoorbaan|spoorlijn|spoorverkeer|spoorwegovergang|spoorstoring|perron|perrons|overweg|overwegen|seinstoring|wisselstoring|sein|ontsporing|ontspoord|spoorstaking)\b" r"|\b(?:openbaar vervoer|dienstregeling|reizigers?|inchecken|uitchecken|pont|ponten|lightrail|pendelbus|shuttlebus)\b" @@ -134,11 +134,29 @@ class RSSBot(Plugin): except Exception: self.log.exception("Fatal error while polling feeds") + @staticmethod + def _filter_score(title: str, summary: str, match_filter: str) -> int: + """Score = 2× hits in titel + 1× hits in summary. Aaneengesloten matches + (bv 'NS-trein', 'openbaar vervoer') tellen als 1 cluster.""" + def count(text: str) -> int: + spans = sorted((m.start(), m.end()) for m in re.finditer(match_filter, text)) + if not spans: + return 0 + clusters, prev_end = 1, spans[0][1] + for s, e in spans[1:]: + if s - prev_end <= 1: + prev_end = max(prev_end, e) + else: + clusters += 1 + prev_end = e + return clusters + return 2 * count(title) + count(summary) + async def _send(self, feed: Feed, entry: Entry, sub: Subscription) -> EventID | None: match_filter = self.config["match_filter"] if match_filter: - haystack = f"{entry.title}\n{html.unescape(re.sub(r'<[^>]+>', '', entry.summary))}" - if not re.search(match_filter, haystack): + summary = html.unescape(re.sub(r"<[^>]+>", "", entry.summary)) + if self._filter_score(entry.title, summary, match_filter) < 2: return None message = sub.notification_template.safe_substitute( diff --git a/maubot.yaml b/maubot.yaml index a401b08..adb1f76 100644 --- a/maubot.yaml +++ b/maubot.yaml @@ -1,5 +1,5 @@ id: nl.eddydevink.rss -version: 1.3.0 +version: 1.3.1 modules: - buzzrss main_class: RSSBot