Greasy Fork

Greasy Fork is available in English.

MEGA链接检测器

检测MEGA链接是否可用,并在旁边显示状态

当前为 2025-09-05 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         MEGA鏈接檢測器
// @name:zh-CN   MEGA链接检测器
// @name:zh-TW   MEGA鏈接檢測器
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  檢測MEGA鏈接是否可用,並在旁邊顯示狀態
// @description:zh-CN  检测MEGA链接是否可用,并在旁边显示状态
// @description:zh-TW  檢測MEGA鏈接是否可用,並在旁邊顯示狀態
// @author       Claude
// @license      MIT
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @connect      mega.nz
// @connect      mega.io
// @connect      g.api.mega.co.nz
// @connect      *
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 啟用調試模式
    const DEBUG = true;

    // 防止重複檢查的連結記錄
    const checkedLinks = new Set();

    // 檢查執行次數
    let executionCount = 0;

    // 日誌函數
    function log(message, data) {
        if (!DEBUG) return;
        if (data) {
            console.log(`[MEGA檢測器] ${message}`, data);
        } else {
            console.log(`[MEGA檢測器] ${message}`);
        }
    }

    // 主函數 - 檢查MEGA連結
    function checkMEGALinks() {
        executionCount++;
        log(`開始檢查MEGA連結 (第${executionCount}次執行)`);

        // 尋找頁面中的所有連結
        const links = document.querySelectorAll('a');
        let megaLinksCount = 0;

        links.forEach(link => {
            const href = link.href;
            // 檢測是否為MEGA連結且尚未檢查過
            if (href && (href.includes('mega.nz') || href.includes('mega.io')) && !checkedLinks.has(href)) {
                checkedLinks.add(href); // 添加到已檢查集合
                megaLinksCount++;
                log(`發現MEGA連結: ${href}`);
                checkLinkStatus(link, href);
            }
        });

        log(`本次檢查發現 ${megaLinksCount} 個新MEGA連結`);
        return megaLinksCount;
    }

    // 檢查MEGA連結狀態
    function checkLinkStatus(linkElement, url) {
        // 創建狀態指示器
        const statusIndicator = document.createElement('span');
        statusIndicator.style.marginLeft = '5px';
        statusIndicator.style.padding = '2px 5px';
        statusIndicator.style.borderRadius = '3px';
        statusIndicator.style.fontSize = '12px';
        statusIndicator.textContent = '檢查中...';
        statusIndicator.style.backgroundColor = '#f0f0f0';
        statusIndicator.style.color = '#666';

        // 將狀態指示器添加到連結旁
        linkElement.parentNode.insertBefore(statusIndicator, linkElement.nextSibling);

        log(`正在檢查連結: ${url}`);

        // 從URL提取文件ID和密鑰
        const { fileID, fileKey } = extractMEGAInfo(url);

        if (!fileID) {
            log(`無法提取文件ID,URL格式可能不符合預期`);
            updateStatusIndicator(statusIndicator, false);
            return;
        }

        // 檢查是否有解密金鑰,如果沒有,標記為未知狀態
        if (!fileKey) {
            log(`未提供解密金鑰,無法確認文件狀態`);
            updateStatusIndicator(statusIndicator, null, true);
            return;
        }

        log(`提取到的文件ID: ${fileID}, 密鑰: ${fileKey ? '有' : '無'}`);

        // 使用GM_xmlhttpRequest發送MEGA API請求
        GM_xmlhttpRequest({
            method: 'POST',
            url: 'https://g.api.mega.co.nz/cs',
            data: JSON.stringify([{"a": "g", "g": 1, "p": fileID, "ssl": 0}]),
            headers: {
                'Content-Type': 'application/json'
            },
            timeout: 10000, // 10秒超時
            onload: function(response) {
                log(`API回應狀態: ${response.status}`, response.responseText);

                try {
                    // 嘗試解析JSON響應
                    const data = JSON.parse(response.responseText);
                    log(`解析API回應:`, data);

                    // 確定檔案狀態
                    if (data && Array.isArray(data)) {
                        // 檢查API錯誤代碼
                        if (data[0] === -9) {
                            // -9 表示資源不存在(通常是文件或文件夾已被刪除)
                            log(`文件不存在或已刪除 (錯誤碼: -9)`, data);
                            updateStatusIndicator(statusIndicator, false);
                        } else if (data[0] === -11) {
                            // -11 表示訪問被拒絕(可能是解密金鑰問題)
                            log(`訪問被拒絕 (錯誤碼: -11)`, data);
                            // 這裡我們將-11標記為未知,但添加特殊說明
                            updateStatusIndicator(statusIndicator, null, true);
                        } else if (typeof data[0] === 'object' && !data[0].e) {
                            // 成功獲取文件信息
                            log(`文件存在且可用`, data);
                            updateStatusIndicator(statusIndicator, true);
                        } else if (typeof data[0] === 'number' && data[0] < 0) {
                            // 其他錯誤代碼
                            log(`API返回錯誤代碼: ${data[0]}`, data);
                            updateStatusIndicator(statusIndicator, null);
                        } else {
                            log(`無法確認文件狀態`, data);
                            updateStatusIndicator(statusIndicator, null);
                        }
                    } else {
                        log(`API回應格式異常`, data);
                        updateStatusIndicator(statusIndicator, null);
                    }
                } catch (e) {
                    log(`JSON解析錯誤`, e);
                    updateStatusIndicator(statusIndicator, null);
                }
            },
            onerror: function(error) {
                log(`API請求出錯`, error);
                updateStatusIndicator(statusIndicator, null);
            },
            ontimeout: function() {
                log(`API請求超時`);
                updateStatusIndicator(statusIndicator, null);
            }
        });
    }

    // 從MEGA URL中提取文件ID和密鑰
    function extractMEGAInfo(url) {
        log(`正在從URL提取MEGA信息: ${url}`);

        let fileID = null;
        let fileKey = null;

        // 處理新版格式: https://mega.nz/file/FILEID#FILEKEY
        let match = url.match(/mega\.[a-z]+\/file\/([a-zA-Z0-9_-]+)(?:#([a-zA-Z0-9_-]+)|$|\?)/i);

        if (!match) {
            // 處理folder格式: https://mega.nz/folder/FOLDERID#FOLDERKEY
            match = url.match(/mega\.[a-z]+\/folder\/([a-zA-Z0-9_-]+)(?:#([a-zA-Z0-9_-]+)|$|\?)/i);
        }

        if (!match) {
            // 處理舊版格式: https://mega.nz/#!FILEID!FILEKEY 或 https://mega.nz/#F!FOLDERID!FOLDERKEY
            match = url.match(/mega\.[a-z]+\/#(?:F|)!([a-zA-Z0-9_-]+)(?:!([a-zA-Z0-9_-]+)|$|\?)/i);
        }

        if (match) {
            fileID = match[1];
            fileKey = match[2];
        }

        return { fileID, fileKey };
    }

    // 更新狀態指示器
    function updateStatusIndicator(indicator, isValid, needsDecryption = false) {
        if (isValid === true) {
            log(`設置狀態指示為可用`);
            indicator.textContent = '可用';
            indicator.style.backgroundColor = '#e6f7e6';
            indicator.style.color = '#2e8b57';
        } else if (isValid === false) {
            log(`設置狀態指示為已失效`);
            indicator.textContent = '已失效';
            indicator.style.backgroundColor = '#ffebee';
            indicator.style.color = '#d32f2f';
        } else {
            if (needsDecryption) {
                log(`設置狀態指示為需要解密金鑰`);
                indicator.textContent = '需要金鑰';
                indicator.style.backgroundColor = '#e3f2fd';
                indicator.style.color = '#1565c0';
            } else {
                log(`設置狀態指示為未知`);
                indicator.textContent = '未知';
                indicator.style.backgroundColor = '#fff9c4';
                indicator.style.color = '#ff8f00';
            }
        }

        // 添加懸停提示
        if (needsDecryption) {
            indicator.title = '此連結需要正確的解密金鑰才能訪問';
        } else if (isValid === null) {
            indicator.title = '無法確定連結狀態';
        }
    }

    // 監視DOM變化,檢測新添加的MEGA連結
    function setupMutationObserver() {
        log('設置DOM變化監視器');

        // 創建一個觀察器實例
        const observer = new MutationObserver(function(mutations) {
            let shouldCheck = false;

            // 檢查是否有新增的節點
            mutations.forEach(function(mutation) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    shouldCheck = true;
                }
            });

            // 如果有新增節點,檢查MEGA連結
            if (shouldCheck) {
                log('檢測到DOM變化,檢查新的MEGA連結');
                checkMEGALinks();
            }
        });

        // 配置觀察選項
        const config = {
            childList: true,     // 觀察子節點的添加或刪除
            subtree: true        // 觀察所有後代節點
        };

        // 開始觀察document.body
        observer.observe(document.body, config);
        log('DOM變化監視器已設置');

        return observer;
    }

    // 確保腳本在不同階段都能執行
    function initialize() {
        log('MEGA鏈接檢測器腳本初始化');

        // 立即執行一次
        if (document.readyState === 'loading') {
            log('文檔仍在加載中,等待DOMContentLoaded事件');
            document.addEventListener('DOMContentLoaded', function() {
                log('DOMContentLoaded事件觸發');
                setTimeout(function() {
                    checkMEGALinks();
                    setupMutationObserver();
                }, 500);
            });
        } else {
            log('文檔已加載完成,直接執行檢查');
            setTimeout(function() {
                checkMEGALinks();
                setupMutationObserver();
            }, 500);
        }

        // 頁面完全加載後再執行一次
        window.addEventListener('load', function() {
            log('頁面完全加載事件觸發');
            setTimeout(function() {
                checkMEGALinks();
            }, 1000);
        });

        // 定期檢查,頻率降低
        setInterval(function() {
            log('定期檢查新的MEGA連結');
            checkMEGALinks();
        }, 30000); // 每30秒檢查一次
    }

    // 啟動腳本
    initialize();

    log('MEGA鏈接檢測器腳本已加載');
})();