Videos: Fix 0 views and empty license field (#3557)

This commit is contained in:
Samantaz Fox 2023-03-20 19:15:12 +01:00
commit 8a44bd11d2
No known key found for this signature in database
GPG key ID: F42821059186176E
6 changed files with 45 additions and 158 deletions

View file

@ -183,6 +183,7 @@
"Show annotations": "Show annotations",
"Genre: ": "Genre: ",
"License: ": "License: ",
"Standard YouTube license": "Standard YouTube license",
"Family friendly? ": "Family friendly? ",
"Wilson score: ": "Wilson score: ",
"Engagement: ": "Engagement: ",

2
mocks

@ -1 +1 @@
Subproject commit dfd53ea6ceb3cbcbbce6004f6ce60b330ad0f9b1
Subproject commit cb16e0343c8f94182615610bfe3c503db89717a7

View file

@ -17,8 +17,8 @@ Spectator.describe "parse_video_info" do
# Basic video infos
expect(info["title"].as_s).to eq("I Gave My 100,000,000th Subscriber An Island")
expect(info["views"].as_i).to eq(32_846_329)
expect(info["likes"].as_i).to eq(2_611_650)
expect(info["views"].as_i).to eq(115_784_415)
expect(info["likes"].as_i).to eq(4_932_790)
# For some reason the video length from VideoDetails and the
# one from microformat differs by 1s...
@ -46,14 +46,14 @@ Spectator.describe "parse_video_info" do
# Related videos
expect(info["relatedVideos"].as_a.size).to eq(19)
expect(info["relatedVideos"].as_a.size).to eq(20)
expect(info["relatedVideos"][0]["id"]).to eq("tVWWp1PqDus")
expect(info["relatedVideos"][0]["title"]).to eq("100 Girls Vs 100 Boys For $500,000")
expect(info["relatedVideos"][0]["id"]).to eq("iogcY_4xGjo")
expect(info["relatedVideos"][0]["title"]).to eq("$1 vs $1,000,000 Hotel Room!")
expect(info["relatedVideos"][0]["author"]).to eq("MrBeast")
expect(info["relatedVideos"][0]["ucid"]).to eq("UCX6OQ3DkcsbYNE6H8uQQuVA")
expect(info["relatedVideos"][0]["view_count"]).to eq("49702799")
expect(info["relatedVideos"][0]["short_view_count"]).to eq("49M")
expect(info["relatedVideos"][0]["view_count"]).to eq("172972109")
expect(info["relatedVideos"][0]["short_view_count"]).to eq("172M")
expect(info["relatedVideos"][0]["author_verified"]).to eq("true")
# Description
@ -76,11 +76,11 @@ Spectator.describe "parse_video_info" do
expect(info["ucid"].as_s).to eq("UCX6OQ3DkcsbYNE6H8uQQuVA")
expect(info["authorThumbnail"].as_s).to eq(
"https://yt3.ggpht.com/ytc/AMLnZu84dsnlYtuUFBMC8imQs0IUcTKA9khWAmUOgQZltw=s48-c-k-c0x00ffffff-no-rj"
"https://yt3.ggpht.com/ytc/AL5GRJUfhQdJS6n-YJtsAf-ouS2myDavDOq_zXBfebal3Q=s48-c-k-c0x00ffffff-no-rj"
)
expect(info["authorVerified"].as_bool).to be_true
expect(info["subCountText"].as_s).to eq("101M")
expect(info["subCountText"].as_s).to eq("135M")
end
it "parses a regular video with no descrition/comments" do
@ -99,7 +99,7 @@ Spectator.describe "parse_video_info" do
# Basic video infos
expect(info["title"].as_s).to eq("Chris Rea - Auberge")
expect(info["views"].as_i).to eq(10_356_197)
expect(info["views"].as_i).to eq(10_698_554)
expect(info["likes"].as_i).to eq(0)
expect(info["lengthSeconds"].as_i).to eq(283_i64)
expect(info["published"].as_s).to eq("2012-05-21T00:00:00Z")
@ -132,16 +132,14 @@ Spectator.describe "parse_video_info" do
# Related videos
expect(info["relatedVideos"].as_a.size).to eq(19)
expect(info["relatedVideos"].as_a.size).to eq(18)
expect(info["relatedVideos"][0]["id"]).to eq("0bkrY_V0yZg")
expect(info["relatedVideos"][0]["title"]).to eq(
"Chris Rea Best Songs Collection - Chris Rea Greatest Hits Full Album 2022"
)
expect(info["relatedVideos"][0]["author"]).to eq("Rock Ultimate")
expect(info["relatedVideos"][0]["ucid"]).to eq("UCekSc2A19di9koUIpj8gxlQ")
expect(info["relatedVideos"][0]["view_count"]).to eq("1992412")
expect(info["relatedVideos"][0]["short_view_count"]).to eq("1.9M")
expect(info["relatedVideos"][0]["id"]).to eq("rfyZrJUmzxU")
expect(info["relatedVideos"][0]["title"]).to eq("cheb mami - bekatni")
expect(info["relatedVideos"][0]["author"]).to eq("pelitovic")
expect(info["relatedVideos"][0]["ucid"]).to eq("UCsp6vFyJeGoLxgn-AsHp1tw")
expect(info["relatedVideos"][0]["view_count"]).to eq("13863619")
expect(info["relatedVideos"][0]["short_view_count"]).to eq("13M")
expect(info["relatedVideos"][0]["author_verified"]).to eq("false")
# Description

View file

@ -1,114 +1,13 @@
require "../../parsers_helper.cr"
Spectator.describe "parse_video_info" do
it "parses scheduled livestreams data (test 1)" do
# Enable mock
_player = load_mock("video/scheduled_live_nintendo.player")
_next = load_mock("video/scheduled_live_nintendo.next")
raw_data = _player.merge!(_next)
info = parse_video_info("QMGibBzTu0g", raw_data)
# Some basic verifications
expect(typeof(info)).to eq(Hash(String, JSON::Any))
expect(info["videoType"].as_s).to eq("Scheduled")
# Basic video infos
expect(info["title"].as_s).to eq("Xenoblade Chronicles 3 Nintendo Direct")
expect(info["views"].as_i).to eq(160)
expect(info["likes"].as_i).to eq(2_283)
expect(info["lengthSeconds"].as_i).to eq(0_i64)
expect(info["published"].as_s).to eq("2022-06-22T14:00:00Z") # Unix 1655906400
# Extra video infos
expect(info["allowedRegions"].as_a).to_not be_empty
expect(info["allowedRegions"].as_a.size).to eq(249)
expect(info["allowedRegions"].as_a).to contain(
"AD", "BA", "BB", "BW", "BY", "EG", "GG", "HN", "NP", "NR", "TR",
"TT", "TV", "TW", "TZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU",
"WF", "WS", "YE", "YT", "ZA", "ZM", "ZW"
)
expect(info["keywords"].as_a).to_not be_empty
expect(info["keywords"].as_a.size).to eq(11)
expect(info["keywords"].as_a).to contain_exactly(
"nintendo",
"game",
"gameplay",
"fun",
"video game",
"action",
"adventure",
"rpg",
"play",
"switch",
"nintendo switch"
).in_any_order
expect(info["allowRatings"].as_bool).to be_true
expect(info["isFamilyFriendly"].as_bool).to be_true
expect(info["isListed"].as_bool).to be_true
expect(info["isUpcoming"].as_bool).to be_true
# Related videos
expect(info["relatedVideos"].as_a.size).to eq(20)
# related video #1
expect(info["relatedVideos"][3]["id"].as_s).to eq("a-SN3lLIUEo")
expect(info["relatedVideos"][3]["author"].as_s).to eq("Nintendo")
expect(info["relatedVideos"][3]["ucid"].as_s).to eq("UCGIY_O-8vW4rfX98KlMkvRg")
expect(info["relatedVideos"][3]["view_count"].as_s).to eq("147796")
expect(info["relatedVideos"][3]["short_view_count"].as_s).to eq("147K")
expect(info["relatedVideos"][3]["author_verified"].as_s).to eq("true")
# Related video #2
expect(info["relatedVideos"][16]["id"].as_s).to eq("l_uC1jFK0lo")
expect(info["relatedVideos"][16]["author"].as_s).to eq("Nintendo")
expect(info["relatedVideos"][16]["ucid"].as_s).to eq("UCGIY_O-8vW4rfX98KlMkvRg")
expect(info["relatedVideos"][16]["view_count"].as_s).to eq("53510")
expect(info["relatedVideos"][16]["short_view_count"].as_s).to eq("53K")
expect(info["relatedVideos"][16]["author_verified"].as_s).to eq("true")
# Description
description = "Tune in on 6/22 at 7 a.m. PT for a livestreamed Xenoblade Chronicles 3 Direct presentation featuring roughly 20 minutes of information about the upcoming RPG adventure for Nintendo Switch."
expect(info["description"].as_s).to eq(description)
expect(info["shortDescription"].as_s).to eq(description)
expect(info["descriptionHtml"].as_s).to eq(description)
# Video metadata
expect(info["genre"].as_s).to eq("Gaming")
expect(info["genreUcid"].as_s).to be_empty
expect(info["license"].as_s).to be_empty
# Author infos
expect(info["author"].as_s).to eq("Nintendo")
expect(info["ucid"].as_s).to eq("UCGIY_O-8vW4rfX98KlMkvRg")
expect(info["authorThumbnail"].as_s).to eq(
"https://yt3.ggpht.com/ytc/AKedOLTt4vtjREUUNdHlyu9c4gtJjG90M9jQheRlLKy44A=s48-c-k-c0x00ffffff-no-rj"
)
expect(info["authorVerified"].as_bool).to be_true
expect(info["subCountText"].as_s).to eq("8.5M")
end
it "parses scheduled livestreams data (test 2)" do
it "parses scheduled livestreams data" do
# Enable mock
_player = load_mock("video/scheduled_live_PBD-Podcast.player")
_next = load_mock("video/scheduled_live_PBD-Podcast.next")
raw_data = _player.merge!(_next)
info = parse_video_info("RG0cjYbXxME", raw_data)
info = parse_video_info("N-yVic7BbY0", raw_data)
# Some basic verifications
expect(typeof(info)).to eq(Hash(String, JSON::Any))
@ -117,11 +16,11 @@ Spectator.describe "parse_video_info" do
# Basic video infos
expect(info["title"].as_s).to eq("The Truth About Greenpeace w/ Dr. Patrick Moore | PBD Podcast | Ep. 171")
expect(info["views"].as_i).to eq(24)
expect(info["likes"].as_i).to eq(22)
expect(info["title"].as_s).to eq("Home Team | PBD Podcast | Ep. 241")
expect(info["views"].as_i).to eq(6)
expect(info["likes"].as_i).to eq(7)
expect(info["lengthSeconds"].as_i).to eq(0_i64)
expect(info["published"].as_s).to eq("2022-07-14T13:00:00Z") # Unix 1657803600
expect(info["published"].as_s).to eq("2023-02-28T14:00:00Z") # Unix 1677592800
# Extra video infos
@ -173,39 +72,22 @@ Spectator.describe "parse_video_info" do
expect(info["relatedVideos"].as_a.size).to eq(20)
# related video #1
expect(info["relatedVideos"][2]["id"]).to eq("La9oLLoI5Rc")
expect(info["relatedVideos"][2]["author"]).to eq("Tom Bilyeu")
expect(info["relatedVideos"][2]["ucid"]).to eq("UCnYMOamNKLGVlJgRUbamveA")
expect(info["relatedVideos"][2]["view_count"]).to eq("13329149")
expect(info["relatedVideos"][2]["short_view_count"]).to eq("13M")
expect(info["relatedVideos"][2]["author_verified"]).to eq("true")
# Related video #2
expect(info["relatedVideos"][9]["id"]).to eq("IQ_4fvpzYuA")
expect(info["relatedVideos"][9]["author"]).to eq("Business Today")
expect(info["relatedVideos"][9]["ucid"]).to eq("UCaPHWiExfUWaKsUtENLCv5w")
expect(info["relatedVideos"][9]["view_count"]).to eq("26432")
expect(info["relatedVideos"][9]["short_view_count"]).to eq("26K")
expect(info["relatedVideos"][9]["author_verified"]).to eq("true")
expect(info["relatedVideos"][0]["id"]).to eq("j7jPzzjbVuk")
expect(info["relatedVideos"][0]["author"]).to eq("Democracy Now!")
expect(info["relatedVideos"][0]["ucid"]).to eq("UCzuqE7-t13O4NIDYJfakrhw")
expect(info["relatedVideos"][0]["view_count"]).to eq("7576")
expect(info["relatedVideos"][0]["short_view_count"]).to eq("7.5K")
expect(info["relatedVideos"][0]["author_verified"]).to eq("true")
# Description
description_start_text = <<-TXT
PBD Podcast Episode 171. In this episode, Patrick Bet-David is joined by Dr. Patrick Moore and Adam Sosnick.
Join the channel to get exclusive access to perks: https://bit.ly/3Q9rSQL
TXT
description_start_text = "PBD Podcast Episode 241. The home team is ready and at it again with the latest news, interesting topics and trending conversations on topics that matter. Try our sponsor Aura for 14 days free - https://aura.com/pbd"
expect(info["description"].as_s).to start_with(description_start_text)
expect(info["shortDescription"].as_s).to start_with(description_start_text)
expect(info["descriptionHtml"].as_s).to start_with(
<<-TXT
PBD Podcast Episode 171. In this episode, Patrick Bet-David is joined by Dr. Patrick Moore and Adam Sosnick.
Join the channel to get exclusive access to perks: <a href="https://bit.ly/3Q9rSQL">bit.ly/3Q9rSQL</a>
TXT
"PBD Podcast Episode 241. The home team is ready and at it again with the latest news, interesting topics and trending conversations on topics that matter. Try our sponsor Aura for 14 days free - <a href=\"https://aura.com/pbd\">aura.com/pbd</a>"
)
# Video metadata
@ -223,6 +105,6 @@ Spectator.describe "parse_video_info" do
"https://yt3.ggpht.com/61ArDiQshJrvSXcGLhpFfIO3hlMabe2fksitcf6oGob0Mdr5gztdkXxRljICUodL4iuTSrtxW4A=s48-c-k-c0x00ffffff-no-rj"
)
expect(info["authorVerified"].as_bool).to be_false
expect(info["subCountText"].as_s).to eq("227K")
expect(info["subCountText"].as_s).to eq("594K")
end
end

View file

@ -185,10 +185,12 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
# We have to try to extract viewCount from videoPrimaryInfoRenderer first,
# then from videoDetails, as the latter is "0" for livestreams (we want
# to get the amount of viewers watching).
views_txt = video_primary_renderer
.try &.dig?("viewCount", "videoViewCountRenderer", "viewCount", "runs", 0, "text")
views_txt ||= video_details["viewCount"]?
views = views_txt.try &.as_s.gsub(/\D/, "").to_i64?
views_txt = extract_text(
video_primary_renderer
.try &.dig?("viewCount", "videoViewCountRenderer", "viewCount")
)
views_txt ||= video_details["viewCount"]?.try &.as_s || ""
views = views_txt.gsub(/\D/, "").to_i64?
length_txt = (microformat["lengthSeconds"]? || video_details["lengthSeconds"])
.try &.as_s.to_i64

View file

@ -181,8 +181,12 @@ we're going to need to do it here in order to allow for translations.
<% end %>
</p>
<% if video.license %>
<% if video.license.empty? %>
<p id="license"><%= translate(locale, "License: ") %><%= translate(locale, "Standard YouTube license") %></p>
<% else %>
<p id="license"><%= translate(locale, "License: ") %><%= video.license %></p>
<% end %>
<% end %>
<p id="family_friendly"><%= translate(locale, "Family friendly? ") %><%= translate_bool(locale, video.is_family_friendly) %></p>
<p id="wilson" style="display: none; visibility: hidden;"></p>
<p id="rating" style="display: none; visibility: hidden;"></p>