summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOmar Roth <omarroth@hotmail.com>2018-07-17 10:53:17 -0500
committerOmar Roth <omarroth@hotmail.com>2018-07-17 10:53:17 -0500
commit0bb07e55f5a59b5ccb7c5392faaf523abd71ae4b (patch)
treefa2ba523cb9c7ef04045988acff217d773522d19 /src
parente1ec1b68378203651e9e4b649009b2856a8aecad (diff)
downloadinvidious-0bb07e55f5a59b5ccb7c5392faaf523abd71ae4b.tar.gz
invidious-0bb07e55f5a59b5ccb7c5392faaf523abd71ae4b.tar.bz2
invidious-0bb07e55f5a59b5ccb7c5392faaf523abd71ae4b.zip
Add ability to automatically extract video signature funtion
Diffstat (limited to 'src')
-rw-r--r--src/invidious.cr25
-rw-r--r--src/invidious/helpers.cr58
2 files changed, 73 insertions, 10 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 618386ea..0e135af7 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -173,7 +173,6 @@ video_threads.times do |i|
end
top_videos = [] of Video
-
spawn do
if CONFIG.dl_api_key
DetectLanguage.configure do |config|
@@ -213,6 +212,20 @@ spawn do
end
end
+# Refresh decrypt function
+decrypt_function = [] of {name: String, value: Int32}
+spawn do
+ loop do
+ begin
+ client = make_client(YT_URL)
+ decrypt_function = update_decrypt_function(client)
+ rescue ex
+ end
+
+ Fiber.yield
+ end
+end
+
before_all do |env|
if env.request.cookies.has_key? "SID"
headers = HTTP::Headers.new
@@ -296,11 +309,11 @@ get "/watch" do |env|
if adaptive_fmts[0]? && adaptive_fmts[0]["s"]?
adaptive_fmts.each do |fmt|
- fmt["url"] += "&signature=" + decrypt_signature(fmt["s"])
+ fmt["url"] += "&signature=" + decrypt_signature(fmt["s"], decrypt_function)
end
fmt_stream.each do |fmt|
- fmt["url"] += "&signature=" + decrypt_signature(fmt["s"])
+ fmt["url"] += "&signature=" + decrypt_signature(fmt["s"], decrypt_function)
end
end
@@ -433,11 +446,11 @@ get "/embed/:id" do |env|
if adaptive_fmts[0]? && adaptive_fmts[0]["s"]?
adaptive_fmts.each do |fmt|
- fmt["url"] += "&signature=" + decrypt_signature(fmt["s"])
+ fmt["url"] += "&signature=" + decrypt_signature(fmt["s"], decrypt_function)
end
fmt_stream.each do |fmt|
- fmt["url"] += "&signature=" + decrypt_signature(fmt["s"])
+ fmt["url"] += "&signature=" + decrypt_signature(fmt["s"], decrypt_function)
end
end
@@ -1044,7 +1057,7 @@ get "/api/manifest/dash/id/:id" do |env|
if adaptive_fmts[0]? && adaptive_fmts[0]["s"]?
adaptive_fmts.each do |fmt|
- fmt["url"] += "&signature=" + decrypt_signature(fmt["s"])
+ fmt["url"] += "&signature=" + decrypt_signature(fmt["s"], decrypt_function)
end
end
diff --git a/src/invidious/helpers.cr b/src/invidious/helpers.cr
index 692c1d29..923b6d1c 100644
--- a/src/invidious/helpers.cr
+++ b/src/invidious/helpers.cr
@@ -324,16 +324,66 @@ def splice(a, b)
return a
end
-def decrypt_signature(a)
+def decrypt_signature(a, code)
a = a.split("")
- a.reverse!
- a.delete_at(0..0)
- a = splice(a, 11)
+ code.each do |item|
+ case item[:name]
+ when "a"
+ a.reverse!
+ when "b"
+ a.delete_at(0..(item[:value] - 1))
+ when "c"
+ a = splice(a, item[:value])
+ end
+ end
return a.join("")
end
+def update_decrypt_function(client)
+ # Video with signature
+ document = client.get("/watch?v=CvFH_6DNRCY").body
+ url = document.match(/src="(?<url>\/yts\/jsbin\/player-.{9}\/en_US\/base.js)"/).not_nil!["url"]
+ player = client.get(url).body
+
+ function_name = player.match(/\(b\|\|\(b="signature"\),d.set\(b,(?<name>[a-zA-Z]{2})\(c\)\)\)/).not_nil!["name"]
+ function_body = player.match(/#{function_name}=function\(a\){(?<body>[^}]+)}/).not_nil!["body"]
+ function_body = function_body.split(";")[1..-2]
+
+ var_name = function_body[0][0, 2]
+
+ operations = {} of String => String
+ matches = player.delete("\n").match(/var #{var_name}={((?<op1>[a-zA-Z]{2}:[^}]+})),((?<op2>[a-zA-Z]{2}:[^}]+})),((?<op3>[a-zA-Z]{2}:[^}]+}))};/).not_nil!
+ 3.times do |i|
+ operation = matches["op#{i + 1}"]
+ op_name = operation[0, 2]
+
+ op_body = operation.match(/\{[^}]+\}/).not_nil![0]
+ case op_body
+ when "{a.reverse()}"
+ operations[op_name] = "a"
+ when "{a.splice(0,b)}"
+ operations[op_name] = "b"
+ else
+ operations[op_name] = "c"
+ end
+ end
+
+ decrypt_function = [] of {name: String, value: Int32}
+ function_body.each do |function|
+ function = function.lchop(var_name + ".")
+ op_name = function[0, 2]
+
+ function = function.lchop(op_name + "(a,")
+ value = function.rchop(")").to_i
+
+ decrypt_function << {name: operations[op_name], value: value}
+ end
+
+ return decrypt_function
+end
+
def rank_videos(db, n, filter, url)
top = [] of {Float64, String}