您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhances avbase.net with video previews, zoom sliders, Sukebei RSS results in a styled table, larger images, titles below images, original size image popups, and adds Jable, Missav, and videoId copy buttons with 404 transparency at the correct position.
// ==UserScript== // @name AvBase Ultimate Enhancer // @namespace http://tampermonkey.net/ // @version 2.3.2 // @description Enhances avbase.net with video previews, zoom sliders, Sukebei RSS results in a styled table, larger images, titles below images, original size image popups, and adds Jable, Missav, and videoId copy buttons with 404 transparency at the correct position. // @match https://www.avbase.net/* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @license MIT // ==/UserScript== (function() { 'use strict'; // 合併後的樣式 GM_addStyle(` .adaptive-container { height: auto !important; min-height: 100%; width: 100%; display: flex; flex-direction: column; grid-column: 1 / -1; align-items: center; overflow: visible; } .vertical-container { display: flex; flex-direction: column; align-items: center; width: 100%; overflow-x: auto; overflow-y: visible; height: auto; } .image-container { display: flex; flex-direction: column; align-items: center; width: 100%; gap: 1px; height: auto; } .scene-container { width: 100%; max-width: 800px; height: auto; min-height: 450px; } .table-wrapper { width: 100%; padding: 10px; height: auto; } .toggle-button { padding: 5px 295px; background-color: #1e293b; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 5px 0; } .toggle-button img { width: 20px; height: 20px; filter: brightness(100%) invert(1); transition: transform 0.2s ease; } .toggle-button:active img { transform: scale(1.2); } .controls-bar { width: 100%; max-width: 800px; background-color: #000000; display: flex; justify-content: space-between; align-items: center; padding: 5px 10px; margin: 0; box-sizing: border-box; } .controls-bar button { background-color: #000000; color: white; border: none; border-radius: 5px; cursor: pointer; padding: 5px; display: flex; align-items: center; justify-content: center; transition: transform 0.2s ease; margin-right: 8px; } .controls-bar button:last-child { margin-right: 0; } .controls-bar button img { width: 20px; height: 20px; filter: brightness(100%) invert(1); } .controls-bar button:active { transform: scale(1.2); } .zoom-slider-container { display: flex; align-items: center; position: relative; margin: 0; } .zoom-button { background-color: #000000; color: white; border: none; border-radius: 5px; cursor: pointer; padding: 5px; display: flex; align-items: center; justify-content: center; margin-right: 8px; } .zoom-button img { width: 20px; height: 20px; filter: brightness(100%) invert(1); } .zoom-slider { -webkit-appearance: none; appearance: none; width: 0; height: 6px; background: #1e293b; outline: none; opacity: 0; transition: opacity 0.3s ease, width 0.3s ease; border-radius: 4px; margin: 0 5px; vertical-align: middle; } .zoom-slider.show { opacity: 1; width: 70px; } .zoom-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 12px; height: 12px; background: #fff; cursor: pointer; border-radius: 50%; } .zoom-slider::-moz-range-thumb { width: 12px; height: 12px; background: #fff; cursor: pointer; border-radius: 50%; } .zoom-value { color: white; font-size: 12px; margin-right: 5px; width: 40px; text-align: right; opacity: 0; transition: opacity 0.3s ease; vertical-align: middle; } .zoom-value.show { opacity: 1; } .volume-slider-container { display: flex; align-items: center; position: relative; } .volume-slider { -webkit-appearance: none; appearance: none; width: 0; height: 6px; background: #1e293b; outline: none; opacity: 0; transition: opacity 0.3s ease, width 0.3s ease; border-radius: 4px; margin: 0 5px; } .volume-slider.show { opacity: 1; width: 70px; } .volume-slider:hover { opacity: 1; } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 12px; height: 12px; background: #fff; cursor: pointer; border-radius: 50%; } .volume-slider::-moz-range-thumb { width: 16px; height: 16px; background: #fff; cursor: pointer; border-radius: 50%; } .fullscreen-button { background-color: #000000; color: white; border: none; border-radius: 5px; cursor: pointer; padding: 5px; display: flex; align-items: center; justify-content: center; } .fullscreen-button img { width: 20px; height: 20px; filter: brightness(100%) invert(1); } .table-wrapper svg { fill: white; width: 20px; height: 20px; } @media (min-width: 1024px) { .cl-container { width: 100%; } } .sm\\:grid-cols-2 { grid-template-columns: repeat(6, minmax(0, 1fr)); } .sm\\:grid-cols-3 { grid-template-columns: repeat(6, minmax(0, 1fr)); } .large-image { width: 100%; max-width: 100%; height: auto; object-fit: contain; display: block; border-radius: 4px; cursor: zoom-in; } .title-below-image { font-size: 0.75rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; padding: 8px; text-align: center; color: #333; text-decoration: none; font-weight: bold; width: 100%; box-sizing: border-box; } .image-title-container { display: block; width: 100%; text-align: center; } .overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); display: flex; justify-content: center; align-items: center; z-index: 1000; opacity: 0; transition: opacity 0.3s ease; } .overlay.show { opacity: 1; } .overlay-image { max-width: 90%; max-height: 90%; width: auto; height: auto; object-fit: contain; cursor: zoom-out; border-radius: 4px; } a-scene .a-canvas + div { display: none !important; } .jable-btn, .missav-btn, .copy-btn { display: flex; align-items: center; justify-content: center; height: 2rem; line-height: 2rem; text-align: center; background-color: #4b5563; color: white; border-radius: 0.25rem; font-size: 0.75rem; font-weight: normal; padding: 0 0.5rem; cursor: pointer; } .jable-btn, .missav-btn { width: 2rem; } .copy-btn { max-width: 10rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .transparent { background-color: transparent !important; } .jable-btn a, .missav-btn a { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; color: inherit; text-decoration: none; } `); // 動態載入 A-Frame 庫 function loadAFrame() { const aframeScript = document.createElement('script'); aframeScript.src = 'https://aframe.io/releases/1.7.0/aframe.min.js'; document.head.appendChild(aframeScript); } // 處理 DMM 鏈接 function processDmmLink(link) { try { if (link.includes('al.dmm.co.jp')) { const urlParams = new URLSearchParams(new URL(link).search); const acred = urlParams.get('acred'); if (acred) return decodeURIComponent(acred); const lurl = urlParams.get('lurl'); if (lurl) return decodeURIComponent(lurl); } return link; } catch (error) { console.error('處理 DMM 鏈接時出錯:', error); return link; } } // 檢查圖片是否存在 function checkImageExists(url) { return new Promise((resolve) => { const img = new Image(); img.onload = () => resolve(true); img.onerror = () => resolve(false); img.src = url; setTimeout(() => resolve(false), 5000); }); } // 檢查視頻可用性 async function checkVideoAvailability(url) { try { const response = await fetch(url, { method: 'HEAD' }); return response.ok; } catch (error) { console.error(`檢查 ${url} 失敗:`, error); return false; } } // 從圖片 URL 提取影片 ID 並構造更大圖片 URL function getLargerImageUrl(smallImageUrl) { let match = smallImageUrl.match(/\/([^\/]+)(ps|jm)\.jpg$/i); if (!match) return null; let videoId = match[1]; const suffix = match[2].toLowerCase(); if (suffix === 'ps' && smallImageUrl.includes('awsimgsrc.dmm.co.jp')) { if (/^[a-zA-Z]+[0-9]{3}$/.test(videoId)) { videoId = videoId.replace(/([a-zA-Z]+)([0-9]{3})/, '$100$2'); } return `https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/${videoId}/${videoId}pl.jpg`; } if (suffix === 'jm' && smallImageUrl.includes('pics.dmm.co.jp')) { return smallImageUrl.replace(/jm\.jpg$/i, 'jp.jpg'); } return smallImageUrl.replace(/ps\.jpg$/i, 'pl.jpg'); } // 獲取 Sukebei RSS 結果 function fetchSukebeiResults(videoId) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: `https://sukebei.nyaa.si/?page=rss&q=${encodeURIComponent(videoId)}`, headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36", "Referer": "https://sukebei.nyaa.si/" }, onload: function(response) { if (response.status === 200) { let parser = new DOMParser(); let xmlDoc = parser.parseFromString(response.responseText, "text/xml"); let items = xmlDoc.getElementsByTagName("item"); let results = []; for (let i = 0; i < items.length; i++) { let item = items[i]; let title = item.getElementsByTagName("title")[0]?.textContent.trim() || ""; let link = item.getElementsByTagName("link")[0]?.textContent.trim() || ""; let size = item.getElementsByTagName("nyaa:size")[0]?.textContent.trim() || ""; let pubDate = item.getElementsByTagName("pubDate")[0]?.textContent.trim() || ""; let infoHash = item.getElementsByTagName("nyaa:infoHash")[0]?.textContent.trim() || ""; let magnet = infoHash ? "magnet:?xt=urn:btih:" + infoHash : ""; results.push({ name: title, link: link, size: size, date: pubDate, magnet: magnet }); } resolve(results); } else { reject(`HTTP error: ${response.status}`); } }, onerror: function(err) { reject(err); } }); }); } // 檢查 Jable 是否返回 404 function checkJableAvailability(videoId) { return new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: `https://jable.tv/videos/${encodeURIComponent(videoId)}/`, onload: response => { const is404 = response.status === 404 || response.responseText.includes('<title>404') || response.responseText.includes('<h1>Not Found</h1>'); resolve(!is404); }, onerror: () => resolve(false) }); }); } // 檢查 Missav 是否返回 404 function checkMissavAvailability(videoId) { return new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: `https://missav.ai/${encodeURIComponent(videoId)}`, onload: response => { const is404 = response.responseText.includes('404') || response.responseText.includes('找不到頁面'); resolve(!is404); }, onerror: () => resolve(false) }); }); } // 圖片增強功能 function enhanceImages() { const resultContainers = document.querySelectorAll('.bg-base.border.border-light.rounded-lg.overflow-hidden'); if (!resultContainers.length) return; resultContainers.forEach((container) => { const imageLink = container.querySelector('div.flex.items-center.justify-center.bg-base2 a[rel="noopener noreferrer sponsored"] img'); const titleLink = container.querySelector('a.text-md.font-bold.btn-ghost.rounded-lg.m-1[class*="line-clamp"]'); if (imageLink && titleLink) { const smallImageUrl = imageLink.src; let largeImageUrl = smallImageUrl; if (smallImageUrl.match(/ps\.jpg$/i) && smallImageUrl.includes('awsimgsrc.dmm.co.jp')) { let videoId = smallImageUrl.match(/\/([^\/]+)ps\.jpg$/i)[1]; if (/^[a-zA-Z]+[0-9]{3}$/.test(videoId)) { videoId = videoId.replace(/([a-zA-Z]+)([0-9]{3})/, '$100$2'); } largeImageUrl = `https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/${videoId}/${videoId}pl.jpg`; } else if (smallImageUrl.match(/jm\.jpg$/i) && smallImageUrl.includes('pics.dmm.co.jp')) { largeImageUrl = smallImageUrl.replace(/jm\.jpg$/i, 'jp.jpg'); } else if (smallImageUrl.match(/ps\.jpg$/i)) { largeImageUrl = smallImageUrl.replace(/ps\.jpg$/i, 'pl.jpg'); } imageLink.src = largeImageUrl; imageLink.classList.add('large-image'); const imageAnchor = imageLink.parentElement; const imageContainerDiv = imageAnchor.closest('.flex.items-center.justify-center.bg-base2.grow-0.shrink-0.w-28.h-40.basis-28'); if (imageContainerDiv) { imageContainerDiv.innerHTML = ''; imageContainerDiv.appendChild(imageLink); imageContainerDiv.style.width = '100%'; imageContainerDiv.style.height = 'auto'; imageContainerDiv.style.display = 'block'; imageContainerDiv.style.padding = '0'; } imageLink.addEventListener('click', async () => { const overlay = document.createElement('div'); overlay.className = 'overlay'; const overlayImage = document.createElement('img'); overlayImage.className = 'overlay-image'; let finalImageUrl = largeImageUrl; const largerImageUrl = getLargerImageUrl(smallImageUrl); if (largerImageUrl) { const largerImageExists = await checkImageExists(largerImageUrl); if (largerImageExists) finalImageUrl = largerImageUrl; } if (smallImageUrl.match(/ps\.jpg$/i)) { let videoId = smallImageUrl.match(/\/([^\/]+)ps\.jpg$/i)[1]; if (/^[a-zA-Z]+[0-9]{3}$/.test(videoId)) { videoId = videoId.replace(/([a-zA-Z]+)([0-9]{3})/, '$100$2'); } const awsPlImageUrl = `https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/${videoId}/${videoId}pl.jpg`; const awsImageExists = await checkImageExists(awsPlImageUrl); if (awsImageExists) finalImageUrl = awsPlImageUrl; } overlayImage.src = finalImageUrl; overlay.appendChild(overlayImage); document.body.appendChild(overlay); setTimeout(() => overlay.classList.add('show'), 10); overlay.addEventListener('click', () => { overlay.classList.remove('show'); setTimeout(() => overlay.remove(), 300); }); }); const imageTitleContainer = document.createElement('div'); imageTitleContainer.className = 'image-title-container'; imageTitleContainer.appendChild(imageContainerDiv); titleLink.classList.remove('text-md'); titleLink.classList.add('title-below-image'); const titleContainer = titleLink.parentElement; titleContainer.style.display = 'block'; titleContainer.style.margin = '0'; imageTitleContainer.appendChild(titleContainer); const flexContainer = container.querySelector('.flex.min-w-0.border-y.border-light'); if (flexContainer) { flexContainer.innerHTML = ''; flexContainer.appendChild(imageTitleContainer); flexContainer.style.display = 'block'; } container.style.display = 'block'; } }); } // 視頻和詳情頁增強功能 async function enhanceDetails() { if (!window.location.href.startsWith('https://www.avbase.net/works/')) return; loadAFrame(); const container = document.querySelector('.flex.overflow-x-auto.overflow-y-hidden'); if (!container) return; const titleLink = document.querySelector('h1.text-lg')?.parentElement; if (titleLink && titleLink.href && titleLink.href.includes('al.dmm.co.jp')) { titleLink.href = processDmmLink(titleLink.href); } const verticalContainer = document.createElement('div'); verticalContainer.className = 'vertical-container'; container.parentNode.replaceChild(verticalContainer, container); const parentContainer = verticalContainer.closest('.h-44.w-full.flex'); if (parentContainer) { parentContainer.className = 'adaptive-container bg-base-300'; } const codeElement = document.querySelector('span[dir="rtl"].pl-1.whitespace-nowrap.overflow-hidden.text-ellipsis'); const code = codeElement ? codeElement.textContent.trim() : null; if (!code) return; // 添加 Jable、Missav 和複製按鈕 const buttonContainer = document.querySelector('div.flex.gap-2.items-center'); if (buttonContainer) { const targetSpan = buttonContainer.querySelector('span.text-xs.flex'); if (targetSpan) { const videoIdElement = document.querySelector('div.flex.gap-2.items-center span.text-xs div span:not(.text-gray-400)') || document.querySelector('span[dir="rtl"].pl-1.whitespace-nowrap.overflow-hidden.text-ellipsis'); const videoId = videoIdElement ? videoIdElement.textContent.trim() : null; if (videoId && !buttonContainer.querySelector('.jable-btn') && !buttonContainer.querySelector('.missav-btn') && !buttonContainer.querySelector('.copy-btn')) { const encodedVideoId = encodeURIComponent(videoId); // Jable 按鈕 const jableButton = document.createElement('div'); jableButton.className = 'jable-btn'; const jableLink = document.createElement('a'); jableLink.href = `https://jable.tv/videos/${encodedVideoId}/`; jableLink.target = '_blank'; jableLink.rel = 'noopener noreferrer'; jableLink.textContent = 'J'; jableButton.appendChild(jableLink); // Missav 按鈕 const missavButton = document.createElement('div'); missavButton.className = 'missav-btn'; const missavLink = document.createElement('a'); missavLink.href = `https://missav.ai/${encodedVideoId}`; missavLink.target = '_blank'; missavLink.rel = 'noopener noreferrer'; missavLink.textContent = 'M'; missavButton.appendChild(missavLink); // 複製按鈕 const copyButton = document.createElement('div'); copyButton.className = 'copy-btn'; copyButton.textContent = encodedVideoId; copyButton.title = '點擊複製 videoId'; // 動態設置按鈕寬度 const charWidth = 0.5; const padding = 1; const textWidth = encodedVideoId.length * charWidth; const copiedWidth = 3 * charWidth; const buttonWidth = Math.max(textWidth, copiedWidth) + padding; copyButton.style.width = `${buttonWidth}rem`; copyButton.addEventListener('click', () => { navigator.clipboard.writeText(encodedVideoId).then(() => { copyButton.textContent = '已復製'; setTimeout(() => copyButton.textContent = encodedVideoId, 1500); }).catch(err => console.error('複製失敗:', err)); }); // 插入按鈕 buttonContainer.insertBefore(copyButton, targetSpan); buttonContainer.insertBefore(missavButton, copyButton); buttonContainer.insertBefore(jableButton, missavButton); // 檢查 404 並設置背景 Promise.all([checkJableAvailability(videoId), checkMissavAvailability(videoId)]) .then(([jableAvailable, missavAvailable]) => { if (!jableAvailable) jableButton.classList.add('transparent'); if (!missavAvailable) missavButton.classList.add('transparent'); }); } } } let videoUrls = []; const isVR = code.toLowerCase().includes('vr') || code.toLowerCase().includes('aqu') || code.toLowerCase().includes('exmo') || code.startsWith('1fsvss'); const prefix = code.includes('_') ? 'h_1' : code.substr(0, 3); if ((code.startsWith('1f') && !code.startsWith('1fsvss')) || code.startsWith('1m')) { videoUrls.push(`https://videos.vpdmm.cc/litevideo/freepv/${code.charAt(0)}/${code.substr(0,3)}/${code.substr(0,6)}${code.substr(8,3)}/${code.substr(0,6)}${code.substr(8,3)}4k.mp4`); } if (isVR) { videoUrls.push(`https://cc3001.dmm.com/vrsample/${code.charAt(0)}/${prefix}/${code}/${code}vrlite.mp4`); } else { videoUrls.push(`https://cc3001.dmm.com/litevideo/freepv/${code.charAt(0)}/${prefix}/${code}/${code}hhb.mp4`); } videoUrls.push(`https://cc3001.dmm.com/litevideo/freepv/${code.charAt(0)}/${prefix}/${code}/${code}_dmb_w.mp4`); if (code.includes('_')) { videoUrls.push(`https://cc3001.dmm.com/vrsample/${code.charAt(0)}/${prefix}/${code}/${code}vrlite.mp4`); } const availabilityChecks = videoUrls.map(url => checkVideoAvailability(url)); const results = await Promise.all(availabilityChecks); const availableVideoUrl = videoUrls[results.findIndex(result => result)]; if (availableVideoUrl) { const sceneContainer = document.createElement('div'); sceneContainer.className = 'scene-container'; verticalContainer.appendChild(sceneContainer); let isVRMode = isVR; let cameraZoom = 160; let lastVolume = 1; function initializePlayer() { sceneContainer.innerHTML = ''; if (isVRMode) { const scene = document.createElement('a-scene'); scene.setAttribute('embedded', ''); scene.setAttribute('vr-mode-ui', 'enabled: false'); sceneContainer.appendChild(scene); const videoSphere = document.createElement('a-videosphere'); videoSphere.setAttribute('src', availableVideoUrl); videoSphere.setAttribute('rotation', '0 -180 0'); videoSphere.setAttribute('phi-start', '0'); videoSphere.setAttribute('phi-length', '180'); videoSphere.setAttribute('autoplay', ''); videoSphere.setAttribute('muted', ''); scene.appendChild(videoSphere); const camera = document.createElement('a-camera'); camera.setAttribute('position', `0 0 ${cameraZoom}`); camera.setAttribute('rotation', '0 90 0'); scene.appendChild(camera); } else { const videoElement = document.createElement('video'); videoElement.src = availableVideoUrl; videoElement.controls = true; videoElement.style.width = '100%'; videoElement.style.maxWidth = '800px'; videoElement.style.height = 'auto'; videoElement.style.aspectRatio = '16/9'; sceneContainer.appendChild(videoElement); videoElement.addEventListener('loadeddata', () => videoElement.play()); } } initializePlayer(); const controlsBar = document.createElement('div'); controlsBar.className = 'controls-bar'; verticalContainer.appendChild(controlsBar); const leftControls = document.createElement('div'); leftControls.style.display = 'flex'; leftControls.style.alignItems = 'center'; controlsBar.appendChild(leftControls); const rightControls = document.createElement('div'); rightControls.style.display = 'flex'; rightControls.style.alignItems = 'center'; controlsBar.appendChild(rightControls); function createButton(svgUrl, onClick, comment) { const button = document.createElement('button'); const img = document.createElement('img'); img.src = svgUrl; img.style.width = '20px'; img.style.height = '20px'; button.appendChild(img); button.addEventListener('click', onClick); return button; } const playPauseButton = createButton( 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/play.svg', () => { const video = isVRMode ? sceneContainer.querySelector('a-videosphere').components.material.material.map.image : sceneContainer.querySelector('video'); if (video.paused) { video.play(); playPauseButton.firstChild.src = 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/pause.svg'; } else { video.pause(); playPauseButton.firstChild.src = 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/play.svg'; } }, '播放/暫停按鈕' ); leftControls.appendChild(playPauseButton); const rewindButton = createButton( 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/seek-backward-10.svg', () => { const video = isVRMode ? sceneContainer.querySelector('a-videosphere').components.material.material.map.image : sceneContainer.querySelector('video'); video.currentTime = Math.max(0, video.currentTime - 5); }, '倒退5秒按鈕' ); leftControls.appendChild(rewindButton); const forwardButton = createButton( 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/seek-forward-10.svg', () => { const video = isVRMode ? sceneContainer.querySelector('a-videosphere').components.material.material.map.image : sceneContainer.querySelector('video'); video.currentTime = Math.min(video.duration, video.currentTime + 5); }, '快進5秒按鈕' ); leftControls.appendChild(forwardButton); const volumeContainer = document.createElement('div'); volumeContainer.className = 'volume-slider-container'; const volumeButton = createButton( 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/volume-high.svg', () => { const video = isVRMode ? sceneContainer.querySelector('a-videosphere').components.material.material.map.image : sceneContainer.querySelector('video'); if (video.muted) { video.muted = false; video.volume = lastVolume; volumeButton.firstChild.src = 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/volume-high.svg'; } else { lastVolume = video.volume; video.muted = true; volumeButton.firstChild.src = 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/mute.svg'; } }, '音量開關按鈕' ); const volumeSlider = document.createElement('input'); volumeSlider.type = 'range'; volumeSlider.className = 'volume-slider'; volumeSlider.min = '0'; volumeSlider.max = '1'; volumeSlider.step = '0.01'; volumeSlider.value = '1'; volumeSlider.addEventListener('input', () => { const video = isVRMode ? sceneContainer.querySelector('a-videosphere').components.material.material.map.image : sceneContainer.querySelector('video'); video.muted = false; video.volume = parseFloat(volumeSlider.value); lastVolume = video.volume; volumeButton.firstChild.src = video.volume === 0 ? 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/mute.svg' : 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/volume-high.svg'; }); volumeContainer.appendChild(volumeButton); volumeContainer.appendChild(volumeSlider); volumeContainer.addEventListener('mouseenter', () => { volumeSlider.classList.add('show'); }); volumeContainer.addEventListener('mouseleave', () => { volumeSlider.classList.remove('show'); }); leftControls.appendChild(volumeContainer); const zoomContainer = document.createElement('div'); zoomContainer.className = 'zoom-slider-container'; const zoomButton = document.createElement('button'); zoomButton.className = 'zoom-button'; const zoomImg = document.createElement('img'); zoomImg.src = 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/search.svg'; zoomImg.style.width = '20px'; zoomImg.style.height = '20px'; zoomButton.appendChild(zoomImg); const zoomSlider = document.createElement('input'); zoomSlider.type = 'range'; zoomSlider.className = 'zoom-slider'; zoomSlider.min = '-480'; zoomSlider.max = '480'; zoomSlider.step = '10'; zoomSlider.value = '160'; const zoomValue = document.createElement('span'); zoomValue.className = 'zoom-value'; zoomValue.textContent = '160'; zoomButton.addEventListener('click', () => { zoomSlider.classList.toggle('show'); zoomValue.classList.toggle('show'); }); zoomSlider.addEventListener('input', () => { if (!isVRMode) return; const camera = sceneContainer.querySelector('a-camera'); if (!camera) return; cameraZoom = parseFloat(zoomSlider.value); camera.setAttribute('position', `0 0 ${cameraZoom}`); zoomValue.textContent = cameraZoom; }); zoomContainer.appendChild(zoomValue); zoomContainer.appendChild(zoomSlider); zoomContainer.appendChild(zoomButton); rightControls.appendChild(zoomContainer); const togglePlayerButton = createButton( isVRMode ? 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/2d-label-icon.svg' : 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/vr-label-icon.svg', () => { const video = isVRMode ? sceneContainer.querySelector('a-videosphere')?.components.material.material.map.image : sceneContainer.querySelector('video'); if (video) { video.pause(); video.currentTime = 0; } isVRMode = !isVRMode; initializePlayer(); togglePlayerButton.firstChild.src = isVRMode ? 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/2d-label-icon.svg' : 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/vr-label-icon.svg'; }, '2D/VR切換按鈕' ); rightControls.appendChild(togglePlayerButton); const fullscreenButton = createButton( 'https://raw.githubusercontent.com/leogfa/svg/65fdb85e8047e4b5b6e221e5516962c534d8efb6/fullscreen.svg', () => { if (!document.fullscreenElement) { sceneContainer.requestFullscreen().catch(err => { console.error('無法進入全螢幕:', err); }); } else { document.exitFullscreen(); } }, '全螢幕切換按鈕' ); fullscreenButton.className = 'fullscreen-button'; rightControls.appendChild(fullscreenButton); } const imageContainer = document.createElement('div'); imageContainer.className = 'image-container'; imageContainer.style.display = 'none'; verticalContainer.appendChild(imageContainer); container.querySelectorAll('a').forEach(link => { let newSrc = link.href; if (newSrc.includes('al.dmm.co.jp')) { newSrc = processDmmLink(newSrc); } const img = link.querySelector('img'); if (img) { img.src = newSrc; img.style.width = 'auto'; img.style.height = 'auto'; img.style.maxWidth = '100%'; img.style.objectFit = 'contain'; } link.href = newSrc; link.style.display = 'block'; link.style.width = 'auto'; link.style.height = 'auto'; imageContainer.appendChild(link); }); const toggleButton = document.createElement('button'); const toggleImg = document.createElement('img'); toggleImg.src = 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/eye.svg'; toggleImg.style.width = '20px'; toggleImg.style.height = '20px'; toggleButton.appendChild(toggleImg); toggleButton.className = 'toggle-button'; toggleButton.addEventListener('click', () => { imageContainer.style.display = imageContainer.style.display === 'none' ? 'flex' : 'none'; toggleImg.src = imageContainer.style.display === 'none' ? 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/eye.svg' : 'https://raw.githubusercontent.com/leogfa/svg/b99823546f418d86bc5c3ecdd53b7c02e38cad9c/no-eye.svg'; verticalContainer.style.height = 'auto'; parentContainer.style.height = 'auto'; }); verticalContainer.insertBefore(toggleButton, imageContainer); const videoIdElement = document.querySelector('div.flex.gap-2.items-center span.text-xs div span:not(.text-gray-400)'); const videoId = videoIdElement ? videoIdElement.textContent.trim() : null; if (videoId) { fetchSukebeiResults(videoId).then(results => { let tableWrapper = document.createElement('div'); tableWrapper.className = 'table-wrapper'; let table = document.createElement('table'); table.style.width = '100%'; table.style.borderCollapse = 'collapse'; table.style.fontSize = '12px'; table.style.margin = '0'; if (results.length) { results.forEach(result => { let tr = document.createElement('tr'); let tdName = document.createElement('td'); tdName.style.padding = '8px'; tdName.style.border = '1px solid #ddd'; tdName.style.width = '60%'; tdName.textContent = result.name; tr.appendChild(tdName); let tdLink = document.createElement('td'); tdLink.style.padding = '8px'; tdLink.style.border = '1px solid #ddd'; tdLink.style.textAlign = 'center'; tdLink.style.width = '15%'; let iconWrapper = document.createElement('div'); iconWrapper.style.display = 'inline-flex'; iconWrapper.style.gap = '8px'; iconWrapper.style.alignItems = 'center'; let aTorrent = document.createElement('a'); aTorrent.href = result.link; aTorrent.target = '_blank'; aTorrent.innerHTML = `<img src="https://raw.githubusercontent.com/leogfa/svg/fde17c8702542028c186c6fb170a8bc26a6c1be5/download.svg" style="width: 24px; height: 24px; filter: brightness(100%) invert(1);">`; iconWrapper.appendChild(aTorrent); let btnMagnet = document.createElement('button'); btnMagnet.style.background = 'none'; btnMagnet.style.border = 'none'; btnMagnet.style.cursor = 'pointer'; btnMagnet.innerHTML = `<img src="https://raw.githubusercontent.com/leogfa/svg/3edada4e4c0a5c1a83938a427459a488d22ec6a4/magnet.svg" style="width: 24px; height: 24px; filter: brightness(100%) invert(1);">`; btnMagnet.addEventListener('click', () => { if (navigator.clipboard) { navigator.clipboard.writeText(result.magnet).then(() => { btnMagnet.textContent = '已複製'; setTimeout(() => { btnMagnet.innerHTML = `<img src="https://raw.githubusercontent.com/leogfa/svg/3edada4e4c0a5c1a83938a427459a488d22ec6a4/magnet.svg" style="width: 24px; height: 24px; filter: brightness(100%) invert(1);">`; }, 1500); }); } }); iconWrapper.appendChild(btnMagnet); tdLink.appendChild(iconWrapper); tr.appendChild(tdLink); let tdSize = document.createElement('td'); tdSize.style.padding = '8px'; tdSize.style.border = '1px solid #ddd'; tdSize.style.textAlign = 'center'; tdSize.style.width = '10%'; tdSize.textContent = result.size; tr.appendChild(tdSize); let tdDate = document.createElement('td'); tdDate.style.padding = '8px'; tdDate.style.border = '1px solid #ddd'; tdDate.style.textAlign = 'center'; tdDate.style.width = '15%'; let d = new Date(result.date); function pad(n) { return n < 10 ? "0" + n : n; } let formattedDate = `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`; tdDate.textContent = formattedDate; tr.appendChild(tdDate); table.appendChild(tr); }); } else { let noResultRow = document.createElement('tr'); let noResultTd = document.createElement('td'); noResultTd.colSpan = "4"; noResultTd.style.padding = '8px'; noResultTd.style.textAlign = 'center'; noResultTd.textContent = '找不到Seed'; noResultRow.appendChild(noResultTd); table.appendChild(noResultRow); } tableWrapper.appendChild(table); imageContainer.insertAdjacentElement('afterend', tableWrapper); }).catch(err => { console.error('Sukebei RSS 搜尋失敗: ', err); }); } } // 主初始化函數 function initialize() { if (!window.location.href.startsWith('https://www.avbase.net/works/')) { enhanceImages(); } enhanceDetails(); let lastUrl = location.href; const urlObserver = new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; enhanceImages(); enhanceDetails(); } }); urlObserver.observe(document, { subtree: true, childList: true }); const contentObserver = new MutationObserver(() => { if (!window.location.href.startsWith('https://www.avbase.net/works/')) { enhanceImages(); } else { enhanceDetails(); } }); contentObserver.observe(document.body, { childList: true, subtree: true }); } initialize(); })();