Skip to content

Fix non-unique channel IDs for empty tvg-id="" - #135

Open
EasterwoodBiker wants to merge 1 commit into
ardoviniandrea:mainfrom
EasterwoodBiker:fix/empty-tvg-id-favorites
Open

EasterwoodBiker wants to merge 1 commit into
ardoviniandrea:mainfrom
EasterwoodBiker:fix/empty-tvg-id-favorites

Conversation

@EasterwoodBiker

Copy link
Copy Markdown

Problem

Live M3U channels whose #EXTINF carries an empty tvg-id="" all collapse to the same generated channel ID, src-<sourceId>_.

The unique-ID builder falls back to a name-based ID only when the tvg-id attribute is absent:

const originalTvgId = idMatch ? idMatch[1] : `no-tvg-id-${name.replace(/[^a-zA-Z0-9]/g, '')}`;

But idMatch is truthy for tvg-id="" (the regex tvg-id="([^"]*)" matches, capturing ""), so originalTvgId becomes "" and every empty-tvg-id channel gets the identical ID <sourceId>_.

Impact

Favorites and "recently watched" both key on this channel ID, so all empty-tvg-id channels become indistinguishable. Toggling a star on one saves a single ambiguous ID (["src-…_"]) that matches none of them on reload, so favorites and recents silently fail to persist.

On one real provider playlist this affected 1821 channels collapsing onto a single ID.

Fix

Guard the fallback on the captured value, so an empty tvg-id is treated the same as a missing one and each channel gets a unique name-based ID:

const originalTvgId = (idMatch && idMatch[1]) ? idMatch[1] : `no-tvg-id-${name.replace(/[^a-zA-Z0-9]/g, '')}`;

The existing if (idMatch) injection branch below is unaffected — it still rewrites the empty tvg-id="" attribute in place with the new unique ID.

Testing

Applied against the same 1821-channel playlist and refreshed the source: the collapsed IDs dropped from 1821-sharing-one to 0, with 1787 unique name-based IDs. Favorites and recents now persist correctly. (The small remainder are genuinely duplicate-named channels — the same limitation the pre-existing name-based fallback already has.)

Live M3U channels whose #EXTINF carries an empty tvg-id="" all collapse
to the same generated channel ID (src-<sourceId>_), because the
name-based fallback only triggers when the tvg-id attribute is absent,
not when it is present-but-empty (idMatch is truthy for tvg-id="", so
idMatch[1] is "").

Channel favorites and "recently watched" both key on this ID, so with a
playlist that has many empty tvg-ids every such channel is
indistinguishable: toggling one star saves a single ambiguous ID that
matches none of them on reload, and the favorite/recent silently fails
to stick. One real playlist had 1821 channels collapse onto one ID.

Guard the fallback on the captured value so an empty tvg-id is treated
the same as a missing one, giving each channel a unique name-based ID.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant