// ==UserScript==
// @name x1080x-preview
// @license MIT
// @namespace https://greasyfork.org/zh-CN/scripts/439204-x1080x-preview
// @version 7.2
// @description 显示影片预览图和预览影片
// @author jasmine
// @match https://*.x567x.me/forum.php?mod=viewthread&tid=*
// @match https://*.x567x.me/home.php?mod=spacecp&ac=pm&from=script
// @match https://x567x.me/forum.php?mod=viewthread&tid=*
// @match https://x567x.me/home.php?mod=spacecp&ac=pm&from=script
// @match https://*.x999x.me/forum.php?mod=viewthread&tid=*
// @match https://*.x999x.me/home.php?mod=spacecp&ac=pm&from=script
// @match https://x999x.me/forum.php?mod=viewthread&tid=*
// @match https://x999x.me/home.php?mod=spacsecp&ac=pm&from=script
// @icon https://www.google.com/s2/favicons?domain=www.x999x.me
// @connect javdb.com
// @connect javbus.com
// @connect ec.sod.co.jp
// @connect cloudfront.net
// @connect r18.com
// @connect www.dmm.co.jp
// @connect accounts.dmm.co.jp
// @connect dahlia-av.jp
// @connect cdn.faleno.net
// @connect faleno.jp
// @connect www.mgstage.com
// @connect www.afesta.tv
// @connect www.bing.com
// @require https://lib.baomitu.com/jquery/3.5.1/jquery.min.js
// @resource fancybox_css https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css
// @require https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js
// @resource videojs_css https://lib.baomitu.com/video.js/5.20.5/video-js.min.css
// @require https://lib.baomitu.com/video.js/5.20.5/video.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/videojs-hotkeys/0.2.27/videojs.hotkeys.min.js
// @resource videojs_resolution_switcher_css https://lib.baomitu.com/videojs-resolution-switcher/0.4.2/videojs-resolution-switcher.min.css
// @require https://lib.baomitu.com/videojs-resolution-switcher/0.4.2/videojs-resolution-switcher.min.js
// @grant GM_xmlhttpRequest
// @grant GM_notification
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_getResourceText
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_log
// @grant GM_openInTab
// @grant GM_info
// ==/UserScript==
(function() {
'use strict';
// 菜单列表
var menu_ALL = [
['menu_showGallery', '显示预览图', '显示预览图', true],
['menu_quality', '画面优先', '画面优先', true],
['menu_jumpSOD', '视频跳转SOD', '视频跳转SOD', true],
['menu_offcial', '搜索官网', '搜索官网', true],
['menu_multi', '并发搜索', '并发搜索', false],
['menu_JavDB', '搜索JavDB', '搜索JavDB', false],
['menu_JavBus', '搜索JavBus', '搜索JavBus', false],
], menu_ID = [];
for (let i=0;i<menu_ALL.length;i++){ // 如果读取到的值为 null 就写入默认值
if (GM_getValue(menu_ALL[i][0]) == null) {
GM_setValue(menu_ALL[i][0], menu_ALL[i][3])
};
}
registerMenuCommand();
// 注册脚本菜单
function registerMenuCommand() {
if (menu_ID.length > menu_ALL.length){ // 如果菜单ID数组多于菜单数组,说明不是首次添加菜单,需要卸载所有脚本菜单
for (let i=0;i<menu_ID.length;i++){
GM_unregisterMenuCommand(menu_ID[i]);
}
}
for (let i=0;i<menu_ALL.length;i++){ // 循环注册脚本菜单
menu_ALL[i][3] = GM_getValue(menu_ALL[i][0]);
menu_ID[i] = GM_registerMenuCommand(`${menu_ALL[i][3]?'✅':'❌'} ${menu_ALL[i][1]}`, function(){menu_switch(`${menu_ALL[i][3]}`,`${menu_ALL[i][0]}`,`${menu_ALL[i][2]}`)});
}
// menu_ID[menu_ID.length] = GM_registerMenuCommand(`📥 导入FanzaCookies`, function () {
// let fanza_cookies = "";
// let cookies = prompt("请使用EditThisCookie导出Cookies后粘贴至此");
// try {
// JSON.parse(cookies).forEach(item=>{
// fanza_cookies += `${item.name}=${item.value};`
// })
// GM_setValue("FANZA_Cookies", fanza_cookies)
// } catch (error) {
// console.error(error);
// }
// })
menu_ID[menu_ID.length + 1] = GM_registerMenuCommand('💬 反馈 & 建议', function () {GM_openInTab(`https://${document.location.hostname}/home.php?mod=spacecp&ac=pm&from=script`, {active: true,insert: true,setParent: true});});
}
// 菜单开关
function menu_switch(menu_status, Name, Tips) {
if (menu_status == 'true'){
GM_setValue(`${Name}`, false);
GM_notification({text: `已关闭 [${Tips}] 功能\n(点击刷新网页后生效)`, timeout: 3500, onclick: function(){location.reload();}});
}else{
GM_setValue(`${Name}`, true);
if (['menu_JavDB', 'menu_JavBus'].includes(Name)) {
GM_setValue('menu_offcial', false)
}
GM_notification({text: `已开启 [${Tips}] 功能\n(点击刷新网页后生效)`, timeout: 3500, onclick: function(){location.reload();}});
}
registerMenuCommand(); // 重新注册脚本菜单
};
// 返回菜单值
function menu_value(menuName) {
for (let menu of menu_ALL) {
if (menu[0] == menuName) {
return menu[3]
}
}
}
// 日志记录
function record_log(msg) {
let log = GM_getValue("log");
if (log !== "") {
log = log + "\n"
}
GM_setValue("log", log + msg);
GM_log(msg);
}
// 根据xpath查找 一个结果
function _xO(path, obj) {
return obj.evaluate(path, obj, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
// 根据xpath查找 多个结果
function _xM(path, obj) {
var xresult = obj.evaluate(path, obj, null, XPathResult.ANY_TYPE, null);
var xnodes = [];
var xres;
while (xres = xresult.iterateNext()) {
xnodes.push(xres.textContent);
}
return xnodes;
}
// 通用请求
function gmFetch(obj) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: obj.method || 'GET',
// timeout in ms
timeout: obj.timeout,
url: obj.url,
headers: obj.headers,
cookie: obj.cookie,
data: obj.data,
revalidate: obj.revalidate ? true: false,
nocache: obj.nocache ? true: false,
onload: res => {
if (res.status >= 200 && res.status < 400 || res.finalUrl === "http://ec.sod.co.jp/prime/") {
resolve(res);
} else {
reject(res);
}
},
onerror: reject,
ontimeout: reject,
});
});
}
// 请求
function fetch(url, headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}){
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: url,
method: "GET",
headers: headers,
//timeout: 5000,
onload: function(r){
if (r.status === 200) {
resolve(r.responseText)
} else {
reject("status error: " + r.status)
}
},
onerror: function(e) {
reject('fetch error')
},
ontimeout: function(e) {
reject('fetch timeout')
}
});
})
}
// 检查连接
function checkURL(url, headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}){
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: url,
method: "HEAD",
headers: headers,
//timeout: 5000,
onload: function(r){
if (r.status === 200) {
resolve(true)
} else {
resolve(false)
}
},
onerror: function(e) {
resolve(false)
},
ontimeout: function(e) {
resolve(false)
}
});
})
}
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
// 格式化页面
function parseResponse(html) {
const parser = new DOMParser()
const tree = parser.parseFromString(html, "text/html")
return tree
}
// DMM获取大图
function preview_src(src)
{
if (src.match(/(p[a-z]\.)jpg/)) {
return src.replace(RegExp.$1, 'pl.');
} else if (src.match(/consumer_game/)) {
return src.replace('js-','-');
} else if (src.match(/js\-([0-9]+)\.jpg$/)) {
return src.replace('js-','jp-');
} else if (src.match(/ts\-([0-9]+)\.jpg$/)) {
return src.replace('ts-','tl-');
} else if (src.match(/(\-[0-9]+\.)jpg$/)) {
return src.replace(RegExp.$1, 'jp' + RegExp.$1);
} else {
return src.replace('-','jp-');
}
}
function getBase64FromImage(url, onSuccess, onError) {
var xhr = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
xhr.open("GET", url);
xhr.onload = function () {
var base64, binary, bytes, mediaType;
bytes = new Uint8Array(xhr.response);
//NOTE String.fromCharCode.apply(String, ...
//may cause "Maximum call stack size exceeded"
binary = [].map.call(bytes, function (byte) {
return String.fromCharCode(byte);
}).join('');
mediaType = xhr.getResponseHeader('content-type');
base64 = [
'data:',
mediaType ? mediaType + ';':'',
'base64,',
btoa(binary)
].join('');
onSuccess(base64);
};
xhr.onerror = onError;
xhr.send();
}
// 插入预览图
function insertImages(item) {
let src;
if (video_type === "sod" && ["sod", "javbus"].includes(source)) {
src = URL.createObjectURL(item)
} else {
src = item
}
const a = document.createElement("a");
const img = document.createElement("img");
a.href = src;
a.setAttribute("data-fancybox", "gallery");
a.setAttribute("class", "x1080x-ga-box");
img.setAttribute("class", "x1080x-auto-img");
img.src = src;
a.appendChild(img);
gallery_div.appendChild(a);
}
//下载预览图
// async function downloadSODImages(gallery, headers) {
// for (let index = 0; index < gallery.length; index++) {
// try {
// await download(gallery[index], gallery[index], headers);
// }
// catch(e){
// record_log(e)
// }
// }
// }
//访问预览图
async function accessSODImages(gallery, headers) {
for (let index = 0; index < gallery.length; index++) {
try {
await fetch(gallery[index], headers);
}
catch(e){
record_log(e)
}
}
}
// 浏览器版本
navigator.sayswho= (function(){
let ua= navigator.userAgent;
let tem;
let M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if(/trident/i.test(M[1])){
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return 'IE '+(tem[1] || '');
}
if(M[1]=== 'Chrome'){
tem= ua.match(/\b(OPR|Edge)\/(\d+)/);
if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
}
M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
return M.join(' ');
})();
// 入口
//const res = await fetch("https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=ssis279/mtype=AhRVShI_/service=litevideo/mode=/width=560/height=360/", {"accept-language": "ja-JP,ja;q=0.9"})
//log(res);
//const re = /const args = ({.+});$/gm;
//const hits = [];
//// Iterate hits
//let match = null;
//do {
// match = re.exec(res);
// if(match) {
// hits.push(match[1]);
// }
//} while (match);
//const obj = JSON.parse(hits[0])
//record_log(obj["bitrates"]); // Prints [ '#with', '#hashtags' ]
//return false
// 意见反馈
if (window.location.href.endsWith("from=script")) {
//let log = GM_getValue("log")
document.querySelector("#username").value = "jpyl0423"
document.querySelector("#sendmessage").value = GM_getValue("log")
return
}
// 基础div
const node = _xO("//div[@class='t_fsz']/table/tbody", document);
if (node == null || !menu_value("menu_showGallery")) {
return;
}
// 封面
let cover = document.querySelector("td[id^=postmessage] img").src
if (!cover.match(/(pics.dmm.co.jp|www.hxmmdd.com)/)) {
return
}
// 预览容器
const tr = document.createElement("tr");
const td = document.createElement("td");
const gallery_div = document.createElement("div")
td.appendChild(gallery_div)
tr.appendChild(td)
gallery_div.setAttribute("class", "x1080x-gallery");
const ga_inner = document.createElement('span');
gallery_div.appendChild(ga_inner)
node.appendChild(tr)
// 播放容器
const play_box = document.createElement("a");
play_box.setAttribute("class", "x1080x-ga-box x1080x-play-box");
play_box.setAttribute("data-fancybox", "");
gallery_div.insertBefore(play_box, gallery_div.firstChild);
// 视频封面
const poster = document.createElement("img");
poster.setAttribute("class", "x1080x-auto-img");
poster.src = cover
const span = document.createElement("span");
span.setAttribute("class", "x1080x-preview");
span.innerHTML = '預告片'
const outer_span = document.createElement("span");
outer_span.setAttribute("class", "x1080x-outer");
outer_span.innerHTML = '外链'
play_box.appendChild(span);
play_box.appendChild(outer_span);
play_box.appendChild(poster);
// 播放器
const video_player = document.createElement("video");
video_player.setAttribute("id", "x1080x-player");
video_player.setAttribute("class", "video-js vjs-default-skin");
play_box.append(video_player)
const options = {
controls: true,
responsive: true,
plugins: {
videoJsResolutionSwitcher: {
default: menu_value('menu_quality') ? `high`: `low`, // Default resolution [{Number}, 'low', 'high'],
dynamicLabel: true
}
},
};
let player = videojs("x1080x-player", options, function(){});
player.ready(function() {
this.hotkeys({
volumeStep: 0.1,
seekStep: 5,
enableModifiersForNumbers: false
});
});
// 加载fancybox样式
const fancybox_css = GM_getResourceText("fancybox_css");
GM_addStyle(fancybox_css);
// 加载video-js样式
const videojs_css = GM_getResourceText("videojs_css");
GM_addStyle(videojs_css);
GM_addStyle(".video-js .vjs-progress-holder, .video-js .vjs-progress-holder .vjs-play-progress,.video-js .vjs-progress-holder .vjs-load-progress,.video-js .vjs-progress-holder .vjs-tooltip-progress-bar,.video-js .vjs-progress-holder .vjs-load-progress div{height:1.0em}");
// 加载videojs-resolution-switcher样式
const videojs_resolution_switcher_css = GM_getResourceText("videojs_resolution_switcher_css");
GM_addStyle(videojs_resolution_switcher_css);
// 自定义样式
let btn_img = `PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA1Mi4xICg2NzA0OCkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+YnRuLXBsYXk8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iYnRuLXBsYXkiIGZpbGwtcnVsZT0ibm9uemVybyI+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yNTYsMCBDMTE0Ljg0MzU0OSwwIDAsMTE0Ljg0MzU0OSAwLDI1NiBDMCwzOTcuMTU2NDUxIDExNC44NDM1NDksNTEyIDI1Niw1MTIgQzM5Ny4xNTY0NTEsNTEyIDUxMiwzOTcuMTU2NDUxIDUxMiwyNTYgQzUxMiwxMTQuODQzNTQ5IDM5Ny4xNTY0NTEsMCAyNTYsMCBaIiBpZD0iU2hhcGUiIGZpbGw9IiMwQTVFRTAiPjwvcGF0aD4KICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGw9IiNGRkZGRkYiIHBvaW50cz0iMTkyIDM4My45OTcyODUgMTkyIDEyNy45OTkwOTUgMzg0IDI1NS45OTcyODUiPjwvcG9seWdvbj4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==`
GM_addStyle(`
.x1080x-gallery {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 10px;
max-width: 95%;
}
.x1080x-ga-box {
display: inline-block;
width: 250px;
height: auto;
text-align: center;
vertical-align: middle;
overflow-x: hidden;
text-overflow: ellipsis;
font-size: .9rem;
background-color: black;
margin: 5px 5px 0px 0px;
cursor: pointer;
}
.x1080x-ga-box .x1080x-auto-img {
position: relative;
height: 120px;
}
.x1080x-play-box {
display: none;
position: relative;
}
.x1080x-play-box span.x1080x-preview {
font-size: .8rem;
color: #fff;
background-color: #fc8300;
position: absolute;
top: 4px;
left: 4px;
text-align: center;
padding: 1px 2px;
border-radius: 3px;
z-index: 999;
}
.x1080x-play-box span.x1080x-outer {
font-size: .8rem;
color: #fff;
background-color: #fc8300;
position: absolute;
top: 4px;
right: 4px;
text-align: center;
padding: 1px 2px;
border-radius: 3px;
z-index: 999;
display: none;
}
.x1080x-play-box:after {
background: url("data:image/svg+xml;base64,${btn_img}") 50% no-repeat;
background-color: rgba(0,0,0,.2);
background-size: 40px 40px;
bottom: 0;
content: "";
display: block;
left: 0;
position: absolute;
right: 0;
top: 0;
height: 100%;
}
.x1080x-play-box:hover::after {
background-color: rgba(33,156,239,0);;
}
#x1080x-player {
display:none;
position: absolute;
width: 50%;
height: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
}
`);
GM_setValue("log", "");
let title_pattern = /\)([^\(\)].*)</g;
let subject = document.querySelector("#thread_subject").innerText
let video_type;
if (subject.match(/\(SOD\)|\(SODVR\)/) && menu_value("menu_offcial")) {
video_type = "sod"
} else if ([subject.match(/\(Prestige\)|\(MAXING\)/), document.body.innerHTML.indexOf("Prestige") != -1].some((e)=>e) && menu_value("menu_offcial")) {
video_type = "mgs"
} else if (subject.match(/\(AfestaVR\)/) && menu_value("menu_offcial")) {
video_type = "afesta"
} else {
video_type = "sod"
}
let is_vr = (subject.indexOf("【VR】") !== -1 || subject.indexOf("【8K VR】")!== -1) ? true: false
let pid = cover.replace("pl.jpg", ".jpg").replace("plzm.jpg", ".jpg").split("/").slice(-1)[0].split(".")[0]
let vid = subject.match(/\w+-\d+/)[0]
// SOD影片有可能在DMM, 番号格式类似: 1mogi00030
if (pid != vid && video_type == "sod") {
video_type = "dmm"
}
if (menu_value("menu_offcial") && pid.startsWith(`1`) == false) {
if (subject.match(/\(DAHLIA\)/)) {
video_type = "dahlia"
pid = pid.replace("-", "")
}
if (subject.match(/\(FALENO\)/) && document.body.innerHTML.indexOf("Prestige") === -1) {
video_type = "faleno"
pid = pid.replace("-", "")
}
}
if (is_vr & video_type == "sod" & vid.startsWith('3') == false) {
vid = `3${vid}`
}
if (pid.match(/\d{3}[A-Z]+-\d{3}/)) {
video_type = "mgs"
}
// MXGS-1341
const regex = /^MXGS-(\d{3,4})$/i;
const match = vid.match(regex);
if (match) {
const numberPart = match[1];
const paddedNumber = numberPart.padStart(5, '0');
vid = `mxgs${paddedNumber}`;
video_type = "dmm"
}
let multi_search = menu_value("menu_multi")
record_log(`浏览器: ${navigator.sayswho}`)
record_log(`插件版本: ${GM_info.script.version}`)
record_log(`标题: ${subject}`)
record_log(`地址: ${window.location.href}`)
record_log(`番号: ${pid}`)
record_log(`视频ID: ${vid}`)
let source;
let dmm = async() => {
if (!multi_search && (video_type !== "dmm" && !(video_type == "sod" && pid.includes("-"))) || !menu_value("menu_offcial")) {
record_log(`DMM Search: 跳过`)
throw new Error('DMM Search: 跳过');
}
let search_id = pid
if (pid.includes("-")) {
search_id = pid.split("-").join("00").toLowerCase()
}
record_log(`DMM Search: ${search_id}`)
let dmm_headers = {"accept-language": "ja-JP,ja;q=0.9"}
let dmm_cookie = "age_check_done=1"
//let dmm_cookie = GM_getValue("FANZA_Cookies") ? GM_getValue("FANZA_Cookies"): "age_check_done=1";
let search_request = {url: `https://www.dmm.co.jp/search/=/searchstr=${search_id}`, headers: dmm_headers}
let search_res = await gmFetch(search_request).catch(err => {record_log(err); return;})
let search_html = parseResponse(search_res.responseText)
let ele_detail = search_html.querySelector(`.tmb a[href*="${search_id}"][href^="https://www.dmm.co.jp"]`)
if (!ele_detail) {
record_log(`DMM Search: 未找到`);
throw new Error('DMM Search: 未找到');
}
let detail_url = ele_detail.getAttribute("href").split("?")[0]
record_log(`DMM Search: 详情页 ${detail_url}`)
let cid_pattern = /cid=(.*?\w)\//
let cid = cid_pattern.exec(detail_url)[1]
let detail_request = {url: detail_url, headers: dmm_headers, cookie: dmm_cookie}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll("#sample-image-block img")].map( item => item.getAttribute("src")).map( item => preview_src(item))
// 预览视频
let video = []
if (is_vr) {
let video_request = {url: `https://www.dmm.co.jp/digital/-/vr-sample-player/=/cid=${cid}/`, headers: dmm_headers, cookie: dmm_cookie}
let video_res = await gmFetch(video_request).catch(err => {record_log(err); return;});
let video_pattern = /var sampleUrl = "(.*)";/g;
let video_url = video_pattern.exec(video_res.responseText)[1]
if (video_url !== '') {
video.push({
src: video_url,
type: 'video/mp4',
label: `VR`,
res: `100`
})
}
} else {
// let video_request = {url: `https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${cid}/mtype=AhRVShI_/service=litevideo/mode=/width=560/height=360/`, headers: dmm_headers, cookie: dmm_cookie};
let video_request = {url: `https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid=${cid}`, headers: dmm_headers, cookie: dmm_cookie};
const video_label = {300: "流畅", 1000: "清晰", 1500: "高清", 2000: "高清", 3000: "HD", "4K (2160p)": "4K", "4K (2160p60)": "4K", "FullHD (1080p)": "1080p", "FullHD (1080p60)": "1080p", "HD (720p)": "720p", "HD (720p60)": "720p","高画質 (576p)": "576p", "中画質 (432p)": "432p", "中画質 (288p)": "288p", "低画質 (144p)": "144p"}
let video_res = await gmFetch(video_request).catch(err => {record_log(err); return;});
let video_pattern = /(const args = |const params = )({.+});$/gm;
if (video_res.responseText) {
let bitrates = JSON.parse(video_pattern.exec(video_res.responseText)[2]).bitrates
video = bitrates.map( function(item) {
return {
src: item.src,
type: 'video/mp4',
label: video_label[item.bitrate],
res: item.bitrate
}
})
}
}
return {imgs: imgs, video: video, source: "dmm"}
}
let dahlia = async() => {
if (!multi_search && video_type !== "dahlia" || !menu_value("menu_offcial")) {
record_log(`DAHLIA Search: 跳过`)
throw new Error('DAHLIA Search: 跳过');
}
let dahlia_cookie = "max-age=0"
let detail_url = `https://dahlia-av.jp/works/${pid}/`
record_log(`DAHLIA Search: 详情页 ${detail_url}`)
let detail_request = {url: detail_url, cookie: dahlia_cookie}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll(".box_works01_ga a")].map( item => item.getAttribute("href"))
// 预览视频
let video = []
let video_url = detail_html.querySelector(".overoll_box .pop_sample").getAttribute("href");
if (video_url !== '') {
video.push({
src: video_url,
type: 'video/mp4',
label: `DAHLIA`,
res: `100`
})
}
return {imgs: imgs, video: video, source: "dmm"}
}
let faleno = async() => {
if (!multi_search && video_type !== "faleno" || !menu_value("menu_offcial")) {
record_log(`FALENO Search: 跳过`)
throw new Error('FALENO Search: 跳过');
}
let faleno_cookie = "modal=off"
let detail_url = `https://faleno.jp/top/works/${pid}/`
record_log(`FALENO Search: 详情页 ${detail_url}`)
let detail_request = {url: detail_url, cookie: faleno_cookie}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll(".box_works01_ga a")].map( item => item.getAttribute("href"))
// 预览视频
let video = []
let video_url = detail_html.querySelector(".pop_sample").getAttribute("href");
if (video_url !== '') {
video.push({
src: video_url,
type: 'video/mp4',
label: `FALENO`,
res: `100`
})
}
return {imgs: imgs, video: video, source: "dmm"}
}
let mgstage = async() => {
if (!multi_search && video_type !== "mgs" || !menu_value("menu_offcial")) {
record_log(`MGSTAGE Search: 跳过`)
throw new Error('MGSTAGE Search: 跳过');
}
record_log(`MGSTAGE Search: ${pid}`)
let cookie = `adc=1`;
let detail_request = {url: `https://www.mgstage.com/product/product_detail/${pid}/`, cookie: cookie}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll(".sample_image")].map( item => item.getAttribute("href"))
// 预览视频
let video = []
let ele = detail_html.querySelector('div.detail_photo p.sample_movie_btn a:not([disabled])');
if (ele) {
let href = ele.getAttribute('href');
let pid = href.split('/').pop();
record_log(`MGSTAGE Search: 视频ID ${pid}`);
let video_request = {url: `https://www.mgstage.com/sampleplayer/sampleRespons.php?pid=${pid}`, cookie: cookie}
let video_res = await gmFetch(video_request).catch(err => {record_log(err); return;})
let re = /https.*?ism/
let json_obj = JSON.parse(video_res.responseText);
let video_url = json_obj.url;
video_url = re.exec(video_url)[0].replace('ism', 'mp4');
video.push({
src: video_url,
type: 'video/mp4',
label: `MGS`,
res: `100`
})
}
return {imgs: imgs, video: video, source: "mgs"}
}
let sod = async() => {
if (!multi_search && video_type !== "sod" || !menu_value("menu_offcial")) {
record_log(`SOD Search: 跳过`)
throw new Error('SOD Search: 跳过');
}
record_log(`SOD Search: ${vid}`)
let detail_request = {url: `https://ec.sod.co.jp/prime/videos/?id=${vid}`}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
let age_check = detail_html.querySelector(".pkg_age")
if (age_check) {
await gmFetch({url: `https://ec.sod.co.jp/prime/_ontime.php`}).catch(err => {record_log(err); return;})
detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
detail_html = parseResponse(detail_res.responseText)
}
// 预览图
let imgs = [...detail_html.querySelectorAll(".img-gallery a")].map( item => item.getAttribute("href"))
let imgs_blob = []
await asyncForEach(imgs, async (img) => {
const response = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "get",
url: img,
headers: {"referer": `https://ec.sod.co.jp/prime/videos/?id=${vid}`},
responseType: "blob",
onload: response => {resolve(response)},
onerror: response => {reject(response)},
});
});
//console.log("response:", response);
const {response: blob} = response;
console.log(blob);
imgs_blob.push(blob)
})
imgs = imgs_blob
// 预览视频
let video = []
let ele_video = detail_html.querySelector(".videos_sampb a");
if (ele_video) {
let video_url = `https://ec.sod.co.jp/prime/videos/${ele_video.getAttribute('href')}`;
video.push({
src: video_url,
type: 'video/mp4',
label: `SOD`,
res: `100`
})
let video_request = {url: video_url}
let video_res = await gmFetch(video_request).catch(err => {record_log(err); return;})
let video_html = parseResponse(video_res.responseText)
let video_src = video_html.querySelector("#moviebox source").getAttribute("src")
video.push({
src: `${video_src}?from=script`,
type: 'video/mp4',
label: `SOD`,
res: `100`
})
}
return {imgs: imgs, video: video, source: "sod"}
}
let afesta = async() => {
if (!multi_search && video_type !== "afesta" || !menu_value("menu_offcial")) {
record_log(`Afesta Search: 跳过`)
throw new Error('Afesta Search: 跳过');
}
record_log(`Afesta Search: ${pid}`)
const params = new URLSearchParams();
params.append("keyword", `${pid}`);
params.append("header", "search");
let search_request = {url: `https://www.afesta.tv/vr/search.php`, method: `POST`, data: `keyword=${pid}&header=search`, headers: {"Content-Type": "application/x-www-form-urlencoded"}}
let search_res = await gmFetch(search_request).catch(err => {record_log(err); return;})
let search_html = parseResponse(search_res.responseText)
let ele_detail = Array.from(search_html.querySelectorAll('.faces-list a')).find(el => el.querySelector(`img`).getAttribute(`data-src`).indexOf(pid) != -1)
if (!ele_detail) {
record_log(`Afesta Search: 未找到`);
throw new Error('Afesta Search: 未找到');
}
let detail_url = ele_detail.getAttribute("href")
record_log(`Afesta Search: 详情页 ${detail_url}`)
let detail_request = {url: detail_url}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll(`.thumbs-grid li a`)]
.map( item => item.getAttribute("href"))
.map( item => {
if (!item.startsWith(`http`)) {
return new URL(item, detail_url).href
} else {
return item
}})
// 预览视频
let video = []
return {imgs: imgs, video: video, source: "afesta"}
}
let javdb = async() => {
if (!menu_value("menu_JavDB") || menu_value("menu_offcial")) {
record_log(`JavDB Search: 跳过`)
throw new Error('JavDB Search: 跳过');
}
record_log(`JavDB Search: ${vid}`)
let cookie = `over18=1`;
let search_request = {url: `https://javdb.com/search?q=${vid}&f=all`, cookie: cookie}
let search_res = await gmFetch(search_request).catch(err => {record_log(err); return;})
let search_html = parseResponse(search_res.responseText)
let ele_detail = Array.from(search_html.querySelectorAll('.video-title strong')).find(el => el.textContent === vid)
if (!ele_detail) {
record_log(`JavDB Search: 未找到`);
throw new Error('JavDB Search: 未找到');
}
let detail_url = `https://javdb.com${ele_detail.closest("a").getAttribute("href")}`
let detail_request = {url: detail_url, cookie: cookie}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll(".preview-images a[class=tile-item]")].map( item => item.getAttribute("href"))
// 预览视频
let video = []
let ele_video = detail_html.querySelector(".preview-video-container")
if (ele_video) {
let video_src = ele_video.nextElementSibling.querySelector("source").getAttribute("src")
video.push({
src: video_src,
type: 'video/mp4',
label: `JavDB`,
res: `100`
})
}
return {imgs: imgs, video: video, source: "javdb"}
}
let javbus = async() => {
if (!menu_value("menu_JavBus") || menu_value("menu_offcial")) {
record_log(`JavBus Search: 跳过`)
throw new Error('JavBus Search: 跳过');
}
record_log(`JavBus Search: ${vid}`)
let detail_request = {url: `https://www.javbus.com/${vid}`}
let detail_res = await gmFetch(detail_request).catch(err => {record_log(err); return;})
let detail_html = parseResponse(detail_res.responseText)
// 预览图
let imgs = [...detail_html.querySelectorAll("#sample-waterfall a")]
.map( item => item.getAttribute("href"))
.map(function(item) {
if(item.startsWith("http")) {
return item
} else {
video_type="sod"
return `https://www.javbus.com${item}`
}
})
if (video_type==="sod") {
let imgs_blob = []
await asyncForEach(imgs, async (img) => {
const response = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "get",
url: img,
headers: {"referer": `https://www.javbus.com/${vid}`},
responseType: "blob",
onload: response => {resolve(response)},
onerror: response => {reject(response)},
});
});
//console.log("response:", response);
const {response: blob} = response;
imgs_blob.push(blob)
})
imgs = imgs_blob
}
// 预览视频
let video = []
return {imgs: imgs, video: video, source: "javbus"}
}
ga_inner.innerHTML = "正在搜索预览图..."
Promise.allSettled([dmm(),dahlia(),faleno(),mgstage(),sod(),afesta(),javdb(),javbus()]).then(results=>{
ga_inner.innerHTML = ""
results.forEach(r => {
if (r.status == "rejected" && r.reason.stack.indexOf("跳过") == -1) {
record_log(`Error Reason: ${r.reason.stack}`)
}
})
let p = results.find(result => result.status==="fulfilled")
if (p) {
source = p.value.source
let imgs = p.value.imgs
let video = p.value.video
if (imgs.length !== 0) {
imgs.forEach(insertImages)
}
if (video.length !==0) {
play_box.setAttribute("style", "display:inline-block");
if (source === "sod") {
if (menu_value("menu_jumpSOD")) {
video = video.slice(0,1)
outer_span.setAttribute("style", "display:block");
} else {
video = video.slice(1)
player.updateSrc(video)
}
} else {
player.updateSrc(video)
}
// 点击弹出播放器
play_box.onclick = function (e) {
e.preventDefault();
if (source === "sod" && menu_value("menu_jumpSOD")) {
GM_openInTab(video[0].src, {active : true})
} else {
video_player.setAttribute("style", "display:block");
$.fancybox.open({
src : '#x1080x-player',
type : 'inline',
opts : {
smallBtn: false,
touch: false,
afterShow : function( instance, current ) {
player.play();
},
afterClose : function( instance, current ) {
player.pause();
}
}
});
}
}
}
if (imgs.length === 0 && video.length === 0 ){
gallery_div.style.display = "none"
}
}
})
//$.fancybox.defaults.loop = "true";
})();