forked from midou/invidious
		
	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,
 | 
			
		||||
  is_family_friendly : Bool,
 | 
			
		||||
  allowed_regions : Array(String),
 | 
			
		||||
  tabs : Array(String)
 | 
			
		||||
  tabs : Array(String),
 | 
			
		||||
  verified : Bool
 | 
			
		||||
 | 
			
		||||
record AboutRelatedChannel,
 | 
			
		||||
  ucid : String,
 | 
			
		||||
@@ -70,6 +71,9 @@ def get_about_info(ucid, locale) : AboutChannel
 | 
			
		||||
    # if banner.includes? "channels/c4/default_banner"
 | 
			
		||||
    #  banner = nil
 | 
			
		||||
    # 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_html = HTML.escape(description)
 | 
			
		||||
@@ -128,6 +132,7 @@ def get_about_info(ucid, locale) : AboutChannel
 | 
			
		||||
    is_family_friendly: is_family_friendly,
 | 
			
		||||
    allowed_regions: allowed_regions,
 | 
			
		||||
    tabs: tabs,
 | 
			
		||||
    verified: author_verified || false,
 | 
			
		||||
  )
 | 
			
		||||
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) } || ""
 | 
			
		||||
              author = node_comment["authorText"]?.try &.["simpleText"]? || ""
 | 
			
		||||
 | 
			
		||||
              json.field "verified", (node_comment["authorCommentBadge"]? != nil)
 | 
			
		||||
 | 
			
		||||
              json.field "author", author
 | 
			
		||||
              json.field "authorThumbnails" do
 | 
			
		||||
                json.array do
 | 
			
		||||
@@ -329,7 +331,11 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      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
 | 
			
		||||
      <div class="pure-g" style="width:100%">
 | 
			
		||||
        <div class="channel-profile pure-u-4-24 pure-u-md-2-24">
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
 
 | 
			
		||||
@@ -182,6 +182,7 @@ module Invidious::Routes::Feeds
 | 
			
		||||
        paid:               false,
 | 
			
		||||
        premium:            false,
 | 
			
		||||
        premiere_timestamp: nil,
 | 
			
		||||
        author_verified:    false, # 	¯\_(ツ)_/¯
 | 
			
		||||
      })
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"]?
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
    <div class="pure-u-2-3">
 | 
			
		||||
        <div class="channel-profile">
 | 
			
		||||
            <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 class="pure-u-1-3">
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
    <div class="pure-u-2-3">
 | 
			
		||||
        <div class="channel-profile">
 | 
			
		||||
            <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 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") %>"/>
 | 
			
		||||
                    </center>
 | 
			
		||||
                <% 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>
 | 
			
		||||
            <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 %>
 | 
			
		||||
@@ -30,7 +30,7 @@
 | 
			
		||||
                <p dir="auto"><%= HTML.escape(item.title) %></p>
 | 
			
		||||
            </a>
 | 
			
		||||
            <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>
 | 
			
		||||
        <% when MixVideo %>
 | 
			
		||||
            <a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>">
 | 
			
		||||
@@ -142,7 +142,7 @@
 | 
			
		||||
 | 
			
		||||
            <div class="video-card-row flexible">
 | 
			
		||||
                <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>
 | 
			
		||||
 | 
			
		||||
                <% endpoint_params = "?v=#{item.id}" %>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
    <div class="pure-u-2-3">
 | 
			
		||||
        <div class="channel-profile">
 | 
			
		||||
            <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 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? %>
 | 
			
		||||
                        <img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>">
 | 
			
		||||
                    <% 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>
 | 
			
		||||
            </a>
 | 
			
		||||
 | 
			
		||||
@@ -281,9 +281,9 @@ we're going to need to do it here in order to allow for translations.
 | 
			
		||||
                                <h5 class="pure-g">
 | 
			
		||||
                                    <div class="pure-u-14-24">
 | 
			
		||||
                                        <% 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 %>
 | 
			
		||||
                                            <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 %>
 | 
			
		||||
                                    </div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user