summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/helpers.cr79
-rw-r--r--src/invidious.cr35
-rw-r--r--src/views/channel.ecr26
3 files changed, 140 insertions, 0 deletions
diff --git a/src/helpers.cr b/src/helpers.cr
index e7a1e688..040f09fe 100644
--- a/src/helpers.cr
+++ b/src/helpers.cr
@@ -670,3 +670,82 @@ def decode_time(string)
return time
end
+
+def produce_playlist_url(ucid, index)
+ ucid = ucid.lstrip("UC")
+ ucid = "VLUU" + ucid
+
+ continuation = write_var_int(index)
+ continuation.unshift(0x08_u8)
+ slice = continuation.to_unsafe.to_slice(continuation.size)
+
+ continuation = Base64.urlsafe_encode(slice, false)
+ continuation = "PT:" + continuation
+ continuation = continuation.bytes
+ continuation.unshift(0x7a_u8, continuation.size.to_u8)
+
+ slice = continuation.to_unsafe.to_slice(continuation.size)
+ continuation = Base64.urlsafe_encode(slice)
+ continuation = URI.escape(continuation)
+ continuation = continuation.bytes
+ continuation.unshift(continuation.size.to_u8)
+
+ continuation.unshift(ucid.size.to_u8)
+ continuation = ucid.bytes + continuation
+ continuation.unshift(0x12.to_u8, ucid.size.to_u8)
+ continuation.unshift(0xe2_u8, 0xa9_u8, 0x85_u8, 0xb2_u8, 2_u8, continuation.size.to_u8)
+
+ slice = continuation.to_unsafe.to_slice(continuation.size)
+ continuation = Base64.urlsafe_encode(slice)
+ continuation = URI.escape(continuation)
+
+ url = "/browse_ajax?action_continuation=1&continuation=#{continuation}"
+
+ return url
+end
+
+def read_var_int(bytes)
+ numRead = 0
+ result = 0
+
+ read = bytes[numRead]
+
+ if bytes.size == 1
+ result = bytes[0].to_i32
+ else
+ while ((read & 0b10000000) != 0)
+ read = bytes[numRead].to_u64
+ value = (read & 0b01111111)
+ result |= (value << (7 * numRead))
+
+ numRead += 1
+ if numRead > 5
+ raise "VarInt is too big"
+ end
+ end
+ end
+
+ return result
+end
+
+def write_var_int(value : Int)
+ bytes = [] of UInt8
+ value = value.to_u32
+
+ if value == 0
+ bytes = [0_u8]
+ else
+ while value != 0
+ temp = (value & 0b01111111).to_u8
+ value = value >> 7
+
+ if value != 0
+ temp |= 0b10000000
+ end
+
+ bytes << temp
+ end
+ end
+
+ return bytes
+end
diff --git a/src/invidious.cr b/src/invidious.cr
index f86d9331..679fd748 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -908,6 +908,41 @@ get "/videoplayback" do |env|
end
end
+get "/channel/:ucid" do |env|
+ ucid = env.params.url["ucid"]
+
+ page = env.params.query["page"]?.try &.to_i
+ page ||= 1
+
+ client = make_client(YT_URL)
+
+ if !ucid.starts_with? "UC"
+ rss = client.get("/feeds/videos.xml?user=#{ucid}").body
+ rss = XML.parse_html(rss)
+
+ ucid = rss.xpath_node("//feed/channelid").not_nil!.content
+ env.redirect "/channel/#{ucid}"
+ end
+
+ url = produce_playlist_url(ucid, (page - 1) * 100)
+ response = client.get(url)
+
+ json = JSON.parse(response.body)
+ document = XML.parse_html(json["content_html"].as_s)
+ author = document.xpath_node(%q(//div[@class="pl-video-owner"]/a)).not_nil!.content
+
+ videos = [] of ChannelVideo
+ document.xpath_nodes(%q(//a[contains(@class,"pl-video-title-link")])).each do |item|
+ href = URI.parse(item["href"])
+ id = HTTP::Params.parse(href.query.not_nil!)["v"]
+ title = item.content
+
+ videos << ChannelVideo.new(id, title, Time.now, Time.now, ucid, author)
+ end
+
+ templated "channel"
+end
+
options "/videoplayback" do |env|
env.response.headers["Access-Control-Allow-Origin"] = "*"
env.response.headers["Access-Control-Allow-Methods"] = "GET"
diff --git a/src/views/channel.ecr b/src/views/channel.ecr
new file mode 100644
index 00000000..857ad57a
--- /dev/null
+++ b/src/views/channel.ecr
@@ -0,0 +1,26 @@
+<% content_for "header" do %>
+<title><%= author %> - Invidious</title>
+<% end %>
+
+<h1><%= author %></h1>
+<% videos.each_slice(4) do |slice| %>
+<div class="pure-g">
+ <% slice.each do |video| %>
+ <%= rendered "components/video" %>
+ <% end %>
+</div>
+<% end %>
+
+<div class="pure-g">
+ <div class="pure-u-1 pure-u-md-1-5">
+ <% if page > 2 %>
+ <a href="/channel/<%= ucid %>?page=<%= page - 1 %>">Previous page</a>
+ <% else %>
+ <a href="/channel/<%= ucid %>">Previous page</a>
+ <% end %>
+ </div>
+ <div class="pure-u-1 pure-u-md-3-5"></div>
+ <div style="text-align:right;" class="pure-u-1 pure-u-md-1-5">
+ <a href="/channel/<%= ucid %>?page=<%= page + 1 %>">Next page</a>
+ </div>
+</div> \ No newline at end of file