Merge branch 'iv-org:master' into main

This commit is contained in:
broquemonsieur 2023-12-03 23:08:57 +00:00 committed by GitHub
commit 5fdaa1bf57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 75 additions and 22 deletions

View File

@ -47,7 +47,7 @@ jobs:
stable: false stable: false
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
@ -87,7 +87,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Build Docker - name: Build Docker
run: docker-compose build --build-arg release=0 run: docker-compose build --build-arg release=0
@ -103,18 +103,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
with: with:
platforms: arm64 platforms: arm64
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
- name: Build Docker ARM64 image - name: Build Docker ARM64 image
uses: docker/build-push-action@v3 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: docker/Dockerfile.arm64 file: docker/Dockerfile.arm64

View File

@ -22,7 +22,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install Crystal - name: Install Crystal
uses: crystal-lang/install-crystal@v1.8.0 uses: crystal-lang/install-crystal@v1.8.0
@ -38,15 +38,15 @@ jobs:
fi fi
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
with: with:
platforms: arm64 platforms: arm64
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
- name: Login to registry - name: Login to registry
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: quay.io registry: quay.io
username: ${{ secrets.QUAY_USERNAME }} username: ${{ secrets.QUAY_USERNAME }}
@ -54,7 +54,7 @@ jobs:
- name: Build and push Docker AMD64 image for Push Event - name: Build and push Docker AMD64 image for Push Event
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: docker/build-push-action@v3 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: docker/Dockerfile file: docker/Dockerfile
@ -67,7 +67,7 @@ jobs:
- name: Build and push Docker ARM64 image for Push Event - name: Build and push Docker ARM64 image for Push Event
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
uses: docker/build-push-action@v3 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: docker/Dockerfile.arm64 file: docker/Dockerfile.arm64

View File

@ -10,7 +10,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v5 - uses: actions/stale@v8
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 365 days-before-stale: 365

View File

@ -40,7 +40,7 @@ services:
- invidious-db - invidious-db
invidious-db: invidious-db:
image: docker.io/library/postgres:13 image: docker.io/library/postgres:14
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- postgresdata:/var/lib/postgresql/data - postgresdata:/var/lib/postgresql/data

View File

@ -33,7 +33,7 @@ RUN if [[ "${release}" == 1 ]] ; then \
fi fi
FROM alpine:3.18 FROM alpine:3.18
RUN apk add --no-cache librsvg ttf-opensans tini RUN apk add --no-cache rsvg-convert ttf-opensans tini
WORKDIR /invidious WORKDIR /invidious
RUN addgroup -g 1000 -S invidious && \ RUN addgroup -g 1000 -S invidious && \
adduser -u 1000 -S invidious -G invidious adduser -u 1000 -S invidious -G invidious

View File

@ -33,7 +33,7 @@ RUN if [[ "${release}" == 1 ]] ; then \
fi fi
FROM alpine:3.18 FROM alpine:3.18
RUN apk add --no-cache librsvg ttf-opensans tini RUN apk add --no-cache rsvg-convert ttf-opensans tini
WORKDIR /invidious WORKDIR /invidious
RUN addgroup -g 1000 -S invidious && \ RUN addgroup -g 1000 -S invidious && \
adduser -u 1000 -S invidious -G invidious adduser -u 1000 -S invidious -G invidious

View File

@ -18,8 +18,8 @@ record AboutChannel,
def get_about_info(ucid, locale) : AboutChannel def get_about_info(ucid, locale) : AboutChannel
begin begin
# "EgVhYm91dA==" is the base64-encoded protobuf object {"2:string":"about"} # Fetch channel information from channel home page
initdata = YoutubeAPI.browse(browse_id: ucid, params: "EgVhYm91dA==") initdata = YoutubeAPI.browse(browse_id: ucid, params: "")
rescue rescue
raise InfoException.new("Could not get channel info.") raise InfoException.new("Could not get channel info.")
end end

View File

@ -208,3 +208,20 @@ def proxy_file(response, env)
IO.copy response.body_io, env.response IO.copy response.body_io, env.response
end end
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

View File

@ -18,6 +18,13 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
"updatedAt" => Time.utc.to_unix, "updatedAt" => Time.utc.to_unix,
"lastChannelRefreshedAt" => 0_i64, "lastChannelRefreshedAt" => 0_i64,
}, },
#
# "totalRequests" => 0_i64,
# "successfulRequests" => 0_i64
# "ratio" => 0_i64
#
"playback" => {} of String => Int64 | Float64,
} }
private getter db : DB::Database private getter db : DB::Database
@ -30,7 +37,7 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
loop do loop do
refresh_stats refresh_stats
sleep 1.minute sleep 10.minute
Fiber.yield Fiber.yield
end end
end end
@ -56,5 +63,8 @@ class Invidious::Jobs::StatisticsRefreshJob < Invidious::Jobs::BaseJob
"updatedAt" => Time.utc.to_unix, "updatedAt" => Time.utc.to_unix,
"lastChannelRefreshedAt" => Invidious::Database::Statistics.channel_last_update.try &.to_unix || 0_i64, "lastChannelRefreshedAt" => Invidious::Database::Statistics.channel_last_update.try &.to_unix || 0_i64,
} }
# Reset playback requests tracker
STATISTICS["playback"] = {} of String => Int64 | Float64
end end
end end

View File

@ -6,6 +6,22 @@ module Invidious::Routes::API::V1::Misc
if !CONFIG.statistics_enabled if !CONFIG.statistics_enabled
return {"software" => SOFTWARE}.to_json return {"software" => SOFTWARE}.to_json
else 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 return Invidious::Jobs::StatisticsRefreshJob::STATISTICS.to_json
end end
end end

View File

@ -80,9 +80,14 @@ module Invidious::Routes::VideoPlayback
# Remove the Range header added previously. # Remove the Range header added previously.
headers.delete("Range") if range_header.nil? headers.delete("Range") if range_header.nil?
playback_statistics = get_playback_statistic()
playback_statistics["totalRequests"] += 1
if response.status_code >= 400 if response.status_code >= 400
env.response.content_type = "text/plain" env.response.content_type = "text/plain"
haltf env, response.status_code haltf env, response.status_code
else
playback_statistics["successfulRequests"] += 1
end end
if url.includes? "&file=seg.ts" if url.includes? "&file=seg.ts"

View File

@ -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. # YouTube may return a different video player response than expected.
# See: https://github.com/TeamNewPipe/NewPipe/issues/8713 # See: https://github.com/TeamNewPipe/NewPipe/issues/8713
# Line to be reverted if one day we solve the video not available issue. # 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 { return {
"version" => JSON::Any.new(Video::SCHEMA_VERSION.to_i64), "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>"), "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>"),

View File

@ -37,7 +37,7 @@ struct YoutubeConnectionPool
conn.close conn.close
conn = HTTP::Client.new(url) 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.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.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
response = yield conn response = yield conn
@ -52,7 +52,7 @@ struct YoutubeConnectionPool
private def build_pool 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 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 = 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.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.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
conn conn
@ -62,7 +62,7 @@ end
def make_client(url : URI, region = nil) def make_client(url : URI, region = nil)
client = HTTPClient.new(url, OpenSSL::SSL::Context::Client.insecure) 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.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
client.read_timeout = 10.seconds client.read_timeout = 10.seconds
client.connect_timeout = 10.seconds client.connect_timeout = 10.seconds