Greasy Fork

Greasy Fork is available in English.

FSM 收藏夹链接提取

Extract and convert FSM torrent links

当前为 2025-03-04 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         FSM 收藏夹链接提取
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Extract and convert FSM torrent links
// @author       You
// @match        https://fsm.name/Torrents/mine?type=favorite*
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    let passkey = '';

    // 获取 passkey
    async function fetchPasskey() {
        try {
            const authorization = localStorage.getItem('token');
            const deviceId = localStorage.getItem('DeviceId');

            const response = await fetch('https://fsm.name/api/Users/infos', {
                headers: {
                    'accept': 'application/json, text/plain, */*',
                    'authorization': authorization,
                    'deviceid': deviceId
                }
            });

            const data = await response.json();
            if (data.success && data.data.passkey) {
                passkey = data.data.passkey;
                return true;
            }
            return false;
        } catch (error) {
            console.error('获取 passkey 失败:', error);
            return false;
        }
    }

    async function extractAndCopyLinks() {
        // 如果没有 passkey,尝试获取
        if (!passkey) {
            const success = await fetchPasskey();
            if (!success) {
                if (window.$notify) {
                    window.$notify({
                        message: '获取 passkey 失败',
                        type: 'error'
                    });
                } else {
                    alert('获取 passkey 失败');
                }
                return;
            }
        }

        // 获取所有链接
        const links = document.querySelectorAll('.el-table__body-wrapper a');

        // 转换链接
        const linksString = Array.from(links)
            .map(link => {
                const tid = new URL(link.href).searchParams.get('tid');
                return `https://api.fsm.name/Torrents/download?tid=${tid}&passkey=${passkey}&source=direct`;
            })
            .join('\n');

        // 复制到剪贴板
        GM_setClipboard(linksString);

        // 显示提示
        if (window.$notify) {
            window.$notify({
                message: '链接已复制到剪贴板',
                type: 'success'
            });
        } else {
            alert('链接已复制到剪贴板');
        }
    }

    function addExtractButton() {
        // 检查是否已存在按钮
        if (document.getElementById('extract-links-btn')) {
            return;
        }

        // 创建按钮
        const extractBtn = document.createElement('button');
        extractBtn.id = 'extract-links-btn';
        extractBtn.className = 'el-button el-button--primary el-button--small';
        extractBtn.style.position = 'fixed';
        extractBtn.style.right = '20px';
        extractBtn.style.bottom = '20px';
        extractBtn.style.zIndex = '9999';
        extractBtn.innerHTML = '提取下载链接';

        // 添加点击事件
        extractBtn.addEventListener('click', extractAndCopyLinks);

        // 添加到页面
        document.body.appendChild(extractBtn);
    }

    // 使用 MutationObserver 确保在页面动态加载后添加按钮
    const observer = new MutationObserver((mutations, obs) => {
        if (document.querySelector('.el-table__body-wrapper')) {
            addExtractButton();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 页面加载完成时也尝试添加按钮
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addExtractButton);
    } else {
        addExtractButton();
    }

    // 初始获取 passkey
    fetchPasskey();
})();