Getting links to audio without VKApi

This page will be useful for those who decided to take an order for a parser of VK audio tracks and sharply understood that they did not understand anything.

What is the problem


Familiar?

https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=AeL2rMfFyZzlD3HkyvfnvNvLx1KOqw5UDfuXCOTvttm4ts1OBJnYELvHyxvODI9fnM9YztD5A3iOyI14sxv2mNiXt3iTzdLInduXzvG9C2uVr3b5mezinfj2lJbpDhGYC25rDxbwsOPQmg1eu2Pbyxr3ntPowNLhDMrrDs8XnKu2sOuOyO8XzMf1otDmBtL6BNvllNjZx3aZuLHpq3aOBvvhzenJnZKTzKnMuwfKBI4TquffrtzKv2nymMyVDu1LzJnuwMLxwMm/BeTcserWlun3ExLVBG#AqSZntu

If yes , then you tried to parse the mobile version of the site and successfully retrieve links. Invalid links. Links to a 25-second voice, reporting that everything is not going according to plan.

If not , you should try.

How to get the right URL


But this is the right question! The fact is that before playing a recording, the VC sets prepared js scripts on such a url. In general, nothing complicated - multiple line flips, bitwise shifts, even one bitwise negation. And all this is compressed by the compressor.

Honestly, earlier looking for the functions responsible for this business was more difficult. Apparently, moles were bred in Vkontakte)) Otherwise, how can a pancake explain what they signed, literally hung a sign on the right place:

image

Okay, okay, we are all slaves of collectors ...

Without further ado, the actual code


JavaScript decoder
var id = 0; //Ваш useridvar n = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=",
	i = {
		v: function(e) {
			return e.split("").reverse().join("")
		},
		r: function(e, t) {
			e = e.split("");
			for (var i, o = n + n, s = e.length; s--;) i = o.indexOf(e[s]), ~i && (e[s] = o.substr(i - t, 1));
			return e.join("")
		},
		s: function(e, t) {
			var n = e.length;
			if (n) {
				var i = r(e, t),
					o = 0;
				for (e = e.split(""); ++o < n;) e[o] = e.splice(i[n - 1 - o], 1, e[o])[0];
				e = e.join("")
			}
			return e
		},
		i: function(e, t) {
			return i.s(e, t ^ id)
		},
		x: function(e, t) {
			var n = [];
			return t = t.charCodeAt(0), each(e.split(""), function(e, i) {
				n.push(String.fromCharCode(i.charCodeAt(0) ^ t))
			}), n.join("")
		}
	};
functiono() {
	returnwindow.wbopen && ~(window.open + "").indexOf("wbopen")
}
functions(e) {
	if (!o() && ~e.indexOf("audio_api_unavailable")) {
		var t = e.split("?extra=")[1].split("#"),
			n = "" === t[1] ? "" : a(t[1]);
		if (t = a(t[0]), "string" != typeof n || !t) return e;
		n = n ? n.split(String.fromCharCode(9)) : [];
		for (var s, r, l = n.length; l--;) {
			if (r = n[l].split(String.fromCharCode(11)), s = r.splice(0, 1, t)[0], !i[s]) return e;
			t = i[s].apply(null, r)
		}
		if (t && "http" === t.substr(0, 4)) return t
	}
	return e
}
functiona(e) {
	if (!e || e.length % 4 == 1) return !1;
	for (var t, i, o = 0, s = 0, a = ""; i = e.charAt(s++);) i = n.indexOf(i), ~i && (t = o % 4 ? 64 * t + i : i, o++ % 4) && (a += String.fromCharCode(255 & t >> (-2 * o & 6)));
	return a
}
functionr(e, t) {
	var n = e.length,
		i = [];
	if (n) {
		var o = n;
		for (t = Math.abs(t); o--;) t = (n * (o + 1) ^ t + o) % n, i[o] = t
	}
	return i
}


The letter in the letter decoder in PHP
global $n, $i, $id;
$n = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=";
$id = 123456789; //user_id
$i = [
	'v' => function($e){
		return strrev($e);
	},
	'r' => function($e, $t){
		global $n;
		$e = str_split($e);
		for ($o = $n . $n, $s = count($e); $s--;){
			$i = stripos($o, $e[$s]);
			if(~$i){
				$e[$s] = substr($o, $i - $t, 1);
			}
		}
		return implode("", $e);
	},
	's' => function($e, $t){
		$n = strlen($e);
		if ($n) {
			$i = r($e, $t);
			$o = 0;
			$e = str_split($e);
			for (; ++$o < $n;){
				$p = array_splice($e, $i[$n - 1 - $o], 1, $e[$o]);
				$e[$o] = $p[0];
			}
			$e = implode("", $e);
		}
		return $e;
	},
	'i' => function($e, $t){
		global $i, $id;
		$k = $i['s'];
		return $k($e, $t ^ $id);
	},
];
functiono(){
	returnfalse;
}
functiona($e){
	global $n;
	if (!$e || strlen($e) % 4 == 1) {
		return !1;
	}
	$s = 0;
	for ($o = 0, $a = "";$s < strlen($e);) {
		$i = $e[$s++];
		$i = strpos($n, $i);
		if ($i !== false) {
			$t = ($o % 4) ? 64 * $t + $i : $i;
			if ($o++ % 4) {
				$a .= chr(255 & $t >> (-2 * $o & 6));
			}
		}
	}
	return $a;
}
functionr($e, $t){
	$n = strlen($e);
	$i = [];
	if ($n) {
		$o = $n;
		$t = abs($t);
		for (; $o--;){
			$t = ($n * ($o + 1) ^ $t + $o) % $n;
			$i[$o] = $t;
		}
	}
	return $i;
}
functions($e){
	global $i;
	if (!o() && strpos($e, "audio_api_unavailable") !== false) {
		$t = explode("?extra=", $e);
		$t = $t[1];
		$t = explode("#", $t);
		$n = ("" === $t[1]) ? "" : a($t[1]);
		$t = a($t[0]);
		if (!is_string($n) || !$t){ return $e;}
		$n = $n ? explode(chr(9), $n) : [];
		for ($l = count($n); $l--;) {
			$r = explode(chr(11), $n[$l]);
			$s = array_splice($r, 0, 1, $t);
			$s = $s[0];
			if (!$i[$s]){ return $e; }
			$t = $i[$s](...$r);
		}
		if ($t && "http" === substr($t, 0, 4)){ return $t;}
	}
	return $e;
}


In both cases

s("https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=encodeextraurl");

I think it will be easier to translate the code if needed with PHP to another language.

The article was written in order to reduce the number of people in the world spent on this task.

Ps: topical solution can always be found here: gist.github.com/in4in-dev/09f32f313f11b2c10778d9e2ffe7e60e
P.s2: User ImIeee also updates its decision in the repository github.com/vodka2/vkaudio (here you will find a solution to Python)

Also popular now: