Scribd Downloader

Redirect Scribd document pages to embed URLs dengan tombol download PDF yang interaktif dan multiple access keys

当前为 2025-11-07 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Scribd Downloader
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Redirect Scribd document pages to embed URLs dengan tombol download PDF yang interaktif dan multiple access keys
// @author       youcantrust
// @match        *://*.scribd.com/*
// @match        *://scribd.com/*
// @run-at       document-start
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      *
// @license MIT

// Copyright (c) [year] [fullname]

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ==/UserScript==

(function() {
    'use strict';

    // Multiple access keys untuk fallback
    const accessKeys = [
        'key-ixxYfpwtHw5XUehk3QyF'
    ];

    // Fungsi untuk mendapatkan access key secara acak
    function getRandomAccessKey() {
        return accessKeys[Math.floor(Math.random() * accessKeys.length)];
    }

    // Fungsi untuk mengekstrak ID dari berbagai format URL Scribd
    function extractDocumentId(url) {
        if (url.includes('/embeds/')) {
            const embedMatch = url.match(/\/embeds\/([^\/\?&]+)/);
            if (embedMatch && embedMatch[1]) {
                return embedMatch[1];
            }
        }

        const patterns = [
            /\/(?:document|doc)\/([^\/\?&]+)/,
            /\/(?:read|pub)\/([^\/\?&]+)/,
            /\/(\d{8,})/,
            /\/(\d+)-[^\/\?&]+/,
            /\/(\d+)(?:\?|$|\/)/,
            /\/([a-zA-Z0-9_-]{8,})(?:\?|$|\/)/,
            /(?:\?|&)id=([^&]+)/,
            /(?:\?|&)document_id=([^&]+)/,
            /(?:\?|&)doc_id=([^&]+)/
        ];

        for (let pattern of patterns) {
            const match = url.match(pattern);
            if (match && match[1]) {
                const potentialId = match[1];
                if (/^\d+$/.test(potentialId) && potentialId.length >= 6) {
                    return potentialId;
                }
                if (/^[a-zA-Z0-9_-]+$/.test(potentialId) && potentialId.length >= 6) {
                    return potentialId;
                }
            }
        }
        return null;
    }

    // Fungsi untuk menambahkan CSS animasi
    function addStyles() {
        const styles = `
            @keyframes pulse-glow {
                0% { box-shadow: 0 0 5px #ff4444, 0 0 10px #ff4444; }
                50% { box-shadow: 0 0 20px #ff4444, 0 0 30px #ff4444; }
                100% { box-shadow: 0 0 5px #ff4444, 0 0 10px #ff4444; }
            }

            @keyframes shake {
                0%, 100% { transform: translateX(0) scale(1.1); }
                10%, 30%, 50%, 70%, 90% { transform: translateX(-5px) scale(1.1); }
                20%, 40%, 60%, 80% { transform: translateX(5px) scale(1.1); }
            }

            @keyframes bounce {
                0%, 20%, 50%, 80%, 100% { transform: translateY(0) scale(1.1); }
                40% { transform: translateY(-10px) scale(1.1); }
                60% { transform: translateY(-5px) scale(1.1); }
            }

            @keyframes float {
                0%, 100% { transform: translateY(0) scale(1.1); }
                50% { transform: translateY(-5px) scale(1.1); }
            }

            @keyframes rainbow {
                0% { background: linear-gradient(45deg, #ff0000, #ff4444); }
                25% { background: linear-gradient(45deg, #ff4444, #ff8800); }
                50% { background: linear-gradient(45deg, #ff8800, #ffaa00); }
                75% { background: linear-gradient(45deg, #ffaa00, #ff4444); }
                100% { background: linear-gradient(45deg, #ff4444, #ff0000); }
            }

            .download-btn {
                position: fixed;
                top: 20px;
                right: 20px;
                z-index: 10000;
                background: linear-gradient(45deg, #ff4444, #ff0000);
                color: white;
                border: none;
                padding: 15px 25px;
                border-radius: 50px;
                font-size: 16px;
                font-weight: bold;
                cursor: pointer;
                box-shadow: 0 4px 15px rgba(255, 0, 0, 0.4);
                transition: all 0.3s ease;
                transform: scale(1.1);
                animation: pulse-glow 2s infinite, shake 3s 3s infinite, float 3s 6s infinite;
            }

            .download-btn:hover {
                animation: none;
                transform: scale(1.2);
                background: linear-gradient(45deg, #ff0000, #cc0000);
                box-shadow: 0 6px 20px rgba(255, 0, 0, 0.6);
            }

            .download-btn:active {
                transform: scale(1.15);
            }

            .download-btn.rainbow {
                animation: rainbow 3s infinite, bounce 2s infinite !important;
            }

            .download-btn.loading {
                animation: pulse-glow 1s infinite !important;
                background: linear-gradient(45deg, #ff8800, #ffaa00) !important;
            }

            .download-btn.success {
                animation: none !important;
                background: linear-gradient(45deg, #00cc00, #00aa00) !important;
                transform: scale(1.1);
            }

            .download-btn.error {
                animation: shake 0.5s infinite !important;
                background: linear-gradient(45deg, #cc0000, #990000) !important;
            }

            .download-pulse {
                position: absolute;
                top: 50%;
                left: 50%;
                width: 100%;
                height: 100%;
                background: rgba(255, 255, 255, 0.3);
                border-radius: 50px;
                transform: translate(-50%, -50%);
                animation: ripple 2s infinite;
            }

            @keyframes ripple {
                0% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
                100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; }
            }
        `;

        const styleSheet = document.createElement('style');
        styleSheet.textContent = styles;
        document.head.appendChild(styleSheet);
    }

    // Fungsi untuk membuat tombol download PDF yang sangat interaktif
    function createDownloadButton(documentId) {
        addStyles();

        const button = document.createElement('button');
        button.className = 'download-btn';
        button.innerHTML = '📥 DOWNLOAD PDF';

        // Tambahkan elemen untuk efek ripple
        const pulse = document.createElement('div');
        pulse.className = 'download-pulse';
        button.appendChild(pulse);

        // Efek hover
        button.addEventListener('mouseenter', function() {
            this.classList.add('rainbow');
        });

        button.addEventListener('mouseleave', function() {
            this.classList.remove('rainbow');
        });

        // Klik handler
        button.addEventListener('click', function() {
            this.classList.remove('rainbow');
            this.classList.add('loading');
            this.innerHTML = '⏳ MENGUNDUH...';

            // Hapus efek pulse saat loading
            const existingPulse = this.querySelector('.download-pulse');
            if (existingPulse) {
                existingPulse.remove();
            }

            downloadAsPDF(documentId, button);
        });

        // Rotasi animasi setiap 10 detik
        let animationIndex = 0;
        const animations = ['shake', 'bounce', 'float'];

        setInterval(() => {
            if (!button.classList.contains('loading') &&
                !button.classList.contains('success') &&
                !button.classList.contains('error')) {

                // Hapus semua class animasi
                animations.forEach(anim => button.style.animation = '');

                // Setel animasi baru
                setTimeout(() => {
                    if (!button.classList.contains('loading') &&
                        !button.classList.contains('success') &&
                        !button.classList.contains('error')) {
                        button.style.animation = `pulse-glow 2s infinite, ${animations[animationIndex]} 3s infinite`;
                    }
                }, 100);

                animationIndex = (animationIndex + 1) % animations.length;
            }
        }, 10000);

        return button;
    }

    // Fungsi untuk mendownload sebagai PDF dengan multiple access keys
    function downloadAsPDF(documentId, button) {
        let currentKeyIndex = 0;

        function tryDownloadWithKey() {
            if (currentKeyIndex >= accessKeys.length) {
                // Semua access keys sudah dicoba, coba endpoint tanpa access key
                tryDirectDownload();
                return;
            }

            const accessKey = accessKeys[currentKeyIndex];
            const endpoints = [
                `https://scribd.com/embeds/${documentId}/content?format=pdf&access_key=${accessKey}`,
                `https://scribd.com/doc/${documentId}/download?format=pdf&access_key=${accessKey}`,
                `https://scribd.com/document/${documentId}/download?format=pdf&access_key=${accessKey}`,
                `https://scribd.com/embeds/${documentId}/download?format=pdf&access_key=${accessKey}`
            ];

            let currentEndpoint = 0;

            function tryDownload() {
                if (currentEndpoint >= endpoints.length) {
                    // Coba access key berikutnya
                    currentKeyIndex++;
                    setTimeout(tryDownloadWithKey, 500);
                    return;
                }

                const endpoint = endpoints[currentEndpoint];
                console.log(`Mencoba mengunduh dari: ${endpoint}`);

                GM_xmlhttpRequest({
                    method: 'GET',
                    url: endpoint,
                    responseType: 'blob',
                    onload: function(response) {
                        if (response.status === 200) {
                            const blob = response.response;
                            const url = URL.createObjectURL(blob);
                            const filename = `scribd_${documentId}_${new Date().getTime()}.pdf`;

                            GM_download({
                                url: url,
                                name: filename,
                                onload: function() {
                                    button.classList.remove('loading');
                                    button.classList.add('success');
                                    button.innerHTML = '✅ BERHASIL!';

                                    setTimeout(() => {
                                        button.classList.remove('success');
                                        button.innerHTML = '📥 DOWNLOAD PDF';

                                        // Tambahkan kembali efek pulse
                                        const pulse = document.createElement('div');
                                        pulse.className = 'download-pulse';
                                        button.appendChild(pulse);
                                    }, 3000);

                                    URL.revokeObjectURL(url);
                                },
                                onerror: function() {
                                    currentEndpoint++;
                                    setTimeout(tryDownload, 500);
                                }
                            });
                        } else {
                            currentEndpoint++;
                            setTimeout(tryDownload, 500);
                        }
                    },
                    onerror: function() {
                        currentEndpoint++;
                        setTimeout(tryDownload, 500);
                    },
                    ontimeout: function() {
                        currentEndpoint++;
                        setTimeout(tryDownload, 500);
                    }
                });
            }

            tryDownload();
        }

        // Fallback: coba download tanpa access key
        function tryDirectDownload() {
            const directEndpoints = [
                `https://scribd.com/embeds/${documentId}/content?format=pdf`,
                `https://scribd.com/doc/${documentId}/download?format=pdf`,
                `https://scribd.com/document/${documentId}/download?format=pdf`,
                `https://scribd.com/embeds/${documentId}/download?format=pdf`
            ];

            let currentDirectEndpoint = 0;

            function tryDirect() {
                if (currentDirectEndpoint >= directEndpoints.length) {
                    // Semua endpoint gagal
                    showError();
                    return;
                }

                const endpoint = directEndpoints[currentDirectEndpoint];
                console.log(`Mencoba mengunduh tanpa access key dari: ${endpoint}`);

                GM_xmlhttpRequest({
                    method: 'GET',
                    url: endpoint,
                    responseType: 'blob',
                    onload: function(response) {
                        if (response.status === 200) {
                            const blob = response.response;
                            const url = URL.createObjectURL(blob);
                            const filename = `scribd_${documentId}_${new Date().getTime()}.pdf`;

                            GM_download({
                                url: url,
                                name: filename,
                                onload: function() {
                                    button.classList.remove('loading');
                                    button.classList.add('success');
                                    button.innerHTML = '✅ BERHASIL!';

                                    setTimeout(() => {
                                        button.classList.remove('success');
                                        button.innerHTML = '📥 DOWNLOAD PDF';

                                        const pulse = document.createElement('div');
                                        pulse.className = 'download-pulse';
                                        button.appendChild(pulse);
                                    }, 3000);

                                    URL.revokeObjectURL(url);
                                },
                                onerror: function() {
                                    currentDirectEndpoint++;
                                    setTimeout(tryDirect, 500);
                                }
                            });
                        } else {
                            currentDirectEndpoint++;
                            setTimeout(tryDirect, 500);
                        }
                    },
                    onerror: function() {
                        currentDirectEndpoint++;
                        setTimeout(tryDirect, 500);
                    },
                    ontimeout: function() {
                        currentDirectEndpoint++;
                        setTimeout(tryDirect, 500);
                    }
                });
            }

            function showError() {
                button.classList.remove('loading');
                button.classList.add('error');
                button.innerHTML = '❌ GAGAL MENGUNDH';

                setTimeout(() => {
                    button.classList.remove('error');
                    button.innerHTML = '📥 DOWNLOAD PDF';

                    // Tambahkan kembali efek pulse
                    const pulse = document.createElement('div');
                    pulse.className = 'download-pulse';
                    button.appendChild(pulse);
                }, 5000);
            }

            tryDirect();
        }

        tryDownloadWithKey();
    }

    // Fungsi untuk menambahkan tombol ke halaman
    function addDownloadButtonToPage(documentId) {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', function() {
                setTimeout(() => {
                    const existingButton = document.querySelector('.download-btn');
                    if (!existingButton) {
                        const button = createDownloadButton(documentId);
                        document.body.appendChild(button);

                        // Tambahkan efek muncul dengan animasi
                        setTimeout(() => {
                            button.style.opacity = '0';
                            button.style.transition = 'opacity 0.5s ease';
                            setTimeout(() => {
                                button.style.opacity = '1';
                            }, 100);
                        }, 100);
                    }
                }, 3000);
            });
        } else {
            setTimeout(() => {
                const existingButton = document.querySelector('.download-btn');
                if (!existingButton) {
                    const button = createDownloadButton(documentId);
                    document.body.appendChild(button);

                    // Tambahkan efek muncul dengan animasi
                    setTimeout(() => {
                        button.style.opacity = '0';
                        button.style.transition = 'opacity 0.5s ease';
                        setTimeout(() => {
                            button.style.opacity = '1';
                        }, 100);
                    }, 100);
                }
            }, 3000);
        }
    }

    // Fungsi untuk memeriksa apakah URL saat ini menggunakan salah satu access key yang valid
    function isValidEmbedUrl(url) {
        return accessKeys.some(key => url.includes(key));
    }

    // Main logic
    const currentUrl = window.location.href;

    // Cek jika kita sudah di embed URL dengan access key yang valid
    if (currentUrl.includes('/embeds/') && isValidEmbedUrl(currentUrl)) {
        const documentId = extractDocumentId(currentUrl);
        if (documentId) {
            console.log('Document ID ditemukan:', documentId);
            addDownloadButtonToPage(documentId);
        }
        return;
    }

    // Jika bukan di embed URL yang valid, lakukan redirect dengan access key acak
    const documentId = extractDocumentId(currentUrl);
    if (documentId && !currentUrl.includes('/embeds/')) {
        const randomAccessKey = getRandomAccessKey();
        const embedUrl = `https://scribd.com/embeds/${documentId}/content?start_page=1&view_mode=scroll&access_key=${randomAccessKey}`;

        console.log(`Redirecting from: ${currentUrl}`);
        console.log(`Document ID found: ${documentId}`);
        console.log(`Using access key: ${randomAccessKey}`);
        console.log(`Redirecting to: ${embedUrl}`);

        window.location.replace(embedUrl);
    }
})();