require "open-uri" require "aws-sdk-s3" module Recordings class Storage class Error < StandardError; end def initialize @backend = MatchLiveTv.replay_storage_local? ? LocalBackend.new : S3Backend.new end def upload(local_path:, key:, content_type: "video/mp4") @backend.upload(local_path: local_path, key: key, content_type: content_type) end def delete(key:) @backend.delete(key: key) end def download_to_temp(key:) local = local_path_for_key(key) return local if local && File.exist?(local) url = presigned_get_url(key: key, expires_in: 600) raise Error, "Impossibile scaricare file dallo storage" if url.blank? dest = File.join(Dir.tmpdir, "replay-dl-#{SecureRandom.hex(8)}.mp4") URI.open(url) do |remote| File.binwrite(dest, remote.read) end dest end def presigned_get_url(key:, expires_in: MatchLiveTv.replay_presigned_url_ttl_seconds) @backend.presigned_get_url(key: key, expires_in: expires_in) end def local_path_for_key(key) @backend.local_path_for_key(key) end def backend_name @backend.name end class LocalBackend def name "local" end def upload(local_path:, key:, content_type:) dest = local_path_for_key(key) FileUtils.mkdir_p(File.dirname(dest)) FileUtils.cp(local_path, dest) File.size(dest) end def delete(key:) path = local_path_for_key(key) FileUtils.rm_f(path) true end def presigned_get_url(key:, expires_in:) nil end def local_path_for_key(key) File.join(MatchLiveTv.recordings_local_path, "replays", key) end end class S3Backend def name "s3" end def upload(local_path:, key:, content_type:) client.put_object( bucket: MatchLiveTv.replay_storage_bucket, key: key, body: File.open(local_path, "rb"), content_type: content_type ) File.size(local_path) end def delete(key:) client.delete_object(bucket: MatchLiveTv.replay_storage_bucket, key: key) true rescue Aws::S3::Errors::ServiceError => e raise Error, e.message end def presigned_get_url(key:, expires_in:) signer = Aws::S3::Presigner.new(client: client) signer.presigned_url( :get_object, bucket: MatchLiveTv.replay_storage_bucket, key: key, expires_in: expires_in ) end def local_path_for_key(_key) nil end private def client @client ||= Aws::S3::Client.new( access_key_id: MatchLiveTv.replay_storage_access_key_id, secret_access_key: MatchLiveTv.replay_storage_secret_access_key, endpoint: MatchLiveTv.replay_storage_endpoint, region: MatchLiveTv.replay_storage_region, force_path_style: MatchLiveTv.replay_storage_force_path_style?, response_checksum_validation: "WHEN_REQUIRED" ) end end end end