mirror of
https://git.nadeko.net/Fijxu/invidious.git
synced 2025-12-19 11:28:51 +00:00
Add invidious companion support (#4985)
* add support for invidious companion * redirect latest_version and dash manifest to invidious companion * fix Shadowing outer local variable `response` * fixing condition for Content-Security-Policy * throw error if inv_sig_helper and invidious_companion used same time * Use sample instead of Random.rand Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> * Remove debug puts functions Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> * modify the description for config.example.yaml about invidious companion * move config checks for invidious companion * separate invidious_companion logic + better config.yaml config * fixing "end" misplacement * fix linting + use .empty? * crystal handle decompression already by itself * fix download function when invidious companion used * fix linting * invidious companion always used so always add CSP and redirect latest_version * apply all the suggestions + rework invidious_companion parameter * format watch.cr * fix ameba Redundant use of `Object#to_s` in interpolation * add ability for invidious companion to check request from invidious * Better document private_url and public_url * Better doc for invidious_companion_key * !empty? to present? * skip proxy for invidious companion * fixing format * missing , * add companion pooling http * fix: don't use http proxy when sending requests to companion * fix: logic where we want to have the invidious logic if companion is not used * chore: remove baseurl usage from invidious companion * chore: change from inv-sig-helper to companion for required playback * fix: use puts + add warning for inv-sig-helper deprecated --------- Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com>
This commit is contained in:
@@ -46,6 +46,43 @@ struct YoutubeConnectionPool
|
||||
end
|
||||
end
|
||||
|
||||
struct CompanionConnectionPool
|
||||
property pool : DB::Pool(HTTP::Client)
|
||||
|
||||
def initialize(capacity = 5, timeout = 5.0)
|
||||
options = DB::Pool::Options.new(
|
||||
initial_pool_size: 0,
|
||||
max_pool_size: capacity,
|
||||
max_idle_pool_size: capacity,
|
||||
checkout_timeout: timeout
|
||||
)
|
||||
|
||||
@pool = DB::Pool(HTTP::Client).new(options) do
|
||||
companion = CONFIG.invidious_companion.sample
|
||||
next make_client(companion.private_url, use_http_proxy: false)
|
||||
end
|
||||
end
|
||||
|
||||
def client(&)
|
||||
conn = pool.checkout
|
||||
|
||||
begin
|
||||
response = yield conn
|
||||
rescue ex
|
||||
conn.close
|
||||
|
||||
companion = CONFIG.invidious_companion.sample
|
||||
conn = make_client(companion.private_url, use_http_proxy: false)
|
||||
|
||||
response = yield conn
|
||||
ensure
|
||||
pool.release(conn)
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
def add_yt_headers(request)
|
||||
request.headers.delete("User-Agent") if request.headers["User-Agent"] == "Crystal"
|
||||
request.headers["User-Agent"] ||= "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
|
||||
@@ -61,9 +98,9 @@ def add_yt_headers(request)
|
||||
end
|
||||
end
|
||||
|
||||
def make_client(url : URI, region = nil, force_resolve : Bool = false, force_youtube_headers : Bool = false)
|
||||
def make_client(url : URI, region = nil, force_resolve : Bool = false, force_youtube_headers : Bool = false, use_http_proxy : Bool = true)
|
||||
client = HTTP::Client.new(url)
|
||||
client.proxy = make_configured_http_proxy_client() if CONFIG.http_proxy
|
||||
client.proxy = make_configured_http_proxy_client() if CONFIG.http_proxy && use_http_proxy
|
||||
|
||||
# Force the usage of a specific configured IP Family
|
||||
if force_resolve
|
||||
@@ -78,8 +115,8 @@ def make_client(url : URI, region = nil, force_resolve : Bool = false, force_you
|
||||
return client
|
||||
end
|
||||
|
||||
def make_client(url : URI, region = nil, force_resolve : Bool = false, &)
|
||||
client = make_client(url, region, force_resolve: force_resolve)
|
||||
def make_client(url : URI, region = nil, force_resolve : Bool = false, use_http_proxy : Bool = true, &)
|
||||
client = make_client(url, region, force_resolve: force_resolve, use_http_proxy: use_http_proxy)
|
||||
begin
|
||||
yield client
|
||||
ensure
|
||||
|
||||
@@ -500,7 +500,11 @@ module YoutubeAPI
|
||||
data["params"] = params
|
||||
end
|
||||
|
||||
return self._post_json("/youtubei/v1/player", data, client_config)
|
||||
if CONFIG.invidious_companion.present?
|
||||
return self._post_invidious_companion("/youtubei/v1/player", data)
|
||||
else
|
||||
return self._post_json("/youtubei/v1/player", data, client_config)
|
||||
end
|
||||
end
|
||||
|
||||
####################################################################
|
||||
@@ -666,6 +670,49 @@ module YoutubeAPI
|
||||
return initial_data
|
||||
end
|
||||
|
||||
####################################################################
|
||||
# _post_invidious_companion(endpoint, data)
|
||||
#
|
||||
# Internal function that does the actual request to Invidious companion
|
||||
# and handles errors.
|
||||
#
|
||||
# The requested data is an endpoint (URL without the domain part)
|
||||
# and the data as a Hash object.
|
||||
#
|
||||
def _post_invidious_companion(
|
||||
endpoint : String,
|
||||
data : Hash,
|
||||
) : Hash(String, JSON::Any)
|
||||
headers = HTTP::Headers{
|
||||
"Content-Type" => "application/json; charset=UTF-8",
|
||||
"Authorization" => "Bearer #{CONFIG.invidious_companion_key}",
|
||||
}
|
||||
|
||||
# Logging
|
||||
LOGGER.debug("Invidious companion: Using endpoint: \"#{endpoint}\"")
|
||||
LOGGER.trace("Invidious companion: POST data: #{data}")
|
||||
|
||||
# Send the POST request
|
||||
|
||||
begin
|
||||
response = COMPANION_POOL.client &.post(endpoint, headers: headers, body: data.to_json)
|
||||
body = response.body
|
||||
if (response.status_code != 200)
|
||||
raise Exception.new(
|
||||
"Error while communicating with Invidious companion: \
|
||||
status code: #{response.status_code} and body: #{body.dump}"
|
||||
)
|
||||
end
|
||||
rescue ex
|
||||
raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found"))
|
||||
end
|
||||
|
||||
# Convert result to Hash
|
||||
initial_data = JSON.parse(body).as_h
|
||||
|
||||
return initial_data
|
||||
end
|
||||
|
||||
####################################################################
|
||||
# _decompress(body_io, headers)
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user