Greasy Fork

来自缓存

Greasy Fork is available in English.

超星学习通PDF下载器

自动检测超星学习通中的PDF文件并添加下载按钮

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         超星学习通PDF下载器
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  自动检测超星学习通中的PDF文件并添加下载按钮
// @author       Hungry Shark
// @match        https://mooc1.chaoxing.com/*
// @match        https://*.chaoxing.com/*
// @icon         https://s1.chu0.com/src/img/png/df/df6f0a1cb5834e1499253980756986ce.png?e=2051020800&token=1srnZGLKZ0Aqlz6dk7yF4SkiYf4eP-YrEOdM1sob:A8wAfloBVYeZ5nxCWRV3GRyerd8=
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @connect      mooc1.chaoxing.com
// @connect      cldisk.com
// @connect      s3.cldisk.com
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 存储检测到的PDF信息
    let pdfInfo = null;
    let checkInterval = null;

    // 创建下载按钮
    function createDownloadButton() {
        // 如果按钮已存在,先移除
        const existingButton = document.getElementById('pdf-download-btn');
        if (existingButton) {
            existingButton.remove();
        }

        const downloadBtn = document.createElement('button');
        downloadBtn.id = 'pdf-download-btn';
        downloadBtn.innerHTML = '📥 下载PDF';
        downloadBtn.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 10000;
            padding: 10px 15px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            transition: all 0.3s ease;
        `;

        downloadBtn.addEventListener('mouseenter', function() {
            this.style.background = '#45a049';
            this.style.transform = 'scale(1.05)';
        });

        downloadBtn.addEventListener('mouseleave', function() {
            this.style.background = '#4CAF50';
            this.style.transform = 'scale(1)';
        });

        downloadBtn.addEventListener('click', downloadPDF);
        document.body.appendChild(downloadBtn);
    }

    // 下载PDF文件
    function downloadPDF() {
        if (!pdfInfo || !pdfInfo.pdf) {
            alert('未找到PDF文件链接');
            return;
        }

        const filename = pdfInfo.filename || 'download.pdf';
        const pdfFilename = filename.replace(/\.[^/.]+$/, "") + '.pdf';

        try {
            // 使用GM_download下载文件
            GM_download({
                url: pdfInfo.pdf,
                name: pdfFilename,
                onload: function() {
                    console.log('PDF下载成功:', pdfFilename);
                    showNotification('PDF下载成功!', 'success');
                },
                onerror: function(error) {
                    console.error('PDF下载失败:', error);
                    showNotification('PDF下载失败,请重试', 'error');

                    // 如果GM_download失败,尝试使用备用方法
                    fallbackDownload(pdfInfo.pdf, pdfFilename);
                }
            });
        } catch (e) {
            console.error('GM_download错误:', e);
            // 使用备用下载方法
            fallbackDownload(pdfInfo.pdf, pdfFilename);
        }
    }

    // 备用下载方法
    function fallbackDownload(url, filename) {
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        a.target = '_blank';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        showNotification('正在打开PDF下载链接...', 'info');
    }

    // 显示通知
    function showNotification(message, type) {
        const notification = document.createElement('div');
        notification.textContent = message;
        notification.style.cssText = `
            position: fixed;
            top: 80px;
            right: 20px;
            z-index: 10001;
            padding: 10px 15px;
            background: ${type === 'success' ? '#4CAF50' : type === 'error' ? '#f44336' : '#2196F3'};
            color: white;
            border-radius: 5px;
            font-size: 14px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            transition: all 0.3s ease;
        `;

        document.body.appendChild(notification);

        setTimeout(() => {
            notification.style.opacity = '0';
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.parentNode.removeChild(notification);
                }
            }, 300);
        }, 3000);
    }

    // 监听XMLHttpRequest请求
    function interceptXHR() {
        const originalOpen = XMLHttpRequest.prototype.open;
        const originalSend = XMLHttpRequest.prototype.send;

        XMLHttpRequest.prototype.open = function(method, url, ...args) {
            this._url = url;
            return originalOpen.apply(this, [method, url, ...args]);
        };

        XMLHttpRequest.prototype.send = function(...args) {
            this.addEventListener('load', function() {
                if (this._url && this._url.includes('/ananas/status/') && this.status === 200) {
                    try {
                        const response = JSON.parse(this.responseText);
                        if (response.pdf && response.status === 'success') {
                            console.log('检测到PDF文件:', response);
                            pdfInfo = response;
                            createDownloadButton();
                        }
                    } catch (e) {
                        console.log('解析响应失败:', e);
                    }
                }
            });
            return originalSend.apply(this, args);
        };
    }

    // 监听Fetch请求
    function interceptFetch() {
        const originalFetch = window.fetch;
        window.fetch = function(...args) {
            return originalFetch.apply(this, args).then(response => {
                const url = args[0];
                if (typeof url === 'string' && url.includes('/ananas/status/')) {
                    response.clone().json().then(data => {
                        if (data.pdf && data.status === 'success') {
                            console.log('检测到PDF文件(Fetch):', data);
                            pdfInfo = data;
                            createDownloadButton();
                        }
                    }).catch(() => {});
                }
                return response;
            });
        };
    }

    // 定期检查页面中是否包含PDF链接
    function checkForPDFLinks() {
        // 检查iframe中的内容
        const iframes = document.querySelectorAll('iframe');
        iframes.forEach(iframe => {
            try {
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                const links = iframeDoc.querySelectorAll('a[href*=".pdf"], embed[src*=".pdf"]');
                if (links.length > 0 && !pdfInfo) {
                    links.forEach(link => {
                        const pdfUrl = link.href || link.src;
                        if (pdfUrl.includes('.pdf')) {
                            pdfInfo = {
                                pdf: pdfUrl,
                                filename: pdfUrl.split('/').pop() || 'document.pdf'
                            };
                            createDownloadButton();
                        }
                    });
                }
            } catch (e) {
                // 跨域限制,无法访问iframe内容
            }
        });

        // 检查直接嵌入的PDF
        const embedPDF = document.querySelector('embed[type="application/pdf"]');
        if (embedPDF && embedPDF.src && !pdfInfo) {
            pdfInfo = {
                pdf: embedPDF.src,
                filename: 'embedded.pdf'
            };
            createDownloadButton();
        }
    }

    // 初始化
    function init() {
        console.log('超星学习通PDF下载器已启动');

        // 拦截XHR请求
        interceptXHR();

        // 拦截Fetch请求
        interceptFetch();

        // 定期检查PDF链接
        checkInterval = setInterval(checkForPDFLinks, 2000);

        // 初始检查
        setTimeout(checkForPDFLinks, 1000);
    }

    // 页面加载完成后初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // 清理定时器
    window.addEventListener('beforeunload', function() {
        if (checkInterval) {
            clearInterval(checkInterval);
        }
    });

})();