Skip to content

Instantly share code, notes, and snippets.

@Thomasvdam
Last active October 9, 2023 18:45
Show Gist options
  • Save Thomasvdam/3208bd212ce71dd0bf66db52ac6e9ac8 to your computer and use it in GitHub Desktop.
Save Thomasvdam/3208bd212ce71dd0bf66db52ac6e9ac8 to your computer and use it in GitHub Desktop.
Copy SoundCloud playlist items from one to another.
// Configuration
const WAIT_OPEN_PLAYLIST_POPUP = 1000;
const WAIT_AFTER_ADD_PLAYLIST = 1500;
const TARGET_PLAYLIST_NAME = 'To Do';
// Should the new playlist be in reverse order?
const REVERSE = false;
// Should liked items be skipped?
const SKIP_LIKED = true;
// Implementation
const delta = REVERSE ? -1 : 1;
const nextIndex = (index) => index + delta;
const listItems = Array.from(document.querySelectorAll('.sc-button-group.sc-button-group-small'));
const addItemToPlaylist = (index) => {
const node = listItems[index];
if (!node) {
console.log('Done with all currently loaded items.');
return;
}
if (SKIP_LIKED) {
const hasLikedButton = node.querySelector('.sc-button-like.sc-button-selected');
if (hasLikedButton) {
console.log('Already liked index: ', index);
setTimeout(() => {
addItemToPlaylist(nextIndex(index));
}, 0);
return;
}
}
node.querySelector('.sc-button-more').click();
document.querySelector('button.sc-button-addtoset').click();
setTimeout(() => {
const playlistRow = Array.from(document.querySelectorAll('.addToPlaylistList__item')).find(node => node.querySelector(`[title="${TARGET_PLAYLIST_NAME}"]`));
const playListButton = playlistRow.querySelector('button.addToPlaylistButton:not(.sc-button-selected)');
if (!playListButton) {
console.log('Already added index: ', index);
setTimeout(() => {
addItemToPlaylist(nextIndex(index));
}, 0);
return;
}
playListButton.click();
console.log('Added index: ', index);
setTimeout(() => {
addItemToPlaylist(nextIndex(index));
}, WAIT_AFTER_ADD_PLAYLIST);
}, WAIT_OPEN_PLAYLIST_POPUP);
};
if (REVERSE) {
addItemToPlaylist(listItems.length - 1);
} else {
addItemToPlaylist(0);
}
@Thomasvdam
Copy link
Author

I wanted to copy most items of one SoundCloud playlist to another and had to improvise as SC doesn't support this by default. I made sure all the items in the list were loaded beforehand and then pasted this in the developer console (Chrome for fancy ES6 goodness). If you want to use this make sure the playlist name is set correctly to your desired target playlist. You might need to fiddle with the timing values based on your internet connection and overall processing speed of your system.

@juugmanjonnypal
Copy link

I thank you so so so much for this script.

@juugmanjonnypal
Copy link

What can I edit to make it start adding from a certain point in a playlist and onwards

@Thomasvdam
Copy link
Author

You can edit the last line addItemToPlaylist(X) and replace X with the index of the point in the playlist that you want it to start. The easiest way to determine the index is to take the song playlist position that SoundCloud shows and subtract 1. So if you want it to start from the 10th item you'd replace the final line with addItemToPlaylist(9). Hope this helps. :)

@asimjanj
Copy link

Thank you so much Thomas for this script, saves a ton of time.

Unfortunately, when I run the script it only copies 26 songs out of the 60 I wish to copy. I've tried to increase 'Configuration' (doubled it) settings and also tried my best to make sure the playlist was fully loaded by scrolling down the page. I also tried to run the script by changing addItemToPlaylist(0) to 26.

I'm sure I'm doing something wrong. Your guidance would be massively appreciated!

@Thomasvdam
Copy link
Author

@asimjanj The first thing that comes to mind is that perhaps the items that aren't being added to the playlist are items that you've favourited. You can disable this behaviour by removing lines 26-36. If this doesn't help please post the console output, that might aid in finding out what's wrong. :)

@asimjanj
Copy link

@Thomasvdam. Genius :) In fact, you were absolutely correct. It worked a charm by commenting out lines 26-36. Thank you so much for your support.

@samhangster
Copy link

Hello! I'm relatively new to JS, I'm was wondering if you could explain to me how to run this program for soundcloud on chrome. Thanks!

@Thomasvdam
Copy link
Author

@samhangster Maybe you've already figured it out but you can run this in the Chrome developer console for the correct SoundCloud page.

  1. In a new browser window navigate to the playlist you want to copy.
  2. Make sure you have scrolled enough so that all items in the playlist have loaded.
  3. Use the right mouse button (or another way for the 'alternate click') to open a menu with various options.
  4. Select the 'Inspect' option, it should be near the bottom. This will open up a new part in your browser window or open a new window entirely, this depends on your settings.
  5. In this new part/window, select the 'console' tab.
  6. Here you can paste the code from the snippet (make sure to set the options correctly) and you should see the SoundCloud page starting to add tracks to your specified playlist.

Hope this helps. :)

@samhangster
Copy link

@Thomasvdam

re:

@samhangster Maybe you've already figured it out but you can run this in the Chrome developer console for the correct SoundCloud page.

  1. In a new browser window navigate to the playlist you want to copy.
  2. Make sure you have scrolled enough so that all items in the playlist have loaded.
  3. Use the right mouse button (or another way for the 'alternate click') to open a menu with various options.
  4. Select the 'Inspect' option, it should be near the bottom. This will open up a new part in your browser window or open a new window entirely, this depends on your settings.
  5. In this new part/window, select the 'console' tab.
  6. Here you can paste the code from the snippet (make sure to set the options correctly) and you should see the SoundCloud page starting to add tracks to your specified playlist.

Hope this helps. :)

First of all, thank you for your help, I really appreciate it. I have been trying to get this to work for days and it still fails to work. I have tampered with all of the options, and i am getting a script error.

VM127:46 Uncaught TypeError: Cannot read property 'querySelector' of undefined
at :46:44
(anonymous) @ VM127:46
setTimeout (async)
addItemToPlaylist @ VM127:44
(anonymous) @ VM127:70

The add to playlist pop up comes up, I select my playlist that I typed in the TARGET_PLAYLIST_NAME slot, and it gets stuck there. Please help me. I am not a noobie when it comes to code, i am fluent in Java and Python but javascript it a different realm. Thanks in advance

@Thomasvdam
Copy link
Author

@samhangster The error is thrown on line 46, but actually originates on line 45:

const playlistRow = Array.from(document.querySelectorAll('.addToPlaylistList__item')).find(node => node.querySelector(`[title="${TARGET_PLAYLIST_NAME}"]`));

It seems that the script is unable to locate a node in the DOM tree that has the correct title associated with it. This is most likely a typo in the TARGET_PLAYLIST_NAME variable, or it's possible that you have a lot of playlists and your target playlist is not on the first 'page' that is loaded. That would require some way to work around that using the filter I think.

On second read of your comment, I noticed that you said you clicked something yourself:

The add to playlist pop up comes up, I select my playlist that I typed in the TARGET_PLAYLIST_NAME slot, and it gets stuck there.

This might throw the script off as it was designed to run without intervention. It's all a bit rickety due to all the timeouts, so tiny adjustments can easily break the entire thing.

@samhangster
Copy link

@Thomasvdam
I got it. I had changed the delays to a lower value thinking it would speed it up or something and it wasn't allowing time for it to even read the playlist name. Thank you for your help!

@JupiterJaeden
Copy link

You are an actual god

@hamhimstudio
Copy link

thank you from the bottom of my heart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment