[Member Haur…] Posted April 11, 2020 Share Posted April 11, 2020 Hi all, and thanks for a great site! I was kinda wondering if any of the good folks (like @OpenType) would be willing to share some secrets on how the media URL is found. I'm extracting a URL from the meta tag that points to twitter-stream, but even though it looks very similar at first glance it is not the same URL as sing.salon generates. Basically what I'm doing is making a Telegram bot that will download and send the media to whoever asks for it. In addition to downloading, I also want to extract the information about the performance and write it to the downloaded files' metadata before sending it to the client. Of course, I'm not hosting that bot for anyone as it would incur a lot of hosting costs, but I'd upload the source to GitHub of course. Is the URL in the content attribute encrypted or encoded in some way? Hope it is OK to ask this. Thanks! 1 Link to comment Share on other sites More sharing options...
[Member Haur…] Posted April 14, 2020 Author Share Posted April 14, 2020 Nvm - I figured it out on my own. Then I wrote a console app for Windows that takes an URL, downloads the file, extracts the metadata from the website and uses it to tag and rename the file into something a lot more useful than a random string of numbers. Still needs some work, but it certainly works. W00t! Link to comment Share on other sites More sharing options...
[Member _Sly…] Posted February 11, 2021 Share Posted February 11, 2021 Any progress on this? I was trying to build a bot from an old github, but it had an old way to extract the url, and smule has changed it since then. Link to comment Share on other sites More sharing options...
[Member Haur…] Posted February 11, 2021 Author Share Posted February 11, 2021 8 hours ago, _Slynn_ said: Any progress on this? I was trying to build a bot from an old github, but it had an old way to extract the url, and smule has changed it since then. Still working on it, and I'll release it as an Android app in Play Store soon-ish Link to comment Share on other sites More sharing options...
[Member Gwap…] Posted February 12, 2021 Share Posted February 12, 2021 //Maybe usefull for someone, but here you go a perfect way to use Smule's own code to decode the media url and download a performance. //tests //video //await downloadPerformance('https://www.smule.com/recording/ava-max-sweet-but-psycho/1998769355_3504039030'); //await downloadPerformance('1998769355_3504039030'); //audio //await downloadPerformance('https://www.smule.com/recording/paper-hearts-guitar-acoustic/823670826_3905415470'); //await downloadPerformance('823670826_3905415470'); //go to smule, copy and paste in console async function downloadPerformance(urlOrKey) { await init(); var pKey = urlOrKey.split('/').pop(); var r = await (await fetch(`/p/${pKey}/json`)).json(); var mediaUrl = r.type == 'video' ? r.video_media_url : r.media_url; var decodedMediaUrl = decodeMediaUrl(mediaUrl); window.open(decodedMediaUrl, '_blank'); } async function init() { var resolveDecodeMediaUrlFn = async () => { return new Promise((resolve, reject) => { var resolveDecode = (version, modules) => { var decodeMediaUrl; for (let id in modules) { let module = modules[id]; let exports = module.exports; if (!exports || typeof exports != 'object' || exports == window) continue; if (version == 'v4') { for (let p in exports) { let pv = exports[p]; if (pv && typeof pv == 'string' && pv == 'X-CSRF-Token') { if (typeof decodeMediaUrl != 'undefined') continue; for (var p2 in exports) { if (typeof exports[p2] != 'function') continue; var fn = exports[p2]; if (fn.toString().indexOf('Failed to decode URL') == -1) continue; resolve((url) => { return fn(url); }); return; } } } } else if (version == 'v3') { if (!exports.hasOwnProperty('__esModule')) continue; if (exports.hasOwnProperty('CSRF_TOKEN_HEADER')) { resolve((url) => { return exports['processRecording'](url); }); return; } } } throw new Error('decode not found'); } var wp = window.webpackJsonp; var mId = 'dummy-' + new Date().getTime(); if (typeof wp === 'function') { wp([], { [mId]: function () { var require = arguments[2]; resolveDecode("v3", require.c); } }, [mId]); } else { wp.push([[mId], { [mId]: function () { var require = arguments[2]; resolveDecode("v4", require.c); } }, [[mId]]]); } }); }; if (!window.decodeMediaUrl) { var r = await resolveDecodeMediaUrlFn(); window.decodeMediaUrl = r; } return window.decodeMediaUrl; }  Link to comment Share on other sites More sharing options...
[Member _Sly…] Posted February 15, 2021 Share Posted February 15, 2021 (edited) I'm trying to build a telegram bot. and the only struggle I am having is extracting that hidden download link so I can send it back in a message. I'm using Python Edited February 15, 2021 by _Slynn_ Link to comment Share on other sites More sharing options...
[Member Gwap…] Posted February 15, 2021 Share Posted February 15, 2021 It is possible to reverse engineer the decoding process. But it's not easy work. And the code for decoding the URL's get updated from time to time. So you have to fix your app every time Smule pushes a new update. I think you could take a view different routes. 1) The easiest one is to contact Smule and pay for API access. That is if they allow something like that. 2) You could try to extract the decoding logic from the core Smule javascript app, and run that in a JavaScript interpreter in side you Python application. You could even automate that process inside of your bot. 3) Use a version of Chromium that you can run in memory, open the Smule website in the background. And run the code i shared earlier. Extract the result. That will eat lot's of resources, but you will not suffer with every Smule update.  Link to comment Share on other sites More sharing options...
[Member Haur…] Posted February 16, 2021 Author Share Posted February 16, 2021 On 2/12/2021 at 8:59 PM, Gwapo_Erik said: //Maybe usefull for someone, but here you go a perfect way to use Smule's own code to decode the media url and download a performance. //tests //video //await downloadPerformance('https://www.smule.com/recording/ava-max-sweet-but-psycho/1998769355_3504039030'); //await downloadPerformance('1998769355_3504039030'); //audio //await downloadPerformance('https://www.smule.com/recording/paper-hearts-guitar-acoustic/823670826_3905415470'); //await downloadPerformance('823670826_3905415470'); //go to smule, copy and paste in console async function downloadPerformance(urlOrKey) { await init(); var pKey = urlOrKey.split('/').pop(); var r = await (await fetch(`/p/${pKey}/json`)).json(); var mediaUrl = r.type == 'video' ? r.video_media_url : r.media_url; var decodedMediaUrl = decodeMediaUrl(mediaUrl); window.open(decodedMediaUrl, '_blank'); } async function init() { var resolveDecodeMediaUrlFn = async () => { return new Promise((resolve, reject) => { var resolveDecode = (version, modules) => { var decodeMediaUrl; for (let id in modules) { let module = modules[id]; let exports = module.exports; if (!exports || typeof exports != 'object' || exports == window) continue; if (version == 'v4') { for (let p in exports) { let pv = exports[p]; if (pv && typeof pv == 'string' && pv == 'X-CSRF-Token') { if (typeof decodeMediaUrl != 'undefined') continue; for (var p2 in exports) { if (typeof exports[p2] != 'function') continue; var fn = exports[p2]; if (fn.toString().indexOf('Failed to decode URL') == -1) continue; resolve((url) => { return fn(url); }); return; } } } } else if (version == 'v3') { if (!exports.hasOwnProperty('__esModule')) continue; if (exports.hasOwnProperty('CSRF_TOKEN_HEADER')) { resolve((url) => { return exports['processRecording'](url); }); return; } } } throw new Error('decode not found'); } var wp = window.webpackJsonp; var mId = 'dummy-' + new Date().getTime(); if (typeof wp === 'function') { wp([], { [mId]: function () { var require = arguments[2]; resolveDecode("v3", require.c); } }, [mId]); } else { wp.push([[mId], { [mId]: function () { var require = arguments[2]; resolveDecode("v4", require.c); } }, [[mId]]]); } }); }; if (!window.decodeMediaUrl) { var r = await resolveDecodeMediaUrlFn(); window.decodeMediaUrl = r; } return window.decodeMediaUrl; }  That's a neat function indeed, but it does rely on being executed in the context of a browser while on smule.com as far as I can tell? I did test it though, and it works perfectly. Pretty impressive reverse engineering! Link to comment Share on other sites More sharing options...
[Member Haur…] Posted February 16, 2021 Author Share Posted February 16, 2021 On 2/15/2021 at 3:12 AM, _Slynn_ said: I'm trying to build a telegram bot. and the only struggle I am having is extracting that hidden download link so I can send it back in a message. I'm using Python I was contemplating making a Telegram bot for this as well actually, but I always wanted to write metadata to the downloaded file so it is possible to actually figure out what song you've downloaded. The app I've been working on is now in internal testing, though only for Android. I don't think it will be possible to publish an iOS app with this functionality as it probably breaches some license or user agreement. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now