125 lines
2.8 KiB
Ruby
125 lines
2.8 KiB
Ruby
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# SPDX-FileCopyrightText: 2023 Hugo Peixoto <hugo.peixoto@gmail.com>
|
|
|
|
require 'sinatra'
|
|
|
|
require './database.rb'
|
|
require './models.rb'
|
|
|
|
def h(bytes)
|
|
if bytes < 2**10
|
|
"#{bytes} bytes"
|
|
elsif bytes < 2**20
|
|
"%.2f KiB" % (1.0 * bytes / 2**10)
|
|
elsif bytes < 2**30
|
|
"%.2f MiB" % (1.0 * bytes / 2**20)
|
|
elsif bytes < 2**40
|
|
"%.2f GiB" % (1.0 * bytes / 2**30)
|
|
else
|
|
"%.2f TiB" % (1.0 * bytes / 2**40)
|
|
end
|
|
end
|
|
|
|
def attempt(attempts, &block)
|
|
begin
|
|
block.call
|
|
rescue
|
|
if attempts > 1
|
|
attempts -= 1
|
|
retry
|
|
else
|
|
raise
|
|
end
|
|
end
|
|
end
|
|
|
|
set :public_folder, __dir__ + '/public'
|
|
get '/' do
|
|
downloads = ActiveRecord::Base.connection.execute("
|
|
SELECT
|
|
COUNT(1) AS total,
|
|
SUM(size) AS bytes
|
|
FROM (select size from downloads group by video_id) as x;
|
|
")[0]
|
|
|
|
videos = ActiveRecord::Base.connection.execute("select count(1) AS total from videos;")[0]
|
|
users = ActiveRecord::Base.connection.execute("select count(distinct email) AS total from downloads;")[0]
|
|
downloads_per_user = ActiveRecord::Base.connection.execute("select SUM(size) AS size, COUNT(1) AS total FROM (select email, video_id, MAX(size) as size from downloads group by email, video_id) x GROUP BY email ORDER BY 1 DESC;")
|
|
|
|
stats = {
|
|
videos_known: videos["total"].to_i,
|
|
videos_downloaded: downloads["total"].to_i,
|
|
|
|
bytes_downloaded: downloads["bytes"].to_i,
|
|
|
|
downloads_per_user: downloads_per_user,
|
|
|
|
users: users["total"],
|
|
}
|
|
|
|
ERB
|
|
.new(File.read("index.html.erb"), trim_mode: "<>-")
|
|
.result_with_hash(stats)
|
|
end
|
|
|
|
get '/videos.json' do
|
|
content_type 'application/json'
|
|
|
|
amount = params['amount'].to_i
|
|
|
|
if amount > 100_000
|
|
{ error: "greedy" }.to_json
|
|
else
|
|
videos = Video
|
|
.left_outer_joins(:downloads)
|
|
.group("randname")
|
|
.order("COUNT(downloads.video_id) ASC, RANDOM()")
|
|
.limit(amount)
|
|
.pluck(:randname)
|
|
|
|
{ videos: videos }.to_json
|
|
end
|
|
end
|
|
|
|
post '/video' do
|
|
content_type 'application/json'
|
|
|
|
data = JSON.parse(request.body.read)
|
|
|
|
attempt(10) do
|
|
Download.create!(
|
|
video: Video.find_by!(randname: data["video_id"]),
|
|
size: data["size"],
|
|
sha256: data["sha256"],
|
|
email: data["email"],
|
|
)
|
|
end
|
|
|
|
{ status: 'ok' }.to_json
|
|
end
|
|
|
|
post '/check' do
|
|
content_type 'application/json'
|
|
|
|
ids = JSON.parse(request.body.read)
|
|
|
|
videos = Video
|
|
.left_outer_joins(:downloads)
|
|
.where(randname: ids)
|
|
.pluck(:randname, :sha256, :size)
|
|
.map { |v| %w[randname sha256 size].zip(v).to_h }
|
|
|
|
{ videos: videos }.to_json
|
|
end
|
|
|
|
|
|
get '/config.json' do
|
|
content_type 'application/json'
|
|
{
|
|
videos_url: "https://sapo.pxto.pt/videos.json",
|
|
upload_url: "https://sapo.pxto.pt/video",
|
|
check_url: "https://sapo.pxto.pt/check",
|
|
max_amount: 100_000,
|
|
}.to_json
|
|
end
|