From a9e88cda88842c5d04d1fc7236ca2c377373d4a5 Mon Sep 17 00:00:00 2001 From: "lzyme.dev@gmail.com" Date: Thu, 3 Sep 2026 21:45:01 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4javxy=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/cover.js | 27 ------ src/api/dmmrsc.js | 61 +++++++++++++ src/core/constants.js | 10 +++ src/main.js | 4 +- src/plugins/detail-page-button.js | 2 +- ...view-video.js => javopen-preview-video.js} | 87 +++++++++---------- 6 files changed, 114 insertions(+), 77 deletions(-) delete mode 100644 src/api/cover.js create mode 100644 src/api/dmmrsc.js rename src/plugins/{javxy-preview-video.js => javopen-preview-video.js} (72%) diff --git a/src/api/cover.js b/src/api/cover.js deleted file mode 100644 index 949c6ab..0000000 --- a/src/api/cover.js +++ /dev/null @@ -1,27 +0,0 @@ -const COVER_API_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95, 10, 68, 85, 76, 10, 70, 74, 83, 64, 87] - .map(v => String.fromCharCode(v ^ 0x25)).join(''); - -const COVER_API_TOKEN = [18, 28, 19, 19, 65, 65, 70, 28, 64, 29, 23, 21, 17, 29, 67, 70, 18, 64, 21, 22, 64, 16, 65, 29, 22, 19, 16, 28, 16, 17, 64, 29] - .map(v => String.fromCharCode(v ^ 0x25)).join(''); - -const getCover = async (code) => { - const query = String(code || '').trim(); - if (!query) return null; - - try { - const r = await gmHttp.get(`${COVER_API_URL}/${encodeURIComponent(query)}`, null, { - 'Authorization': `Bearer ${COVER_API_TOKEN}`, - }, {timeout: 15000}); - - if (r?.cover?.large) { - //clog.log('高清封面地址:', r.cover.large); - return r.cover.large; - } - return null; - } catch (e) { - clog.error('获取封面失败:', e.message); - return null; - } -}; - -export {getCover}; \ No newline at end of file diff --git a/src/api/dmmrsc.js b/src/api/dmmrsc.js new file mode 100644 index 0000000..334cc8c --- /dev/null +++ b/src/api/dmmrsc.js @@ -0,0 +1,61 @@ +const COVER_API_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95, 10, 68, 85, 76, 10, 70, 74, 83, 64, 87] + .map(v => String.fromCharCode(v ^ 0x25)).join(''); + +const TRAILER_API_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95, 10, 68, 85, 76, 10, 81, 87, 68, 76, 73, 64, 87] + .map(v => String.fromCharCode(v ^ 0x25)).join(''); + +const BASE_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95] + .map(v => String.fromCharCode(v ^ 0x25)).join(''); + +const COVER_API_TOKEN = [18, 28, 19, 19, 65, 65, 70, 28, 64, 29, 23, 21, 17, 29, 67, 70, 18, 64, 21, 22, 64, 16, 65, 29, 22, 19, 16, 28, 16, 17, 64, 29] + .map(v => String.fromCharCode(v ^ 0x25)).join(''); + +const getCover = async (code) => { + const query = String(code || '').trim(); + if (!query) return null; + + try { + const r = await gmHttp.get(`${COVER_API_URL}/${encodeURIComponent(query)}`, null, { + 'Authorization': `Bearer ${COVER_API_TOKEN}`, + }, {timeout: 15000}); + + if (r?.cover?.large) { + //clog.log('高清封面地址:', r.cover.large); + return r.cover.large; + } + return null; + } catch (e) { + clog.error('获取封面失败:', e.message); + return null; + } +}; + +const getTrailer = async (code) => { + const query = String(code || '').trim(); + if (!query) return null; + + try { + const r = await gmHttp.get(`${TRAILER_API_URL}/${encodeURIComponent(query)}`, null, { + 'Authorization': `Bearer ${COVER_API_TOKEN}`, + }, {timeout: 15000}); + + if (r?.trailers && Array.isArray(r.trailers) && r.trailers.length > 0) { + const qualityMap = {}; + r.trailers.forEach((item) => { + if (item.proxy && item.quality) { + qualityMap[item.quality] = `${BASE_URL}${item.proxy}`; + } + }); + if (Object.keys(qualityMap).length > 0) { + clog.log('预告片播放地址:', JSON.stringify(qualityMap)); + return qualityMap; + } + } + return null; + } catch (e) { + clog.error('获取预告片失败:', e.message); + return null; + } +}; + +export {getCover, getTrailer}; \ No newline at end of file diff --git a/src/core/constants.js b/src/core/constants.js index bbccb7a..ce44ca1 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -63,6 +63,16 @@ const currentHref = window.location.href, quality: "mmb", text: "中画质 (432p)", canSelect: !0 + }, { + id: "video-dm", + quality: "dm", + text: "低画质 (1000kbps)", + canSelect: !0 + }, { + id: "video-dmb", + quality: "dmb", + text: "中画质 (1500kbps)", + canSelect: !0 }, { id: "video-mhb", quality: "mhb", diff --git a/src/main.js b/src/main.js index 83a7738..01c98bd 100644 --- a/src/main.js +++ b/src/main.js @@ -29,7 +29,7 @@ import { TOP250Plugin } from './plugins/top250.js'; import { NavBarPlugin } from './plugins/nav-bar.js'; import { BusDetailPagePlugin } from './plugins/bus-detail-page.js'; import { BusPreviewVideoPlugin } from './plugins/bus-preview-video.js'; -import {JavxyPreviewVideoPlugin} from './plugins/javxy-preview-video.js'; +import {JavopenPreviewVideoPlugin} from './plugins/javopen-preview-video.js'; import { ImageRecognitionPlugin } from './plugins/image-recognition.js'; import { BusNavBarPlugin } from './plugins/bus-nav-bar.js'; import { RelatedPlugin } from './plugins/related.js'; @@ -879,7 +879,7 @@ const pluginManager = function() { pluginManager2.register(DetailPageButtonPlugin); pluginManager2.register(HighlightMagnetPlugin); pluginManager2.register(PreviewVideoPlugin); - pluginManager2.register(JavxyPreviewVideoPlugin); + pluginManager2.register(JavopenPreviewVideoPlugin); pluginManager2.register(FilterTitleKeywordPlugin); pluginManager2.register(ActressInfoPlugin); pluginManager2.register(OtherSitePlugin); diff --git a/src/plugins/detail-page-button.js b/src/plugins/detail-page-button.js index c513e11..f6ef562 100644 --- a/src/plugins/detail-page-button.js +++ b/src/plugins/detail-page-button.js @@ -13,7 +13,7 @@ import { } from '../core/constants.js'; import { HotkeyManager } from './preview-video.js'; import {GM_xmlhttpRequest} from 'vite-plugin-monkey/dist/client'; -import {getCover} from '../api/cover.js'; +import {getCover} from '../api/dmmrsc.js'; class DetailPageButtonPlugin extends BasePlugin { getName() { diff --git a/src/plugins/javxy-preview-video.js b/src/plugins/javopen-preview-video.js similarity index 72% rename from src/plugins/javxy-preview-video.js rename to src/plugins/javopen-preview-video.js index 64fba8c..81ee252 100644 --- a/src/plugins/javxy-preview-video.js +++ b/src/plugins/javopen-preview-video.js @@ -1,11 +1,11 @@ import {BasePlugin} from '../core/base-plugin.js'; import {__publicField, isJavBus, isJavDb, qualityOptions} from '../core/constants.js'; import {isM3U8Url, attachHlsToVideo, destroyHls, loadHlsLibrary, getHlsClass} from '../lib/hls-runtime.js'; -import {getJavxyVideoUrls} from '../api/javxy.js'; +import {getTrailer} from '../api/dmmrsc.js'; -class JavxyPreviewVideoPlugin extends BasePlugin { +class JavopenPreviewVideoPlugin extends BasePlugin { getName() { - return "JavxyPreviewVideoPlugin"; + return "JavopenPreviewVideoPlugin"; } _attachVideoSrc(videoEl, src) { @@ -17,20 +17,13 @@ class JavxyPreviewVideoPlugin extends BasePlugin { if (HlsClass) { attachHlsToVideo(videoEl, src).catch((err) => { clog.error('视频预览 HLS 加载失败:', err); - videoEl.src = src; - videoEl.load && videoEl.load(); }); } else { loadHlsLibrary().then((HlsClass) => { if (videoEl && videoEl.isConnected && HlsClass) { attachHlsToVideo(videoEl, src).catch((err) => { clog.error('视频预览 HLS 延迟加载失败:', err); - videoEl.src = src; - videoEl.load && videoEl.load(); }); - } else if (videoEl && videoEl.isConnected) { - videoEl.src = src; - videoEl.load && videoEl.load(); } }); } @@ -51,38 +44,38 @@ class JavxyPreviewVideoPlugin extends BasePlugin { async initCss() { return ` - .jhs-javxy-video-modal { + .jhs-javopen-video-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.95); z-index: 12345700; display: flex; justify-content: center; align-items: center; opacity: 0; visibility: hidden; transition: opacity 0.2s; } - .jhs-javxy-video-modal.is-open { opacity: 1; visibility: visible; } - .jhs-javxy-video-modal-inner { + .jhs-javopen-video-modal.is-open { opacity: 1; visibility: visible; } + .jhs-javopen-video-modal-inner { display: flex; flex-direction: column; align-items: center; gap: 12px; max-width: 90vw; max-height: 90vh; } - .jhs-javxy-video-wrapper { + .jhs-javopen-video-wrapper { width: 80vw; max-height: 80vh; aspect-ratio: 16/9; background: #000; position: relative; } - .jhs-javxy-video-wrapper video { + .jhs-javopen-video-wrapper video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - .jhs-javxy-quality-bar { + .jhs-javopen-quality-bar { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; } - .jhs-javxy-quality-btn { + .jhs-javopen-quality-btn { min-width: 60px; padding: 5px 10px; font-size: 13px; background: rgba(255,255,255,0.2); color: #fff; border: 1px solid rgba(255,255,255,0.5); border-radius: 4px; cursor: pointer; transition: background 0.2s; } - .jhs-javxy-quality-btn:hover { background: rgba(255,255,255,0.4); } - .jhs-javxy-quality-btn.active { + .jhs-javopen-quality-btn:hover { background: rgba(255,255,255,0.4); } + .jhs-javopen-quality-btn.active { background: #1890ff; border-color: #096dd9; font-weight: bold; } - .jhs-javxy-loading { + .jhs-javopen-loading { color: #fff; font-size: 16px; text-align: center; } `; @@ -94,10 +87,10 @@ class JavxyPreviewVideoPlugin extends BasePlugin { const carNum = this.getPageInfo().carNum; if (!carNum) return; - this._addJavxyButton(carNum); + this._addJavopenButton(carNum); } - _addJavxyButton(carNum) { + _addJavopenButton(carNum) { let $target = null; if (isJavDb) { @@ -128,7 +121,7 @@ class JavxyPreviewVideoPlugin extends BasePlugin { e.stopPropagation(); $btn.css("pointer-events", "none").find("span").text("..."); try { - await this._openJavxyPlayer(carNum); + await this._openJavopenPlayer(carNum); } finally { $btn.css("pointer-events", "").find("span").text("视频预览"); } @@ -136,23 +129,23 @@ class JavxyPreviewVideoPlugin extends BasePlugin { $target.after($btn); } - async _openJavxyPlayer(carNum) { - if ($("#jhs-javxy-video-modal").length === 0) { + async _openJavopenPlayer(carNum) { + if ($("#jhs-javopen-video-modal").length === 0) { $("body").append(` -
-
-
- +
+
+
+
-
+
`); - const $modal = $("#jhs-javxy-video-modal"); + const $modal = $("#jhs-javopen-video-modal"); $modal.on("click", (e) => { - if (e.target.id === "jhs-javxy-video-modal") { + if (e.target.id === "jhs-javopen-video-modal") { $modal.removeClass("is-open"); - const videoEl = document.getElementById("jhs-javxy-video"); + const videoEl = document.getElementById("jhs-javopen-video"); if (videoEl) { destroyHls(videoEl); videoEl.pause(); @@ -162,7 +155,7 @@ class JavxyPreviewVideoPlugin extends BasePlugin { $(document).on("keydown", (e) => { if (e.key === "Escape" && $modal.hasClass("is-open")) { $modal.removeClass("is-open"); - const videoEl = document.getElementById("jhs-javxy-video"); + const videoEl = document.getElementById("jhs-javopen-video"); if (videoEl) { destroyHls(videoEl); videoEl.pause(); @@ -171,23 +164,23 @@ class JavxyPreviewVideoPlugin extends BasePlugin { }); } - const $modal = $("#jhs-javxy-video-modal"); - const $wrapper = $modal.find(".jhs-javxy-video-wrapper"); - const $qualityBar = $modal.find(".jhs-javxy-quality-bar"); - $wrapper.html('
视频预览加载中...
'); + const $modal = $("#jhs-javopen-video-modal"); + const $wrapper = $modal.find(".jhs-javopen-video-wrapper"); + const $qualityBar = $modal.find(".jhs-javopen-quality-bar"); + $wrapper.html('
视频预览加载中...
'); $qualityBar.empty(); $modal.addClass("is-open"); let videoMap = null; try { - videoMap = await getJavxyVideoUrls(carNum); + videoMap = await getTrailer(carNum); } catch (err) { - $wrapper.html(`
视频预览请求失败: ${err.message}
`); + $wrapper.html(`
视频预览请求失败: ${err.message}
`); return; } if (!videoMap || Object.keys(videoMap).length === 0) { - $wrapper.html('
未找到可用的视频源
'); + $wrapper.html('
未找到可用的视频源
'); return; } @@ -195,10 +188,10 @@ class JavxyPreviewVideoPlugin extends BasePlugin { const defaultQuality = this._selectDefaultQuality(qualityList, '720p'); const defaultUrl = videoMap[defaultQuality]; - $wrapper.html(`