您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Collect and copy video/image links across current or all XenForo thread pages, one page at a time, using localStorage clipboard workaround (Cloudflare safe). Supports separate video/image modes with domain matching.
// ==UserScript== // @name SimpCity Video & Image Link Copier // @version 2.0 // @namespace RiisDevScripts // @description Collect and copy video/image links across current or all XenForo thread pages, one page at a time, using localStorage clipboard workaround (Cloudflare safe). Supports separate video/image modes with domain matching. // @author https://github.com/RiisDev/ // @match *https://simpcity.cr/threads/* // @grant GM_setClipboard // @icon https://simpcity.cr/data/assets/logo/favicon.png // @run-at document-end // @license MIT // ==/UserScript== (function () { 'use strict'; function showChoiceDialog(autoCopy) { const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.3); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); display: flex; align-items: center; justify-content: center; z-index: 10000; `; const modal = document.createElement('div'); modal.className = 'p-body-background p-body-background--main'; modal.style.cssText = ` background: var(--xf-palette-pureWhite); border-radius: 6px; padding: 20px; max-width: 320px; text-align: center; box-shadow: 0 4px 12px rgba(0,0,0,0.15); `; const title = document.createElement('h3'); title.textContent = 'Auto Copy Links'; title.style.marginBottom = '12px'; const prompt = document.createElement('p'); prompt.textContent = 'Which links do you want to auto copy across all pages?'; prompt.style.marginBottom = '20px'; const btnContainer = document.createElement('div'); btnContainer.style.display = 'flex'; btnContainer.style.justifyContent = 'space-between'; btnContainer.style.gap = '10px'; function createOptionBtn(text, type) { const btn = document.createElement('button'); btn.className = 'button--primary button rippleButton'; btn.textContent = text; btn.style.flex = '1'; if (autoCopy){ btn.addEventListener('click', () => { document.body.removeChild(overlay); startAutoCopy(type); }); } else { btn.addEventListener('click', () => { const links = extractLinks(type); if (links.length > 0) { GM_setClipboard(links.join('\n')); showXenforoNotice(`✅ Copied ${links.length} ${type} link(s)!`); } else { showXenforoNotice(`⚠️ No ${type} links found.`); } document.body.removeChild(overlay); localStorage.removeItem(XF_LINKS_TYPE); localStorage.removeItem(STORAGE_KEY); }); } return btn; } const btnVideo = createOptionBtn('Video', 'video'); const btnImage = createOptionBtn('Image', 'image'); const btnBoth = createOptionBtn('Both', 'all'); const btnCancel = document.createElement('button'); btnCancel.className = 'button--link button rippleButton'; btnCancel.textContent = 'Cancel'; btnCancel.style.flex = '1'; btnCancel.addEventListener('click', () => { document.body.removeChild(overlay); if (autoCopy) { showXenforoNotice('Auto copy cancelled.', 'warning'); } else { showXenforoNotice('Copy cancelled.', 'warning'); } }); btnContainer.appendChild(btnVideo); btnContainer.appendChild(btnImage); btnContainer.appendChild(btnBoth); btnContainer.appendChild(btnCancel); modal.appendChild(title); modal.appendChild(prompt); modal.appendChild(btnContainer); overlay.appendChild(modal); document.body.appendChild(overlay); } function showXenforoNotice(message, type = 'success', duration = 3000) { const notice = document.createElement('div'); notice.className = `p-notice p-notice--${type}`; notice.style.cssText = ` position: fixed; top: 80px; right: 30px; z-index: 9999; max-width: 300px; padding: 10px 15px; box-shadow: 0 2px 5px rgba(0,0,0,0.3); border-radius: 5px; font-size: 14px; opacity: 0; border: 2px solid hsla(var(--xf-textColorEmphasized)); animation: fadeInOut 0.3s forwards; `; notice.innerHTML = `<div class="p-notice__content">${message}</div>`; document.body.appendChild(notice); setTimeout(() => { notice.style.animation = 'fadeOut 0.3s forwards'; setTimeout(() => notice.remove(), 300); }, duration); } const style = document.createElement('style'); style.textContent = ` @keyframes fadeInOut { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; transform: translateY(-10px); } } `; document.head.appendChild(style); const XF_LINKS_TYPE = 'xf_links_type'; const STORAGE_KEY = 'xf_links_collector'; const imageDomains = ['bunkr', 'cyberdrop', 'pixeldrain', 'ibb.co', 'postimg', 'jpg5.su']; const videoDomains = ['gofile', 'pixeldrain', 'mega', 'mediafire', 'xhamster', 'pornhub', 'bunkr', 'cyberdrop', 'cyberfile', 'saint2', 'pvvstream', 'noodlemagazine.com', 'xvideos', 'vk']; const isVideoLink = url => { try { return videoDomains.some(domain => new URL(url).hostname.includes(domain)); } catch { return false; } }; const isImageLink = url => { try { return imageDomains.some(domain => new URL(url).hostname.includes(domain)); } catch { return false; } }; function GetStorageLinks() { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]'); } function GetType() { return localStorage.getItem(XF_LINKS_TYPE); } function extractLinks(type) { if (!GetType()) { localStorage.setItem(XF_LINKS_TYPE, type);} const links = new Set(); const anchors = document.querySelectorAll('.message--post a[href]'); anchors.forEach(a => { const href = a.href.trim(); if ( href && ( (type === 'video' && isVideoLink(href)) || (type === 'image' && isImageLink(href)) || (type === 'all' && (isVideoLink(href) || isImageLink(href))) ) ) { links.add(href); } }); const iframes = document.querySelectorAll('iframe.saint-iframe[src]'); if (type !== 'image') { iframes.forEach(iframe => { const src = iframe.src.trim(); if (src && isVideoLink(src)) { links.add(src); } }); } return Array.from(links); }; function getNextPageUrl() { const nextBtn = document.querySelector('.pageNav-jump--next'); return nextBtn ? nextBtn.href : null; }; function saveLinks(newLinks) { const existing = GetStorageLinks(); const merged = [...new Set([...existing, ...newLinks])]; localStorage.setItem(STORAGE_KEY, JSON.stringify(merged)); return merged; }; function copyAndFinish(type) { const allLinks = GetStorageLinks(); if (allLinks.length > 0) { GM_setClipboard(allLinks.join('\n')); showXenforoNotice(`✅ Copied ${allLinks.length} ${type} link(s) from all pages!`); } else { showXenforoNotice(`⚠️ No ${type} links were found.`); } localStorage.removeItem(STORAGE_KEY); localStorage.removeItem(XF_LINKS_TYPE); }; function startAutoCopy(type) { localStorage.removeItem(STORAGE_KEY); localStorage.removeItem(XF_LINKS_TYPE); const links = extractLinks(type); saveLinks(links); const nextPage = getNextPageUrl(); if (nextPage) { window.location.href = nextPage; } else { copyAndFinish(type); } } function autoContinueIfNeeded() { const linksExist = GetStorageLinks(); const type = GetType(); if (!linksExist || !type) return; const links = extractLinks(type); saveLinks(links); const nextPage = getNextPageUrl(); if (nextPage) { setTimeout(() => { window.location.href = nextPage; }, 1000); } else { copyAndFinish(type); } }; function addButton(label, clickHandler) { const buttonGroup = document.querySelector('.buttonGroup'); if (!buttonGroup) return; const btn = document.createElement('a'); btn.href = '#'; btn.className = 'button--link button rippleButton'; btn.innerHTML = `<span class="button-text">${label}</span>`; btn.addEventListener('click', e => { e.preventDefault(); clickHandler(); }); buttonGroup.prepend(btn); }; function addButtons() { addButton('📋 Start Auto Copy', () => { showChoiceDialog(true); }); addButton('📋 Copy Links', () => { showChoiceDialog(false); }); }; window.addEventListener('load', () => { addButtons(); autoContinueIfNeeded(); }); })();