channels: complete carousel header review fixes

Fall back to the ucid-based channel URL when a legacy auto-generated header omits urlCanonical, and cover it with a focused regression spec.

Remove the unrelated selected-tab guard and its spec so this change remains scoped to auto-generated channel headers.
This commit is contained in:
EazyHood 2026-09-02 10:50:36 -05:00
parent f11ced5a02
commit d1962c9f21
4 changed files with 24 additions and 25 deletions

View File

@ -200,6 +200,27 @@ Spectator.describe "extract_auto_generated_channel_header" do
expect(header[:tags]).to eq(["Gaming"])
end
it "falls back to the channel URL when the canonical URL is missing" do
initdata = JSON.parse(<<-JSON).as_h
{
"header": {
"interactiveTabbedHeaderRenderer": {
"title": {"simpleText": "Legacy gaming"}
}
},
"microformat": {
"microformatDataRenderer": {
"familySafe": true
}
}
}
JSON
header = extract_auto_generated_channel_header(initdata, "UCMissingCanonical")
expect(header[:author_url]).to eq("https://www.youtube.com/channel/UCMissingCanonical")
end
it "keeps an explicit familySafe: false" do
initdata = JSON.parse(<<-JSON).as_h
{

View File

@ -1,22 +0,0 @@
require "../../parsers_helper"
Spectator.describe "YouTubeTabs" do
it "treats a selected tab without content as empty" do
initdata = JSON.parse(<<-JSON).as_h
{
"contents": {
"twoColumnBrowseResultsRenderer": {
"tabs": [
{"tabRenderer": {"selected": true}}
]
}
}
}
JSON
items, continuation = extract_items(initdata)
expect(items).to be_empty
expect(continuation).to be_nil
end
end

View File

@ -42,7 +42,8 @@ def extract_auto_generated_channel_header(initdata : Hash(String, JSON::Any), uc
if header = initdata.dig?("header", "interactiveTabbedHeaderRenderer")
author = header.dig("title", "simpleText").as_s
author_url = initdata.dig("microformat", "microformatDataRenderer", "urlCanonical").as_s
author_url = initdata.dig?("microformat", "microformatDataRenderer", "urlCanonical").try &.as_s?
author_url ||= "https://www.youtube.com/channel/#{ucid}"
author_thumbnail = header.dig?("boxArt", "thumbnails", 0, "url").try &.as_s || ""
banner = header.dig?("banner", "thumbnails").try &.[-1]?.try &.["url"].as_s?

View File

@ -964,8 +964,7 @@ private module Extractors
private def self.extract(target)
raw_items = [] of JSON::Any
content = extract_selected_tab(target["tabs"])["content"]?
return raw_items if content.nil?
content = extract_selected_tab(target["tabs"])["content"]
if section_list_contents = content.dig?("sectionListRenderer", "contents")
raw_items = unpack_section_list(section_list_contents)