Merge 137ae95f558ab06119edb623124ff35c7fe502d7 into d51a7a44ad91d2fa7d1330970a15a0d8f365f250

This commit is contained in:
Fijxu 2026-01-23 15:32:28 -03:00 committed by GitHub
commit c8647e63e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 54 additions and 9 deletions

View File

@ -434,7 +434,7 @@ if (!video_data.params.listen && video_data.params.quality === 'dash') {
}
player.vttThumbnails({
src: '/api/v1/storyboards/' + video_data.id + '?height=90',
src: '/api/v1/storyboards/' + video_data.id + '?height=90' + `${video_data.invidious_companion_check_id ? `&check=${video_data.invidious_companion_check_id}` : ""}`,
showTimestamp: true
});

View File

@ -89,6 +89,15 @@ db:
##
#invidious_companion_key: "CHANGE_ME!!"
##
## Verify requests for endpoints that use Invidious companion
## to fetch data
##
## Accepted values: true, false
## Default: true
##
#invidious_companion_verify_requests: true
#########################################
#
# Server config

View File

@ -173,6 +173,9 @@ class Config
# Invidious companion API key
property invidious_companion_key : String = ""
# Verify requests on endpoints that use Invidious companion
property invidious_companion_verify_requests : Bool = true
# Saved cookies in "name1=value1; name2=value2..." format
@[YAML::Field(converter: Preferences::StringToCookies)]
property cookies : HTTP::Cookies = HTTP::Cookies.new

View File

@ -384,9 +384,13 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String)
return text
end
def encrypt_ecb_without_salt(data, key)
def ecb_without_salt(data, key, encrypt : Bool)
cipher = OpenSSL::Cipher.new("aes-128-ecb")
cipher.encrypt
if encrypt
cipher.encrypt
else
cipher.decrypt
end
cipher.key = key
io = IO::Memory.new
@ -394,11 +398,25 @@ def encrypt_ecb_without_salt(data, key)
io.write(cipher.final)
io.rewind
return io
if encrypt
return io
else
return io.gets_to_end
end
end
def invidious_companion_encrypt(data)
timestamp = Time.utc.to_unix
encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key)
encrypted_data = ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key, encrypt: true)
return Base64.urlsafe_encode(encrypted_data)
end
def invidious_companion_decrypt(check_id)
check_id_decoded = Base64.decode_string(check_id)
begin
decrypted_data = ecb_without_salt(check_id_decoded, CONFIG.invidious_companion_key, encrypt: false)
rescue
return nil
end
return decrypted_data.as(String).split("|")
end

View File

@ -181,6 +181,18 @@ module Invidious::Routes::API::V1::Videos
id = env.params.url["id"]
region = env.params.query["region"]?
if CONFIG.invidious_companion.present? && CONFIG.invidious_companion_verify_requests
invidious_companion_check_id = env.params.query["check"]?
if check_id = invidious_companion_check_id
video_id = invidious_companion_decrypt(check_id).try &.[1]
if id != video_id
haltf env, 401, "ID incorrect."
end
else
haltf env, 401, "No check ID."
end
end
begin
video = get_video(id, region: region)
rescue ex : NotFoundException

View File

@ -1,6 +1,3 @@
<%
invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion
%>
<video style="outline:none;width:100%;background-color:#000" playsinline poster="<%= thumbnail %>"
id="player" class="on-video_player video-js player-style-<%= params.player_style %>"
preload="<% if params.preload %>auto<% else %>none<% end %>"

View File

@ -1,3 +1,7 @@
<%
invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion
%>
<!DOCTYPE html>
<html lang="<%= preferences.locale %>">

View File

@ -1,6 +1,7 @@
<% ucid = video.ucid %>
<% title = HTML.escape(video.title) %>
<% author = HTML.escape(video.author) %>
<% invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion %>
<% content_for "header" do %>
@ -66,7 +67,8 @@ we're going to need to do it here in order to allow for translations.
"projection_type" => video.projection_type,
"local_disabled" => CONFIG.disabled?("local"),
"support_reddit" => true,
"live_now" => video.live_now
"live_now" => video.live_now,
"invidious_companion_check_id" => invidious_companion_check_id,
}.to_pretty_json
%>
</script>