diff --git a/CHANGELOG.md b/CHANGELOG.md index f84dc790..5af38003 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,102 +2,7 @@ ## vX.Y.0 (future) -## v2.20250314.0 -### Wrap-up - -This release brings the long awaited feature of supporting multiple audio tracks in a video, some bug fixes and UX improvements, and many other things primarily oriented to self-hosting instances, and developers using the API. - -The `Community` channel tab has been replaced by `Posts` in light of YouTube changes, but the URL remains the same. - -Tamil is now available as an interface language - -Automatic instance redirects will no longer have the chance to annoyingly redirect to the same instance you're on. - -Due to their requirements for video playback, Invidious will log warning messages when either inv-sig-helper, `po_token` or `visitor_data` is not configured - -Invidious is now able to listen through a UNIX socket - -User notifications are now batched for each channel - -**The minimum Crystal version supported by Invidious now `1.12.0`** - -### New features & important changes - -#### For users - -* Invidious now supports videos with multiple audio tracks allowing you to select which one you want to hear with! -* Channel pages now have a proper previous page button -* RSS feeds for channels will no longer contain the channel's profile picture -* Support for channel `courses` page has been added -* `Community` tabs has been replaced with `Posts` to comply with YouTube changes -* Tamil is now an available interface language. - -#### For instance owners -* Invidious is now able to listen on a UNIX socket -* User notifications are now batched by channels, significantly reducing database load. -* **`1.12.0` is now the oldest Crystal version that Invidious supports** -* The example config will no longer force an http proxy to be configured -* Invidious will now warn when any top-level config option must be set to a custom value, instead of just `HMAC_KEY` -* Due to their requirements for video playback, Invidious will log warning messages when either inv-sig-helper, `po_token` or `visitor_data` is not configured - -#### For developers -* Invidious is now compliant to Crystal 1.15 formatting rules, which are incompatible with earlier versions. -* `/api/v1/transcripts/{id}` has been added to the API to allow for fetching the transcripts for a video. The arguments are the same as the captions endpoint. -* `author_thumbnail` field has been added to videos in the various paged api endpoints -* `published` field has been added to the API response for a video's related videos. -* Docker builds now uses the Crystal compiler cache, reducing build times on repeated builds significantly. -* Invidious ajax action handlers has undergone a clean up and may face compatibility issues with code that depends on these endpoints. -* The versions of Crystal that we test in CI/CD are now: `1.12.1`, `1.13.2`, `1.14.0`, `1.15.0` - -### Bugs fixed - -#### User-side -* Local video listen mode is now preserved when clicking on a video in the sidebar playlist widget -* Automatic instance redirects will no longer redirect to the same instance the user is on -* Fix some thumbnails responses returning 404 -* Videos: Fix missing host parameter on playback URLs when `local=true` -* Fix HLS being used for non-livestream videos -* Fix timeupdate event errors when required elements are missing -* User: Ensure IO is properly closed when importing NewPipe subscriptions - -#### For instance owners -* Fix http proxy configuration being forced by the standard example config - -#### API -* `/api/v1/videos/{id}` will no longer return an occasional empty JSON response - -### Full list of pull requests merged since the last release (newest first) -* Make Invidious compliant to Crystal 1.15 formatting rules (https://github.com/iv-org/invidious/pull/5014, by @syeopite) -* Remove formatter check on container workflows (https://github.com/iv-org/invidious/pull/5153, by @syeopite) -* Videos: Fix missing host parameter on playback URLs when `local=true` (https://github.com/iv-org/invidious/pull/4992, by @SamantazFox) -* Remove stdlib override for proxy initialization (https://github.com/iv-org/invidious/pull/5065, by @syeopite) -* Add support for author thumbnails in search api for videos (https://github.com/iv-org/invidious/pull/5072, thanks @ChunkyProgrammer) -* Skip route if resp got closed by before handlers (https://github.com/iv-org/invidious/pull/5073, by @syeopite) -* Fix video thumbnails in mixes (https://github.com/iv-org/invidious/pull/5116, thanks @iBicha) -* CI: Drop support for versions prior to 1.12 and add 1.15.0 (https://github.com/iv-org/invidious/pull/5148, by @syeopite) -* [Continuing #5094] Set language info for dash audio streams and sort (https://github.com/iv-org/invidious/pull/5149, thanks @giuliano-macedo) -* Warn when any top-level config is "CHANGE_ME!!" (https://github.com/iv-org/invidious/pull/5150, by @syeopite) -* Comment out http_proxy in example config (https://github.com/iv-org/invidious/pull/5151, by @syeopite) -* API: Add a 'published' video parameter for related videos (https://github.com/iv-org/invidious/pull/4149, thanks @RadoslavL) -* Ensure IO is properly closed when importing NewPipe subscriptions (https://github.com/iv-org/invidious/pull/4346, thanks @ChunkyProgrammer) -* Carry over audio-only mode in playlist links (https://github.com/iv-org/invidious/pull/4784, thanks @krystof1119) -* Routes: Clean ajax actions handlers (https://github.com/iv-org/invidious/pull/5036, by @SamantazFox) -* Frontend: Add a first page and previous page buttons for channel navigation (https://github.com/iv-org/invidious/pull/4123, thanks @RadoslavL) -* RSS: Channel + Playlist improvements (https://github.com/iv-org/invidious/pull/4298, thanks @ChunkyProgrammer) -* Batch user notifications together (https://github.com/iv-org/invidious/pull/4486, thanks @999eagle) -* JS: Update timeupdate event making it more defensive to prevent errors (https://github.com/iv-org/invidious/pull/4782, thanks @PMK) -* Add API endpoint for fetching transcripts from YouTube by (https://github.com/iv-org/invidious/pull/4788, by @syeopite) -* Translations update from Hosted Weblate by (https://github.com/iv-org/invidious/pull/4989, thanks to our many translators) -* Add the ability to listen on UNIX sockets (https://github.com/iv-org/invidious/pull/5112, thanks @Caian) -* Pick a different instance upon redirect (https://github.com/iv-org/invidious/pull/5154, thanks @epicsam123) -* Add Courses to channel page and channel API (https://github.com/iv-org/invidious/pull/5158, thanks @ChunkyProgrammer) -* fix /api/v1/videos/:id returns 200 with no content (https://github.com/iv-org/invidious/pull/5162, thanks @Drikanis) -* Use Crystal compiler cache in docker builds (https://github.com/iv-org/invidious/pull/5163, by @syeopite) -* Channels: Fix community tab by (https://github.com/iv-org/invidious/pull/5183, thanks @Fijxu) -* Fix typo in `src/invidious/routes/images.cr` (https://github.com/iv-org/invidious/pull/5184, by @syeopite) -* Fix an issue with the HLS manifest check for livestream videos (https://github.com/iv-org/invidious/pull/5189, thanks @alexmaras) -* Warn when `po_token`, `visitor_data` and/or `inv-sig-helper` is not configured (https://github.com/iv-org/invidious/pull/5202, by @syeopite) ## v2.20241110.0 ### Wrap-up diff --git a/config/config.example.yml b/config/config.example.yml index d6119f29..b04e0a30 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -54,53 +54,6 @@ db: ## #signature_server: -## -## Invidious companion is an external program -## for loading the video streams from YouTube servers. -## -## When this setting is commented out, Invidious companion is not used. -## Otherwise, Invidious will proxy the requests to Invidious companion. -## -## Note: multiple URL can be configured. In this case, invidious will -## randomly pick one every time video data needs to be retrieved. This -## URL is then kept in the video metadata cache to allow video playback -## to work. Once said cache has expired, requesting that video's data -## again will cause a new companion URL to be picked. -## -## The parameter private_url needs to be configured for the internal -## communication between the companion and Invidious. -## And public_url is the public URL from which companion is listening -## to the requests from the user(s). -## -## If you are using a reverse proxy then you will probably need to -## configure the public_url to be the same as the domain used for Invidious. -## Also apply when used from an external IP address (without a domain). -## Examples: https://MYINVIDIOUSDOMAIN or http://192.168.1.100:8282 -## -## Both parameter can have identical URL when Invidious is hosted in -## an internal network or at home or locally (localhost). -## -## Accepted values: "http(s)://:" -## Default: -## -#invidious_companion: -# - private_url: "http://localhost:8282" -# public_url: "http://localhost:8282" - -## -## API key for Invidious companion, used for securing the communication -## between Invidious and Invidious companion. -## The size of the key needs to be more or equal to 16. -## -## Note: This parameter is mandatory when Invidious companion is enabled -## and should be a random string. -## Such random string can be generated on linux with the following -## command: `pwgen 16 1` -## -## Accepted values: a string -## Default: -## -#invidious_companion_key: "CHANGE_ME!!" ######################################### # @@ -858,9 +811,9 @@ default_user_preferences: ## Default video quality. ## ## Accepted values: dash, hd720, medium, small - ## Default: dash + ## Default: hd720 ## - #quality: dash + #quality: hd720 ## ## Default dash video quality. diff --git a/shard.yml b/shard.yml index de2b99e4..af7e4186 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 2.20250314.0-dev +version: 2.20241110.0-dev authors: - Invidious team diff --git a/src/invidious.cr b/src/invidious.cr index d3300ece..12ffad33 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -97,10 +97,6 @@ YT_POOL = YoutubeConnectionPool.new(YT_URL, capacity: CONFIG.pool_size) GGPHT_POOL = YoutubeConnectionPool.new(URI.parse("https://yt3.ggpht.com"), capacity: CONFIG.pool_size) -COMPANION_POOL = CompanionConnectionPool.new( - capacity: CONFIG.pool_size -) - # CLI Kemal.config.extra_options do |parser| parser.banner = "Usage: invidious [arguments]" diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 4d69854c..453256b5 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -35,7 +35,7 @@ struct ConfigPreferences property max_results : Int32 = 40 property notifications_only : Bool = false property player_style : String = "invidious" - property quality : String = "dash" + property quality : String = "hd720" property quality_dash : String = "auto" property default_home : String? = "Popular" property feed_menu : Array(String) = ["Popular", "Trending", "Subscriptions", "Playlists"] @@ -74,16 +74,6 @@ end class Config include YAML::Serializable - class CompanionConfig - include YAML::Serializable - - @[YAML::Field(converter: Preferences::URIConverter)] - property private_url : URI = URI.parse("") - - @[YAML::Field(converter: Preferences::URIConverter)] - property public_url : URI = URI.parse("") - end - # Number of threads to use for crawling videos from channels (for updating subscriptions) property channel_threads : Int32 = 1 # Time interval between two executions of the job that crawls channel videos (subscriptions update). @@ -170,12 +160,6 @@ class Config # poToken for passing bot attestation property po_token : String? = nil - # Invidious companion - property invidious_companion : Array(CompanionConfig) = [] of CompanionConfig - - # Invidious companion API key - property invidious_companion_key : String = "" - # Saved cookies in "name1=value1; name2=value2..." format @[YAML::Field(converter: Preferences::StringToCookies)] property cookies : HTTP::Cookies = HTTP::Cookies.new @@ -256,27 +240,6 @@ class Config end {% end %} - if config.invidious_companion.present? - # invidious_companion and signature_server can't work together - if config.signature_server - puts "Config: You can not run inv_sig_helper and invidious_companion at the same time." - exit(1) - elsif config.invidious_companion_key.empty? - puts "Config: Please configure a key if you are using invidious companion." - exit(1) - elsif config.invidious_companion_key == "CHANGE_ME!!" - puts "Config: The value of 'invidious_companion_key' needs to be changed!!" - exit(1) - elsif config.invidious_companion_key.size != 16 - puts "Config: The value of 'invidious_companion_key' needs to be a size of 16 characters." - exit(1) - end - elsif config.signature_server - puts("WARNING: inv-sig-helper is deprecated. Please switch to Invidious companion: https://docs.invidious.io/companion-installation/") - else - puts("WARNING: Invidious companion is required to view and playback videos. For more information see https://docs.invidious.io/companion-installation/") - end - # HMAC_key is mandatory # See: https://github.com/iv-org/invidious/issues/3854 if config.hmac_key.empty? diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 85462eb8..4d9bb28d 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -383,22 +383,3 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String) end return text end - -def encrypt_ecb_without_salt(data, key) - cipher = OpenSSL::Cipher.new("aes-128-ecb") - cipher.encrypt - cipher.key = key - - io = IO::Memory.new - io.write(cipher.update(data)) - io.write(cipher.final) - io.rewind - - return io -end - -def invidious_companion_encrypt(data) - timestamp = Time.utc.to_unix - encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key) - return Base64.urlsafe_encode(encrypted_data) -end diff --git a/src/invidious/routes/api/manifest.cr b/src/invidious/routes/api/manifest.cr index c27caad7..6c4225e5 100644 --- a/src/invidious/routes/api/manifest.cr +++ b/src/invidious/routes/api/manifest.cr @@ -8,11 +8,6 @@ module Invidious::Routes::API::Manifest id = env.params.url["id"] region = env.params.query["region"]? - if CONFIG.invidious_companion.present? - invidious_companion = CONFIG.invidious_companion.sample - return env.redirect "#{invidious_companion.public_url}/api/manifest/dash/id/#{id}?#{env.params.query}" - end - # Since some implementations create playlists based on resolution regardless of different codecs, # we can opt to only add a source to a representation if it has a unique height within that representation unique_res = env.params.query["unique_res"]?.try { |q| (q == "true" || q == "1").to_unsafe } diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index bdbb2d89..00f24159 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -203,14 +203,6 @@ module Invidious::Routes::Embed return env.redirect url end - if CONFIG.invidious_companion.present? - invidious_companion = CONFIG.invidious_companion.sample - env.response.headers["Content-Security-Policy"] = - env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion.public_url}") - .gsub("connect-src", "connect-src #{invidious_companion.public_url}") - end - rendered "embed" end end diff --git a/src/invidious/routes/video_playback.cr b/src/invidious/routes/video_playback.cr index b1c788c2..a8f9f665 100644 --- a/src/invidious/routes/video_playback.cr +++ b/src/invidious/routes/video_playback.cr @@ -256,11 +256,6 @@ module Invidious::Routes::VideoPlayback # YouTube /videoplayback links expire after 6 hours, # so we have a mechanism here to redirect to the latest version def self.latest_version(env) - if CONFIG.invidious_companion.present? - invidious_companion = CONFIG.invidious_companion.sample - return env.redirect "#{invidious_companion.public_url}/latest_version?#{env.params.query}" - end - id = env.params.query["id"]? itag = env.params.query["itag"]?.try &.to_i? diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr index ab588ad6..1f384546 100644 --- a/src/invidious/routes/watch.cr +++ b/src/invidious/routes/watch.cr @@ -192,14 +192,6 @@ module Invidious::Routes::Watch captions: video.captions ) - if CONFIG.invidious_companion.present? - invidious_companion = CONFIG.invidious_companion.sample - env.response.headers["Content-Security-Policy"] = - env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion.public_url}") - .gsub("connect-src", "connect-src #{invidious_companion.public_url}") - end - templated "watch" end @@ -322,19 +314,14 @@ module Invidious::Routes::Watch env.params.query["label"] = URI.decode_www_form(label.as_s) return Invidious::Routes::API::V1::Videos.captions(env) - elsif itag = download_widget["itag"]?.try &.as_i.to_s + elsif itag = download_widget["itag"]?.try &.as_i # URL params specific to /latest_version env.params.query["id"] = video_id + env.params.query["itag"] = itag.to_s env.params.query["title"] = filename env.params.query["local"] = "true" - if (CONFIG.invidious_companion.present?) - video = get_video(video_id) - invidious_companion = CONFIG.invidious_companion.sample - return env.redirect "#{invidious_companion.public_url}/latest_version?#{env.params.query}" - else - return Invidious::Routes::VideoPlayback.latest_version(env) - end + return Invidious::Routes::VideoPlayback.latest_version(env) else return error_template(400, "Invalid label or itag") end diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 348a0a66..962f87bd 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -15,7 +15,7 @@ struct Video # NOTE: don't forget to bump this number if any change is made to # the `params` structure in videos/parser.cr!!! # - SCHEMA_VERSION = 3 + SCHEMA_VERSION = 2 property id : String diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 26d74f37..5ca4bdb2 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -108,29 +108,27 @@ def extract_video_info(video_id : String) params = parse_video_info(video_id, player_response) params["reason"] = JSON::Any.new(reason) if reason - if !CONFIG.invidious_companion.present? - new_player_response = nil + new_player_response = nil - # Don't use Android test suite client if po_token is passed because po_token doesn't - # work for Android test suite client. - if reason.nil? && CONFIG.po_token.nil? - # Fetch the video streams using an Android client in order to get the - # decrypted URLs and maybe fix throttling issues (#2194). See the - # following issue for an explanation about decrypted URLs: - # https://github.com/TeamNewPipe/NewPipeExtractor/issues/562 - client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite - new_player_response = try_fetch_streaming_data(video_id, client_config) - end + # Don't use Android test suite client if po_token is passed because po_token doesn't + # work for Android test suite client. + if reason.nil? && CONFIG.po_token.nil? + # Fetch the video streams using an Android client in order to get the + # decrypted URLs and maybe fix throttling issues (#2194). See the + # following issue for an explanation about decrypted URLs: + # https://github.com/TeamNewPipe/NewPipeExtractor/issues/562 + client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite + new_player_response = try_fetch_streaming_data(video_id, client_config) + end - # Replace player response and reset reason - if !new_player_response.nil? - # Preserve captions & storyboard data before replacement - new_player_response["storyboards"] = player_response["storyboards"] if player_response["storyboards"]? - new_player_response["captions"] = player_response["captions"] if player_response["captions"]? + # Replace player response and reset reason + if !new_player_response.nil? + # Preserve captions & storyboard data before replacement + new_player_response["storyboards"] = player_response["storyboards"] if player_response["storyboards"]? + new_player_response["captions"] = player_response["captions"] if player_response["captions"]? - player_response = new_player_response - params.delete("reason") - end + player_response = new_player_response + params.delete("reason") end {"captions", "playabilityStatus", "playerConfig", "storyboards"}.each do |f| diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index af352102..523f6bbf 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -22,8 +22,6 @@ audio_streams.each_with_index do |fmt, i| src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" src_url += "&local=true" if params.local - src_url = invidious_companion.public_url.to_s + src_url + - "&check=#{invidious_companion_encrypt(video.id)}" if (invidious_companion) bitrate = fmt["bitrate"] mimetype = HTML.escape(fmt["mimeType"].as_s) @@ -36,12 +34,8 @@ <% end %> <% end %> <% else %> - <% if params.quality == "dash" - src_url = "/api/manifest/dash/id/" + video.id + "?local=true&unique_res=1" - src_url = invidious_companion.public_url.to_s + src_url + - "&check=#{invidious_companion_encrypt(video.id)}" if (invidious_companion) - %> - + <% if params.quality == "dash" %> + <% end %> <% @@ -50,8 +44,6 @@ fmt_stream.each_with_index do |fmt, i| src_url = "/latest_version?id=#{video.id}&itag=#{fmt["itag"]}" src_url += "&local=true" if params.local - src_url = invidious_companion.public_url.to_s + src_url + - "&check=#{invidious_companion_encrypt(video.id)}" if (invidious_companion) quality = fmt["quality"] mimetype = HTML.escape(fmt["mimeType"].as_s) diff --git a/src/invidious/yt_backend/connection_pool.cr b/src/invidious/yt_backend/connection_pool.cr index 0daed46c..c4a73aa7 100644 --- a/src/invidious/yt_backend/connection_pool.cr +++ b/src/invidious/yt_backend/connection_pool.cr @@ -46,43 +46,6 @@ 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" @@ -98,9 +61,9 @@ def add_yt_headers(request) end end -def make_client(url : URI, region = nil, force_resolve : Bool = false, force_youtube_headers : Bool = false, use_http_proxy : Bool = true) +def make_client(url : URI, region = nil, force_resolve : Bool = false, force_youtube_headers : Bool = false) client = HTTP::Client.new(url) - client.proxy = make_configured_http_proxy_client() if CONFIG.http_proxy && use_http_proxy + client.proxy = make_configured_http_proxy_client() if CONFIG.http_proxy # Force the usage of a specific configured IP Family if force_resolve @@ -115,8 +78,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, use_http_proxy : Bool = true, &) - client = make_client(url, region, force_resolve: force_resolve, use_http_proxy: use_http_proxy) +def make_client(url : URI, region = nil, force_resolve : Bool = false, &) + client = make_client(url, region, force_resolve: force_resolve) begin yield client ensure diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index b40092a1..ec080d8c 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -500,11 +500,7 @@ module YoutubeAPI data["params"] = params end - 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 + return self._post_json("/youtubei/v1/player", data, client_config) end #################################################################### @@ -670,49 +666,6 @@ 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) #