Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});

Expand Down
9 changes: 9 additions & 0 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/invidious/config.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 22 additions & 4 deletions src/invidious/helpers/utils.cr
Original file line number Diff line number Diff line change
Expand Up @@ -384,21 +384,39 @@ 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
io.write(cipher.update(data))
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
12 changes: 12 additions & 0 deletions src/invidious/routes/api/v1/videos.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions src/invidious/views/components/player.ecr
Original file line number Diff line number Diff line change
@@ -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 %>"
Expand Down
4 changes: 4 additions & 0 deletions src/invidious/views/embed.ecr
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<%
invidious_companion_check_id = invidious_companion_encrypt(video.id) if invidious_companion
%>

<!DOCTYPE html>
<html lang="<%= preferences.locale %>">

Expand Down
4 changes: 3 additions & 1 deletion src/invidious/views/watch.ecr
Original file line number Diff line number Diff line change
@@ -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 %>
Expand Down Expand Up @@ -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>
Expand Down