77 lines
2.5 KiB
Crystal
77 lines
2.5 KiB
Crystal
require "json"
|
|
|
|
include CrystalGauntlet
|
|
|
|
module CrystalGauntlet::Songs
|
|
extend self
|
|
|
|
GD_AUDIO_FORMAT = "mp3"
|
|
|
|
def is_custom_song(id)
|
|
id >= 50
|
|
end
|
|
|
|
def is_reuploaded_song(id)
|
|
id >= 5000000
|
|
end
|
|
|
|
class Song
|
|
def initialize(name : String, author : String, size : Int32, download_url : String | Nil, normalized_url : String)
|
|
@name = name
|
|
@author = author
|
|
@size = size
|
|
@download_url = download_url
|
|
end
|
|
end
|
|
|
|
def is_source_allowed(source : String) : Bool
|
|
config_get("songs.allow_all_sources").as?(Bool) || config_get("songs.sources.#{source}.allow").as?(Bool) || false
|
|
end
|
|
|
|
def reupload(url : String, id : Int32) : Song | Nil
|
|
puts url
|
|
|
|
output = IO::Memory.new
|
|
# todo: ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ LOOK OUT FOR SHELL INJECTION BULLSHIT!!!!!!!!!!!!!!!!!!
|
|
Process.run(config_get("songs.sources.ytdlp_binary").as?(String) || "yt-dlp", ["-J", url], output: output)
|
|
output.close
|
|
|
|
puts output.to_s
|
|
|
|
metadata = JSON.parse(output.to_s)
|
|
|
|
if !is_source_allowed(metadata["extractor"].as_s? || "unknown")
|
|
raise "source forbidden: #{metadata["extractor"]}"
|
|
end
|
|
|
|
max_duration = config_get("songs.sources.max_duration").as?(Int64) || 0
|
|
|
|
if max_duration > 0
|
|
if !metadata["duration"]
|
|
raise "failed to determine track duration"
|
|
elsif metadata["duration"].as_f >= max_duration
|
|
raise "track goes above max track duration (#{max_duration}s)"
|
|
end
|
|
end
|
|
|
|
if config_get("songs.sources.allow_transcoding")
|
|
if !config_get("songs.sources.proxy_downloads").as?(Bool)
|
|
raise "can't download a song with transcoding but without proxying allowed"
|
|
end
|
|
|
|
canonical_url = metadata["webpage_url"].as_s? || metadata["original_url"].as_s? || url
|
|
|
|
target_path = Path.new("data", "#{id}.mp3")
|
|
|
|
Process.run(config_get("songs.sources.ytdlp_binary").as?(String) || "yt-dlp", ["-f", "ba", "-x", "--audio-format", GD_AUDIO_FORMAT, "-o", target_path.to_s, "--ffmpeg-location", config_get("songs.sources.ffmpeg_binary").as?(String) || "ffmpeg", canonical_url], output: STDOUT, error: STDOUT)
|
|
|
|
size = File.size(target_path)
|
|
|
|
# todo: don't point to localhost
|
|
Song.new(metadata["fulltitle"].as_s? || metadata["title"].as_s? || "Song", metadata["uploader"].as_s? || "", size.to_i32, "http://localhost:8080/#{id}.mp3", canonical_url)
|
|
else
|
|
# todo
|
|
end
|
|
end
|
|
end
|