mirror of
https://github.com/iv-org/invidious.git
synced 2025-08-13 16:18:29 +00: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
|
git: https://github.com/crystal-lang/crystal-db.git
|
||||||
version: 0.10.1
|
version: 0.10.1
|
||||||
|
|
||||||
|
duktape:
|
||||||
|
git: https://github.com/jessedoyle/duktape.cr.git
|
||||||
|
version: 1.0.0
|
||||||
|
|
||||||
exception_page:
|
exception_page:
|
||||||
git: https://github.com/crystal-loot/exception_page.git
|
git: https://github.com/crystal-loot/exception_page.git
|
||||||
version: 0.1.5
|
version: 0.1.5
|
||||||
|
@ -25,6 +25,9 @@ dependencies:
|
|||||||
lsquic:
|
lsquic:
|
||||||
github: iv-org/lsquic.cr
|
github: iv-org/lsquic.cr
|
||||||
version: ~> 2.18.1-2
|
version: ~> 2.18.1-2
|
||||||
|
duktape:
|
||||||
|
github: jessedoyle/duktape.cr
|
||||||
|
version: ~> 1.0.0
|
||||||
|
|
||||||
crystal: 1.0.0
|
crystal: 1.0.0
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
require "duktape/runtime"
|
||||||
|
|
||||||
alias SigProc = Proc(Array(String), Int32, Array(String))
|
alias SigProc = Proc(Array(String), Int32, Array(String))
|
||||||
|
|
||||||
struct DecryptFunction
|
struct DecryptFunction
|
||||||
@decrypt_function = [] of {SigProc, Int32}
|
@decrypt_function = [] of {SigProc, Int32}
|
||||||
@decrypt_time = Time.monotonic
|
@decrypt_time = Time.monotonic
|
||||||
|
|
||||||
|
@playerjs_decrypt_n_function = {} of String => String
|
||||||
|
@last_decrypted_n = {id: "", n: "", dec_n: ""}
|
||||||
|
|
||||||
def initialize(@use_polling = true)
|
def initialize(@use_polling = true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -70,4 +75,36 @@ struct DecryptFunction
|
|||||||
|
|
||||||
return "&#{sp}=#{sig.join("")}"
|
return "&#{sp}=#{sig.join("")}"
|
||||||
end
|
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
|
end
|
||||||
|
@ -586,6 +586,7 @@ struct Video
|
|||||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}#{DECRYPT_FUNCTION.decrypt_signature(fmt)}")
|
fmt["url"] = JSON::Any.new("#{fmt["url"]}#{DECRYPT_FUNCTION.decrypt_signature(fmt)}")
|
||||||
end
|
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"]}&host=#{URI.parse(fmt["url"].as_s).host}")
|
||||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}®ion=#{self.info["region"]}") if self.info["region"]?
|
fmt["url"] = JSON::Any.new("#{fmt["url"]}®ion=#{self.info["region"]}") if self.info["region"]?
|
||||||
end
|
end
|
||||||
@ -605,6 +606,7 @@ struct Video
|
|||||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}#{DECRYPT_FUNCTION.decrypt_signature(fmt)}")
|
fmt["url"] = JSON::Any.new("#{fmt["url"]}#{DECRYPT_FUNCTION.decrypt_signature(fmt)}")
|
||||||
end
|
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"]}&host=#{URI.parse(fmt["url"].as_s).host}")
|
||||||
fmt["url"] = JSON::Any.new("#{fmt["url"]}®ion=#{self.info["region"]}") if self.info["region"]?
|
fmt["url"] = JSON::Any.new("#{fmt["url"]}®ion=#{self.info["region"]}") if self.info["region"]?
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user