From f80f4f2521786bd979d25584df7b8a926e8058d1 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 22 Sep 2018 10:49:42 -0500 Subject: [PATCH] Add '/api/v1/channels/search' --- src/invidious.cr | 101 ++++++++++++++++++++++++++++++- src/invidious/helpers/helpers.cr | 10 +-- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 65d5b109..bdd00b0f 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -2598,7 +2598,104 @@ end end end +get "/api/v1/channels/search/:ucid" do |env| + env.response.content_type = "application/json" + + ucid = env.params.url["ucid"] + + query = env.params.query["q"]? + query ||= "" + + page = env.params.query["page"]?.try &.to_i? + page ||= 1 + + count, search_results = channel_search(query, page, ucid) + response = JSON.build do |json| + json.array do + search_results.each do |item| + json.object do + case item + when SearchVideo + json.field "type", "video" + json.field "title", item.title + json.field "videoId", item.id + + json.field "author", item.author + json.field "authorId", item.ucid + json.field "authorUrl", "/channel/#{item.ucid}" + + json.field "videoThumbnails" do + generate_thumbnails(json, item.id) + end + + json.field "description", item.description + json.field "descriptionHtml", item.description_html + + json.field "viewCount", item.views + json.field "published", item.published.epoch + json.field "publishedText", "#{recode_date(item.published)} ago" + json.field "lengthSeconds", item.length_seconds + json.field "liveNow", item.live_now + when SearchPlaylist + json.field "type", "playlist" + json.field "title", item.title + json.field "playlistId", item.id + + json.field "author", item.author + json.field "authorId", item.ucid + json.field "authorUrl", "/channel/#{item.ucid}" + + json.field "videos" do + json.array do + item.videos.each do |video| + json.object do + json.field "title", video.title + json.field "videoId", video.id + json.field "lengthSeconds", video.length_seconds + + json.field "videoThumbnails" do + generate_thumbnails(json, video.id) + end + end + end + end + end + when SearchChannel + json.field "type", "channel" + json.field "author", item.author + json.field "authorId", item.ucid + json.field "authorUrl", "/channel/#{item.ucid}" + + json.field "authorThumbnails" do + json.array do + qualities = [32, 48, 76, 100, 176, 512] + + qualities.each do |quality| + json.object do + json.field "url", item.author_thumbnail.gsub("=s176-", "=s#{quality}-") + json.field "width", quality + json.field "height", quality + end + end + end + end + + json.field "subCount", item.subscriber_count + json.field "videoCount", item.video_count + json.field "description", item.description + json.field "descriptionHtml", item.description_html + end + end + end + end + end + + response +end + get "/api/v1/search" do |env| + env.response.content_type = "application/json" + query = env.params.query["q"]? query ||= "" @@ -2621,8 +2718,6 @@ get "/api/v1/search" do |env| content_type = env.params.query["type"]?.try &.downcase content_type ||= "video" - env.response.content_type = "application/json" - begin search_params = produce_search_params(sort_by, date, content_type, duration, features) rescue ex @@ -2634,9 +2729,9 @@ get "/api/v1/search" do |env| end end + count, search_results = search(query, page, search_params).as(Tuple) response = JSON.build do |json| json.array do - count, search_results = search(query, page, search_params).as(Tuple) search_results.each do |item| json.object do case item diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr index fa0d5de4..e1fc4d52 100644 --- a/src/invidious/helpers/helpers.cr +++ b/src/invidious/helpers/helpers.cr @@ -220,7 +220,7 @@ def extract_items(nodeset, ucid = nil) author = "" author_id = "" else - author = anchor.content + author = anchor.content.strip author_id = anchor["href"].split("/")[-1] end @@ -234,7 +234,7 @@ def extract_items(nodeset, ucid = nil) description_html = node.xpath_node(%q(.//div[contains(@class, "yt-lockup-description")])) description_html, description = html_to_content(description_html) - case node.xpath_node(%q(.//div)).not_nil!["class"] + case node.xpath_node(%q(.//div[contains(@class, "yt-lockup-tile")])).not_nil!["class"] when .includes? "yt-lockup-playlist" plid = HTTP::Params.parse(URI.parse(id).query.not_nil!)["list"] @@ -245,10 +245,10 @@ def extract_items(nodeset, ucid = nil) video_count ||= 0 videos = [] of SearchPlaylistVideo - node.xpath_nodes(%q(.//ol[contains(@class, "yt-lockup-playlist-items")]/li)).each do |video| + node.xpath_nodes(%q(.//*[contains(@class, "yt-lockup-playlist-items")]/li)).each do |video| anchor = video.xpath_node(%q(.//a)) if anchor - video_title = anchor.content + video_title = anchor.content.strip id = HTTP::Params.parse(URI.parse(anchor["href"]).query.not_nil!)["v"] end video_title ||= "" @@ -276,7 +276,7 @@ def extract_items(nodeset, ucid = nil) videos ) when .includes? "yt-lockup-channel" - author = title + author = title.strip ucid = id.split("/")[-1] author_thumbnail = node.xpath_node(%q(.//div/span/img)).try &.["data-thumb"]?