|
|
@ -1412,7 +1412,11 @@ get "/feed/channel/:ucid" do |env|
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
if auto_generated
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset)
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
|
|
|
|
end
|
|
|
|
else
|
|
|
|
else
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -1440,13 +1444,18 @@ get "/feed/channel/:ucid" do |env|
|
|
|
|
xml.element("entry") do
|
|
|
|
xml.element("entry") do
|
|
|
|
xml.element("id") { xml.text "yt:video:#{video.id}" }
|
|
|
|
xml.element("id") { xml.text "yt:video:#{video.id}" }
|
|
|
|
xml.element("yt:videoId") { xml.text video.id }
|
|
|
|
xml.element("yt:videoId") { xml.text video.id }
|
|
|
|
xml.element("yt:channelId") { xml.text ucid }
|
|
|
|
xml.element("yt:channelId") { xml.text video.ucid }
|
|
|
|
xml.element("title") { xml.text video.title }
|
|
|
|
xml.element("title") { xml.text video.title }
|
|
|
|
xml.element("link", rel: "alternate", href: "#{host_url}/watch?v=#{video.id}")
|
|
|
|
xml.element("link", rel: "alternate", href: "#{host_url}/watch?v=#{video.id}")
|
|
|
|
|
|
|
|
|
|
|
|
xml.element("author") do
|
|
|
|
xml.element("author") do
|
|
|
|
xml.element("name") { xml.text channel.author }
|
|
|
|
if auto_generated
|
|
|
|
xml.element("uri") { xml.text "#{host_url}/channel/#{ucid}" }
|
|
|
|
xml.element("name") { xml.text video.author }
|
|
|
|
|
|
|
|
xml.element("uri") { xml.text "#{host_url}/channel/#{video.ucid}" }
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
xml.element("name") { xml.text author }
|
|
|
|
|
|
|
|
xml.element("uri") { xml.text "#{host_url}/channel/#{ucid}" }
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
xml.element("published") { xml.text video.published.to_s("%Y-%m-%dT%H:%M:%S%:z") }
|
|
|
|
xml.element("published") { xml.text video.published.to_s("%Y-%m-%dT%H:%M:%S%:z") }
|
|
|
@ -1650,7 +1659,11 @@ get "/channel/:ucid" do |env|
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
if auto_generated
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset)
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
|
|
|
|
end
|
|
|
|
else
|
|
|
|
else
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -2296,7 +2309,11 @@ get "/api/v1/channels/:ucid" do |env|
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
if auto_generated
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset)
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
|
|
|
|
end
|
|
|
|
else
|
|
|
|
else
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -2390,6 +2407,16 @@ get "/api/v1/channels/:ucid" do |env|
|
|
|
|
json.field "title", video.title
|
|
|
|
json.field "title", video.title
|
|
|
|
json.field "videoId", video.id
|
|
|
|
json.field "videoId", video.id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if auto_generated
|
|
|
|
|
|
|
|
json.field "author", video.author
|
|
|
|
|
|
|
|
json.field "authorId", video.ucid
|
|
|
|
|
|
|
|
json.field "authorUrl", "/channel/#{video.ucid}"
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
json.field "author", author
|
|
|
|
|
|
|
|
json.field "authorId", ucid
|
|
|
|
|
|
|
|
json.field "authorUrl", "/channel/#{ucid}"
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
json.field "videoThumbnails" do
|
|
|
|
json.field "videoThumbnails" do
|
|
|
|
generate_thumbnails(json, video.id)
|
|
|
|
generate_thumbnails(json, video.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -2417,6 +2444,7 @@ get "/api/v1/channels/:ucid/videos" do |env|
|
|
|
|
page ||= 1
|
|
|
|
page ||= 1
|
|
|
|
|
|
|
|
|
|
|
|
client = make_client(YT_URL)
|
|
|
|
client = make_client(YT_URL)
|
|
|
|
|
|
|
|
|
|
|
|
if !ucid.match(/UC[a-zA-Z0-9_-]{22}/)
|
|
|
|
if !ucid.match(/UC[a-zA-Z0-9_-]{22}/)
|
|
|
|
rss = client.get("/feeds/videos.xml?user=#{ucid}")
|
|
|
|
rss = client.get("/feeds/videos.xml?user=#{ucid}")
|
|
|
|
rss = XML.parse_html(rss.body)
|
|
|
|
rss = XML.parse_html(rss.body)
|
|
|
@ -2428,43 +2456,62 @@ get "/api/v1/channels/:ucid/videos" do |env|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
ucid = ucid.content
|
|
|
|
ucid = ucid.content
|
|
|
|
url = "/api/v1/channels/#{ucid}/videos"
|
|
|
|
author = rss.xpath_node("//author/name").not_nil!.content
|
|
|
|
if env.params.query
|
|
|
|
next env.redirect "/feed/channel/#{ucid}"
|
|
|
|
url += "?#{env.params.query}"
|
|
|
|
else
|
|
|
|
|
|
|
|
rss = client.get("/feeds/videos.xml?channel_id=#{ucid}")
|
|
|
|
|
|
|
|
rss = XML.parse_html(rss.body)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ucid = rss.xpath_node("//feed/channelid")
|
|
|
|
|
|
|
|
if !ucid
|
|
|
|
|
|
|
|
error_message = "User does not exist."
|
|
|
|
|
|
|
|
next templated "error"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
next env.redirect url
|
|
|
|
|
|
|
|
|
|
|
|
ucid = ucid.content
|
|
|
|
|
|
|
|
author = rss.xpath_node("//author/name").not_nil!.content
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
url = produce_channel_videos_url(ucid, page)
|
|
|
|
# Auto-generated channels
|
|
|
|
response = client.get(url)
|
|
|
|
# https://support.google.com/youtube/answer/2579942
|
|
|
|
|
|
|
|
if author.ends_with? " - Topic"
|
|
|
|
|
|
|
|
auto_generated = true
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
url = produce_channel_videos_url(ucid, auto_generated: auto_generated)
|
|
|
|
|
|
|
|
response = client.get(url)
|
|
|
|
json = JSON.parse(response.body)
|
|
|
|
json = JSON.parse(response.body)
|
|
|
|
if !json["content_html"]?
|
|
|
|
|
|
|
|
env.response.content_type = "application/json"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if response.status_code == 500
|
|
|
|
if json["content_html"]? && !json["content_html"].as_s.empty?
|
|
|
|
response = {"Error" => "Channel does not exist"}.to_json
|
|
|
|
document = XML.parse_html(json["content_html"].as_s)
|
|
|
|
halt env, status_code: 404, response: response
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if auto_generated
|
|
|
|
|
|
|
|
videos = extract_videos(nodeset)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
next Array(String).new.to_json
|
|
|
|
videos = extract_videos(nodeset, ucid)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
videos = [] of SearchVideo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
content_html = json["content_html"].as_s
|
|
|
|
result = JSON.build do |json|
|
|
|
|
if content_html.empty?
|
|
|
|
|
|
|
|
env.response.content_type = "application/json"
|
|
|
|
|
|
|
|
next Hash(String, String).new.to_json
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
document = XML.parse_html(content_html)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
videos = JSON.build do |json|
|
|
|
|
|
|
|
|
json.array do
|
|
|
|
json.array do
|
|
|
|
nodeset = document.xpath_nodes(%q(//li[contains(@class, "feed-item-container")]))
|
|
|
|
videos.each do |video|
|
|
|
|
extract_videos(nodeset, ucid).each do |video|
|
|
|
|
|
|
|
|
json.object do
|
|
|
|
json.object do
|
|
|
|
json.field "title", video.title
|
|
|
|
json.field "title", video.title
|
|
|
|
json.field "videoId", video.id
|
|
|
|
json.field "videoId", video.id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if auto_generated
|
|
|
|
|
|
|
|
json.field "author", video.author
|
|
|
|
|
|
|
|
json.field "authorId", video.ucid
|
|
|
|
|
|
|
|
json.field "authorUrl", "/channel/#{video.ucid}"
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
json.field "author", author
|
|
|
|
|
|
|
|
json.field "authorId", ucid
|
|
|
|
|
|
|
|
json.field "authorUrl", "/channel/#{ucid}"
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
json.field "videoThumbnails" do
|
|
|
|
json.field "videoThumbnails" do
|
|
|
|
generate_thumbnails(json, video.id)
|
|
|
|
generate_thumbnails(json, video.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -2481,7 +2528,7 @@ get "/api/v1/channels/:ucid/videos" do |env|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
env.response.content_type = "application/json"
|
|
|
|
env.response.content_type = "application/json"
|
|
|
|
videos
|
|
|
|
result
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
get "/api/v1/search" do |env|
|
|
|
|
get "/api/v1/search" do |env|
|
|
|
@ -2527,6 +2574,7 @@ get "/api/v1/search" do |env|
|
|
|
|
json.field "videoId", video.id
|
|
|
|
json.field "videoId", video.id
|
|
|
|
|
|
|
|
|
|
|
|
json.field "author", video.author
|
|
|
|
json.field "author", video.author
|
|
|
|
|
|
|
|
json.field "authorId", video.ucid
|
|
|
|
json.field "authorUrl", "/channel/#{video.ucid}"
|
|
|
|
json.field "authorUrl", "/channel/#{video.ucid}"
|
|
|
|
|
|
|
|
|
|
|
|
json.field "videoThumbnails" do
|
|
|
|
json.field "videoThumbnails" do
|
|
|
|