mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-03 22:21:55 +00:00 
			
		
		
		
	Add filters to '/api/v1/search' endpoint
This commit is contained in:
		@@ -2569,14 +2569,44 @@ get "/api/v1/search" do |env|
 | 
			
		||||
  page = env.params.query["page"]?.try &.to_i?
 | 
			
		||||
  page ||= 1
 | 
			
		||||
 | 
			
		||||
  sort_by = env.params.query["sort_by"]?.try &.downcase
 | 
			
		||||
  sort_by ||= "relevance"
 | 
			
		||||
 | 
			
		||||
  date = env.params.query["date"]?.try &.downcase
 | 
			
		||||
  date ||= ""
 | 
			
		||||
 | 
			
		||||
  duration = env.params.query["date"]?.try &.downcase
 | 
			
		||||
  duration ||= ""
 | 
			
		||||
 | 
			
		||||
  features = env.params.query["features"]?.try &.split(",").map { |feature| feature.downcase }
 | 
			
		||||
  features ||= [] of String
 | 
			
		||||
 | 
			
		||||
  # TODO: Support other content types
 | 
			
		||||
  content_type = "video"
 | 
			
		||||
 | 
			
		||||
  begin
 | 
			
		||||
    search_params = build_search_params(sort_by, date, content_type, duration, features)
 | 
			
		||||
  rescue ex
 | 
			
		||||
    env.response.content_type = "application/json"
 | 
			
		||||
    next JSON.build do |json|
 | 
			
		||||
      json.object do
 | 
			
		||||
        json.field "error", ex.message
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  client = make_client(YT_URL)
 | 
			
		||||
  html = client.get("/results?q=#{URI.escape(query)}&page=#{page}&sp=EgIQAVAU&disable_polymer=1").body
 | 
			
		||||
  html = client.get("/results?q=#{URI.escape(query)}&page=#{page}&sp=#{search_params}&disable_polymer=1").body
 | 
			
		||||
  html = XML.parse_html(html)
 | 
			
		||||
 | 
			
		||||
  results = JSON.build do |json|
 | 
			
		||||
    json.array do
 | 
			
		||||
      html.xpath_nodes(%q(//ol[@class="item-section"]/li)).each do |node|
 | 
			
		||||
        anchor = node.xpath_node(%q(.//h3[contains(@class,"yt-lockup-title")]/a)).not_nil!
 | 
			
		||||
        anchor = node.xpath_node(%q(.//h3[contains(@class,"yt-lockup-title")]/a))
 | 
			
		||||
        if !anchor
 | 
			
		||||
          next
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if anchor["href"].starts_with? "https://www.googleadservices.com"
 | 
			
		||||
          next
 | 
			
		||||
        end
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
def search(query, page = 1)
 | 
			
		||||
def search(query, page = 1, search_params = build_search_params(content_type: "video"))
 | 
			
		||||
  client = make_client(YT_URL)
 | 
			
		||||
  html = client.get("/results?q=#{URI.escape(query)}&page=#{page}&sp=EgIQAVAU").body
 | 
			
		||||
  html = client.get("/results?q=#{URI.escape(query)}&page=#{page}&sp=#{search_params}").body
 | 
			
		||||
  html = XML.parse_html(html)
 | 
			
		||||
 | 
			
		||||
  videos = [] of ChannelVideo
 | 
			
		||||
@@ -28,3 +28,97 @@ def search(query, page = 1)
 | 
			
		||||
 | 
			
		||||
  return videos
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def build_search_params(sort_by = "relevance", date : String = "", content_type : String = "", duration : String = "", features : Array(String) = [] of String)
 | 
			
		||||
  head = "\x08"
 | 
			
		||||
  head += case sort_by
 | 
			
		||||
          when "relevance"
 | 
			
		||||
            "\x00"
 | 
			
		||||
          when "rating"
 | 
			
		||||
            "\x01"
 | 
			
		||||
          when "upload_date"
 | 
			
		||||
            "\x02"
 | 
			
		||||
          when "view_count"
 | 
			
		||||
            "\x03"
 | 
			
		||||
          else
 | 
			
		||||
            raise "No sort #{sort_by}"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
  body = ""
 | 
			
		||||
  body += case date
 | 
			
		||||
          when "hour"
 | 
			
		||||
            "\x08\x01"
 | 
			
		||||
          when "today"
 | 
			
		||||
            "\x08\x02"
 | 
			
		||||
          when "week"
 | 
			
		||||
            "\x08\x03"
 | 
			
		||||
          when "month"
 | 
			
		||||
            "\x08\x04"
 | 
			
		||||
          when "year"
 | 
			
		||||
            "\x08\x05"
 | 
			
		||||
          else
 | 
			
		||||
            ""
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
  body += case content_type
 | 
			
		||||
          when "video"
 | 
			
		||||
            "\x10\x01"
 | 
			
		||||
          when "channel"
 | 
			
		||||
            "\x10\x02"
 | 
			
		||||
          when "playlist"
 | 
			
		||||
            "\x10\x03"
 | 
			
		||||
          when "movie"
 | 
			
		||||
            "\x10\x04"
 | 
			
		||||
          when "show"
 | 
			
		||||
            "\x10\x05"
 | 
			
		||||
          else
 | 
			
		||||
            ""
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
  body += case duration
 | 
			
		||||
          when "short"
 | 
			
		||||
            "\x18\x01"
 | 
			
		||||
          when "long"
 | 
			
		||||
            "\x18\x02"
 | 
			
		||||
          else
 | 
			
		||||
            ""
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
  features.each do |feature|
 | 
			
		||||
    body += case feature
 | 
			
		||||
            when "hd"
 | 
			
		||||
              "\x20\x01"
 | 
			
		||||
            when "subtitles"
 | 
			
		||||
              "\x28\x01"
 | 
			
		||||
            when "creative_commons"
 | 
			
		||||
              "\x30\x01"
 | 
			
		||||
            when "3d"
 | 
			
		||||
              "\x38\x01"
 | 
			
		||||
            when "live"
 | 
			
		||||
              "\x40\x01"
 | 
			
		||||
            when "purchased"
 | 
			
		||||
              "\x48\x01"
 | 
			
		||||
            when "4k"
 | 
			
		||||
              "\x70\x01"
 | 
			
		||||
            when "360"
 | 
			
		||||
              "\x78\x01"
 | 
			
		||||
            when "location"
 | 
			
		||||
              "\xb8\x01\x01"
 | 
			
		||||
            when "hdr"
 | 
			
		||||
              "\xc8\x01\x01"
 | 
			
		||||
            else
 | 
			
		||||
              raise "Unknown feature #{feature}"
 | 
			
		||||
            end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  if body.size > 0
 | 
			
		||||
    token = head + "\x12" + body.size.to_u8.unsafe_chr + body
 | 
			
		||||
  else
 | 
			
		||||
    token = head
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  token = Base64.urlsafe_encode(token)
 | 
			
		||||
  token = URI.escape(token)
 | 
			
		||||
 | 
			
		||||
  return token
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user