// ==UserScript==
// @name Tidal Special
// @namespace http://tampermonkey.net/
// @version 0.3
// @description Click on elements and copy links to clipboard with user confirmation and success message, and download links as a .txt file
// @author You
// @match https://tidal.com/browse/playlist/*
// @match https://pixeldrain.com/*
// @icon https://w7.pngwing.com/pngs/973/746/png-transparent-tidal-round-logo-tech-companies-thumbnail.png
// @grant none
// @license MIT
// @run-at document-end
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
// Function to read text from the clipboard
async function readClipboard() {
try {
const text = await navigator.clipboard.readText();
return text;
} catch (err) {
console.error('Failed to read clipboard:', err);
}
}
function createLoader() {
// Check if the loader already exists
if (document.querySelector('.loader-overlay')) {
return; // Exit if the loader is already present
}
// Create the overlay div
const overlay = document.createElement('div');
overlay.className = 'loader-overlay'; // Add a class for easy removal
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100vw';
overlay.style.height = '100vh';
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; // Black background with slight transparency
overlay.style.color = '#fff'; // White text color
overlay.style.display = 'flex';
overlay.style.flexDirection = 'column'; // Stack items vertically
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.fontSize = '1.5em';
overlay.style.zIndex = '9999'; // Ensure it's on top of other content
// Add the loading text
const loadingText = document.createElement('div');
loadingText.className = 'loader-text';
loadingText.innerHTML = '
STAY ON PAGE
';
loadingText.style.textAlign = "center";
overlay.appendChild(loadingText);
// Create the button
const button = document.createElement('button');
button.textContent = 'Start Extraction';
button.style.marginTop = '20px'; // Space between text and button
button.style.padding = '10px 20px';
button.style.cursor = 'pointer';
// Attach the click event handler to the button
button.addEventListener('click', () => {
handleClick()
button.hidden = true
});
// Add the button to the overlay
overlay.appendChild(button);
// Append the overlay to the body
document.body.appendChild(overlay);
}
function updateLoaderMessage(message) {
const loadingText = document.querySelector('.loader-text');
if (loadingText) {
loadingText.textContent = message;
}
}
function removeLoader() {
// Find the overlay by its class name and remove it
const overlay = document.querySelector('.loader-overlay');
if (overlay) {
document.body.removeChild(overlay);
}
}
function downloadLinks(links) {
const blob = new Blob([links.join('\n')], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'links.txt';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Collect all links
let collectedLinks = [];
async function handleClick() {
updateLoaderMessage('Starting extraction...');
// Click on all elements with class "track-options"
let trackOptions = document.querySelectorAll('.track-options');
let index = 0;
function processNext() {
if (index >= trackOptions.length) {
updateLoaderMessage('All links collected!');
setTimeout(() => {
updateLoaderMessage('Downloading links...');
downloadLinks(collectedLinks);
updateLoaderMessage('Success! All links have been collected and downloaded.');
setTimeout(removeLoader, 3000); // Show success message for a few seconds before removing the loader
}, 1000); // Adjust the delay for the success message as needed
return;
}
let element = trackOptions[index++];
element.click();
// Wait for the modal to appear and then click the button
setTimeout(async () => {
let copyButton = document.querySelector('#__layout > div > div.font-weight-bold.modal-wrapper-mobile-only > div > ul > li:nth-child(4) > button');
if (copyButton) {
copyButton.click();
// Assuming there's a delay before the link is copied
setTimeout(async () => {
// Use a way to obtain the copied link if possible or retrieve it from modal
let link = await readClipboard();
if (link) {
collectedLinks.push(link);
updateLoaderMessage(`Collected ${collectedLinks.length} links...`);
} else {
console.warn('No link was copied.');
}
processNext();
}, 10); // Adjust the delay as needed
} else {
console.error('Copy button not found');
processNext();
}
}, 10); // Adjust the delay as needed
}
processNext();
}
if (window.location.host == "tidal.com") {
createLoader();
}
if (window.location.host == "pixeldrain.com") {
// ==UserScript==
// @name Pixel Drain Auto Audio Downloader
// @namespace http://tampermonkey.net/
// @version 0.2
// @description Automatically download audio files from Pixel Drain
// @author Your Name
// @match https://pixeldrain.com/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
function autoDownloadAudio() {
// Select all audio elements
const audioElements = document.querySelectorAll('audio.player');
audioElements.forEach(audio => {
// Find the source element
const source = audio.querySelector('source');
if (!source) return;
// Check if the file is already downloaded or not
if (source.dataset.downloaded) return;
// Mark the file as downloaded to avoid multiple downloads
source.dataset.downloaded = 'true';
// Construct the absolute URL
const audioUrl = source.src;
const absoluteUrl = new URL(audioUrl, window.location.origin).href;
// Create a temporary anchor element to trigger download
const a = document.createElement('a');
a.href = absoluteUrl;
a.download = ''; // Use the filename if needed, e.g., `source.src.split('/').pop()`
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
}
// Run the function when the page is loaded
window.addEventListener('load', autoDownloadAudio);
// Also check for dynamically loaded content
const observer = new MutationObserver((mutations) => {
mutations.forEach(() => {
autoDownloadAudio();
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
})();