diff --git a/src/invidious/helpers/serialized_yt_data.cr b/src/invidious/helpers/serialized_yt_data.cr
index bfbc237ce..3918bd130 100644
--- a/src/invidious/helpers/serialized_yt_data.cr
+++ b/src/invidious/helpers/serialized_yt_data.cr
@@ -12,6 +12,7 @@ struct SearchVideo
property live_now : Bool
property premium : Bool
property premiere_timestamp : Time?
+ property author_verified : Bool
def to_xml(auto_generated, query_params, xml : XML::Builder)
query_params["v"] = self.id
@@ -129,6 +130,7 @@ struct SearchPlaylist
property video_count : Int32
property videos : Array(SearchPlaylistVideo)
property thumbnail : String?
+ property author_verified : Bool
def to_json(locale : String?, json : JSON::Builder)
json.object do
@@ -141,6 +143,8 @@ struct SearchPlaylist
json.field "authorId", self.ucid
json.field "authorUrl", "/channel/#{self.ucid}"
+ json.field "authorVerified", self.author_verified
+
json.field "videoCount", self.video_count
json.field "videos" do
json.array do
@@ -182,6 +186,7 @@ struct SearchChannel
property video_count : Int32
property description_html : String
property auto_generated : Bool
+ property author_verified : Bool
def to_json(locale : String?, json : JSON::Builder)
json.object do
@@ -189,7 +194,7 @@ struct SearchChannel
json.field "author", self.author
json.field "authorId", self.ucid
json.field "authorUrl", "/channel/#{self.ucid}"
-
+ json.field "authorVerified", self.author_verified
json.field "authorThumbnails" do
json.array do
qualities = {32, 48, 76, 100, 176, 512}
diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr
index f7f7b426a..b5b583996 100644
--- a/src/invidious/routes/feeds.cr
+++ b/src/invidious/routes/feeds.cr
@@ -182,6 +182,7 @@ module Invidious::Routes::Feeds
paid: false,
premium: false,
premiere_timestamp: nil,
+ author_verified: false, # ¯\_(ツ)_/¯
})
end
diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr
index 8a6a0f1ac..7c1f68a86 100644
--- a/src/invidious/videos.cr
+++ b/src/invidious/videos.cr
@@ -613,6 +613,10 @@ struct Video
info["authorThumbnail"]?.try &.as_s || ""
end
+ def author_verified : Bool
+ info["authorVerified"]?.try &.as_bool || false
+ end
+
def sub_count_text : String
info["subCountText"]?.try &.as_s || "-"
end
@@ -864,6 +868,12 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)?
.try &.dig?("runs", 0)
author = channel_info.try &.dig?("text")
+ author_verified_badge = related["ownerBadges"]?.try do |badges_array|
+ badges_array.as_a.find(&.dig("metadataBadgeRenderer", "tooltip").as_s.== "Verified")
+ end
+
+ author_verified = (author_verified_badge && author_verified_badge.size > 0).to_s
+
ucid = channel_info.try { |ci| HelperExtractors.get_browse_id(ci) }
# "4,088,033 views", only available on compact renderer
@@ -887,6 +897,7 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)?
"length_seconds" => JSON::Any.new(length || "0"),
"view_count" => JSON::Any.new(view_count || "0"),
"short_view_count" => JSON::Any.new(short_view_count || "0"),
+ "author_verified" => JSON::Any.new(author_verified),
}
end
@@ -1081,6 +1092,10 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_
author_info = video_secondary_renderer.try &.dig?("owner", "videoOwnerRenderer")
author_thumbnail = author_info.try &.dig?("thumbnail", "thumbnails", 0, "url")
+ author_verified_badge = author_info.try &.dig?("badges", 0, "metadataBadgeRenderer", "tooltip")
+ author_verified = (!author_verified_badge.nil? && author_verified_badge == "Verified")
+ params["authorVerified"] = JSON::Any.new(author_verified)
+
params["authorThumbnail"] = JSON::Any.new(author_thumbnail.try &.as_s || "")
params["subCountText"] = JSON::Any.new(author_info.try &.["subscriberCountText"]?
diff --git a/src/invidious/views/channel.ecr b/src/invidious/views/channel.ecr
index 40b553a9c..92f81ee49 100644
--- a/src/invidious/views/channel.ecr
+++ b/src/invidious/views/channel.ecr
@@ -20,7 +20,7 @@
-
<%= author %>
+
<%= author %><% if !channel.verified.nil? && channel.verified %>
<% end %>
diff --git a/src/invidious/views/community.ecr b/src/invidious/views/community.ecr
index f0add06bf..3bc29e552 100644
--- a/src/invidious/views/community.ecr
+++ b/src/invidious/views/community.ecr
@@ -19,7 +19,7 @@
-
<%= author %>
+
<%= author %><% if !channel.verified.nil? && channel.verified %>
<% end %>
diff --git a/src/invidious/views/components/item.ecr b/src/invidious/views/components/item.ecr
index ce7af783f..fb7ad1dc7 100644
--- a/src/invidious/views/components/item.ecr
+++ b/src/invidious/views/components/item.ecr
@@ -8,7 +8,7 @@
"/>
<% end %>
-
<%= HTML.escape(item.author) %>
+
<%= HTML.escape(item.author) %><% if !item.author_verified.nil? && item.author_verified %> <% end %>
<%= translate_count(locale, "generic_subscribers_count", item.subscriber_count, NumberFormatting::Separator) %>
<% if !item.auto_generated %>
<%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %>
<% end %>
@@ -30,7 +30,7 @@
<%= HTML.escape(item.title) %>
- <%= HTML.escape(item.author) %>
+ <%= HTML.escape(item.author) %><% if !item.is_a?(InvidiousPlaylist) && !item.author_verified.nil? && item.author_verified %> <% end %>
<% when MixVideo %>
@@ -142,7 +142,7 @@
<% endpoint_params = "?v=#{item.id}" %>
diff --git a/src/invidious/views/playlists.ecr b/src/invidious/views/playlists.ecr
index 12dba088f..c8718e7b7 100644
--- a/src/invidious/views/playlists.ecr
+++ b/src/invidious/views/playlists.ecr
@@ -19,7 +19,7 @@
-
<%= author %>
+
<%= author %><% if !channel.verified.nil? && channel.verified %>
<% end %>
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr
index 2e493f4cc..8b6eb903a 100644
--- a/src/invidious/views/watch.ecr
+++ b/src/invidious/views/watch.ecr
@@ -207,7 +207,7 @@ we're going to need to do it here in order to allow for translations.
<% if !video.author_thumbnail.empty? %>
<% end %>
-
<%= author %>
+
<%= author %><% if !video.author_verified.nil? && video.author_verified %> <% end %>
@@ -281,9 +281,9 @@ we're going to need to do it here in order to allow for translations.
diff --git a/src/invidious/yt_backend/extractors.cr b/src/invidious/yt_backend/extractors.cr
index ce39bc284..4657bb1d9 100644
--- a/src/invidious/yt_backend/extractors.cr
+++ b/src/invidious/yt_backend/extractors.cr
@@ -102,7 +102,11 @@ private module Parsers
premium = false
premiere_timestamp = item_contents.dig?("upcomingEventData", "startTime").try { |t| Time.unix(t.as_s.to_i64) }
+ author_verified_badge = item_contents["ownerBadges"]?.try do |badges_array|
+ badges_array.as_a.find(&.dig("metadataBadgeRenderer", "tooltip").as_s.== "Verified")
+ end
+ author_verified = (author_verified_badge && author_verified_badge.size > 0)
item_contents["badges"]?.try &.as_a.each do |badge|
b = badge["metadataBadgeRenderer"]
case b["label"].as_s
@@ -129,6 +133,7 @@ private module Parsers
live_now: live_now,
premium: premium,
premiere_timestamp: premiere_timestamp,
+ author_verified: author_verified || false,
})
end
@@ -156,7 +161,11 @@ private module Parsers
private def self.parse(item_contents, author_fallback)
author = extract_text(item_contents["title"]) || author_fallback.name
author_id = item_contents["channelId"]?.try &.as_s || author_fallback.id
+ author_verified_badge = item_contents["ownerBadges"]?.try do |badges_array|
+ badges_array.as_a.find(&.dig("metadataBadgeRenderer", "tooltip").as_s.== "Verified")
+ end
+ author_verified = (author_verified_badge && author_verified_badge.size > 0)
author_thumbnail = HelperExtractors.get_thumbnails(item_contents)
# When public subscriber count is disabled, the subscriberCountText isn't sent by InnerTube.
# Always simpleText
@@ -179,6 +188,7 @@ private module Parsers
video_count: video_count,
description_html: description_html,
auto_generated: auto_generated,
+ author_verified: author_verified || false,
})
end
@@ -206,18 +216,23 @@ private module Parsers
private def self.parse(item_contents, author_fallback)
title = extract_text(item_contents["title"]) || ""
plid = item_contents["playlistId"]?.try &.as_s || ""
+ author_verified_badge = item_contents["ownerBadges"]?.try do |badges_array|
+ badges_array.as_a.find(&.dig("metadataBadgeRenderer", "tooltip").as_s.== "Verified")
+ end
+ author_verified = (author_verified_badge && author_verified_badge.size > 0)
video_count = HelperExtractors.get_video_count(item_contents)
playlist_thumbnail = HelperExtractors.get_thumbnails(item_contents)
SearchPlaylist.new({
- title: title,
- id: plid,
- author: author_fallback.name,
- ucid: author_fallback.id,
- video_count: video_count,
- videos: [] of SearchPlaylistVideo,
- thumbnail: playlist_thumbnail,
+ title: title,
+ id: plid,
+ author: author_fallback.name,
+ ucid: author_fallback.id,
+ video_count: video_count,
+ videos: [] of SearchPlaylistVideo,
+ thumbnail: playlist_thumbnail,
+ author_verified: author_verified || false,
})
end
@@ -251,7 +266,11 @@ private module Parsers
author_info = item_contents.dig?("shortBylineText", "runs", 0)
author = author_info.try &.["text"].as_s || author_fallback.name
author_id = author_info.try { |x| HelperExtractors.get_browse_id(x) } || author_fallback.id
+ author_verified_badge = item_contents["ownerBadges"]?.try do |badges_array|
+ badges_array.as_a.find(&.dig("metadataBadgeRenderer", "tooltip").as_s.== "Verified")
+ end
+ author_verified = (author_verified_badge && author_verified_badge.size > 0)
videos = item_contents["videos"]?.try &.as_a.map do |v|
v = v["childVideoRenderer"]
v_title = v.dig?("title", "simpleText").try &.as_s || ""
@@ -267,13 +286,14 @@ private module Parsers
# TODO: item_contents["publishedTimeText"]?
SearchPlaylist.new({
- title: title,
- id: plid,
- author: author,
- ucid: author_id,
- video_count: video_count,
- videos: videos,
- thumbnail: playlist_thumbnail,
+ title: title,
+ id: plid,
+ author: author,
+ ucid: author_id,
+ video_count: video_count,
+ videos: videos,
+ thumbnail: playlist_thumbnail,
+ author_verified: author_verified || false,
})
end