- 新网站 -feat:自定义需要默认显示的网站
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -22,3 +22,5 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# **/buckup
|
||||
123
dist/jop.user.js
vendored
123
dist/jop.user.js
vendored
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name JAV 添加跳转在线观看 三合一
|
||||
// @namespace https://greasyfork.org/zh-CN/scripts/429173
|
||||
// @version 1.1.0
|
||||
// @version 1.1.1
|
||||
// @author mission522
|
||||
// @description 在 JavDB、JavBus、JavLibrary 网站的影片详情页添加跳转在线播放按钮,并在按钮上标注是否支持在线播放、包含无码或包含字幕
|
||||
// @license MIT
|
||||
@@ -13,6 +13,7 @@
|
||||
// @require https://cdn.jsdelivr.net/npm/preact@10.11.0/dist/preact.min.js
|
||||
// @connect jable.tv
|
||||
// @connect missav.com
|
||||
// @connect supjav.com
|
||||
// @connect netflav.com
|
||||
// @connect avgle.com
|
||||
// @connect javhhh.com
|
||||
@@ -21,6 +22,7 @@
|
||||
// @connect jav.guru
|
||||
// @connect javmost.cx
|
||||
// @connect hayav.com
|
||||
// @connect avjoy.me
|
||||
// @connect javfc2.net
|
||||
// @connect paipancon.com
|
||||
// @connect ggjav.com
|
||||
@@ -28,10 +30,11 @@
|
||||
// @connect javbus.com
|
||||
// @connect javdb005.com
|
||||
// @grant GM_getValue
|
||||
// @grant GM_setValue
|
||||
// @grant GM_xmlhttpRequest
|
||||
// ==/UserScript==
|
||||
|
||||
(e=>{const o=document.createElement("style");o.dataset.source="vite-plugin-monkey",o.innerText=e,document.head.appendChild(o)})(".jopApp{box-sizing:border-box;display:flex;flex-wrap:wrap;justify-content:flex-start;gap:10px;width:100%;height:100%;z-index:1;background-color:#fff;transition:right .2s ease-in-out;font-family:Roboto,Helvetica,Arial,sans-serif;color:#000}.jop-button{position:relative;display:flex;align-items:center;justify-content:center;box-sizing:border-box;padding:3px 10px;border-radius:4px;font-weight:500;font-size:14px;border:1px solid #dcdfe6;color:#606266}.jop-button:visited{color:#606266}.jop-button:hover{text-decoration:none;color:#409eff;border:1px solid #c6e2ff;background-color:#ecf5ff}.jop-button_label{position:absolute;font-size:10px;padding:4px;border-radius:4px;top:-13px;right:-10px;line-height:.75;color:#67c23a;border:1px solid #e1f3d8;background:white}.jop-button_green{color:#fff!important;background-color:#67c23a}.jop-button_green:hover{color:#fff!important;background-color:#95d475}.jop-button_red{color:#fff!important;background-color:#f56c6c}.jop-button_red:hover{color:#fff!important;background-color:#f89898}.jop-loading{display:inline-block;width:14px;height:14px;margin-right:10px;border:2px dashed #dcdfe6;border-top-color:transparent;border-radius:100%;animation:btnLoading infinite 1s linear}@keyframes btnLoading{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.jop-tag{padding:3px 6px;color:#409eff!important;background:#ecf5ff;border:1px solid #d9ecff;border-radius:4px}.db-panel .movie-panel-info div.panel-block{padding:5.5px 12px}.db-panel .jopApp{padding:15px 12px}.lib-panel .jopApp{padding:20px 30px}");
|
||||
(t=>{const o=document.createElement("style");o.dataset.source="vite-plugin-monkey",o.innerText=t,document.head.appendChild(o)})(".jop-list{box-sizing:border-box;display:flex;flex-wrap:wrap;justify-content:flex-start;gap:10px;width:100%;height:100%;z-index:1;background-color:#fff;transition:right .2s ease-in-out;font-family:Roboto,Helvetica,Arial,sans-serif;color:#000}.jop-button,.jop-button_def{position:relative;display:flex;align-items:center;justify-content:center;box-sizing:border-box;padding:3px 10px;border-radius:4px;font-weight:500;font-size:14px;border:1px solid #dcdfe6;color:#606266;cursor:pointer}.jop-button_def{margin:10px 0;width:100px}.jop-button:visited{color:#606266}.jop-button:hover{text-decoration:none;color:#409eff;border:1px solid #c6e2ff;background-color:#ecf5ff}.jop-button_label{position:absolute;font-size:10px;padding:4px;border-radius:4px;top:-13px;right:-10px;line-height:.75;color:#67c23a;border:1px solid #e1f3d8;background:white}.jop-button_green{color:#fff!important;background-color:#67c23a}.jop-button_green:hover{color:#fff!important;background-color:#95d475}.jop-button_red{color:#fff!important;background-color:#f56c6c}.jop-button_red:hover{color:#fff!important;background-color:#f89898}.jop-loading{display:inline-block;width:14px;height:14px;margin-right:10px;border:2px dashed #dcdfe6;border-top-color:transparent;border-radius:100%;animation:btnLoading infinite 1s linear}@keyframes btnLoading{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.jop-tag{padding:3px 6px;color:#409eff!important;background:#ecf5ff;border:1px solid #d9ecff;border-radius:4px}.jop-setting-list{display:flex;flex-wrap:wrap;background-color:#fff}.jop-setting-title{margin:10px 0 5px}.jop-setting-item{display:flex;height:20px;justify-content:center;align-items:center;margin-right:15px}.db-panel .movie-panel-info div.panel-block{padding:5.5px 12px}.db-panel .jop-app{padding:15px 12px}.lib-panel .jop-app{padding:20px 30px;margin-top:10px}input[type=checkbox],input[type=radio]{margin:0 0 0 5px}");
|
||||
|
||||
(function(preact2, client) {
|
||||
"use strict";
|
||||
@@ -396,6 +399,18 @@
|
||||
},
|
||||
method: print
|
||||
},
|
||||
{
|
||||
name: "Supjav",
|
||||
disable: false,
|
||||
hostname: "supjav.com",
|
||||
url: "https://supjav.com/zh/?s={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: `.posts.clearfix>.post>a.img[title]`,
|
||||
titleQuery: `h3>a[rel="bookmark"][itemprop="url"]`
|
||||
},
|
||||
method: print
|
||||
},
|
||||
{
|
||||
name: "NETFLAV",
|
||||
disable: false,
|
||||
@@ -488,6 +503,18 @@
|
||||
domQuery: {},
|
||||
method: print
|
||||
},
|
||||
{
|
||||
name: "AvJoy",
|
||||
disable: false,
|
||||
hostname: "avjoy.me",
|
||||
url: "https://avjoy.me/search/video/{{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
titleQuery: `.content-info>.content-title`,
|
||||
linkQuery: `.content-row>a`
|
||||
},
|
||||
method: print
|
||||
},
|
||||
{
|
||||
name: "JAVFC2",
|
||||
disable: false,
|
||||
@@ -676,8 +703,9 @@
|
||||
isSuccess: "pedding",
|
||||
hasSubtitle: false,
|
||||
hasLeakage: false,
|
||||
targetLink: siteItem.url.replace("{{code}}", CODE)
|
||||
targetLink: ""
|
||||
});
|
||||
const link = siteItem.url.replace("{{code}}", CODE);
|
||||
const {
|
||||
isSuccess,
|
||||
hasSubtitle,
|
||||
@@ -685,20 +713,20 @@
|
||||
targetLink
|
||||
} = status;
|
||||
s(() => {
|
||||
xhr(siteItem, targetLink, CODE).then((res) => {
|
||||
xhr(siteItem, link, CODE).then((res) => {
|
||||
setStatus({
|
||||
isSuccess: res.isSuccess ? "fulfilled" : "rejected",
|
||||
hasSubtitle: res.hasSubtitle,
|
||||
hasLeakage: res.hasLeakage,
|
||||
targetLink
|
||||
targetLink: res.targetLink
|
||||
});
|
||||
});
|
||||
}, [xhr, siteItem, CODE, targetLink]);
|
||||
}, [xhr, siteItem, CODE, link]);
|
||||
const colorClass = isSuccess === "pedding" ? " " : isSuccess === "fulfilled" ? "jop-button_green " : "jop-button_red ";
|
||||
return o("a", {
|
||||
className: "jop-button " + colorClass,
|
||||
target: "_blank",
|
||||
href: targetLink,
|
||||
href: targetLink === "" ? link : targetLink,
|
||||
children: [(hasSubtitle || hasLeakage) && o("div", {
|
||||
className: "jop-button_label",
|
||||
children: [hasSubtitle && o("span", {
|
||||
@@ -711,17 +739,84 @@
|
||||
})]
|
||||
});
|
||||
});
|
||||
const Setting = ({
|
||||
sites,
|
||||
setSites,
|
||||
disable
|
||||
}) => {
|
||||
const [showSetting, setShowSetting] = y(false);
|
||||
return o(preact2.Fragment, {
|
||||
children: [!showSetting ? o("div", {
|
||||
className: "jop-button_def",
|
||||
onClick: (e2) => {
|
||||
setShowSetting(!showSetting);
|
||||
},
|
||||
children: "\u8BBE\u7F6E"
|
||||
}) : o("h4", {
|
||||
className: "jop-setting-title",
|
||||
children: "\u52FE\u9009\u9ED8\u8BA4\u663E\u793A\u7684\u7F51\u7AD9"
|
||||
}), showSetting && o(preact2.Fragment, {
|
||||
children: [o("div", {
|
||||
className: "jop-setting",
|
||||
children: o("div", {
|
||||
className: "jop-setting-list",
|
||||
children: sites.map((item, index) => o("div", {
|
||||
className: "jop-setting-item",
|
||||
children: [item.name, o("input", {
|
||||
type: "checkbox",
|
||||
className: "jop-setting-checkbox",
|
||||
checked: !disable.includes(item.name),
|
||||
onChange: (e2) => {
|
||||
var _a;
|
||||
const checked = (_a = e2.target) == null ? void 0 : _a.checked;
|
||||
sites[index].disable = !checked;
|
||||
}
|
||||
})]
|
||||
}))
|
||||
})
|
||||
}), o("div", {
|
||||
className: "jop-button_def",
|
||||
onClick: (e2) => {
|
||||
setShowSetting(!showSetting);
|
||||
const newDisable = sites.map((item) => {
|
||||
if (item.disable)
|
||||
return item.name;
|
||||
});
|
||||
client.GM_setValue("disable", newDisable);
|
||||
setSites([...sites]);
|
||||
},
|
||||
children: "\u4FDD\u5B58"
|
||||
})]
|
||||
})]
|
||||
});
|
||||
};
|
||||
const App = w(function({
|
||||
current,
|
||||
CODE
|
||||
}) {
|
||||
const gmSiteList = client.GM_getValue("gmSiteList", siteList);
|
||||
const siteListFilter = gmSiteList.filter((item) => item.disableHostname !== current.name && !item.disable);
|
||||
const disable = client.GM_getValue("disable", ["AvJoy", "baihuse", "AV01"]);
|
||||
const [sites, setSites] = y(siteList);
|
||||
const siteListFilter = sites.filter((item) => item.disableHostname !== current.name && !item.disable);
|
||||
let filter = [];
|
||||
disable.forEach((disItem) => {
|
||||
filter = siteListFilter.filter((jtem) => {
|
||||
return disItem !== jtem.name;
|
||||
});
|
||||
});
|
||||
return o(preact2.Fragment, {
|
||||
children: siteListFilter.map((item) => o(SiteButton, {
|
||||
siteItem: item,
|
||||
CODE
|
||||
}))
|
||||
children: [o("div", {
|
||||
class: "jop-list",
|
||||
children: filter.map((item) => o(SiteButton, {
|
||||
siteItem: item,
|
||||
CODE
|
||||
}))
|
||||
}), o("div", {
|
||||
children: o(Setting, {
|
||||
sites,
|
||||
setSites,
|
||||
disable
|
||||
})
|
||||
})]
|
||||
});
|
||||
});
|
||||
function main() {
|
||||
@@ -734,7 +829,7 @@
|
||||
if (panel === null)
|
||||
return;
|
||||
const app = document.createElement("div");
|
||||
app.classList.add("jopApp");
|
||||
app.classList.add("jop-app");
|
||||
panel.append(app);
|
||||
preact2.render(o(App, {
|
||||
current,
|
||||
|
||||
@@ -1,31 +1,36 @@
|
||||
import { memo } from "preact/compat";
|
||||
import { siteList } from "@/utils/siteList";
|
||||
import { memo, useState } from "preact/compat";
|
||||
import { SiteItem, siteList } from "@/utils/siteList";
|
||||
import { GM_getValue } from "$";
|
||||
import type { Current } from "@/utils/matchList";
|
||||
import SiteButton from "./SiteButton";
|
||||
|
||||
export type RenderSiteItem = {
|
||||
name: string;
|
||||
targetLink: string;
|
||||
status: {
|
||||
isSuccess: "pedding" | "rejected" | "fulfilled";
|
||||
hasSubtitle: boolean;
|
||||
hasLeakage: boolean;
|
||||
};
|
||||
};
|
||||
import { Setting } from "./Setting";
|
||||
|
||||
const App = memo(function ({ current, CODE }: { current: Current; CODE: string }) {
|
||||
const gmSiteList = GM_getValue("gmSiteList", siteList);
|
||||
/** 禁用 disable */
|
||||
const siteListFilter = gmSiteList.filter(
|
||||
const disable = GM_getValue<SiteItem["name"][]>("disable", ["AvJoy", "baihuse", "AV01"]);
|
||||
// sites 最原始的 siteList.json
|
||||
const [sites, setSites] = useState(siteList);
|
||||
/** 禁用 hostname */
|
||||
const siteListFilter = sites.filter(
|
||||
(item) => item.disableHostname !== current.name && !item.disable,
|
||||
);
|
||||
|
||||
let filter: SiteItem[] = [];
|
||||
disable.forEach((disItem) => {
|
||||
filter = siteListFilter.filter((jtem) => {
|
||||
return disItem !== jtem.name;
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{siteListFilter.map((item) => (
|
||||
<SiteButton siteItem={item} CODE={CODE} />
|
||||
))}
|
||||
<div class="jop-list">
|
||||
{filter.map((item) => (
|
||||
<SiteButton siteItem={item} CODE={CODE} />
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<Setting sites={sites} setSites={setSites} disable={disable} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
66
src/components/Setting.tsx
Normal file
66
src/components/Setting.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import { SiteItem } from "@/utils/siteList";
|
||||
import { StateUpdater, useState } from "preact/hooks";
|
||||
import { GM_setValue } from "vite-plugin-monkey/dist/client";
|
||||
|
||||
export const Setting = ({
|
||||
sites,
|
||||
setSites,
|
||||
disable,
|
||||
}: {
|
||||
sites: SiteItem[];
|
||||
setSites: StateUpdater<SiteItem[]>;
|
||||
disable: SiteItem["name"][];
|
||||
}) => {
|
||||
const [showSetting, setShowSetting] = useState(false);
|
||||
return (
|
||||
<>
|
||||
{!showSetting ? (
|
||||
<div
|
||||
className="jop-button_def"
|
||||
onClick={(e) => {
|
||||
setShowSetting(!showSetting);
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</div>
|
||||
) : (
|
||||
<h4 className="jop-setting-title">勾选默认显示的网站</h4>
|
||||
)}
|
||||
{showSetting && (
|
||||
<>
|
||||
<div className="jop-setting">
|
||||
<div className="jop-setting-list">
|
||||
{sites.map((item, index) => (
|
||||
<div className="jop-setting-item">
|
||||
{item.name}
|
||||
<input
|
||||
type="checkbox"
|
||||
className="jop-setting-checkbox"
|
||||
checked={!disable.includes(item.name)}
|
||||
onChange={(e: any) => {
|
||||
const checked: boolean = e.target?.checked;
|
||||
sites[index].disable = !checked;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="jop-button_def"
|
||||
onClick={(e) => {
|
||||
setShowSetting(!showSetting);
|
||||
const newDisable = sites.map((item) => {
|
||||
if (item.disable) return item.name;
|
||||
});
|
||||
GM_setValue("disable", newDisable);
|
||||
setSites([...sites]);
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import { SiteItem } from "@/utils/siteList";
|
||||
import xhr from "@/utils/xhr";
|
||||
import { memo, useEffect, useState } from "preact/compat";
|
||||
|
||||
interface Status {
|
||||
isSuccess: "pedding" | "rejected" | "fulfilled";
|
||||
hasSubtitle: boolean;
|
||||
@@ -14,20 +13,21 @@ const SiteButton = memo(({ siteItem, CODE }: { siteItem: SiteItem; CODE: string
|
||||
isSuccess: "pedding",
|
||||
hasSubtitle: false,
|
||||
hasLeakage: false,
|
||||
targetLink: siteItem.url.replace("{{code}}", CODE),
|
||||
targetLink: "",
|
||||
});
|
||||
const link = siteItem.url.replace("{{code}}", CODE);
|
||||
const { isSuccess, hasSubtitle, hasLeakage, targetLink } = status;
|
||||
|
||||
useEffect(() => {
|
||||
xhr(siteItem, targetLink, CODE).then((res) => {
|
||||
xhr(siteItem, link, CODE).then((res) => {
|
||||
setStatus({
|
||||
isSuccess: res.isSuccess ? "fulfilled" : "rejected",
|
||||
hasSubtitle: res.hasSubtitle,
|
||||
hasLeakage: res.hasLeakage,
|
||||
targetLink,
|
||||
targetLink: res.targetLink,
|
||||
});
|
||||
});
|
||||
}, [xhr, siteItem, CODE, targetLink]);
|
||||
}, [xhr, siteItem, CODE, link]);
|
||||
const colorClass =
|
||||
isSuccess === "pedding"
|
||||
? " "
|
||||
@@ -36,7 +36,11 @@ const SiteButton = memo(({ siteItem, CODE }: { siteItem: SiteItem; CODE: string
|
||||
: "jop-button_red ";
|
||||
|
||||
return (
|
||||
<a className={"jop-button " + colorClass} target="_blank" href={targetLink}>
|
||||
<a
|
||||
className={"jop-button " + colorClass}
|
||||
target="_blank"
|
||||
href={targetLink === "" ? link : targetLink}
|
||||
>
|
||||
{(hasSubtitle || hasLeakage) && (
|
||||
<div className="jop-button_label">
|
||||
{hasSubtitle && <span>字幕 </span>}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { StateUpdater } from "preact/hooks";
|
||||
import { GM_setValue } from "vite-plugin-monkey/dist/client";
|
||||
import { RenderSiteItem } from "./App";
|
||||
import { RenderSiteItem } from "../App";
|
||||
|
||||
export const ListSetting = ({
|
||||
siteLists,
|
||||
@@ -1,6 +1,6 @@
|
||||
import { GM_getValue, GM_setValue } from "$";
|
||||
import { StateUpdater, useState } from "preact/hooks";
|
||||
import { RenderSiteItem } from "./App";
|
||||
import { RenderSiteItem } from "../App";
|
||||
import { ListSetting } from "./ListSetting";
|
||||
|
||||
const Top = ({
|
||||
@@ -21,7 +21,7 @@ function main() {
|
||||
if (panel === null) return;
|
||||
|
||||
const app = document.createElement("div");
|
||||
app.classList.add("jopApp");
|
||||
app.classList.add("jop-app");
|
||||
panel.append(app);
|
||||
|
||||
render(<App current={current} CODE={CODE} />, app);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* */
|
||||
.jopApp {
|
||||
.jop-list {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -15,8 +15,8 @@
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
.jop-button {
|
||||
.jop-button,
|
||||
.jop-button_def {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -29,6 +29,11 @@
|
||||
font-size: 14px;
|
||||
border: 1px solid #dcdfe6;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
.jop-button_def {
|
||||
margin: 10px 0;
|
||||
width: 100px;
|
||||
}
|
||||
.jop-button:visited {
|
||||
color: #606266;
|
||||
@@ -101,17 +106,44 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* */
|
||||
.jop-setting-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: white;
|
||||
}
|
||||
.jop-setting-title {
|
||||
margin: 10px 0 5px 0;
|
||||
}
|
||||
.jop-setting-item {
|
||||
display: flex;
|
||||
height: 20px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 15px;
|
||||
}
|
||||
/* */
|
||||
|
||||
/* db */
|
||||
.db-panel .movie-panel-info div.panel-block {
|
||||
padding: 5.5px 12px;
|
||||
}
|
||||
.db-panel .jopApp {
|
||||
.db-panel .jop-app {
|
||||
padding: 15px 12px;
|
||||
}
|
||||
/* */
|
||||
|
||||
/* lib */
|
||||
.lib-panel .jopApp {
|
||||
.lib-panel .jop-app {
|
||||
padding: 20px 30px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
/* */
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
/* */
|
||||
|
||||
@@ -5,8 +5,6 @@ export interface DomQuery_parser {
|
||||
spaceCode?: boolean;
|
||||
linkQuery: string;
|
||||
titleQuery: string;
|
||||
/** 确定返回颜色,暂未启用 */
|
||||
certainColor?: string;
|
||||
}
|
||||
|
||||
export interface DomQuery_get {
|
||||
@@ -18,8 +16,9 @@ export interface DomQuery_get {
|
||||
|
||||
interface SiteItemBase {
|
||||
name: string;
|
||||
/** 针对 matchList 的 hostname */
|
||||
/** 用户定义的 disable */
|
||||
disable: boolean;
|
||||
/** 针对 matchList 的 hostname */
|
||||
disableHostname?: string;
|
||||
hostname: string;
|
||||
url: string;
|
||||
@@ -68,13 +67,29 @@ export const siteList: SiteItem[] = [
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
// 有可能搜出仨:leakage subtitle 4k
|
||||
name: "Supjav",
|
||||
disable: false,
|
||||
hostname: "supjav.com",
|
||||
url: "https://supjav.com/zh/?s={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
linkQuery: `.posts.clearfix>.post>a.img[title]`,
|
||||
titleQuery: `h3>a[rel="bookmark"][itemprop="url"]`,
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "NETFLAV",
|
||||
disable: false,
|
||||
hostname: "netflav.com",
|
||||
url: "https://netflav.com/search?type=title&keyword={{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: { linkQuery: ".grid_cell>a", titleQuery: ".grid_cell>a>.grid_title" },
|
||||
domQuery: {
|
||||
linkQuery: ".grid_cell>a",
|
||||
titleQuery: ".grid_cell>a>.grid_title",
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
@@ -148,10 +163,23 @@ export const siteList: SiteItem[] = [
|
||||
hostname: "hayav.com",
|
||||
url: "https://hayav.com/video/{{code}}/",
|
||||
fetcher: "get",
|
||||
domQuery: {},
|
||||
domQuery: {
|
||||
// subQuery: `.site__col>.entry-header>h1.entry-title`,
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
{
|
||||
name: "AvJoy",
|
||||
disable: false,
|
||||
hostname: "avjoy.me",
|
||||
url: "https://avjoy.me/search/video/{{code}}",
|
||||
fetcher: "parser",
|
||||
domQuery: {
|
||||
titleQuery: `.content-info>.content-title`,
|
||||
linkQuery: `.content-row>a`,
|
||||
},
|
||||
method: print,
|
||||
},
|
||||
|
||||
{
|
||||
name: "JAVFC2",
|
||||
disable: false,
|
||||
|
||||
120
src/utils/xhr.ts
120
src/utils/xhr.ts
@@ -19,7 +19,6 @@ function videoPageParser(responseText: string, { subQuery, leakQuery, videoQuery
|
||||
// 部分网站收录视频,但是未提供播放资源,所以需要使用 videoQuery 进一步检测是否存在在线播放
|
||||
/** videoQuery 为 undefine 时,不需要查找 video */
|
||||
const videoNode = videoQuery ? doc.querySelector<HTMLElement>(videoQuery) : true;
|
||||
|
||||
return {
|
||||
isSuccess: !!videoNode,
|
||||
hasSubtitle: subNodeText.includes("字幕") || subNodeText.includes("subtitle"),
|
||||
@@ -122,67 +121,68 @@ async function xhr(siteItem: SiteItem, targetLink: string, CODE: string) {
|
||||
});
|
||||
return xhrPromise;
|
||||
}
|
||||
export default xhr;
|
||||
|
||||
/** 获取 javdb 的分数
|
||||
* 没用了,白写
|
||||
*/
|
||||
export function getDbScore(url: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
GM_xmlhttpRequest({
|
||||
method: "GET",
|
||||
url,
|
||||
onload: (response) => {
|
||||
const doc = new DOMParser().parseFromString(response.responseText, "text/html");
|
||||
const plist = doc.querySelector<HTMLElement>(`.panel.movie-panel-info`);
|
||||
const innerHtml = plist?.innerHTML;
|
||||
const matchResult = innerHtml?.match(/\d\.\d分/);
|
||||
if (!innerHtml || !matchResult) {
|
||||
reject("无评分");
|
||||
return;
|
||||
} else {
|
||||
resolve(matchResult[0]);
|
||||
}
|
||||
},
|
||||
onerror(error) {
|
||||
reject(error);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
// export function getDbScore(url: string): Promise<string> {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// GM_xmlhttpRequest({
|
||||
// method: "GET",
|
||||
// url,
|
||||
// onload: (response) => {
|
||||
// const doc = new DOMParser().parseFromString(response.responseText, "text/html");
|
||||
// const plist = doc.querySelector<HTMLElement>(`.panel.movie-panel-info`);
|
||||
// const innerHtml = plist?.innerHTML;
|
||||
// const matchResult = innerHtml?.match(/\d\.\d分/);
|
||||
// if (!innerHtml || !matchResult) {
|
||||
// reject("无评分");
|
||||
// return;
|
||||
// } else {
|
||||
// resolve(matchResult[0]);
|
||||
// }
|
||||
// },
|
||||
// onerror(error) {
|
||||
// reject(error);
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
interface dbResult {
|
||||
score: string;
|
||||
release: string;
|
||||
}
|
||||
export function parserJavdb(code?: string): Promise<dbResult> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!code) reject("没找到");
|
||||
GM_xmlhttpRequest({
|
||||
url: `https://javdb005.com/search?q=${code}`,
|
||||
method: "GET",
|
||||
onload: (response) => {
|
||||
const doc = new DOMParser().parseFromString(response.responseText, "text/html");
|
||||
const firstItem = doc.querySelectorAll<HTMLElement>(`.movie-list>.item`)[0];
|
||||
const titleString = firstItem.querySelector<HTMLElement>(`.video-title>strong`)?.innerHTML;
|
||||
const releaseString = firstItem.querySelector<HTMLElement>(`.meta`)?.innerHTML.trim();
|
||||
if (titleString !== code || !releaseString) {
|
||||
reject("没找到");
|
||||
} else {
|
||||
const fullScoreText = firstItem.querySelector<HTMLElement>(`.score .value`)?.innerHTML;
|
||||
const matchResult = fullScoreText?.match(/\d\.\d*分/);
|
||||
if (!matchResult) reject("没找到");
|
||||
else
|
||||
resolve({
|
||||
// score: matchResult[0],
|
||||
score: matchResult[0].replace("分", ""),
|
||||
release: releaseString,
|
||||
});
|
||||
}
|
||||
},
|
||||
onerror(error) {
|
||||
reject(error);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
export default xhr;
|
||||
// interface dbResult {
|
||||
// score: string;
|
||||
// release: string;
|
||||
// }
|
||||
/** 没用了,白写 */
|
||||
// export function parserJavdb(code?: string): Promise<dbResult> {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// if (!code) reject("没找到");
|
||||
// GM_xmlhttpRequest({
|
||||
// url: `https://javdb005.com/search?q=${code}`,
|
||||
// method: "GET",
|
||||
// onload: (response) => {
|
||||
// const doc = new DOMParser().parseFromString(response.responseText, "text/html");
|
||||
// const firstItem = doc.querySelectorAll<HTMLElement>(`.movie-list>.item`)[0];
|
||||
// const titleString = firstItem.querySelector<HTMLElement>(`.video-title>strong`)?.innerHTML;
|
||||
// const releaseString = firstItem.querySelector<HTMLElement>(`.meta`)?.innerHTML.trim();
|
||||
// if (titleString !== code || !releaseString) {
|
||||
// reject("没找到");
|
||||
// } else {
|
||||
// const fullScoreText = firstItem.querySelector<HTMLElement>(`.score .value`)?.innerHTML;
|
||||
// const matchResult = fullScoreText?.match(/\d\.\d*分/);
|
||||
// if (!matchResult) reject("没找到");
|
||||
// else
|
||||
// resolve({
|
||||
// // score: matchResult[0],
|
||||
// score: matchResult[0].replace("分", ""),
|
||||
// release: releaseString,
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// onerror(error) {
|
||||
// reject(error);
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
@@ -18,5 +18,6 @@
|
||||
"paths": { "@/*": ["./src/*"] }
|
||||
},
|
||||
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
|
||||
"exclude": ["**/backup"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const connectList = siteList.map((site) => site.hostname).concat(["javdb005.com"
|
||||
|
||||
const UserscriptConfig: MonkeyUserScript = {
|
||||
author: "mission522",
|
||||
version: "1.1.0",
|
||||
version: "1.1.1",
|
||||
license: "MIT",
|
||||
name: "JAV 添加跳转在线观看 三合一",
|
||||
match: ["*://*/cn/?v=jav*"],
|
||||
|
||||
Reference in New Issue
Block a user