Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channels: Add sort options to streams #4224

Merged
merged 8 commits into from
Jul 10, 2024
40 changes: 22 additions & 18 deletions src/invidious/channels/videos.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def produce_channel_videos_continuation(ucid, page = 1, auto_generated = nil, sort_by = "newest", v2 = false)
def produce_channel_content_continuation(ucid, content_type, page = 1, auto_generated = nil, sort_by = "newest", v2 = false)
object_inner_2 = {
"2:0:embedded" => {
"1:0:varint" => 0_i64,
Expand All @@ -16,6 +16,13 @@ def produce_channel_videos_continuation(ucid, page = 1, auto_generated = nil, so
.try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) }

content_type_numerical =
case content_type
when "videos" then 15
when "livestreams" then 14
else 15 # Fallback to "videos"
end

sort_by_numerical =
case sort_by
when "newest" then 1_i64
Expand All @@ -27,7 +34,7 @@ def produce_channel_videos_continuation(ucid, page = 1, auto_generated = nil, so
object_inner_1 = {
"110:embedded" => {
"3:embedded" => {
"15:embedded" => {
"#{content_type_numerical}:embedded" => {
"1:embedded" => {
"1:string" => object_inner_2_encoded,
},
Expand Down Expand Up @@ -62,9 +69,13 @@ def produce_channel_videos_continuation(ucid, page = 1, auto_generated = nil, so
return continuation
end

def make_initial_content_ctoken(ucid, content_type, sort_by) : String
return produce_channel_content_continuation(ucid, content_type, sort_by: sort_by)
end

# Used in bypass_captcha_job.cr
def produce_channel_videos_url(ucid, page = 1, auto_generated = nil, sort_by = "newest", v2 = false)
continuation = produce_channel_videos_continuation(ucid, page, auto_generated, sort_by, v2)
continuation = produce_channel_content_continuation(ucid, "videos", page, auto_generated, sort_by, v2)
return "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
end

Expand All @@ -75,10 +86,6 @@ module Invidious::Channel::Tabs
# Regular videos
# -------------------

def make_initial_video_ctoken(ucid, sort_by) : String
return produce_channel_videos_continuation(ucid, sort_by: sort_by)
end

# Wrapper for AboutChannel, as we still need to call get_videos with
# an author name and ucid directly (e.g in RSS feeds).
# TODO: figure out how to get rid of that
Expand All @@ -100,7 +107,7 @@ module Invidious::Channel::Tabs
end

def get_videos(author : String, ucid : String, *, continuation : String? = nil, sort_by = "newest")
continuation ||= make_initial_video_ctoken(ucid, sort_by)
continuation ||= make_initial_content_ctoken(ucid, "videos", sort_by)
initial_data = YoutubeAPI.browse(continuation: continuation)

return extract_items(initial_data, author, ucid)
Expand Down Expand Up @@ -144,21 +151,18 @@ module Invidious::Channel::Tabs
# Livestreams
# -------------------

def get_livestreams(channel : AboutChannel, continuation : String? = nil)
if continuation.nil?
# EgdzdHJlYW1z8gYECgJ6AA%3D%3D is the protobuf object to load "streams"
initial_data = YoutubeAPI.browse(channel.ucid, params: "EgdzdHJlYW1z8gYECgJ6AA%3D%3D")
else
initial_data = YoutubeAPI.browse(continuation: continuation)
end
def get_livestreams(channel : AboutChannel, continuation : String? = nil, sort_by = "newest")
continuation ||= make_initial_content_ctoken(channel.ucid, "livestreams", sort_by)

initial_data = YoutubeAPI.browse(continuation: continuation)

return extract_items(initial_data, channel.author, channel.ucid)
end

def get_60_livestreams(channel : AboutChannel, continuation : String? = nil)
def get_60_livestreams(channel : AboutChannel, *, continuation : String? = nil, sort_by = "newest")
if continuation.nil?
# Fetch the first "page" of streams
items, next_continuation = get_livestreams(channel)
# Fetch the first "page" of stream
items, next_continuation = get_livestreams(channel, sort_by: sort_by)
else
# Fetch a "page" of streams using the given continuation token
items, next_continuation = get_livestreams(channel, continuation: continuation)
Expand Down
3 changes: 2 additions & 1 deletion src/invidious/routes/api/v1/channels.cr
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,12 @@ module Invidious::Routes::API::V1::Channels
get_channel()

# Retrieve continuation from URL parameters
sort_by = env.params.query["sort_by"]?.try &.downcase || "newest"
continuation = env.params.query["continuation"]?

begin
videos, next_continuation = Channel::Tabs.get_60_livestreams(
channel, continuation: continuation
channel, continuation: continuation, sort_by: sort_by
)
rescue ex
return error_json(500, ex)
Expand Down
7 changes: 3 additions & 4 deletions src/invidious/routes/channels.cr
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,12 @@ module Invidious::Routes::Channels
return env.redirect "/channel/#{channel.ucid}"
end

# TODO: support sort option for livestreams
sort_by = ""
sort_options = [] of String
sort_by = env.params.query["sort_by"]?.try &.downcase
SamantazFox marked this conversation as resolved.
Show resolved Hide resolved
sort_options = {"newest", "oldest", "popular"}

# Fetch items and continuation token
items, next_continuation = Channel::Tabs.get_60_livestreams(
channel, continuation: continuation
channel, continuation: continuation, sort_by: (sort_by || "newest")
SamantazFox marked this conversation as resolved.
Show resolved Hide resolved
)

selected_tab = Frontend::ChannelPage::TabsAvailable::Streams
Expand Down