Merge remote-tracking branch 'upstream/master'
All checks were successful
Invidious CI / build (push) Successful in 5m23s

This commit is contained in:
Fijxu 2024-11-13 21:14:26 -03:00
commit 9b9efc6841
Signed by: Fijxu
GPG key ID: 32C1DDF333EDA6A4
6 changed files with 116 additions and 35 deletions

View file

@ -3,8 +3,84 @@
## vX.Y.0 (future) ## vX.Y.0 (future)
## v2.20241110.0
### Wrap-up
This release is most importantly here to fix to the annoying "Youtube API returned error 400"
error that prevented all channel pages from loading.
If you're updating from the previous release, it provides no improvements on the ability to play
videos. If updating from a commit in-between release, it removes the "Please sign in" error caused
by a previous attempt at restoring video playback on large instances.
In the preferences, a new option allows for control of video preload. When enabled, this option
tells the browser to load the video as soon as the page is loaded (this used to be the default).
When disabled, the video starts loading only when the "play" button is pressed.
New interface languages available: Bulgarian, Welsh and Lombard
New dependency required: `tzdata`.
An HTTP proxy can be configured directly in Invidious, if needed. \
**NOTE:** In that case, it is recommended to comment out `force_resolve`.
### New features & important changes
#### For users
* Channels: Fix "Youtube API returned error 400" error preventing channel pages from loading
* Channels: Shorts can now be sorted by "newest", "oldest" and "popular"
* Preferences: Addition of the new "preload" option
* New interface languages available: Bulgarian, Welsh and Lombard
* Added "Filipino (auto-generated)" to the list of caption languages available
* Lots of new translations from Weblate
#### For instance owners
* Allow the configuration of an HTTP proxy to talk to Youtube
* Invidious tries to reconnect to `inv_sig_helper` if the socket is closed
* The instance list is downloaded in the background to improve redirection speed
* New `colorize_logs` option makes each log level a different color
#### For developpers
* `/api/v1/channels/{id}/shorts` now supports the `sort-by` parameter with the following values:
`newest`, `oldest` and `popular`
* Older `/api/v1/channels/xyz/{id}` (tab name before UCID) were removed
* API/Search: New video metadata available: `isNew`, `is4k`, `is8k`, `isVr180`, `isVr360`,
`is3d` and `hasCaptions`
### Bugs fixed
#### User-side
* Channels: The second page of shorts now loads as expected
* Channels: Fixed intermittent empty "playlists" tab
* Search: Fixed `youtu.be` URLs not being properly redirected to the watch page
* Fixed `DB::MappingException` error on the subscriptions feed (due to missing `tzdata` in docker)
* Switching to another instance is much faster
* Fixed an "invalid byte sequence" error when subscribing to a playlist
* Videos: Playback URLs were sometimes broken when cached and `inv_sig_helper` was used
#### For instance owners
* Fix `force_resolve` being ignored in some cases
#### API
* API/Videos: Fixed `live_now` and `premiere_timestamp` sometimes not having the right values
### Full list of pull requests merged since the last release (newest first) ### Full list of pull requests merged since the last release (newest first)
* API: Add "sort_by" parameter to channels/shorts endpoint ([#5071], thanks @iBicha)
* Docker: Install tzdata in Dockerfile ([#5070], by @SamantazFox)
* Videos: Stop using TVHTML5_SIMPLY_EMBEDDED_PLAYER ([#5063], thanks @unixfox)
* Routing: Deprecate old channel API routes ([#5045], by @SamantazFox)
* Videos: use WEB client instead of WEB CREATOR ([#4984], thanks @unixfox)
* Parsers: Fix parsing live_now and premiere_timestamp ([#4934], thanks @absidue)
* Stale bot updates ([#5060], thanks @syeopite) * Stale bot updates ([#5060], thanks @syeopite)
* Channels: Fix "Youtube API returned error 400" ([#5059], by @SamantazFox) * Channels: Fix "Youtube API returned error 400" ([#5059], by @SamantazFox)
* Channels: Fix for live videos ([#5027], thanks @iBicha) * Channels: Fix for live videos ([#5027], thanks @iBicha)
@ -52,15 +128,21 @@
[#4928]: https://github.com/iv-org/invidious/pull/4928 [#4928]: https://github.com/iv-org/invidious/pull/4928
[#4930]: https://github.com/iv-org/invidious/pull/4930 [#4930]: https://github.com/iv-org/invidious/pull/4930
[#4931]: https://github.com/iv-org/invidious/pull/4931 [#4931]: https://github.com/iv-org/invidious/pull/4931
[#4934]: https://github.com/iv-org/invidious/pull/4934
[#4942]: https://github.com/iv-org/invidious/pull/4942 [#4942]: https://github.com/iv-org/invidious/pull/4942
[#4984]: https://github.com/iv-org/invidious/pull/4984
[#4991]: https://github.com/iv-org/invidious/pull/4991 [#4991]: https://github.com/iv-org/invidious/pull/4991
[#4993]: https://github.com/iv-org/invidious/pull/4993 [#4993]: https://github.com/iv-org/invidious/pull/4993
[#4995]: https://github.com/iv-org/invidious/pull/4995 [#4995]: https://github.com/iv-org/invidious/pull/4995
[#5027]: https://github.com/iv-org/invidious/pull/5027 [#5027]: https://github.com/iv-org/invidious/pull/5027
[#5034]: https://github.com/iv-org/invidious/pull/5034 [#5034]: https://github.com/iv-org/invidious/pull/5034
[#5045]: https://github.com/iv-org/invidious/pull/5045
[#5046]: https://github.com/iv-org/invidious/pull/5046 [#5046]: https://github.com/iv-org/invidious/pull/5046
[#5059]: https://github.com/iv-org/invidious/pull/5059 [#5059]: https://github.com/iv-org/invidious/pull/5059
[#5060]: https://github.com/iv-org/invidious/pull/5060 [#5060]: https://github.com/iv-org/invidious/pull/5060
[#5063]: https://github.com/iv-org/invidious/pull/5063
[#5070]: https://github.com/iv-org/invidious/pull/5070
[#5071]: https://github.com/iv-org/invidious/pull/5071
## v2.20240825.2 (2024-08-26) ## v2.20240825.2 (2024-08-26)

View file

@ -1,5 +1,6 @@
FROM alpine:3.19 AS builder FROM alpine:3.20 AS builder
RUN apk add --no-cache 'crystal=1.10.1-r0' shards sqlite-static yaml-static yaml-dev libxml2-static zlib-static openssl-libs-static openssl-dev musl-dev xz-static RUN apk add --no-cache 'crystal=1.12.2-r0' shards sqlite-static yaml-static yaml-dev libxml2-static \
zlib-static openssl-libs-static openssl-dev musl-dev xz-static
ARG release ARG release
@ -32,8 +33,8 @@ RUN if [[ "${release}" == 1 ]] ; then \
--link-flags "-lxml2 -llzma"; \ --link-flags "-lxml2 -llzma"; \
fi fi
FROM alpine:3.18 FROM alpine:3.20
RUN apk add --no-cache rsvg-convert ttf-opensans tini RUN apk add --no-cache rsvg-convert ttf-opensans tini tzdata
WORKDIR /invidious WORKDIR /invidious
RUN addgroup -g 1000 -S invidious && \ RUN addgroup -g 1000 -S invidious && \
adduser -u 1000 -S invidious -G invidious adduser -u 1000 -S invidious -G invidious

View file

@ -1,13 +1,12 @@
name: invidious name: invidious
version: 0.20.1 version: 2.20241110.0-dev
authors: authors:
- Omar Roth <omarroth@protonmail.com> - Invidious team <contact@invidious.io>
- Invidious team - Contributors!
targets: description: |
invidious: Invidious is an alternative front-end to YouTube
main: src/invidious.cr
dependencies: dependencies:
pg: pg:
@ -45,6 +44,10 @@ development_dependencies:
github: crystal-ameba/ameba github: crystal-ameba/ameba
version: ~> 1.6.1 version: ~> 1.6.1
crystal: ">= 1.0.0, < 2.0.0" crystal: ">= 1.10.0, < 2.0.0"
license: AGPLv3 license: AGPLv3
repository: https://github.com/iv-org/invidious
homepage: https://invidious.io
documentation: https://docs.invidious.io

View file

@ -197,6 +197,7 @@ module Invidious::Routes::API::V1::Channels
get_channel() get_channel()
# Retrieve continuation from URL parameters # Retrieve continuation from URL parameters
sort_by = env.params.query["sort_by"]?.try &.downcase || "newest"
continuation = env.params.query["continuation"]? continuation = env.params.query["continuation"]?
if channel.is_age_gated if channel.is_age_gated
@ -211,7 +212,7 @@ module Invidious::Routes::API::V1::Channels
else else
begin begin
videos, next_continuation = Channel::Tabs.get_shorts( videos, next_continuation = Channel::Tabs.get_shorts(
channel, continuation: continuation channel, continuation: continuation, sort_by: sort_by
) )
rescue ex rescue ex
return error_json(500, ex) return error_json(500, ex)

View file

@ -244,17 +244,16 @@ module Invidious::Routing
# Channels # Channels
get "/api/v1/channels/:ucid", {{namespace}}::Channels, :home get "/api/v1/channels/:ucid", {{namespace}}::Channels, :home
get "/api/v1/channels/:ucid/latest", {{namespace}}::Channels, :latest
get "/api/v1/channels/:ucid/videos", {{namespace}}::Channels, :videos
get "/api/v1/channels/:ucid/shorts", {{namespace}}::Channels, :shorts get "/api/v1/channels/:ucid/shorts", {{namespace}}::Channels, :shorts
get "/api/v1/channels/:ucid/streams", {{namespace}}::Channels, :streams get "/api/v1/channels/:ucid/streams", {{namespace}}::Channels, :streams
get "/api/v1/channels/:ucid/podcasts", {{namespace}}::Channels, :podcasts get "/api/v1/channels/:ucid/podcasts", {{namespace}}::Channels, :podcasts
get "/api/v1/channels/:ucid/releases", {{namespace}}::Channels, :releases get "/api/v1/channels/:ucid/releases", {{namespace}}::Channels, :releases
get "/api/v1/channels/:ucid/playlists", {{namespace}}::Channels, :playlists
get "/api/v1/channels/:ucid/community", {{namespace}}::Channels, :community
get "/api/v1/channels/:ucid/channels", {{namespace}}::Channels, :channels get "/api/v1/channels/:ucid/channels", {{namespace}}::Channels, :channels
get "/api/v1/channels/:ucid/search", {{namespace}}::Channels, :search
{% for route in {"videos", "latest", "playlists", "community", "search"} %}
get "/api/v1/channels/#{{{route}}}/:ucid", {{namespace}}::Channels, :{{route}}
get "/api/v1/channels/:ucid/#{{{route}}}", {{namespace}}::Channels, :{{route}}
{% end %}
# Posts # Posts
get "/api/v1/post/:id", {{namespace}}::Channels, :post get "/api/v1/post/:id", {{namespace}}::Channels, :post
@ -272,11 +271,6 @@ module Invidious::Routing
# Authenticated # Authenticated
# The notification APIs cannot be extracted yet! They require the *local* notifications constant defined in invidious.cr
#
# Invidious::Routing.get "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications
# Invidious::Routing.post "/api/v1/auth/notifications", {{namespace}}::Authenticated, :notifications
get "/api/v1/auth/preferences", {{namespace}}::Authenticated, :get_preferences get "/api/v1/auth/preferences", {{namespace}}::Authenticated, :get_preferences
post "/api/v1/auth/preferences", {{namespace}}::Authenticated, :set_preferences post "/api/v1/auth/preferences", {{namespace}}::Authenticated, :set_preferences

View file

@ -107,8 +107,8 @@ def extract_video_info(video_id : String, user_po_token, user_visitor_data)
new_player_response = nil new_player_response = nil
# Don't use Android client if po_token is passed because po_token doesn't # Don't use Android test suite client if po_token is passed because po_token doesn't
# work for Android client. # work for Android test suite client.
if reason.nil? && po_token.nil? if reason.nil? && po_token.nil?
# Fetch the video streams using an Android client in order to get the # Fetch the video streams using an Android client in order to get the
# decrypted URLs and maybe fix throttling issues (#2194). See the # decrypted URLs and maybe fix throttling issues (#2194). See the
@ -118,15 +118,6 @@ def extract_video_info(video_id : String, user_po_token, user_visitor_data)
new_player_response = try_fetch_streaming_data(video_id, client_config, po_token, visitor_data) new_player_response = try_fetch_streaming_data(video_id, client_config, po_token, visitor_data)
end end
# Last hope
# Only trigger if reason found and po_token or didn't work wth Android client.
# TvHtml5ScreenEmbed now requires sig helper for it to work but po_token is not required
# if the IP address is not blocked.
if po_token.nil? && reason || po_token.nil? && new_player_response.nil?
client_config.client_type = YoutubeAPI::ClientType::TvHtml5ScreenEmbed
new_player_response = try_fetch_streaming_data(video_id, client_config, po_token, visitor_data)
end
# Replace player response and reset reason # Replace player response and reset reason
if !new_player_response.nil? if !new_player_response.nil?
# Preserve captions & storyboard data before replacement # Preserve captions & storyboard data before replacement
@ -229,8 +220,17 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
premiere_timestamp = microformat.dig?("liveBroadcastDetails", "startTimestamp") premiere_timestamp = microformat.dig?("liveBroadcastDetails", "startTimestamp")
.try { |t| Time.parse_rfc3339(t.as_s) } .try { |t| Time.parse_rfc3339(t.as_s) }
premiere_timestamp ||= player_response.dig?(
"playabilityStatus", "liveStreamability",
"liveStreamabilityRenderer", "offlineSlate",
"liveStreamOfflineSlateRenderer", "scheduledStartTime"
)
.try &.as_s.to_i64
.try { |t| Time.unix(t) }
live_now = microformat.dig?("liveBroadcastDetails", "isLiveNow") live_now = microformat.dig?("liveBroadcastDetails", "isLiveNow")
.try &.as_bool || false .try &.as_bool
live_now ||= video_details.dig?("isLive").try &.as_bool || false
post_live_dvr = video_details.dig?("isPostLiveDvr") post_live_dvr = video_details.dig?("isPostLiveDvr")
.try &.as_bool || false .try &.as_bool || false