Add filters to '/api/v1/search' endpoint

This commit is contained in:
Omar Roth 2018-08-04 17:12:58 -05:00
parent 3f0c823798
commit 3ada6a9234
2 changed files with 128 additions and 4 deletions

View file

@ -2569,14 +2569,44 @@ get "/api/v1/search" do |env|
page = env.params.query["page"]?.try &.to_i? page = env.params.query["page"]?.try &.to_i?
page ||= 1 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) 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) html = XML.parse_html(html)
results = JSON.build do |json| results = JSON.build do |json|
json.array do json.array do
html.xpath_nodes(%q(//ol[@class="item-section"]/li)).each do |node| 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" if anchor["href"].starts_with? "https://www.googleadservices.com"
next next
end end

View file

@ -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) 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) html = XML.parse_html(html)
videos = [] of ChannelVideo videos = [] of ChannelVideo
@ -28,3 +28,97 @@ def search(query, page = 1)
return videos return videos
end 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