[vlc-commits] soundcloud.lua: dynamically extract API magic

Pierre Ynard git at videolan.org
Wed Apr 1 09:54:27 CEST 2020


vlc | branch: master | Pierre Ynard <linkfanel at yahoo.fr> | Wed Apr  1 09:26:49 2020 +0200| [6abb32a9ba076de8662a53889926280e6d80f5e1] | committer: Pierre Ynard

soundcloud.lua: dynamically extract API magic

It seems that the client_id API magic now gets invalidated much faster,
rendering the current model, where it is hard-coded into the script,
not viable anymore. Instead, this fetches and parses javascript assets
linked from the web page to search and extract the up-to-date magic from
them.

This is significantly slower as for now it fetches all of several
indiscriminate javascript assets, but at least it works, and should not
require that kind of maintenance anymore.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6abb32a9ba076de8662a53889926280e6d80f5e1
---

 share/lua/playlist/soundcloud.lua | 48 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/share/lua/playlist/soundcloud.lua b/share/lua/playlist/soundcloud.lua
index caa417ade2..3860837fcf 100644
--- a/share/lua/playlist/soundcloud.lua
+++ b/share/lua/playlist/soundcloud.lua
@@ -1,7 +1,7 @@
 --[[
  $Id$
 
- Copyright © 2012, 2015, 2019 the VideoLAN team
+ Copyright © 2012, 2015, 2019-2020 the VideoLAN team
 
  Authors: Cheng Sun <chengsun9atgmail.com>
           Pierre Ynard
@@ -38,10 +38,33 @@ function fix_quotes( value )
     return string.gsub( value, "\\\"", "\"" )
 end
 
+-- Search and extract API magic parameter from web asset
+function extract_magic( url )
+    local s = vlc.stream( url )
+    if not s then
+        return nil
+    end
+
+    while true do
+        local line = s:readline()
+        if not line then break end
+
+        -- The API magic appears under a similar form several times
+        -- in one of the javascript assets
+        -- {client_id:"z21TN9SfM0GjGteSzk4ViM1KEwMRNWZF"}
+        local client_id = string.match( line, '[{,]client_id:"(%w+)"[},]' )
+        if client_id then
+            vlc.msg.dbg( "Found soundcloud API magic" )
+            return client_id
+        end
+    end
+    return nil
+end
+
 -- Parse function.
 function parse()
     while true do
-        line = vlc.readline()
+        local line = vlc.readline()
         if not line then break end
 
         -- API endpoint for audio stream URL
@@ -52,6 +75,19 @@ function parse()
             stream = string.match( line, '"url":"([^"]-/stream/progressive[^"]-)"' )
         end
 
+        -- API magic parameter
+        if not client_id then
+            local script = string.match( line, '<script( .-)>' )
+            if script then
+                local src = string.match( script, ' src="(.-)"' )
+                if src then
+                    -- Assume absolute path
+                    -- https://a-v2.sndcdn.com/assets/48-551fb851-3.js
+                    client_id = extract_magic( src )
+                end
+            end
+        end
+
         -- Metadata
         if not name then
             name = string.match( line, "[\"']title[\"'] *: *\"(.-[^\\])\"" )
@@ -80,10 +116,10 @@ function parse()
     end
 
     if stream then
-        -- API magic
-        local client_id = "uzhloVwKlWX9bzQ5F1mrqQdjYxKEqDRM"
-
-        local api = vlc.stream( stream..( string.match( stream, "?" ) and "&" or "?" ).."client_id="..client_id )
+        if client_id then
+            stream = stream..( string.match( stream, "?" ) and "&" or "?" ).."client_id="..client_id
+        end
+        local api = vlc.stream( stream )
 
         if api then
             local streams = api:readline() -- data is on one line only



More information about the vlc-commits mailing list