Greasy Fork is available in English.

Tidal Special

Click on elements and copy links to clipboard with user confirmation and success message, and download links as a .txt file

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==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
// ==/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 = '<h1>STAY ON PAGE </h1>';
        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 });
        })();

    }
})();