mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-03 22:21:55 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into actioncheckoutv4
This commit is contained in:
		@@ -18,8 +18,8 @@ record AboutChannel,
 | 
			
		||||
 | 
			
		||||
def get_about_info(ucid, locale) : AboutChannel
 | 
			
		||||
  begin
 | 
			
		||||
    # "EgVhYm91dA==" is the base64-encoded protobuf object {"2:string":"about"}
 | 
			
		||||
    initdata = YoutubeAPI.browse(browse_id: ucid, params: "EgVhYm91dA==")
 | 
			
		||||
    # Fetch channel information from channel home page
 | 
			
		||||
    initdata = YoutubeAPI.browse(browse_id: ucid, params: "")
 | 
			
		||||
  rescue
 | 
			
		||||
    raise InfoException.new("Could not get channel info.")
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -208,3 +208,20 @@ def proxy_file(response, env)
 | 
			
		||||
    IO.copy response.body_io, env.response
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Fetch the playback requests tracker from the statistics endpoint.
 | 
			
		||||
#
 | 
			
		||||
# Creates a new tracker when unavailable.
 | 
			
		||||
def get_playback_statistic
 | 
			
		||||
  if (tracker = Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"]) && tracker.as(Hash).empty?
 | 
			
		||||
    tracker = {
 | 
			
		||||
      "totalRequests"      => 0_i64,
 | 
			
		||||
      "successfulRequests" => 0_i64,
 | 
			
		||||
      "ratio"              => 0_f64,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"] = tracker
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  return tracker.as(Hash(String, Int64 | Float64))
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,13 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
 | 
			
		||||
      "updatedAt"              => Time.utc.to_unix,
 | 
			
		||||
      "lastChannelRefreshedAt" => 0_i64,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    #    "totalRequests" => 0_i64,
 | 
			
		||||
    #    "successfulRequests" => 0_i64
 | 
			
		||||
    #    "ratio"   => 0_i64
 | 
			
		||||
    #
 | 
			
		||||
    "playback" => {} of String => Int64 | Float64,
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getter db : DB::Database
 | 
			
		||||
@@ -30,7 +37,7 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
 | 
			
		||||
 | 
			
		||||
    loop do
 | 
			
		||||
      refresh_stats
 | 
			
		||||
      sleep 1.minute
 | 
			
		||||
      sleep 10.minute
 | 
			
		||||
      Fiber.yield
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@@ -56,5 +63,8 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
 | 
			
		||||
      "updatedAt"              => Time.utc.to_unix,
 | 
			
		||||
      "lastChannelRefreshedAt" => Invidious::Database::Statistics.channel_last_update.try &.to_unix || 0_i64,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Reset playback requests tracker
 | 
			
		||||
    STATISTICS["playback"] = {} of String => Int64 | Float64
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,22 @@ module Invidious::Routes::API::V1::Misc
 | 
			
		||||
    if !CONFIG.statistics_enabled
 | 
			
		||||
      return {"software" => SOFTWARE}.to_json
 | 
			
		||||
    else
 | 
			
		||||
      # Calculate playback success rate
 | 
			
		||||
      if (tracker = Invidious::Jobs::StatisticsRefreshJob::STATISTICS["playback"]?)
 | 
			
		||||
        tracker = tracker.as(Hash(String, Int64 | Float64))
 | 
			
		||||
 | 
			
		||||
        if !tracker.empty?
 | 
			
		||||
          total_requests = tracker["totalRequests"]
 | 
			
		||||
          success_count = tracker["successfulRequests"]
 | 
			
		||||
 | 
			
		||||
          if total_requests.zero?
 | 
			
		||||
            tracker["ratio"] = 1_i64
 | 
			
		||||
          else
 | 
			
		||||
            tracker["ratio"] = (success_count / (total_requests)).round(2)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      return Invidious::Jobs::StatisticsRefreshJob::STATISTICS.to_json
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -80,9 +80,14 @@ module Invidious::Routes::VideoPlayback
 | 
			
		||||
    # Remove the Range header added previously.
 | 
			
		||||
    headers.delete("Range") if range_header.nil?
 | 
			
		||||
 | 
			
		||||
    playback_statistics = get_playback_statistic()
 | 
			
		||||
    playback_statistics["totalRequests"] += 1
 | 
			
		||||
 | 
			
		||||
    if response.status_code >= 400
 | 
			
		||||
      env.response.content_type = "text/plain"
 | 
			
		||||
      haltf env, response.status_code
 | 
			
		||||
    else
 | 
			
		||||
      playback_statistics["successfulRequests"] += 1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if url.includes? "&file=seg.ts"
 | 
			
		||||
 
 | 
			
		||||
@@ -78,6 +78,11 @@ def extract_video_info(video_id : String, proxy_region : String? = nil)
 | 
			
		||||
    # YouTube may return a different video player response than expected.
 | 
			
		||||
    # See: https://github.com/TeamNewPipe/NewPipe/issues/8713
 | 
			
		||||
    # Line to be reverted if one day we solve the video not available issue.
 | 
			
		||||
 | 
			
		||||
    # Although technically not a call to /videoplayback the fact that YouTube is returning the
 | 
			
		||||
    # wrong video means that we should count it as a failure.
 | 
			
		||||
    get_playback_statistic()["totalRequests"] += 1
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      "version" => JSON::Any.new(Video::SCHEMA_VERSION.to_i64),
 | 
			
		||||
      "reason"  => JSON::Any.new("Can't load the video on this Invidious instance. YouTube is currently trying to block Invidious instances. <a href=\"https://github.com/iv-org/invidious/issues/3822\">Click here for more info about the issue.</a>"),
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ struct YoutubeConnectionPool
 | 
			
		||||
        conn.close
 | 
			
		||||
        conn = HTTP::Client.new(url)
 | 
			
		||||
 | 
			
		||||
        conn.family = (url.host == "www.youtube.com") ? CONFIG.force_resolve : Socket::Family::INET
 | 
			
		||||
        conn.family = CONFIG.force_resolve
 | 
			
		||||
        conn.family = Socket::Family::INET if conn.family == Socket::Family::UNSPEC
 | 
			
		||||
        conn.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
 | 
			
		||||
        response = yield conn
 | 
			
		||||
@@ -52,7 +52,7 @@ struct YoutubeConnectionPool
 | 
			
		||||
  private def build_pool
 | 
			
		||||
    DB::Pool(HTTP::Client).new(initial_pool_size: 0, max_pool_size: capacity, max_idle_pool_size: capacity, checkout_timeout: timeout) do
 | 
			
		||||
      conn = HTTP::Client.new(url)
 | 
			
		||||
      conn.family = (url.host == "www.youtube.com") ? CONFIG.force_resolve : Socket::Family::INET
 | 
			
		||||
      conn.family = CONFIG.force_resolve
 | 
			
		||||
      conn.family = Socket::Family::INET if conn.family == Socket::Family::UNSPEC
 | 
			
		||||
      conn.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
 | 
			
		||||
      conn
 | 
			
		||||
@@ -62,7 +62,7 @@ end
 | 
			
		||||
 | 
			
		||||
def make_client(url : URI, region = nil)
 | 
			
		||||
  client = HTTPClient.new(url, OpenSSL::SSL::Context::Client.insecure)
 | 
			
		||||
  client.family = (url.host == "www.youtube.com") ? CONFIG.force_resolve : Socket::Family::UNSPEC
 | 
			
		||||
  client.family = CONFIG.force_resolve
 | 
			
		||||
  client.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
 | 
			
		||||
  client.read_timeout = 10.seconds
 | 
			
		||||
  client.connect_timeout = 10.seconds
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user