|
|
@ -1,6 +1,17 @@
|
|
|
|
alias SigProc = Proc(Array(String), Int32, Array(String))
|
|
|
|
alias SigProc = Proc(Array(String), Int32, Array(String))
|
|
|
|
|
|
|
|
|
|
|
|
def fetch_decrypt_function(id = "CvFH_6DNRCY")
|
|
|
|
struct DecryptFunction
|
|
|
|
|
|
|
|
@decrypt_function = [] of {SigProc, Int32}
|
|
|
|
|
|
|
|
@decrypt_time = Time.monotonic
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initialize(@use_polling = true)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_decrypt_function
|
|
|
|
|
|
|
|
@decrypt_function = fetch_decrypt_function
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private def fetch_decrypt_function(id = "CvFH_6DNRCY")
|
|
|
|
document = YT_POOL.client &.get("/watch?v=#{id}&gl=US&hl=en").body
|
|
|
|
document = YT_POOL.client &.get("/watch?v=#{id}&gl=US&hl=en").body
|
|
|
|
url = document.match(/src="(?<url>\/s\/player\/[^\/]+\/player_ias[^\/]+\/en_US\/base.js)"/).not_nil!["url"]
|
|
|
|
url = document.match(/src="(?<url>\/s\/player\/[^\/]+\/player_ias[^\/]+\/en_US\/base.js)"/).not_nil!["url"]
|
|
|
|
player = YT_POOL.client &.get(url).body
|
|
|
|
player = YT_POOL.client &.get(url).body
|
|
|
@ -45,9 +56,18 @@ def decrypt_signature(fmt : Hash(String, JSON::Any))
|
|
|
|
|
|
|
|
|
|
|
|
sp = fmt["sp"].as_s
|
|
|
|
sp = fmt["sp"].as_s
|
|
|
|
sig = fmt["s"].as_s.split("")
|
|
|
|
sig = fmt["s"].as_s.split("")
|
|
|
|
DECRYPT_FUNCTION.each do |proc, value|
|
|
|
|
if !@use_polling
|
|
|
|
|
|
|
|
now = Time.monotonic
|
|
|
|
|
|
|
|
if now - @decrypt_time > 60.seconds || @decrypt_function.size == 0
|
|
|
|
|
|
|
|
@decrypt_function = fetch_decrypt_function
|
|
|
|
|
|
|
|
@decrypt_time = Time.monotonic
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@decrypt_function.each do |proc, value|
|
|
|
|
sig = proc.call(sig, value)
|
|
|
|
sig = proc.call(sig, value)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
return "&#{sp}=#{sig.join("")}"
|
|
|
|
return "&#{sp}=#{sig.join("")}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|