Videos: Fix 0 views and empty license field (#3557)
This commit is contained in:
commit
8a44bd11d2
|
@ -183,6 +183,7 @@
|
||||||
"Show annotations": "Show annotations",
|
"Show annotations": "Show annotations",
|
||||||
"Genre: ": "Genre: ",
|
"Genre: ": "Genre: ",
|
||||||
"License: ": "License: ",
|
"License: ": "License: ",
|
||||||
|
"Standard YouTube license": "Standard YouTube license",
|
||||||
"Family friendly? ": "Family friendly? ",
|
"Family friendly? ": "Family friendly? ",
|
||||||
"Wilson score: ": "Wilson score: ",
|
"Wilson score: ": "Wilson score: ",
|
||||||
"Engagement: ": "Engagement: ",
|
"Engagement: ": "Engagement: ",
|
||||||
|
|
2
mocks
2
mocks
|
@ -1 +1 @@
|
||||||
Subproject commit dfd53ea6ceb3cbcbbce6004f6ce60b330ad0f9b1
|
Subproject commit cb16e0343c8f94182615610bfe3c503db89717a7
|
|
@ -17,8 +17,8 @@ Spectator.describe "parse_video_info" do
|
||||||
# Basic video infos
|
# Basic video infos
|
||||||
|
|
||||||
expect(info["title"].as_s).to eq("I Gave My 100,000,000th Subscriber An Island")
|
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["views"].as_i).to eq(115_784_415)
|
||||||
expect(info["likes"].as_i).to eq(2_611_650)
|
expect(info["likes"].as_i).to eq(4_932_790)
|
||||||
|
|
||||||
# For some reason the video length from VideoDetails and the
|
# For some reason the video length from VideoDetails and the
|
||||||
# one from microformat differs by 1s...
|
# one from microformat differs by 1s...
|
||||||
|
@ -46,14 +46,14 @@ Spectator.describe "parse_video_info" do
|
||||||
|
|
||||||
# Related videos
|
# 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]["id"]).to eq("iogcY_4xGjo")
|
||||||
expect(info["relatedVideos"][0]["title"]).to eq("100 Girls Vs 100 Boys For $500,000")
|
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]["author"]).to eq("MrBeast")
|
||||||
expect(info["relatedVideos"][0]["ucid"]).to eq("UCX6OQ3DkcsbYNE6H8uQQuVA")
|
expect(info["relatedVideos"][0]["ucid"]).to eq("UCX6OQ3DkcsbYNE6H8uQQuVA")
|
||||||
expect(info["relatedVideos"][0]["view_count"]).to eq("49702799")
|
expect(info["relatedVideos"][0]["view_count"]).to eq("172972109")
|
||||||
expect(info["relatedVideos"][0]["short_view_count"]).to eq("49M")
|
expect(info["relatedVideos"][0]["short_view_count"]).to eq("172M")
|
||||||
expect(info["relatedVideos"][0]["author_verified"]).to eq("true")
|
expect(info["relatedVideos"][0]["author_verified"]).to eq("true")
|
||||||
|
|
||||||
# Description
|
# Description
|
||||||
|
@ -76,11 +76,11 @@ Spectator.describe "parse_video_info" do
|
||||||
expect(info["ucid"].as_s).to eq("UCX6OQ3DkcsbYNE6H8uQQuVA")
|
expect(info["ucid"].as_s).to eq("UCX6OQ3DkcsbYNE6H8uQQuVA")
|
||||||
|
|
||||||
expect(info["authorThumbnail"].as_s).to eq(
|
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["authorVerified"].as_bool).to be_true
|
||||||
expect(info["subCountText"].as_s).to eq("101M")
|
expect(info["subCountText"].as_s).to eq("135M")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "parses a regular video with no descrition/comments" do
|
it "parses a regular video with no descrition/comments" do
|
||||||
|
@ -99,7 +99,7 @@ Spectator.describe "parse_video_info" do
|
||||||
# Basic video infos
|
# Basic video infos
|
||||||
|
|
||||||
expect(info["title"].as_s).to eq("Chris Rea - Auberge")
|
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["likes"].as_i).to eq(0)
|
||||||
expect(info["lengthSeconds"].as_i).to eq(283_i64)
|
expect(info["lengthSeconds"].as_i).to eq(283_i64)
|
||||||
expect(info["published"].as_s).to eq("2012-05-21T00:00:00Z")
|
expect(info["published"].as_s).to eq("2012-05-21T00:00:00Z")
|
||||||
|
@ -132,16 +132,14 @@ Spectator.describe "parse_video_info" do
|
||||||
|
|
||||||
# Related videos
|
# 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]["id"]).to eq("rfyZrJUmzxU")
|
||||||
expect(info["relatedVideos"][0]["title"]).to eq(
|
expect(info["relatedVideos"][0]["title"]).to eq("cheb mami - bekatni")
|
||||||
"Chris Rea Best Songs Collection - Chris Rea Greatest Hits Full Album 2022"
|
expect(info["relatedVideos"][0]["author"]).to eq("pelitovic")
|
||||||
)
|
expect(info["relatedVideos"][0]["ucid"]).to eq("UCsp6vFyJeGoLxgn-AsHp1tw")
|
||||||
expect(info["relatedVideos"][0]["author"]).to eq("Rock Ultimate")
|
expect(info["relatedVideos"][0]["view_count"]).to eq("13863619")
|
||||||
expect(info["relatedVideos"][0]["ucid"]).to eq("UCekSc2A19di9koUIpj8gxlQ")
|
expect(info["relatedVideos"][0]["short_view_count"]).to eq("13M")
|
||||||
expect(info["relatedVideos"][0]["view_count"]).to eq("1992412")
|
|
||||||
expect(info["relatedVideos"][0]["short_view_count"]).to eq("1.9M")
|
|
||||||
expect(info["relatedVideos"][0]["author_verified"]).to eq("false")
|
expect(info["relatedVideos"][0]["author_verified"]).to eq("false")
|
||||||
|
|
||||||
# Description
|
# Description
|
||||||
|
|
|
@ -1,114 +1,13 @@
|
||||||
require "../../parsers_helper.cr"
|
require "../../parsers_helper.cr"
|
||||||
|
|
||||||
Spectator.describe "parse_video_info" do
|
Spectator.describe "parse_video_info" do
|
||||||
it "parses scheduled livestreams data (test 1)" do
|
it "parses scheduled livestreams data" 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
|
|
||||||
# Enable mock
|
# Enable mock
|
||||||
_player = load_mock("video/scheduled_live_PBD-Podcast.player")
|
_player = load_mock("video/scheduled_live_PBD-Podcast.player")
|
||||||
_next = load_mock("video/scheduled_live_PBD-Podcast.next")
|
_next = load_mock("video/scheduled_live_PBD-Podcast.next")
|
||||||
|
|
||||||
raw_data = _player.merge!(_next)
|
raw_data = _player.merge!(_next)
|
||||||
info = parse_video_info("RG0cjYbXxME", raw_data)
|
info = parse_video_info("N-yVic7BbY0", raw_data)
|
||||||
|
|
||||||
# Some basic verifications
|
# Some basic verifications
|
||||||
expect(typeof(info)).to eq(Hash(String, JSON::Any))
|
expect(typeof(info)).to eq(Hash(String, JSON::Any))
|
||||||
|
@ -117,11 +16,11 @@ Spectator.describe "parse_video_info" do
|
||||||
|
|
||||||
# Basic video infos
|
# Basic video infos
|
||||||
|
|
||||||
expect(info["title"].as_s).to eq("The Truth About Greenpeace w/ Dr. Patrick Moore | PBD Podcast | Ep. 171")
|
expect(info["title"].as_s).to eq("Home Team | PBD Podcast | Ep. 241")
|
||||||
expect(info["views"].as_i).to eq(24)
|
expect(info["views"].as_i).to eq(6)
|
||||||
expect(info["likes"].as_i).to eq(22)
|
expect(info["likes"].as_i).to eq(7)
|
||||||
expect(info["lengthSeconds"].as_i).to eq(0_i64)
|
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
|
# Extra video infos
|
||||||
|
|
||||||
|
@ -173,39 +72,22 @@ Spectator.describe "parse_video_info" do
|
||||||
|
|
||||||
expect(info["relatedVideos"].as_a.size).to eq(20)
|
expect(info["relatedVideos"].as_a.size).to eq(20)
|
||||||
|
|
||||||
# related video #1
|
expect(info["relatedVideos"][0]["id"]).to eq("j7jPzzjbVuk")
|
||||||
expect(info["relatedVideos"][2]["id"]).to eq("La9oLLoI5Rc")
|
expect(info["relatedVideos"][0]["author"]).to eq("Democracy Now!")
|
||||||
expect(info["relatedVideos"][2]["author"]).to eq("Tom Bilyeu")
|
expect(info["relatedVideos"][0]["ucid"]).to eq("UCzuqE7-t13O4NIDYJfakrhw")
|
||||||
expect(info["relatedVideos"][2]["ucid"]).to eq("UCnYMOamNKLGVlJgRUbamveA")
|
expect(info["relatedVideos"][0]["view_count"]).to eq("7576")
|
||||||
expect(info["relatedVideos"][2]["view_count"]).to eq("13329149")
|
expect(info["relatedVideos"][0]["short_view_count"]).to eq("7.5K")
|
||||||
expect(info["relatedVideos"][2]["short_view_count"]).to eq("13M")
|
expect(info["relatedVideos"][0]["author_verified"]).to eq("true")
|
||||||
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")
|
|
||||||
|
|
||||||
# Description
|
# Description
|
||||||
|
|
||||||
description_start_text = <<-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"
|
||||||
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
|
|
||||||
|
|
||||||
expect(info["description"].as_s).to start_with(description_start_text)
|
expect(info["description"].as_s).to start_with(description_start_text)
|
||||||
expect(info["shortDescription"].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(
|
expect(info["descriptionHtml"].as_s).to start_with(
|
||||||
<<-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>"
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Video metadata
|
# Video metadata
|
||||||
|
@ -223,6 +105,6 @@ Spectator.describe "parse_video_info" do
|
||||||
"https://yt3.ggpht.com/61ArDiQshJrvSXcGLhpFfIO3hlMabe2fksitcf6oGob0Mdr5gztdkXxRljICUodL4iuTSrtxW4A=s48-c-k-c0x00ffffff-no-rj"
|
"https://yt3.ggpht.com/61ArDiQshJrvSXcGLhpFfIO3hlMabe2fksitcf6oGob0Mdr5gztdkXxRljICUodL4iuTSrtxW4A=s48-c-k-c0x00ffffff-no-rj"
|
||||||
)
|
)
|
||||||
expect(info["authorVerified"].as_bool).to be_false
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -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,
|
# We have to try to extract viewCount from videoPrimaryInfoRenderer first,
|
||||||
# then from videoDetails, as the latter is "0" for livestreams (we want
|
# then from videoDetails, as the latter is "0" for livestreams (we want
|
||||||
# to get the amount of viewers watching).
|
# to get the amount of viewers watching).
|
||||||
views_txt = video_primary_renderer
|
views_txt = extract_text(
|
||||||
.try &.dig?("viewCount", "videoViewCountRenderer", "viewCount", "runs", 0, "text")
|
video_primary_renderer
|
||||||
views_txt ||= video_details["viewCount"]?
|
.try &.dig?("viewCount", "videoViewCountRenderer", "viewCount")
|
||||||
views = views_txt.try &.as_s.gsub(/\D/, "").to_i64?
|
)
|
||||||
|
views_txt ||= video_details["viewCount"]?.try &.as_s || ""
|
||||||
|
views = views_txt.gsub(/\D/, "").to_i64?
|
||||||
|
|
||||||
length_txt = (microformat["lengthSeconds"]? || video_details["lengthSeconds"])
|
length_txt = (microformat["lengthSeconds"]? || video_details["lengthSeconds"])
|
||||||
.try &.as_s.to_i64
|
.try &.as_s.to_i64
|
||||||
|
|
|
@ -181,8 +181,12 @@ we're going to need to do it here in order to allow for translations.
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<% if video.license %>
|
<% 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>
|
<p id="license"><%= translate(locale, "License: ") %><%= video.license %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<p id="family_friendly"><%= translate(locale, "Family friendly? ") %><%= translate_bool(locale, video.is_family_friendly) %></p>
|
<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="wilson" style="display: none; visibility: hidden;"></p>
|
||||||
<p id="rating" style="display: none; visibility: hidden;"></p>
|
<p id="rating" style="display: none; visibility: hidden;"></p>
|
||||||
|
|
Loading…
Reference in a new issue