FSM 一键收藏 不喜欢 加上图片放大功能

Enhanced torrent page with gallery viewer, quick actions and keyboard shortcuts

// ==UserScript==
// @name         FSM 一键收藏 不喜欢 加上图片放大功能
// @namespace    http://tampermonkey.net/
// @version      0.4.0
// @description  Enhanced torrent page with gallery viewer, quick actions and keyboard shortcuts
// @author       You
// @match        https://fsm.name/Torrents/details*
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js
// @resource     FANCYBOX_CSS https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @run-at       document-end
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    try {
        const fancyboxCSS = GM_getResourceText('FANCYBOX_CSS');
        GM_addStyle(fancyboxCSS);

        GM_addStyle(`
            .fancybox-bg {
                background: #000;
            }
            .fancybox-is-open .fancybox-bg {
                opacity: .9;
            }
            .fancybox-container {
                z-index: 999999 !important;
            }

            .unified-gallery {
                display: grid;
                grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
                gap: 10px;
                padding: 10px;
                margin: 15px 0;
            }

            .unified-gallery a {
                display: block;
                position: relative;
                overflow: hidden;
                border-radius: 4px;
                background: #f5f5f5;
            }

            .unified-gallery img {
                width: 100%;
                height: auto;
                display: block;
                transition: transform 0.3s ease;
            }

            .unified-gallery a:hover img {
                transform: scale(1.05);
            }
        `);
    } catch (error) {
        console.error('Failed to add styles:', error);
    }

    const $ = window.jQuery.noConflict(true);

    function initFancybox() {
        try {
            $('[data-fancybox="gallery"]').fancybox({
                buttons: [
                    "zoom",
                    "slideShow",
                    "fullScreen",
                    "download",
                    "thumbs",
                    "close"
                ],
                loop: true,
                protect: false,
                animationEffect: "zoom",
                transitionEffect: "slide",
                thumbs: {
                    autoStart: true,
                    hideOnClose: true
                },
                mobile: {
                    clickContent: function(current, event) {
                        return current.type === "image" ? "toggleControls" : false;
                    },
                    clickSlide: function(current, event) {
                        return current.type === "image" ? "toggleControls" : "close";
                    },
                }
            });
        } catch (error) {
            console.error('Fancybox initialization failed:', error);
        }
    }

    function reorganizeGallery(img) {
        try {
            console.log('进入reorganizeGallery')
            const contentArea = document.querySelector('.el-card__body');
            if (!contentArea) return;

            const unifiedGallery = document.createElement('div');
            unifiedGallery.className = 'unified-gallery';

            const allImages = [];
            const detailsImages = document.querySelectorAll('.ql-editor img');
            detailsImages.forEach(img => {
                if (img.src) allImages.push(img.src);
            });

            const supplementImages = document.querySelectorAll('.screenshots .el-image img');
            supplementImages.forEach(img => {
                if (img.src) allImages.push(img.src);
            });
            console.log('allImages:',allImages)
            const uniqueImages = [...new Set(allImages)];

            uniqueImages.forEach(src => {
                const link = document.createElement('a');
                link.href = src;
                link.setAttribute('data-fancybox', 'gallery');

                const img = document.createElement('img');
                img.src = src;
                img.loading = 'lazy';

                link.appendChild(img);
                unifiedGallery.appendChild(link);
            });

            const headers = Array.from(document.querySelectorAll('h4')).filter(h =>
                h.textContent === '种子详情' || h.textContent === '补充信息'
            );

            headers.forEach(header => {
                let next = header.nextElementSibling;
                while (next && next.tagName !== 'H4') {
                    const temp = next.nextElementSibling;
                    next.remove();
                    next = temp;
                }
                header.remove();
            });

            const originalScreenshots = document.querySelector('.screenshots');
            if (originalScreenshots) {
                originalScreenshots.remove();
            }

            if (uniqueImages.length > 0) {
                contentArea.appendChild(unifiedGallery);
                setTimeout(initFancybox, 500);
            }
        } catch (error) {
            console.error('Failed to reorganize gallery:', error);
        }
    }

    function voteTorrent(tid, value) {
        const authorization = localStorage.getItem('token')
        const deviceId = localStorage.getItem('DeviceId')
        const formData = new FormData();
        formData.append('tid', tid);
        formData.append('status', value);

        fetch('/api/Torrents/voteTorrent', {
            method: 'POST',
            headers: {
                'accept': 'application/json, text/plain, */*',
                'authorization': authorization,
                'deviceid': deviceId,
                'origin': 'https://fsm.name',
                'referer': window.location.href
            },
            body: formData,
            credentials: 'same-origin'
        })
        .then(response => {
            if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
            return response.json();
        })
        .then(res => {
            if (res?.success) {
                if (window.$notify) {
                    window.$notify({
                        message: '操作成功',
                        type: 'success'
                    });
                } else {
                    window.close();
                }
            }
        })
        .catch(error => {
            if (window.$notify) {
                window.$notify({
                    message: '操作失败',
                    type: 'error'
                });
            } else {
                alert('操作失败');
            }
        });
    }

    function addButtons() {
        const sideBlk = document.querySelector('.side-blk');
        if (!sideBlk) return;

        const urlParams = new URLSearchParams(window.location.search);
        const tid = urlParams.get('tid');
        if (!tid) return;

        const favoriteDiv = document.createElement('div');
        const favoriteBtn = document.createElement('button');
        favoriteBtn.className = 'el-button el-button--info el-button--large is-plain is-circle side-btn el-tooltip__trigger el-tooltip__trigger';
        favoriteBtn.style.display = 'block';
        favoriteBtn.innerHTML = `<i class="el-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" d="m512 747.84 228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72zM313.6 924.48a70.4 70.4 0 0 1-102.144-74.24l37.888-220.928L88.96 472.96A70.4 70.4 0 0 1 128 352.896l221.76-32.256 99.2-200.96a70.4 70.4 0 0 1 126.208 0l99.2 200.96 221.824 32.256a70.4 70.4 0 0 1 39.04 120.064L774.72 629.376l37.888 220.928a70.4 70.4 0 0 1-102.144 74.24L512 820.096l-198.4 104.32z"></path></svg></i>`;
        favoriteBtn.addEventListener('click', () => {
            voteTorrent(tid, 'VALUE');
        });
        favoriteDiv.appendChild(favoriteBtn);

        const dislikeDiv = document.createElement('div');
        const dislikeBtn = document.createElement('button');
        dislikeBtn.className = 'el-button el-button--info el-button--large is-plain is-circle side-btn el-tooltip__trigger el-tooltip__trigger';
        dislikeBtn.style.display = 'block';
        dislikeBtn.innerHTML = `<i class="el-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" d="M160 256H96a32 32 0 0 1 0-64h256V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64h-64v672a32 32 0 0 1-32 32H192a32 32 0 0 1-32-32zm448-64v-64H416v64zM224 896h576V256H224zm192-128a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32m192 0a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32"></path></svg></i>`;
        dislikeBtn.addEventListener('click', () => {
            voteTorrent(tid, 'POINTLESS');
        });
        dislikeDiv.appendChild(dislikeBtn);

        sideBlk.appendChild(favoriteDiv);
        sideBlk.appendChild(dislikeDiv);

        window.dislikeButton = dislikeBtn;
    }

    function addKeyboardShortcuts() {
        document.addEventListener('keydown', function(event) {
            if (event.key === 'x' &&
                !['INPUT', 'TEXTAREA', 'SELECT'].includes(document.activeElement.tagName)) {
                window.dislikeButton?.click();
            }
        });
    }

    let keyboardShortcutsAdded = false;

    const galleryObserver = new MutationObserver((mutations, obs) => {
        const contentBody = document.querySelector('.el-card__body');
        const screenshots = document.querySelector('.ql-editor.ql-content-fix.img-beautify');
        console.log(contentBody , screenshots)
        if (contentBody && screenshots) {
            obs.disconnect();
            setTimeout(reorganizeGallery, 2000);

            setTimeout(() => {
                if (!document.querySelector('[data-fancybox="gallery"]')) {
                    reorganizeGallery();
                }
            }, 3000);
        }
    });

    const buttonsObserver = new MutationObserver((mutations, obs) => {
        const sideBlk = document.querySelector('.side-blk');
        if (sideBlk) {
            obs.disconnect();
            addButtons();

            if (!keyboardShortcutsAdded) {
                addKeyboardShortcuts();
                keyboardShortcutsAdded = true;
            }
        }
    });

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

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

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            addButtons();
            if (!keyboardShortcutsAdded) {
                addKeyboardShortcuts();
                keyboardShortcutsAdded = true;
            }
        });
    } else {
        addButtons();
        if (!keyboardShortcutsAdded) {
            addKeyboardShortcuts();
            keyboardShortcutsAdded = true;
        }
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址