Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/scripts/core_manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"matching_core.py": "2ac7ac4cb283306152701bfd977ff2f13700d63d8023fdfa280b1480f5a969dc"
"matching_core.py": "d9a2d065584fb797789f3afe3d51dbd94d3d28a1666361b1f22c8eec6b03943b"
}
32 changes: 27 additions & 5 deletions Lineuparr/matching_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,9 +702,21 @@ def _trailing_number(name):
'KIND', 'KING', 'KINGS', 'KISS', 'KITE', 'KNEE', 'KNEW', 'KNOW', 'KNOWN',
})

# OTA branding context that immediately follows a station callsign: a channel
# number (optionally prefixed by a broadcast suffix), e.g. "KING 5", "WAVE 3",
# "WOOD TV8", "WHO 13". Used to rescue a denylisted common-word callsign in a
# loose position WITHOUT also rescuing bare program words ("King of the Hill",
# "Doctor Who"), which never carry this trailing number. bug-098.
_OTA_NUMBER_CONTEXT = re.compile(r'^\s+(?:TV|DT|CD|LP|LD)?\s*\d{1,3}\b', re.IGNORECASE)

def _is_callsign_allowed(self, callsign):
"""A candidate callsign is allowed if it is not denylisted, OR the plugin
supplied a known-real callsign set that contains it (DB rescue)."""
supplied a known-real callsign set that contains it (DB rescue).

NOTE: this full rescue is used only at the PARENTHESIZED priorities (1/1b),
where the parentheses are an unambiguous OTA signal. The end-of-name and
loose priorities deliberately do NOT use it for denylisted words -- see
bug-098 hardening in _compute_callsign_with_confidence."""
return (callsign not in self._CALLSIGN_DENYLIST
or (self._known_callsigns is not None and callsign in self._known_callsigns))

Expand Down Expand Up @@ -746,18 +758,28 @@ def _compute_callsign_with_confidence(self, channel_name):
if paren_suffix_match:
return paren_suffix_match.group(1).upper(), True

# Priority 3: Callsigns at the end
# Priority 3: Callsigns at the end. A denylisted common word at the end
# ("WOLF KING", "Doctor Who") is NOT rescued here -- end position alone is
# too weak a signal for a word that is also a real callsign. Non-denylisted
# callsigns (and suffixed forms like "KING-TV") still match. bug-098.
end_match = re.search(r'\b([KW][A-Z]{2,4}(?:-(?:TV|CD|LP|DT|LD))?)\s*(?:\.[a-z]+)?\s*$', channel_name, re.IGNORECASE)
if end_match:
callsign = end_match.group(1).upper()
if self._is_callsign_allowed(callsign):
if callsign not in self._CALLSIGN_DENYLIST:
return callsign, True

# Priority 4: Any word matching callsign pattern (low confidence)
# Priority 4: Any word matching callsign pattern (low confidence). A
# denylisted common word is rescued here ONLY in OTA branding context --
# immediately followed by a channel number ("KING 5", "WAVE 3", "WOOD
# TV8", "WHO 13") -- never as a bare program word ("King of the Hill",
# "Doctor Who", "Will Ferrell"). bug-098.
word_match = re.search(r'\b([KW][A-Z]{2,4}(?:-(?:TV|CD|LP|DT|LD))?)\b', channel_name, re.IGNORECASE)
if word_match:
callsign = word_match.group(1).upper()
if self._is_callsign_allowed(callsign):
if callsign not in self._CALLSIGN_DENYLIST:
return callsign, False
if (self._known_callsigns is not None and callsign in self._known_callsigns
and self._OTA_NUMBER_CONTEXT.match(channel_name[word_match.end():])):
return callsign, False

return None, False
Expand Down
2 changes: 1 addition & 1 deletion Lineuparr/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Lineuparr",
"version": "1.26.1791747",
"version": "1.26.1802331",
"description": "Mirror real-world provider channel lineups by creating channel groups, channels, and fuzzy-matching IPTV streams to them.",
"author": "PiratesIRC",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion Lineuparr/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def _clean_json_text(s):


class PluginConfig:
PLUGIN_VERSION = "1.26.1791747"
PLUGIN_VERSION = "1.26.1802331"

DEFAULT_FUZZY_MATCH_THRESHOLD = 80
DEFAULT_PRIORITIZE_QUALITY = True
Expand Down
Loading