summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/invidious.cr182
-rw-r--r--src/invidious/channels.cr29
2 files changed, 67 insertions, 144 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index b151a090..c2e174a1 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -1399,43 +1399,17 @@ get "/feed/subscriptions" do |env|
end
get "/feed/channel/:ucid" do |env|
+ env.response.content_type = "text/xml"
ucid = env.params.url["ucid"]
- client = make_client(YT_URL)
-
- if !ucid.match(/UC[a-zA-Z0-9_-]{22}/)
- rss = client.get("/feeds/videos.xml?user=#{ucid}")
- rss = XML.parse_html(rss.body)
-
- ucid = rss.xpath_node("//feed/channelid")
- if !ucid
- error_message = "User does not exist."
- halt env, status_code: 404, response: error_message
- end
-
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
- next env.redirect "/feed/channel/#{ucid}"
- 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
-
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
+ begin
+ author, ucid, auto_generated = get_about_info(ucid)
+ rescue ex
+ error_message = "User does not exist"
+ halt env, status_code: 404, response: error_message
end
- # Auto-generated channels
- # https://support.google.com/youtube/answer/2579942
- if author.ends_with?(" - Topic") ||
- {"Popular on YouTube", "Music", "Sports", "Gaming"}.includes? author
- auto_generated = true
- end
+ client = make_client(YT_URL)
page = 1
@@ -1459,8 +1433,6 @@ get "/feed/channel/:ucid" do |env|
end
end
- channel = get_channel(ucid, client, PG_DB, pull_all_videos: false)
-
host_url = make_host_url(Kemal.config.ssl || CONFIG.https_only, env.request.headers["Host"]?)
path = env.request.path
@@ -1470,11 +1442,11 @@ get "/feed/channel/:ucid" do |env|
xml.element("link", rel: "self", href: "#{host_url}#{path}")
xml.element("id") { xml.text "yt:channel:#{ucid}" }
xml.element("yt:channelId") { xml.text ucid }
- xml.element("title") { xml.text channel.author }
+ xml.element("title") { xml.text author }
xml.element("link", rel: "alternate", href: "#{host_url}/channel/#{ucid}")
xml.element("author") do
- xml.element("name") { xml.text channel.author }
+ xml.element("name") { xml.text author }
xml.element("uri") { xml.text "#{host_url}/channel/#{ucid}" }
end
@@ -1513,7 +1485,6 @@ get "/feed/channel/:ucid" do |env|
end
end
- env.response.content_type = "text/xml"
feed
end
@@ -1691,40 +1662,11 @@ get "/channel/:ucid" do |env|
page = env.params.query["page"]?.try &.to_i?
page ||= 1
- client = make_client(YT_URL)
-
- if !ucid.match(/UC[a-zA-Z0-9_-]{22}/)
- rss = client.get("/feeds/videos.xml?user=#{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
-
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
- next env.redirect "/channel/#{ucid}"
- 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
-
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
- end
-
- # Auto-generated channels
- # https://support.google.com/youtube/answer/2579942
- if author.ends_with?(" - Topic") ||
- {"Popular on YouTube", "Music", "Sports", "Gaming"}.includes? author
- auto_generated = true
+ begin
+ author, ucid, auto_generated = get_about_info(ucid)
+ rescue ex
+ error_message = "User does not exist"
+ next templated "error"
end
if !auto_generated
@@ -1735,6 +1677,8 @@ get "/channel/:ucid" do |env|
end
end
+ client = make_client(YT_URL)
+
videos = [] of SearchVideo
2.times do |i|
url = produce_channel_videos_url(ucid, page * 2 + (i - 1), auto_generated: auto_generated)
@@ -2175,8 +2119,8 @@ get "/api/v1/videos/:id" do |env|
video = get_video(id, PG_DB)
rescue ex
env.response.content_type = "application/json"
- response = {"error" => ex.message}.to_json
- halt env, status_code: 500, response: response
+ error_message = {"error" => ex.message}.to_json
+ halt env, status_code: 500, response: error_message
end
fmt_stream = video.fmt_stream(decrypt_function)
@@ -2425,42 +2369,20 @@ get "/api/v1/top" do |env|
end
get "/api/v1/channels/:ucid" do |env|
- ucid = env.params.url["ucid"]
-
- client = make_client(YT_URL)
- if !ucid.match(/UC[a-zA-Z0-9_-]{22}/)
- rss = client.get("/feeds/videos.xml?user=#{ucid}")
- rss = XML.parse_html(rss.body)
-
- ucid = rss.xpath_node("//feed/channelid")
- if !ucid
- env.response.content_type = "application/json"
- next {"error" => "User does not exist"}.to_json
- end
+ env.response.content_type = "application/json"
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
- next env.redirect "/api/v1/channels/#{ucid}"
- else
- rss = client.get("/feeds/videos.xml?channel_id=#{ucid}")
- rss = XML.parse_html(rss.body)
+ ucid = env.params.url["ucid"]
- ucid = rss.xpath_node("//feed/channelid")
- if !ucid
- error_message = "User does not exist."
- next templated "error"
- end
+ begin
+ author, ucid, auto_generated = get_about_info(ucid)
+ rescue ex
+ puts ex.message
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
+ error_message = {"error" => "User does not exist"}.to_json
+ halt env, status_code: 404, response: error_message
end
- # Auto-generated channels
- # https://support.google.com/youtube/answer/2579942
- if author.ends_with?(" - Topic") ||
- {"Popular on YouTube", "Music", "Sports", "Gaming"}.includes? author
- auto_generated = true
- end
+ client = make_client(YT_URL)
page = 1
@@ -2601,51 +2523,25 @@ get "/api/v1/channels/:ucid" do |env|
end
end
- env.response.content_type = "application/json"
channel_info
end
["/api/v1/channels/:ucid/videos", "/api/v1/channels/videos/:ucid"].each do |route|
get route do |env|
+ env.response.content_type = "application/json"
+
ucid = env.params.url["ucid"]
page = env.params.query["page"]?.try &.to_i?
page ||= 1
- client = make_client(YT_URL)
-
- if !ucid.match(/UC[a-zA-Z0-9_-]{22}/)
- rss = client.get("/feeds/videos.xml?user=#{ucid}")
- rss = XML.parse_html(rss.body)
-
- ucid = rss.xpath_node("//feed/channelid")
- if !ucid
- env.response.content_type = "application/json"
- next {"error" => "User does not exist"}.to_json
- end
-
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
- next env.redirect "/feed/channel/#{ucid}"
- 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
-
- ucid = ucid.content
- author = rss.xpath_node("//author/name").not_nil!.content
+ begin
+ author, ucid, auto_generated = get_about_info(ucid)
+ rescue ex
+ error_message = {"error" => "User does not exist"}.to_json
+ halt env, status_code: 404, response: error_message
end
- # Auto-generated channels
- # https://support.google.com/youtube/answer/2579942
- if author.ends_with?(" - Topic") ||
- {"Popular on YouTube", "Music", "Sports", "Gaming"}.includes? author
- auto_generated = true
- end
+ client = make_client(YT_URL)
videos = [] of SearchVideo
2.times do |i|
@@ -2700,7 +2596,6 @@ end
end
end
- env.response.content_type = "application/json"
result
end
end
@@ -2826,6 +2721,7 @@ get "/api/v1/search" do |env|
end
get "/api/v1/playlists/:plid" do |env|
+ env.response.content_type = "application/json"
plid = env.params.url["plid"]
page = env.params.query["page"]?.try &.to_i?
@@ -2834,9 +2730,8 @@ get "/api/v1/playlists/:plid" do |env|
begin
videos = extract_playlist(plid, page)
rescue ex
- env.response.content_type = "application/json"
- response = {"error" => "Playlist is empty"}.to_json
- halt env, status_code: 404, response: response
+ error_message = {"error" => "Playlist is empty"}.to_json
+ halt env, status_code: 404, response: error_message
end
playlist = fetch_playlist(plid)
@@ -2881,7 +2776,6 @@ get "/api/v1/playlists/:plid" do |env|
end
end
- env.response.content_type = "application/json"
response
end
diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr
index 02e260ad..672d3c04 100644
--- a/src/invidious/channels.cr
+++ b/src/invidious/channels.cr
@@ -176,3 +176,32 @@ def produce_channel_videos_url(ucid, page = 1, auto_generated = nil)
return url
end
+
+def get_about_info(ucid)
+ client = make_client(YT_URL)
+
+ about = client.get("/user/#{ucid}/about?disable_polymer=1")
+ about = XML.parse_html(about.body)
+
+ if !about.xpath_node(%q(//span[@class="qualified-channel-title-text"]/a))
+ about = client.get("/channel/#{ucid}/about?disable_polymer=1")
+ about = XML.parse_html(about.body)
+ end
+
+ if !about.xpath_node(%q(//span[@class="qualified-channel-title-text"]/a))
+ raise "User does not exist."
+ end
+
+ author = about.xpath_node(%q(//span[@class="qualified-channel-title-text"]/a)).not_nil!.content
+ ucid = about.xpath_node(%q(//link[@rel="canonical"])).not_nil!["href"].split("/")[-1]
+
+ # Auto-generated channels
+ # https://support.google.com/youtube/answer/2579942
+ auto_generated = false
+ if about.xpath_node(%q(//ul[@class="about-custom-links"]/li/a[@title="Auto-generated by YouTube"])) ||
+ about.xpath_node(%q(//span[@class="qualified-channel-title-badge"]/span[@title="Auto-generated by YouTube"]))
+ auto_generated = true
+ end
+
+ return {author, ucid, auto_generated}
+end