mirror of https://github.com/iv-org/invidious.git
Add channel page
This commit is contained in:
parent
e865a801aa
commit
36ba69be1f
|
@ -670,3 +670,82 @@ def decode_time(string)
|
||||||
|
|
||||||
return time
|
return time
|
||||||
end
|
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
|
||||||
|
|
|
@ -908,6 +908,41 @@ get "/videoplayback" do |env|
|
||||||
end
|
end
|
||||||
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|
|
options "/videoplayback" do |env|
|
||||||
env.response.headers["Access-Control-Allow-Origin"] = "*"
|
env.response.headers["Access-Control-Allow-Origin"] = "*"
|
||||||
env.response.headers["Access-Control-Allow-Methods"] = "GET"
|
env.response.headers["Access-Control-Allow-Methods"] = "GET"
|
||||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue