- // ==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;
- }
- }
- })();