Skip to content

Instantly share code, notes, and snippets.

@RomanTruba
Created September 22, 2015 22:40
Show Gist options
  • Save RomanTruba/d9cec6687fe623ac888f to your computer and use it in GitHub Desktop.
Save RomanTruba/d9cec6687fe623ac888f to your computer and use it in GitHub Desktop.
Download music from VK
import com.sun.istack.internal.Nullable;
import org.apache.commons.lang.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPInputStream;
public class MainClass
{
//retrieve access_token here https://vk.com/app35569
public static final String VK_ACCESS_TOKEN = "";
//leave empty for self
public static final String VK_TARGET_USER_ID = "";
//set audio id, where need to stop
public static final long VK_TARGET_AUDIO_ID = 0;
public static final int VK_PAGE_SIZE = 50;
public long mOverallBytesLoaded = 0;
//Mac OS path setup
public static final String MUSIC_DEST_FOLDER = System.getProperty("user.home") + "/Desktop/music_result";
public static void main(String[] args)
{
new MainClass().run();
}
public static final String VK_API_URL = "https://api.vk.com/method";
public String joinParams(Map<String, String> params)
{
ArrayList<String> pairs = new ArrayList<String>();
for (String key : params.keySet())
{
pairs.add(key + "=" + params.get(key));
}
return StringUtils.join(pairs, "&");
}
public String constructUrlForPageWithOffset(int offset)
{
Map<String, String> params = new HashMap<String, String>();
params.put("count", "" + VK_PAGE_SIZE);
params.put("offset", "" + offset);
params.put("user_id", VK_TARGET_USER_ID);
params.put("access_token", VK_ACCESS_TOKEN);
params.put("v", "5.35");
return String.format(Locale.getDefault(), "%s/%s?%s", VK_API_URL, "audio.get",
joinParams(params));
}
@Nullable
public String loadPage(String pageUrl) {
try
{
URLConnection connection = new URL(pageUrl).openConnection();
connection.setRequestProperty("Accept-Encoding", "gzip");
InputStream input = connection.getInputStream();
if ("gzip".equals(connection.getContentEncoding())) {
input = new GZIPInputStream(input);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder builder = new StringBuilder("");
String inputLine;
while ((inputLine = reader.readLine()) != null)
{
builder.append(inputLine);
}
reader.close();
return builder.toString();
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
public boolean saveContentAtUrlToFile(String contentUrl, File targetFile) {
try
{
URLConnection connection = new URL(contentUrl).openConnection();
InputStream inputStream = connection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(targetFile);
int contentLen = connection.getContentLength();
int maxLevel = 20, level = 1;
int BUFFER_SIZE = contentLen / maxLevel;
int bytesRead;
int totalBytesRead = 0;
byte[] buffer = new byte[BUFFER_SIZE];
System.out.println("Start: " + contentUrl);
System.out.print("0.");
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
if (totalBytesRead > BUFFER_SIZE * level)
{
System.out.print(".");
level++;
}
}
mOverallBytesLoaded += totalBytesRead;
System.out.println("Done (" + humanReadableByteCount(totalBytesRead, true) + ")");
inputStream.close();
outputStream.close();
return true;
}
catch (IOException e)
{
e.printStackTrace();
}
return false;
}
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
public void run() {
int currentOffset = 0;
int totalSongsLoaded = 0;
boolean canLoadNextPage = true;
JSONParser parser=new JSONParser();
File targetDir = new File(MUSIC_DEST_FOLDER);
boolean b = targetDir.mkdirs();
if (b) {
System.out.println("Directory prepared");
}
do {
System.out.println("Loading page for user: " + VK_TARGET_USER_ID + " with offset: " + currentOffset);
String request = constructUrlForPageWithOffset(currentOffset);
String rawJson = loadPage(request);
if (rawJson == null) {
System.out.println("Can't load request: " + request);
break;
}
try
{
JSONObject wholeResponse = (JSONObject)parser.parse(rawJson);
Object response = wholeResponse.get("response");
if (response == null) {
System.out.println("Failed to parse response: " + rawJson);
break;
}
JSONObject responseData = (JSONObject)response;
JSONArray items = (JSONArray)responseData.get("items");
if (items == null) {
System.out.println("Failed to receive items: " + rawJson);
break;
}
int size = items.size();
for (Object item : items) {
VKAudio audio = new VKAudio((JSONObject) item);
canLoadNextPage = VK_TARGET_AUDIO_ID != audio.id;
String fileName = String.format("%s - %s.mp3", audio.artist, audio.title);
File targetFile = new File(targetDir + File.separator + fileName);
System.out.println("Downloading: " + audio.toString());
if (!saveContentAtUrlToFile(audio.url, targetFile)) {
System.out.println("Failed to load audio: " + audio.toString());
} else {
totalSongsLoaded++;
}
System.out.println();
if (!canLoadNextPage) {
System.out.println("Target song reached");
break;
}
}
currentOffset += size;
}
catch (ParseException e)
{
e.printStackTrace();
}
} while (canLoadNextPage);
System.out.println("Finished loading. Songs loaded: " + totalSongsLoaded + ". Bytes loaded: " + humanReadableByteCount(mOverallBytesLoaded, true));
}
public static class VKAudio {
public Long id;
public String artist;
public String title;
public String url;
public VKAudio(JSONObject data)
{
this.id = (Long) data.get("id");
this.artist = ((String) data.get("artist")).trim();
this.title = ((String) data.get("title")).trim();
this.url = (String) data.get("url");
}
@Override
public String toString()
{
return String.format("Audio(id %d): %s - %s", id, artist, title);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment