-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
trying to only use next endpoint for the major data #5003
base: master
Are you sure you want to change the base?
Conversation
de76e24
to
250cffb
Compare
da00958
to
a340868
Compare
60a5c1c
to
9438a6d
Compare
Thank you very much for this. Looking at instance yewtu.be which uses invidious-custom, it seems to be working just as expected, exactly as described in my linked issue, and with a 100% success rate. Thank you for this great work - this is a huge step towards making Invidious convenient to use again. For me personally, it solves the entire problem. The only thing I can potentially suggest is for the video thumbnail to be loaded and displayed on the page, separately from the broken video player. But that would be just a nice-to-have feature, and I'm guessing it may not be trivial to implement, when the official Youtube website just shows a black error screen, with the thumbnail nowhere to be seen. |
if reason = info["reason"]? | ||
if info["reason"]? && info["subreason"]? | ||
reason = info["reason"].as_s | ||
puts info |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the debug puts here
next_steps = error_redirect_helper(env) | ||
error_message = <<-END_HTML | ||
<div class="error_message"> | ||
<h2>#{translate(locale, "error_processing_data_youtube")}</h2> | ||
<p>#{translate(locale, message)}</p> | ||
#{error_redirect_helper(env)} | ||
</div> | ||
END_HTML |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your changes here will show the Error while processing the data sent by YouTube
message on any InfoException
while also removing the next steps message on all InfoException
s
Example:
And InfoException
s are raised in places unrelated to YouTube as well such as when a user inserts the wrong password.
Related: #4651
@@ -4,5 +4,4 @@ | |||
|
|||
<div class="h-box"> | |||
<%= error_message %> | |||
<%= next_steps %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error page is used for everything and not just the watch page, so it must contain at least the "refresh" and "switch instance" buttons. Alternatively, we could split the error page logic for the watch page from the rest.
<%= translate(locale, "error_from_youtube_unplayable") %> <%= video.reason %> | ||
</h3> | ||
<h3> | ||
<%= translate(locale, "next_steps_error_message") %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably want to use error_redirect_helper()
. This error message alone (without any actions listed underneath) will be very confusing.
<span id="refresh-page"> | ||
<a href="<% env.request.resource %>"><%= translate(locale, "refresh_page") %></a> | ||
</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you add this link here? All browsers allow to refresh the page natively, and the close procimity with the "watch on youtube" link is prone to miss-clicks.
if !(video_details = player_response.dig?("videoDetails")) | ||
video_details = {} of String => JSON::Any | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you can use the more compact form:
if !(video_details = player_response.dig?("videoDetails")) | |
video_details = {} of String => JSON::Any | |
end | |
video_details = player_response.dig?("videoDetails") | |
video_details ||= {} of String => JSON::Any |
published_txt = video_primary_renderer | ||
.try &.dig?("dateText", "simpleText") | ||
|
||
if published_txt.try &.as_s.includes?("ago") && !published_txt.nil? | ||
published = decode_date(published_txt.as_s.lchop("Started streaming ")) | ||
elsif published_txt && published_txt.try &.as_s.matches?(/(\w{3} \d{1,2}, \d{4})$/) | ||
published = Time.parse(published_txt.as_s.match!(/(\w{3} \d{1,2}, \d{4})$/)[0], "%b %-d, %Y", Time::Location::UTC) | ||
else | ||
published = Time.utc | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I'd recommend using "scheduledStartTime"
(see below) in the player response, as it's more accurate and doesn't need complex parsing logic.
{
"playabilityStatus": {
"status": "LIVE_STREAM_OFFLINE",
"reason": "This live event will begin in 32 hours.",
"playableInEmbed": true,
"liveStreamability": {
"liveStreamabilityRenderer": {
"videoId": "hUoukmX_BRQ",
"offlineSlate": {
"liveStreamOfflineSlateRenderer": {
"scheduledStartTime": "1729468800",
"mainText": {
"runs": [
{"text": "Live in "},
{"text": "32 hours"}
]
},
"subtitleText": {
"simpleText": "October 21 at 12:00 AM"
}
}
}
}
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -96,7 +98,10 @@ we're going to need to do it here in order to allow for translations. | |||
|
|||
<% if video.reason %> | |||
<h3> | |||
<%= video.reason %> | |||
<%= translate(locale, "error_from_youtube_unplayable") %> <%= video.reason %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto: keeping the error message inside a player placeholder.
# dont error when it's a premiere. | ||
# we already parsed most of the data and display the premiere date | ||
raise InfoException.new(reason.as_s || "") | ||
raise NotFoundException.new(reason + ": Video not found" || "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That will expand to "Video unavailable: Video not found"
, which is not very explicit, imo.
if info.dig?("subreason").nil? | ||
subreason = info["subreason"].as_s | ||
else | ||
subreason = "No additional reason" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bloc of code can be summarized to the following, as you're already checking info["subreason"]?
falsiness in the parent if
if info.dig?("subreason").nil? | |
subreason = info["subreason"].as_s | |
else | |
subreason = "No additional reason" | |
end | |
subreason = info["subreason"].as_s |
@@ -313,7 +313,7 @@ def get_video(id, refresh = true, region = nil, force_refresh = false) | |||
end | |||
else | |||
video = fetch_video(id, region) | |||
Invidious::Database::Videos.insert(video) if !region | |||
Invidious::Database::Videos.insert(video) if !region && !video.info.dig?("reason") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should make a getter dunction inside the Video
class for reason/subreason.
"reason" => JSON::Any.new(reason), | ||
"version" => JSON::Any.new(Video::SCHEMA_VERSION.to_i64), | ||
"reason" => JSON::Any.new(reason), | ||
"subreason" => JSON::Any.new(subreason), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to bump SCHEMA_VERSION
in the Video
class!
Description
This PR aims to avoid throwing a raw error and instead display all the data that we can extract from the /next endpoint but without displaying the "player" (video.js) element.
This is one big step towards #4985. Invidious will have to be able to display the watch page even when YouTube is blocking the IP.
This will give the same result as on www.youtube.com:
This way the user can still view the title of the video, accessing the channel page, viewing the comments and much more which is not yet blocked.
What changed?
TODO
Try these videos ID for testing - on both a blocked IP and a not blocked one
Fixes