Merge pull request #3077 from SamantazFox/verified-checkmark
Merge "Youtube verification badge" again (with fixes)
This commit is contained in:
		| @@ -12,7 +12,8 @@ record AboutChannel, | |||||||
|   joined : Time, |   joined : Time, | ||||||
|   is_family_friendly : Bool, |   is_family_friendly : Bool, | ||||||
|   allowed_regions : Array(String), |   allowed_regions : Array(String), | ||||||
|   tabs : Array(String) |   tabs : Array(String), | ||||||
|  |   verified : Bool | ||||||
|  |  | ||||||
| record AboutRelatedChannel, | record AboutRelatedChannel, | ||||||
|   ucid : String, |   ucid : String, | ||||||
| @@ -70,6 +71,9 @@ def get_about_info(ucid, locale) : AboutChannel | |||||||
|     # if banner.includes? "channels/c4/default_banner" |     # if banner.includes? "channels/c4/default_banner" | ||||||
|     #  banner = nil |     #  banner = nil | ||||||
|     # end |     # end | ||||||
|  |     # author_verified_badges = initdata["header"]?.try &.["c4TabbedHeaderRenderer"]?.try &.["badges"]? | ||||||
|  |     author_verified_badge = initdata["header"].dig?("c4TabbedHeaderRenderer", "badges", 0, "metadataBadgeRenderer", "tooltip") | ||||||
|  |     author_verified = (author_verified_badge && author_verified_badge == "Verified") | ||||||
|  |  | ||||||
|     description = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?.try &.as_s? || "" |     description = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?.try &.as_s? || "" | ||||||
|     description_html = HTML.escape(description) |     description_html = HTML.escape(description) | ||||||
| @@ -128,6 +132,7 @@ def get_about_info(ucid, locale) : AboutChannel | |||||||
|     is_family_friendly: is_family_friendly, |     is_family_friendly: is_family_friendly, | ||||||
|     allowed_regions: allowed_regions, |     allowed_regions: allowed_regions, | ||||||
|     tabs: tabs, |     tabs: tabs, | ||||||
|  |     verified: author_verified || false, | ||||||
|   ) |   ) | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -146,6 +146,8 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b | |||||||
|               content_html = node_comment["contentText"]?.try { |t| parse_content(t) } || "" |               content_html = node_comment["contentText"]?.try { |t| parse_content(t) } || "" | ||||||
|               author = node_comment["authorText"]?.try &.["simpleText"]? || "" |               author = node_comment["authorText"]?.try &.["simpleText"]? || "" | ||||||
|  |  | ||||||
|  |               json.field "verified", (node_comment["authorCommentBadge"]? != nil) | ||||||
|  |  | ||||||
|               json.field "author", author |               json.field "author", author | ||||||
|               json.field "authorThumbnails" do |               json.field "authorThumbnails" do | ||||||
|                 json.array do |                 json.array do | ||||||
| @@ -329,7 +331,11 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false) | |||||||
|       end |       end | ||||||
|  |  | ||||||
|       author_name = HTML.escape(child["author"].as_s) |       author_name = HTML.escape(child["author"].as_s) | ||||||
|  |       if child["verified"]?.try &.as_bool && child["authorIsChannelOwner"]?.try &.as_bool | ||||||
|  |         author_name += " <i class=\"icon ion ion-md-checkmark-circle\"></i>" | ||||||
|  |       elsif child["verified"]?.try &.as_bool | ||||||
|  |         author_name += " <i class=\"icon ion ion-md-checkmark\"></i>" | ||||||
|  |       end | ||||||
|       html << <<-END_HTML |       html << <<-END_HTML | ||||||
|       <div class="pure-g" style="width:100%"> |       <div class="pure-g" style="width:100%"> | ||||||
|         <div class="channel-profile pure-u-4-24 pure-u-md-2-24"> |         <div class="channel-profile pure-u-4-24 pure-u-md-2-24"> | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ struct SearchVideo | |||||||
|   property live_now : Bool |   property live_now : Bool | ||||||
|   property premium : Bool |   property premium : Bool | ||||||
|   property premiere_timestamp : Time? |   property premiere_timestamp : Time? | ||||||
|  |   property author_verified : Bool | ||||||
|  |  | ||||||
|   def to_xml(auto_generated, query_params, xml : XML::Builder) |   def to_xml(auto_generated, query_params, xml : XML::Builder) | ||||||
|     query_params["v"] = self.id |     query_params["v"] = self.id | ||||||
| @@ -129,6 +130,7 @@ struct SearchPlaylist | |||||||
|   property video_count : Int32 |   property video_count : Int32 | ||||||
|   property videos : Array(SearchPlaylistVideo) |   property videos : Array(SearchPlaylistVideo) | ||||||
|   property thumbnail : String? |   property thumbnail : String? | ||||||
|  |   property author_verified : Bool | ||||||
|  |  | ||||||
|   def to_json(locale : String?, json : JSON::Builder) |   def to_json(locale : String?, json : JSON::Builder) | ||||||
|     json.object do |     json.object do | ||||||
| @@ -141,6 +143,8 @@ struct SearchPlaylist | |||||||
|       json.field "authorId", self.ucid |       json.field "authorId", self.ucid | ||||||
|       json.field "authorUrl", "/channel/#{self.ucid}" |       json.field "authorUrl", "/channel/#{self.ucid}" | ||||||
|  |  | ||||||
|  |       json.field "authorVerified", self.author_verified | ||||||
|  |  | ||||||
|       json.field "videoCount", self.video_count |       json.field "videoCount", self.video_count | ||||||
|       json.field "videos" do |       json.field "videos" do | ||||||
|         json.array do |         json.array do | ||||||
| @@ -182,6 +186,7 @@ struct SearchChannel | |||||||
|   property video_count : Int32 |   property video_count : Int32 | ||||||
|   property description_html : String |   property description_html : String | ||||||
|   property auto_generated : Bool |   property auto_generated : Bool | ||||||
|  |   property author_verified : Bool | ||||||
|  |  | ||||||
|   def to_json(locale : String?, json : JSON::Builder) |   def to_json(locale : String?, json : JSON::Builder) | ||||||
|     json.object do |     json.object do | ||||||
| @@ -189,7 +194,7 @@ struct SearchChannel | |||||||
|       json.field "author", self.author |       json.field "author", self.author | ||||||
|       json.field "authorId", self.ucid |       json.field "authorId", self.ucid | ||||||
|       json.field "authorUrl", "/channel/#{self.ucid}" |       json.field "authorUrl", "/channel/#{self.ucid}" | ||||||
|  |       json.field "authorVerified", self.author_verified | ||||||
|       json.field "authorThumbnails" do |       json.field "authorThumbnails" do | ||||||
|         json.array do |         json.array do | ||||||
|           qualities = {32, 48, 76, 100, 176, 512} |           qualities = {32, 48, 76, 100, 176, 512} | ||||||
|   | |||||||
| @@ -182,6 +182,7 @@ module Invidious::Routes::Feeds | |||||||
|         paid:               false, |         paid:               false, | ||||||
|         premium:            false, |         premium:            false, | ||||||
|         premiere_timestamp: nil, |         premiere_timestamp: nil, | ||||||
|  |         author_verified:    false, # 	¯\_(ツ)_/¯ | ||||||
|       }) |       }) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -613,6 +613,10 @@ struct Video | |||||||
|     info["authorThumbnail"]?.try &.as_s || "" |     info["authorThumbnail"]?.try &.as_s || "" | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def author_verified : Bool | ||||||
|  |     info["authorVerified"]?.try &.as_bool || false | ||||||
|  |   end | ||||||
|  |  | ||||||
|   def sub_count_text : String |   def sub_count_text : String | ||||||
|     info["subCountText"]?.try &.as_s || "-" |     info["subCountText"]?.try &.as_s || "-" | ||||||
|   end |   end | ||||||
| @@ -864,6 +868,12 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)? | |||||||
|     .try &.dig?("runs", 0) |     .try &.dig?("runs", 0) | ||||||
|  |  | ||||||
|   author = channel_info.try &.dig?("text") |   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) } |   ucid = channel_info.try { |ci| HelperExtractors.get_browse_id(ci) } | ||||||
|  |  | ||||||
|   # "4,088,033 views", only available on compact renderer |   # "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"), |     "length_seconds"   => JSON::Any.new(length || "0"), | ||||||
|     "view_count"       => JSON::Any.new(view_count || "0"), |     "view_count"       => JSON::Any.new(view_count || "0"), | ||||||
|     "short_view_count" => JSON::Any.new(short_view_count || "0"), |     "short_view_count" => JSON::Any.new(short_view_count || "0"), | ||||||
|  |     "author_verified"  => JSON::Any.new(author_verified), | ||||||
|   } |   } | ||||||
| end | 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_info = video_secondary_renderer.try &.dig?("owner", "videoOwnerRenderer") | ||||||
|   author_thumbnail = author_info.try &.dig?("thumbnail", "thumbnails", 0, "url") |   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["authorThumbnail"] = JSON::Any.new(author_thumbnail.try &.as_s || "") | ||||||
|  |  | ||||||
|   params["subCountText"] = JSON::Any.new(author_info.try &.["subscriberCountText"]? |   params["subCountText"] = JSON::Any.new(author_info.try &.["subscriberCountText"]? | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|     <div class="pure-u-2-3"> |     <div class="pure-u-2-3"> | ||||||
|         <div class="channel-profile"> |         <div class="channel-profile"> | ||||||
|             <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> |             <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> | ||||||
|             <span><%= author %></span> |             <span><%= author %></span><% if !channel.verified.nil? && channel.verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="pure-u-1-3"> |     <div class="pure-u-1-3"> | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
|     <div class="pure-u-2-3"> |     <div class="pure-u-2-3"> | ||||||
|         <div class="channel-profile"> |         <div class="channel-profile"> | ||||||
|             <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> |             <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> | ||||||
|             <span><%= author %></span> |             <span><%= author %></span><% if !channel.verified.nil? && channel.verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="pure-u-1-3" style="text-align:right"> |     <div class="pure-u-1-3" style="text-align:right"> | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|                         <img loading="lazy" style="width:56.25%" src="/ggpht<%= URI.parse(item.author_thumbnail).request_target.gsub(/=s\d+/, "=s176") %>"/> |                         <img loading="lazy" style="width:56.25%" src="/ggpht<%= URI.parse(item.author_thumbnail).request_target.gsub(/=s\d+/, "=s176") %>"/> | ||||||
|                     </center> |                     </center> | ||||||
|                 <% end %> |                 <% end %> | ||||||
|                 <p dir="auto"><%= HTML.escape(item.author) %></p> |                 <p dir="auto"><%= HTML.escape(item.author) %><% if !item.author_verified.nil? && item.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></p> | ||||||
|             </a> |             </a> | ||||||
|             <p><%= translate_count(locale, "generic_subscribers_count", item.subscriber_count, NumberFormatting::Separator) %></p> |             <p><%= translate_count(locale, "generic_subscribers_count", item.subscriber_count, NumberFormatting::Separator) %></p> | ||||||
|             <% if !item.auto_generated %><p><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %></p><% end %> |             <% if !item.auto_generated %><p><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %></p><% end %> | ||||||
| @@ -30,7 +30,7 @@ | |||||||
|                 <p dir="auto"><%= HTML.escape(item.title) %></p> |                 <p dir="auto"><%= HTML.escape(item.title) %></p> | ||||||
|             </a> |             </a> | ||||||
|             <a href="/channel/<%= item.ucid %>"> |             <a href="/channel/<%= item.ucid %>"> | ||||||
|                 <p dir="auto"><b><%= HTML.escape(item.author) %></b></p> |                 <p dir="auto"><b><%= HTML.escape(item.author) %><% if !item.is_a?(InvidiousPlaylist) && !item.author_verified.nil? && item.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></b></p> | ||||||
|             </a> |             </a> | ||||||
|         <% when MixVideo %> |         <% when MixVideo %> | ||||||
|             <a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>"> |             <a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>"> | ||||||
| @@ -142,7 +142,7 @@ | |||||||
|  |  | ||||||
|             <div class="video-card-row flexible"> |             <div class="video-card-row flexible"> | ||||||
|                 <div class="flex-left"><a href="/channel/<%= item.ucid %>"> |                 <div class="flex-left"><a href="/channel/<%= item.ucid %>"> | ||||||
|                     <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %></p> |                     <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %><% if !item.is_a?(ChannelVideo) && !item.author_verified.nil? && item.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></p> | ||||||
|                 </a></div> |                 </a></div> | ||||||
|  |  | ||||||
|                 <% endpoint_params = "?v=#{item.id}" %> |                 <% endpoint_params = "?v=#{item.id}" %> | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
|     <div class="pure-u-2-3"> |     <div class="pure-u-2-3"> | ||||||
|         <div class="channel-profile"> |         <div class="channel-profile"> | ||||||
|             <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> |             <img src="/ggpht<%= URI.parse(channel.author_thumbnail).request_target %>"> | ||||||
|             <span><%= author %></span> |             <span><%= author %></span><% if !channel.verified.nil? && channel.verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="pure-u-1-3" style="text-align:right"> |     <div class="pure-u-1-3" style="text-align:right"> | ||||||
|   | |||||||
| @@ -207,7 +207,7 @@ we're going to need to do it here in order to allow for translations. | |||||||
|                     <% if !video.author_thumbnail.empty? %> |                     <% if !video.author_thumbnail.empty? %> | ||||||
|                         <img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>"> |                         <img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>"> | ||||||
|                     <% end %> |                     <% end %> | ||||||
|                     <span id="channel-name"><%= author %></span> |                     <span id="channel-name"><%= author %><% if !video.author_verified.nil? && video.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></span> | ||||||
|                 </div> |                 </div> | ||||||
|             </a> |             </a> | ||||||
|  |  | ||||||
| @@ -281,9 +281,9 @@ we're going to need to do it here in order to allow for translations. | |||||||
|                                 <h5 class="pure-g"> |                                 <h5 class="pure-g"> | ||||||
|                                     <div class="pure-u-14-24"> |                                     <div class="pure-u-14-24"> | ||||||
|                                         <% if rv["ucid"]? %> |                                         <% if rv["ucid"]? %> | ||||||
|                                             <b style="width:100%"><a href="/channel/<%= rv["ucid"] %>"><%= rv["author"]? %></a></b> |                                             <b style="width:100%"><a href="/channel/<%= rv["ucid"] %>"><%= rv["author"]? %><% if rv["author_verified"]? == "true" %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></a></b> | ||||||
|                                         <% else %> |                                         <% else %> | ||||||
|                                             <b style="width:100%"><%= rv["author"]? %></b> |                                             <b style="width:100%"><%= rv["author"]? %><% if rv["author_verified"]? == "true" %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></b> | ||||||
|                                         <% end %> |                                         <% end %> | ||||||
|                                     </div> |                                     </div> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -102,7 +102,11 @@ private module Parsers | |||||||
|       premium = false |       premium = false | ||||||
|  |  | ||||||
|       premiere_timestamp = item_contents.dig?("upcomingEventData", "startTime").try { |t| Time.unix(t.as_s.to_i64) } |       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| |       item_contents["badges"]?.try &.as_a.each do |badge| | ||||||
|         b = badge["metadataBadgeRenderer"] |         b = badge["metadataBadgeRenderer"] | ||||||
|         case b["label"].as_s |         case b["label"].as_s | ||||||
| @@ -129,6 +133,7 @@ private module Parsers | |||||||
|         live_now:           live_now, |         live_now:           live_now, | ||||||
|         premium:            premium, |         premium:            premium, | ||||||
|         premiere_timestamp: premiere_timestamp, |         premiere_timestamp: premiere_timestamp, | ||||||
|  |         author_verified:    author_verified || false, | ||||||
|       }) |       }) | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -156,7 +161,11 @@ private module Parsers | |||||||
|     private def self.parse(item_contents, author_fallback) |     private def self.parse(item_contents, author_fallback) | ||||||
|       author = extract_text(item_contents["title"]) || author_fallback.name |       author = extract_text(item_contents["title"]) || author_fallback.name | ||||||
|       author_id = item_contents["channelId"]?.try &.as_s || author_fallback.id |       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) |       author_thumbnail = HelperExtractors.get_thumbnails(item_contents) | ||||||
|       # When public subscriber count is disabled, the subscriberCountText isn't sent by InnerTube. |       # When public subscriber count is disabled, the subscriberCountText isn't sent by InnerTube. | ||||||
|       # Always simpleText |       # Always simpleText | ||||||
| @@ -179,6 +188,7 @@ private module Parsers | |||||||
|         video_count:      video_count, |         video_count:      video_count, | ||||||
|         description_html: description_html, |         description_html: description_html, | ||||||
|         auto_generated:   auto_generated, |         auto_generated:   auto_generated, | ||||||
|  |         author_verified:  author_verified || false, | ||||||
|       }) |       }) | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -206,18 +216,23 @@ private module Parsers | |||||||
|     private def self.parse(item_contents, author_fallback) |     private def self.parse(item_contents, author_fallback) | ||||||
|       title = extract_text(item_contents["title"]) || "" |       title = extract_text(item_contents["title"]) || "" | ||||||
|       plid = item_contents["playlistId"]?.try &.as_s || "" |       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) |       video_count = HelperExtractors.get_video_count(item_contents) | ||||||
|       playlist_thumbnail = HelperExtractors.get_thumbnails(item_contents) |       playlist_thumbnail = HelperExtractors.get_thumbnails(item_contents) | ||||||
|  |  | ||||||
|       SearchPlaylist.new({ |       SearchPlaylist.new({ | ||||||
|         title:       title, |         title:           title, | ||||||
|         id:          plid, |         id:              plid, | ||||||
|         author:      author_fallback.name, |         author:          author_fallback.name, | ||||||
|         ucid:        author_fallback.id, |         ucid:            author_fallback.id, | ||||||
|         video_count: video_count, |         video_count:     video_count, | ||||||
|         videos:      [] of SearchPlaylistVideo, |         videos:          [] of SearchPlaylistVideo, | ||||||
|         thumbnail:   playlist_thumbnail, |         thumbnail:       playlist_thumbnail, | ||||||
|  |         author_verified: author_verified || false, | ||||||
|       }) |       }) | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -251,7 +266,11 @@ private module Parsers | |||||||
|       author_info = item_contents.dig?("shortBylineText", "runs", 0) |       author_info = item_contents.dig?("shortBylineText", "runs", 0) | ||||||
|       author = author_info.try &.["text"].as_s || author_fallback.name |       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_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| |       videos = item_contents["videos"]?.try &.as_a.map do |v| | ||||||
|         v = v["childVideoRenderer"] |         v = v["childVideoRenderer"] | ||||||
|         v_title = v.dig?("title", "simpleText").try &.as_s || "" |         v_title = v.dig?("title", "simpleText").try &.as_s || "" | ||||||
| @@ -267,13 +286,14 @@ private module Parsers | |||||||
|       # TODO: item_contents["publishedTimeText"]? |       # TODO: item_contents["publishedTimeText"]? | ||||||
|  |  | ||||||
|       SearchPlaylist.new({ |       SearchPlaylist.new({ | ||||||
|         title:       title, |         title:           title, | ||||||
|         id:          plid, |         id:              plid, | ||||||
|         author:      author, |         author:          author, | ||||||
|         ucid:        author_id, |         ucid:            author_id, | ||||||
|         video_count: video_count, |         video_count:     video_count, | ||||||
|         videos:      videos, |         videos:          videos, | ||||||
|         thumbnail:   playlist_thumbnail, |         thumbnail:       playlist_thumbnail, | ||||||
|  |         author_verified: author_verified || false, | ||||||
|       }) |       }) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Samantaz Fox
					Samantaz Fox