mirror of
https://github.com/iv-org/invidious.git
synced 2025-04-22 16:29:10 -04:00
decrypt n
This commit is contained in:
parent
67a18dcff6
commit
a533888830
@ -4,6 +4,10 @@ shards:
|
||||
git: https://github.com/crystal-lang/crystal-db.git
|
||||
version: 0.10.1
|
||||
|
||||
duktape:
|
||||
git: https://github.com/jessedoyle/duktape.cr.git
|
||||
version: 1.0.0
|
||||
|
||||
exception_page:
|
||||
git: https://github.com/crystal-loot/exception_page.git
|
||||
version: 0.1.5
|
||||
|
@ -25,6 +25,9 @@ dependencies:
|
||||
lsquic:
|
||||
github: iv-org/lsquic.cr
|
||||
version: ~> 2.18.1-2
|
||||
duktape:
|
||||
github: jessedoyle/duktape.cr
|
||||
version: ~> 1.0.0
|
||||
|
||||
crystal: 1.0.0
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
require "duktape/runtime"
|
||||
|
||||
alias SigProc = Proc(Array(String), Int32, Array(String))
|
||||
|
||||
struct DecryptFunction
|
||||
@decrypt_function = [] of {SigProc, Int32}
|
||||
@decrypt_time = Time.monotonic
|
||||
|
||||
@playerjs_decrypt_n_function = {} of String => String
|
||||
@last_decrypted_n = {id: "", n: "", dec_n: ""}
|
||||
|
||||
def initialize(@use_polling = true)
|
||||
end
|
||||
|
||||
@ -70,4 +75,36 @@ struct DecryptFunction
|
||||
|
||||
return "&#{sp}=#{sig.join("")}"
|
||||
end
|
||||
|
||||
def overwrite_n(id : String, fmt : Hash(String, JSON::Any))
|
||||
uri = URI.parse(fmt["url"].as_s)
|
||||
params = HTTP::Params.parse(uri.query.not_nil!)
|
||||
return fmt["url"].as_s unless params["n"]?
|
||||
n = params["n"]
|
||||
|
||||
function_name = "(cache #1)"
|
||||
if (@last_decrypted_n[:id] == id && @last_decrypted_n[:n] == n)
|
||||
dec_n = @last_decrypted_n[:dec_n]
|
||||
else
|
||||
document = YT_POOL.client &.get("/watch?v=#{id}&gl=US&hl=en").body
|
||||
playerjs = document.match(/src="(?<url>\/s\/player\/[^\/]+\/player_ias[^\/]+\/en_US\/base.js)"/).not_nil!["url"]
|
||||
function_name = "(cache #2)"
|
||||
function_body = @playerjs_decrypt_n_function[playerjs]?
|
||||
if (!function_body)
|
||||
player = YT_POOL.client &.get(playerjs).body
|
||||
function_name = player.match(/a\.get\("n"\)\)&&\(b=(?<nfunc>[a-zA-Z0-9]+)\(b\)/m).not_nil!["nfunc"]
|
||||
function_body = player.match(/^#{Regex.escape(function_name)}=(?<body>function\(\w\)\{.*?"enhanced_except_[^\}]+\}[^\}]+\})/m).not_nil!["body"]
|
||||
@playerjs_decrypt_n_function[playerjs] = function_body
|
||||
end
|
||||
rt = Duktape::Runtime.new do |sbx|
|
||||
sbx.eval! "var dec=#{function_body}"
|
||||
end
|
||||
dec_n = rt.call("dec", n).to_s
|
||||
@last_decrypted_n = {id: id, n: n, dec_n: dec_n}
|
||||
end
|
||||
|
||||
LOGGER.debug("decrypt_n: #{id} fn = #{function_name} n = #{n} -> #{dec_n}")
|
||||
params["n"] = dec_n
|
||||
return URI.new(uri.scheme, uri.host, uri.port, uri.path, params).to_s
|
||||
end
|
||||
end
|
||||
|
@ -586,6 +586,7 @@ struct Video
|
||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}#{DECRYPT_FUNCTION.decrypt_signature(fmt)}")
|
||||
end
|
||||
|
||||
fmt["url"] = JSON::Any.new(DECRYPT_FUNCTION.overwrite_n(self.id, fmt))
|
||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}&host=#{URI.parse(fmt["url"].as_s).host}")
|
||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}®ion=#{self.info["region"]}") if self.info["region"]?
|
||||
end
|
||||
@ -605,6 +606,7 @@ struct Video
|
||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}#{DECRYPT_FUNCTION.decrypt_signature(fmt)}")
|
||||
end
|
||||
|
||||
fmt["url"] = JSON::Any.new(DECRYPT_FUNCTION.overwrite_n(self.id, fmt))
|
||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}&host=#{URI.parse(fmt["url"].as_s).host}")
|
||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}®ion=#{self.info["region"]}") if self.info["region"]?
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user