Fix channel links for multi-creator related videos

This commit is contained in:
krysto9872 2026-08-05 21:49:10 -06:00
parent 7d93ccbd04
commit 55522a2426
2 changed files with 105 additions and 1 deletions

View File

@ -0,0 +1,74 @@
require "../../parsers_helper.cr"
Spectator.describe "parse_related_video" do
it "extracts a channel id from a multi-creator collaborator dialog" do
related = JSON.parse(<<-JSON)
{
"videoId": "dbVdnL6HWOg",
"title": {"simpleText": "Example video"},
"shortBylineText": {
"runs": [{
"text": "Piers Morgan Uncensored y ProfSteveKeen",
"navigationEndpoint": {
"showDialogCommand": {
"panelLoadingStrategy": {
"inlineContent": {
"dialogViewModel": {
"customContent": {
"listViewModel": {
"listItems": [{
"listItemViewModel": {
"rendererContext": {
"commandContext": {
"onTap": {
"innertubeCommand": {
"browseEndpoint": {
"browseId": "UCatt7TBjfBkiJWx8khav_Gg"
}
}
}
}
}
}
}]
}
}
}
}
}
}
}
}]
}
}
JSON
parsed = Invidious::Videos::Parser.parse_related_video(related)
expect(parsed).to_not be_nil
expect(parsed.not_nil!["author"]).to eq("Piers Morgan Uncensored y ProfSteveKeen")
expect(parsed.not_nil!["ucid"]).to eq("UCatt7TBjfBkiJWx8khav_Gg")
end
it "keeps extracting a direct channel id" do
related = JSON.parse(<<-JSON)
{
"videoId": "example",
"title": {"simpleText": "Example video"},
"shortBylineText": {
"runs": [{
"text": "Example channel",
"navigationEndpoint": {
"browseEndpoint": {"browseId": "UCexample"}
}
}]
}
}
JSON
parsed = Invidious::Videos::Parser.parse_related_video(related)
expect(parsed).to_not be_nil
expect(parsed.not_nil!["ucid"]).to eq("UCexample")
end
end

View File

@ -1141,7 +1141,37 @@ module HelperExtractors
# Retrieves the ID required for querying the InnerTube browse endpoint.
# Returns an empty string when it's unable to do so
def self.get_browse_id(container)
return container.dig?("navigationEndpoint", "browseEndpoint", "browseId").try &.as_s || ""
if browse_id = container.dig?("navigationEndpoint", "browseEndpoint", "browseId").try &.as_s
return browse_id
end
find_browse_id(container) || ""
end
# YouTube wraps the channel links for videos with multiple creators in a
# collaborator dialog instead of putting a browse endpoint directly on the
# byline run. Search nested navigation data so those videos still get a
# usable channel link.
private def self.find_browse_id(container : JSON::Any) : String?
if browse_id = container.dig?("browseEndpoint", "browseId").try &.as_s
return browse_id
end
if object = container.as_h?
object.each_value do |value|
if browse_id = find_browse_id(value)
return browse_id
end
end
elsif array = container.as_a?
array.each do |value|
if browse_id = find_browse_id(value)
return browse_id
end
end
end
nil
end
end