NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Export Google Music Playlist // @namespace http://ziks.net/ // @version 0.1 // @description Adds a button to export a Google Music playlist // @author Ziks // @match https://play.google.com/music/listen // @require http://code.jquery.com/jquery-latest.js // @require https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js // @grant none // ==/UserScript== var pollingPlaylist = false; function startPollingPlaylist() { if (!window.location.hash.match(/#\/pl\//g)) return; if (pollingPlaylist) return; pollingPlaylist = true; pollPlaylist(); } function stopPollingPlaylist() { if (!pollingPlaylist) return; pollingPlaylist = false; } var scraping = false; var toScrape = 0; var scrapedInfo = null; function startScraping() { if (!window.location.hash.match(/#\/pl\//g)) return; if (scraping) return; scraping = true; scrapedInfo = []; $("#music-content")[0].scrollTop = 0; setTimeout(scrapeInfo, 17); } function stopScraping() { scraping = false; window.open(exportJSON(), 'Exported Playlist'); } function exportJSON() { return "data:application/json," + encodeURIComponent(JSON.stringify(scrapedInfo)); } function scrapeInfo() { if (!scraping) return; if (scrapedInfo.length >= toScrape) { stopScraping(); return; } $("tr.song-row").each(function() { var index = parseInt($(this).find('td[data-col="index"]').text()); var lengthStr = $(this).find('td[data-col="duration"]').text(); var matches = (/(?:([0-9]+):)?([0-9]+):([0-9]+)/g).exec(lengthStr); var length = (parseInt(matches[1]) || 0) * 60 * 60 + parseInt(matches[2]) * 60 + parseInt(matches[3]); scrapedInfo.push({ index: index, title: $(this).find('td[data-col="title"]').text(), length: length, artist: $(this).find('td[data-col="artist"]').text(), album: $(this).find('td[data-col="album"]').text() }); }); $("#music-content")[0].scrollTop = $("tr.song-row").height() * scrapedInfo.length; setTimeout(scrapeInfo, 17); } function pollPlaylist() { if (!pollingPlaylist) return; var songCountText = $(".song-count").text(); var regex = /([0-9]+)\s+SONGS/g; var match = regex.exec(songCountText); if (!match) { setTimeout(pollPlaylist, 250); return; } toScrape = parseInt(match[1]); stopPollingPlaylist(); var orig = $(".goog-menuitem:has(.goog-menuitem-content:contains(Export playlist))"); if (orig.length > 0) { return; } var editButton = $(".goog-menuitem:has(.goog-menuitem-content:contains(Edit playlist))"); var exportButton = $('<div class="goog-menuitem" role="menuitem" style="-webkit-user-select: none;" aria-hidden="false">' + '<div class="goog-menuitem-content" style="-webkit-user-select: none;">Export playlist</div>' + '</div>').insertAfter(editButton); exportButton.hover(function() { exportButton.attr("class", "goog-menuitem goog-menuitem-highlight"); }, function() { exportButton.attr("class", "goog-menuitem"); }); exportButton.click(startScraping); } $(function() { startPollingPlaylist(); }); $(window).on('hashchange', function() { startPollingPlaylist(); });