Last active
February 26, 2025 06:16
-
-
Save engalar/50f742215c2e96efb54ab4e2d177181e to your computer and use it in GitHub Desktop.
tampermonkey
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Notion | |
// @namespace http://tampermonkey.net/ | |
// @version 1.2.1 | |
// @description try to take over the world! | |
// @author You | |
// @match https://www.notion.so/* | |
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | |
// @grant GM_xmlhttpRequest | |
// @grant GM_notification | |
// @grant GM_log | |
// @require https://gist.githubusercontent.com/engalar/50f742215c2e96efb54ab4e2d177181e/raw/util.js | |
// @downloadURL https://gist.githubusercontent.com/engalar/50f742215c2e96efb54ab4e2d177181e/raw/notion.user.js | |
// @updateURL https://gist.githubusercontent.com/engalar/50f742215c2e96efb54ab4e2d177181e/raw/notion.user.js | |
// @grant GM_addStyle | |
// @grant GM_getResourceText | |
// @grant GM_getResourceURL | |
// @grant GM_addElement | |
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/codemirror.min.js | |
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/addon/fold/foldgutter.js | |
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/addon/fold/foldcode.js | |
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/addon/fold/brace-fold.js | |
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/mode/javascript/javascript.min.js | |
// @resource foldgutter_css https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/addon/fold/foldgutter.min.css | |
// @resource codemirror_css https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/codemirror.min.css | |
// @resource sweetalert2 https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css | |
// @resource sweetalert2js https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.js | |
// ==/UserScript== | |
//https://gist.github.com/engalar/50f742215c2e96efb54ab4e2d177181e/edit | |
(function() { | |
'use strict'; | |
// 配置常量 | |
const NEO4J_CONFIG = { | |
url: 'http://localhost:7474/db/neo4j/tx/commit', | |
auth: { | |
username: 'neo4j', | |
password: 'password' | |
} | |
}; | |
const blockSelector = ".layout-content .notion-code-block.notion-selectable"; | |
const CAPTION_PREFIX = 'cypher-'; | |
// 按顺序加载 JS 文件 | |
const jsResources = [ | |
/* 'codemirror_js', | |
'foldgutter_js', | |
'foldcode_js', | |
'brace_fold_js', */ | |
'sweetalert2js' | |
]; | |
jsResources.forEach(res => { | |
GM_addElement('script', { | |
textContent: GM_getResourceText(res) | |
}); | |
}); | |
// 加载 SweetAlert2 的 CSS 和 JS | |
GM_addStyle(GM_getResourceText('sweetalert2')); | |
GM_addStyle(` | |
.CodeMirror-vscrollbar { | |
scrollbar-color: rgb(50 25 25 / 20%) rgba(0, 0, 0, 0); | |
} | |
.swal2-popup{ | |
height: 80%; | |
} | |
`); | |
// 加载 CodeMirror 样式 | |
GM_addStyle(GM_getResourceText('codemirror_css')); | |
// 添加折叠样式 | |
GM_addStyle(GM_getResourceText('foldgutter_css')); | |
// 工具函数 | |
const generateAuthHeader = ({username, password}) => | |
`Basic ${btoa(`${username}:${password}`)}`; | |
function processText(input) { | |
return input.split('\n') | |
.map(line => line.split('//')[0].trim()) | |
.filter(line => line !== '') | |
.join('\n') | |
.split(';') | |
.map(s => s.trim()) | |
.filter(s => s !== ''); | |
} | |
// DOM操作相关函数 | |
function createButton(lang) { | |
const button = document.createElement("div"); | |
button.setAttribute("role", "button"); | |
button.setAttribute("tabindex", "0"); | |
button.setAttribute("aria-expanded", "false"); | |
Object.assign(button.style, { | |
userSelect: 'none', | |
transition: 'background 20ms ease-in', | |
cursor: 'pointer', | |
display: 'inline-flex', | |
alignItems: 'center', | |
whiteSpace: 'nowrap', | |
height: '20px', | |
borderRadius: '4px', | |
fontSize: '12px', | |
lineHeight: '1.2', | |
paddingLeft: '5px', | |
paddingRight: '5px', | |
color: 'rgba(255, 255, 255, 0.443)', | |
marginRight: '5px' | |
}); | |
button.textContent = `处理${lang}`; | |
// 添加hover效果 | |
button.addEventListener("mouseover", () => | |
button.style.background = "rgba(255, 255, 255, 0.055)"); | |
button.addEventListener("mouseout", () => | |
button.style.background = "transparent"); | |
return button; | |
} | |
// 内容提取函数 | |
function extractCodeContent(block, lang) { | |
const tokenContainer = block.children[0].children[0].children[2]; | |
return lang=='Plain Text'? tokenContainer.innerText: Array.from(tokenContainer.querySelectorAll('.token')) | |
.map(t => t.innerText) | |
.join('') | |
.trim(); | |
} | |
// 关联块查找逻辑 | |
function findAssociatedBlock(currentBlock, targetLang) { | |
const caption = currentBlock.querySelector('.notion-block-caption')?.innerText.split('\n')[0]; | |
if (!caption?.startsWith(CAPTION_PREFIX)) return null; | |
const allBlocks = document.querySelectorAll(blockSelector); | |
for (const block of allBlocks) { | |
if (block === currentBlock) continue; | |
const blockCaption = block.querySelector('.notion-block-caption')?.innerText.split('\n')[0]; | |
const blockLang = block.children[0].children[0].children[0].children[0].children[0].childNodes[0].textContent; | |
if (blockCaption === caption && blockLang === targetLang) { | |
return block; | |
} | |
} | |
return null; | |
} | |
function showJsonDialog(jsonData) { | |
// 创建容器 | |
const container = document.createElement('div'); | |
container.style.minHeight = '400px'; | |
// 初始化 CodeMirror | |
const editor = CodeMirror(container, { | |
value: JSON.stringify(jsonData, null, 2), | |
mode: { name: 'javascript', json: true }, | |
lineNumbers: true, | |
foldGutter: true, // 启用折叠槽 | |
gutters: [ | |
"CodeMirror-linenumbers", | |
"CodeMirror-foldgutter" // 添加折叠槽 | |
], | |
readOnly: true, | |
lineWrapping: true, | |
viewportMargin: Infinity, | |
}); | |
// 显示对话框 | |
Swal.fire({ | |
title: 'neo4j result', | |
html: container, | |
width: '80%', | |
didOpen: () => { | |
editor.refresh(); | |
// 强制左对齐内容 | |
editor.setSize('100%', '80vh'); | |
const wrapper = editor.getWrapperElement(); | |
wrapper.style.margin = '0 auto'; | |
wrapper.style.textAlign = 'left'; | |
} | |
}); | |
} | |
// 点击处理核心逻辑 | |
async function handleButtonClick(codeBlock) { | |
const blockLang = codeBlock.children[0].children[0].children[0].children[0].children[0].childNodes[0].textContent; | |
let cypherBlock, parameters; | |
if (blockLang === 'JSON') { | |
// 参数块处理逻辑 | |
cypherBlock = findAssociatedBlock(codeBlock, 'Plain Text'); | |
if (!cypherBlock) { | |
GM_notification({ text: "未找到关联的Cypher语句块", timeout: 2000 }); | |
return; | |
} | |
parameters = JSON.parse(extractCodeContent(codeBlock, 'JSON')); | |
} else { | |
// Cypher语句块处理逻辑 | |
cypherBlock = codeBlock; | |
parameters = {}; | |
} | |
const cypher = extractCodeContent(cypherBlock, 'Plain Text'); | |
if (!cypher) { | |
GM_notification({ text: "Cypher语句不能为空", timeout: 2000 }); | |
return; | |
} | |
try { | |
const response = await util.req({ | |
method: 'POST', | |
url: NEO4J_CONFIG.url, | |
headers: { | |
'Authorization': generateAuthHeader(NEO4J_CONFIG.auth), | |
'Content-Type': 'application/json' | |
}, | |
data: JSON.stringify({ | |
statements: processText(cypher).map(query => ({ | |
statement: query, | |
resultDataContents: [/*"row", */"graph"], | |
parameters | |
})) | |
}) | |
}); | |
const data = JSON.parse(response.response); | |
if (data.errors.length > 0) { | |
GM_notification({ | |
text: `执行失败: ${data.errors[0].message}`, | |
timeout: 3000 | |
}); | |
} else { | |
GM_notification({ | |
text: `成功执行 ${data.results.length} 条语句`, | |
timeout: 2000 | |
}); | |
} | |
showJsonDialog(data); | |
} catch (e) { | |
GM_notification({ | |
text: `请求失败: ${e.message}`, | |
timeout: 3000 | |
}); | |
} | |
} | |
// 主流程:初始化代码块 | |
function initCodeBlock(codeBlock) { | |
if(codeBlock.__neo4j) return; | |
const lang = codeBlock.children[0].children[0].children[0].children[0].children[0].childNodes[0].textContent; | |
// 仅处理带特定前缀的代码块 | |
const caption = codeBlock.querySelector('.notion-block-caption')?.innerText.split('\n')[0]; | |
if (lang!='Plain Text'&&!caption?.startsWith(CAPTION_PREFIX)) return; | |
// 仅处理Plain Text和JSON类型的块 | |
if (!['Plain Text', 'JSON'].includes(lang)) return; | |
// 创建并添加按钮 | |
const toolContainer = codeBlock.children[0].children[0].children[0].children[0]; | |
const button = createButton(lang); | |
button.addEventListener('click', () => handleButtonClick(codeBlock)); | |
toolContainer.appendChild(button); | |
codeBlock.__neo4j = true; | |
} | |
// 初始加载处理 | |
util.findTargetElements(blockSelector).then(codeBlocks => { | |
codeBlocks.forEach(initCodeBlock); | |
}); | |
setInterval(() => { | |
util.findTargetElements(blockSelector).then(codeBlocks => { | |
codeBlocks.forEach(initCodeBlock); | |
}); | |
}, 2000); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bundle.js | |
(function (global) { | |
const util = (function () { | |
function observeElementInsertion(selector, callback, targetElement = document) { | |
const observer = new MutationObserver((mutations) => { | |
mutations.forEach((mutation) => { | |
if (mutation.addedNodes.length > 0) { | |
Array.from(mutation.addedNodes).forEach((node) => { | |
if (node.nodeType === Node.ELEMENT_NODE && node.matches(selector)) { | |
callback(node); | |
} | |
}); | |
} | |
}); | |
}); | |
observer.observe(targetElement, { | |
childList: true, | |
subtree: true | |
}); | |
return observer; | |
} | |
// 查找单个目标元素 | |
function findTargetElement(targetContainer) { | |
const body = window.document; | |
let tabContainer; | |
let tryTime = 0; | |
const maxTryTime = 120; | |
let startTimestamp; | |
return new Promise((resolve, reject) => { | |
function tryFindElement(timestamp) { | |
if (!startTimestamp) { | |
startTimestamp = timestamp; | |
} | |
const elapsedTime = timestamp - startTimestamp; | |
if (elapsedTime >= 500) { | |
GM_log("查找元素:" + targetContainer + ",第" + tryTime + "次"); | |
tabContainer = body.querySelector(targetContainer); | |
if (tabContainer) { | |
resolve(tabContainer); | |
} else if (++tryTime === maxTryTime) { | |
reject(); | |
} else { | |
startTimestamp = timestamp; | |
} | |
} | |
if (!tabContainer && tryTime < maxTryTime) { | |
requestAnimationFrame(tryFindElement); | |
} | |
} | |
requestAnimationFrame(tryFindElement); | |
}); | |
} | |
// 新增:查找所有匹配的目标元素 | |
function findTargetElements(targetContainer) { | |
const body = window.document; | |
let elements = []; | |
let tryTime = 0; | |
const maxTryTime = 120; | |
let startTimestamp; | |
return new Promise((resolve, reject) => { | |
function tryFindElements(timestamp) { | |
if (!startTimestamp) { | |
startTimestamp = timestamp; | |
} | |
const elapsedTime = timestamp - startTimestamp; | |
if (elapsedTime >= 500) { | |
GM_log("查找元素:" + targetContainer + ",第" + tryTime + "次"); | |
elements = Array.from(body.querySelectorAll(targetContainer)); | |
if (elements.length > 0) { | |
resolve(elements); | |
} else if (++tryTime === maxTryTime) { | |
reject(); | |
} else { | |
startTimestamp = timestamp; | |
} | |
} | |
if (elements.length === 0 && tryTime < maxTryTime) { | |
requestAnimationFrame(tryFindElements); | |
} | |
} | |
requestAnimationFrame(tryFindElements); | |
}); | |
} | |
function urlChangeReload() { | |
const oldHref = window.location.href; | |
let interval = setInterval(() => { | |
let newHref = window.location.href; | |
if (oldHref !== newHref) { | |
clearInterval(interval); | |
window.location.reload(); | |
} | |
}, 500); | |
} | |
function reomveVideo() { | |
setInterval(() => { | |
for (let video of document.getElementsByTagName("video")) { | |
if (video.src) { | |
video.removeAttribute("src"); | |
video.muted = true; | |
video.load(); | |
video.pause(); | |
} | |
} | |
}, 500); | |
} | |
function syncRequest(option) { | |
return new Promise((resolve, reject) => { | |
option.onload = (res) => { | |
resolve(res); | |
}; | |
option.onerror = (err) => { | |
reject(err); | |
}; | |
GM_xmlhttpRequest(option); | |
}); | |
} | |
return { | |
req: (option) => syncRequest(option), | |
findTargetEle: (targetEle) => findTargetElement(targetEle), | |
findTargetElements: (targetEle) => findTargetElements(targetEle), // 新增 | |
urlChangeReload: () => urlChangeReload(), | |
observeElementInsertion, | |
reomveVideo: () => reomveVideo() | |
} | |
})(); | |
// 将util对象添加到全局对象中 | |
global.util = util; | |
})(window); // 将全局对象设置为window |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name 少废话 - 全网VIP视频免费看 | |
// @namespace http://tampermonkey.net/ | |
// @version 4.1.1 | |
// @description 少废话 - 全网VIP视频免费看。支持:所有主流视频网站; | |
// @author sfh | |
// @match *://*.youku.com/* | |
// @match *://*.iqiyi.com/* | |
// @match *://*.iq.com/* | |
// @match *://*.le.com/* | |
// @match *://v.qq.com/* | |
// @match *://m.v.qq.com/*Q | |
// @match *://*.tudou.com/* | |
// @match *://*.mgtv.com/* | |
// @match *://tv.sohu.com/* | |
// @match *://film.sohu.com/* | |
// @match *://*.1905.com/* | |
// @match *://*.bilibili.com/* | |
// @match *://*.pptv.com/* | |
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js | |
// @grant unsafeWindow | |
// @grant GM_addStyle | |
// @grant GM_openInTab | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_xmlhttpRequest | |
// @grant GM_log | |
// @grant GM_notification | |
// @license gpl-3.0 | |
// @downloadURL https://gist.githubusercontent.com/engalar/50f742215c2e96efb54ab4e2d177181e/raw/video.user.js | |
// @updateURL https://gist.githubusercontent.com/engalar/50f742215c2e96efb54ab4e2d177181e/raw/video.user.js | |
// ==/UserScript== | |
const util = (function () { | |
function findTargetElement(targetContainer) { | |
const body = window.document; | |
let tabContainer; | |
let tryTime = 0; | |
const maxTryTime = 120; | |
let startTimestamp; | |
return new Promise((resolve, reject) => { | |
function tryFindElement(timestamp) { | |
if (!startTimestamp) { | |
startTimestamp = timestamp; | |
} | |
const elapsedTime = timestamp - startTimestamp; | |
if (elapsedTime >= 500) { | |
GM_log("查找元素:" + targetContainer + ",第" + tryTime + "次"); | |
tabContainer = body.querySelector(targetContainer); | |
if (tabContainer) { | |
resolve(tabContainer); | |
} else if (++tryTime === maxTryTime) { | |
reject(); | |
} else { | |
startTimestamp = timestamp; | |
} | |
} | |
if (!tabContainer && tryTime < maxTryTime) { | |
requestAnimationFrame(tryFindElement); | |
} | |
} | |
requestAnimationFrame(tryFindElement); | |
}); | |
} | |
function urlChangeReload() { | |
const oldHref = window.location.href; | |
let interval = setInterval(() => { | |
let newHref = window.location.href; | |
if (oldHref !== newHref) { | |
clearInterval(interval); | |
window.location.reload(); | |
} | |
}, 500); | |
} | |
function reomveVideo() { | |
setInterval(() => { | |
for (let video of document.getElementsByTagName("video")) { | |
if (video.src) { | |
video.removeAttribute("src"); | |
video.muted = true; | |
video.load(); | |
video.pause(); | |
} | |
} | |
}, 500); | |
} | |
function syncRequest(option) { | |
return new Promise((resolve, reject) => { | |
option.onload = (res) => { | |
resolve(res); | |
}; | |
option.onerror = (err) => { | |
reject(err); | |
}; | |
GM_xmlhttpRequest(option); | |
}); | |
} | |
return { | |
req: (option) => syncRequest(option), | |
findTargetEle: (targetEle) => findTargetElement(targetEle), | |
urlChangeReload: () => urlChangeReload(), | |
reomveVideo: () => reomveVideo() | |
} | |
})(); | |
const superVip = (function () { | |
const _CONFIG_ = { | |
isMobile: navigator.userAgent.match(/(Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini)/i), | |
currentPlayerNode: null, | |
vipBoxId: 'vip_jx_box' + Math.ceil(Math.random() * 100000000), | |
flag: "flag_vip", | |
autoPlayerKey: "auto_player_key" + window.location.host, | |
autoPlayerVal: "auto_player_value_" + window.location.host, | |
videoParseList: [ | |
{ | |
"name": "👍虾米", | |
"type": "1,2", | |
"url": "https://jx.xmflv.com/?url=" | |
}, | |
{ | |
"name": "👍m1907", | |
"type": "1,2", | |
"url": "https://im1907.top/?jx=" | |
}, | |
{ | |
"name": "👍yparse", | |
"type": "1,2", | |
"url": "https://jx.yparse.com/index.php?url=" | |
}, | |
{ | |
"name": "YT", | |
"type": "1,3", | |
"url": "https://jx.yangtu.top/?url=" | |
}, | |
{ | |
"name": "Player-JY", | |
"type": "1,3", | |
"url": "https://jx.playerjy.com/?url=" | |
}, | |
{ | |
"name": "剖元", | |
"type": "1,3", | |
"url": "https://www.pouyun.com/?url=" | |
}, | |
{ | |
"name": "冰豆", | |
"type": "1,3", | |
"url": "https://bd.jx.cn/?url=" | |
}, | |
], | |
playerContainers: [ | |
{ | |
host: "v.qq.com", | |
container: "#mod_player,#player-container,.container-player", | |
name: "QQ", | |
displayNodes: ["#mask_layer", ".mod_vip_popup", "#mask_layer", ".panel-tip-pay", ".txp_videos_container", ".preview-mini-player"] | |
}, | |
{ | |
host: "m.v.qq.com", | |
container: ".mod_player,#player", | |
name: "Default", | |
displayNodes: [".mod_vip_popup", "[class^=app_],[class^=app-],[class*=_app_],[class*=-app-],[class$=_app],[class$=-app]", "div[dt-eid=open_app_bottom]", "div.video_function.video_function_new", "a[open-app]", "section.mod_source", "section.mod_box.mod_sideslip_h.mod_multi_figures_h,section.mod_sideslip_privileges,section.mod_game_rec", ".at-app-banner"] | |
}, | |
{ | |
host: "w.mgtv.com", | |
container: "#mgtv-player-wrap", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "www.mgtv.com", | |
container: "#mgtv-player-wrap", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "m.mgtv.com", | |
container: ".video-area", | |
name: "Default", | |
displayNodes: ["div[class^=mg-app]", ".video-area-bar", ".open-app-popup"] | |
}, | |
{ | |
host: "www.bilibili.com", | |
container: "#player_module,#bilibiliPlayer,#bilibili-player", | |
name: "Bilibili", | |
displayNodes: [] | |
}, | |
{ | |
host: "m.bilibili.com", | |
container: ".player-wrapper,.player-container,.mplayer", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "www.iqiyi.com", | |
container: "#flashbox", | |
name: "Default", | |
displayNodes: ["#playerPopup", "div[class^=qy-header-login-pop]", "section[class^=modal-cover_]", ".toast"] | |
}, | |
{ | |
host: "m.iqiyi.com", | |
container: ".m-video-player-wrap", | |
name: "Default", | |
displayNodes: ["div.m-iqyGuide-layer", "a[down-app-android-url]", "[name=m-extendBar]", "[class*=ChannelHomeBanner]", "section.m-hotWords-bottom"] | |
}, | |
{ | |
host: "www.iq.com", | |
container: ".intl-video-wrap", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "v.youku.com", | |
container: "#player", | |
name: "Default", | |
displayNodes: ["#iframaWrapper", "#checkout_counter_mask", "#checkout_counter_popup"] | |
}, | |
{ | |
host: "m.youku.com", | |
container: "#player,.h5-detail-player", | |
name: "Default", | |
displayNodes: [".callEnd_box", ".h5-detail-guide", ".h5-detail-vip-guide"] | |
}, | |
{ | |
host: "tv.sohu.com", | |
container: "#player", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "film.sohu.com", | |
container: "#playerWrap", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "www.le.com", | |
container: "#le_playbox", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "video.tudou.com", | |
container: ".td-playbox", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "v.pptv.com", | |
container: "#pptv_playpage_box", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "vip.pptv.com", | |
container: ".w-video", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "www.wasu.cn", | |
container: "#flashContent", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "www.acfun.cn", | |
container: "#player", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "vip.1905.com", | |
container: "#player,#vodPlayer", | |
name: "Default", | |
displayNodes: [] | |
}, | |
{ | |
host: "www.1905.com", | |
container: "#player,#vodPlayer", | |
name: "Default", | |
displayNodes: [] | |
}, | |
] | |
}; | |
class BaseConsumer { | |
constructor() { | |
this.parse = () => { | |
util.findTargetEle('body') | |
.then((container) => this.preHandle(container)) | |
.then((container) => this.generateElement(container)) | |
.then((container) => this.bindEvent(container)) | |
.then((container) => this.autoPlay(container)) | |
.then((container) => this.postHandle(container)); | |
} | |
} | |
preHandle(container) { | |
_CONFIG_.currentPlayerNode.displayNodes.forEach((item, index) => { | |
util.findTargetEle(item) | |
.then((obj) => obj.style.display = 'none') | |
.catch(e => console.warn("不存在元素", e)); | |
}); | |
return new Promise((resolve, reject) => resolve(container)); | |
} | |
generateElement(container) { | |
GM_addStyle(` | |
#${_CONFIG_.vipBoxId} {cursor:pointer; position:fixed; top:120px; left:0px; z-index:9999999; text-align:left;} | |
#${_CONFIG_.vipBoxId} .img_box{width:32px; height:32px;line-height:32px;text-align:center;background-color:#1c84c6;margin:10px 0px;} | |
#${_CONFIG_.vipBoxId} .vip_list {display:none; position:absolute; border-radius:5px; left:32px; top:0; text-align:center; background-color: #3f4149; border:1px solid white;padding:10px 0px; width:380px; max-height:400px; overflow-y:auto;} | |
#${_CONFIG_.vipBoxId} .vip_list li{border-radius:2px; font-size:12px; color:#DCDCDC; text-align:center; width:calc(25% - 14px); line-height:21px; float:left; border:1px solid gray; padding:0 4px; margin:4px 2px;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;-o-text-overflow:ellipsis;} | |
#${_CONFIG_.vipBoxId} .vip_list li:hover{color:#1c84c6; border:1px solid #1c84c6;} | |
#${_CONFIG_.vipBoxId} .vip_list ul{padding-left: 10px;} | |
#${_CONFIG_.vipBoxId} .vip_list::-webkit-scrollbar{width:5px; height:1px;} | |
#${_CONFIG_.vipBoxId} .vip_list::-webkit-scrollbar-thumb{box-shadow:inset 0 0 5px rgba(0, 0, 0, 0.2); background:#A8A8A8;} | |
#${_CONFIG_.vipBoxId} .vip_list::-webkit-scrollbar-track{box-shadow:inset 0 0 5px rgba(0, 0, 0, 0.2); background:#F1F1F1;} | |
#${_CONFIG_.vipBoxId} li.selected{color:#1c84c6; border:1px solid #1c84c6;} | |
#${_CONFIG_.vipBoxId} .vip_list2 {display:none; position:absolute; border-radius:5px; left:32px; top:0; text-align:center; background-color: #3f4149; border:1px solid white;padding:10px 0px; width:380px; max-height:400px; overflow-y:auto;} | |
#${_CONFIG_.vipBoxId} .vip_list2 li{border-radius:2px; font-size:12px; color:#DCDCDC; text-align:center; width:calc(25% - 14px); line-height:21px; float:left; border:1px solid gray; padding:0 4px; margin:4px 2px;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;-o-text-overflow:ellipsis;} | |
#${_CONFIG_.vipBoxId} .vip_list2 li:hover{color:#1c84c6; border:1px solid #1c84c6;} | |
#${_CONFIG_.vipBoxId} .vip_list2 ul{padding-left: 10px;} | |
#${_CONFIG_.vipBoxId} .vip_list2::-webkit-scrollbar{width:5px; height:1px;} | |
#${_CONFIG_.vipBoxId} .vip_list2::-webkit-scrollbar-thumb{box-shadow:inset 0 0 5px rgba(0, 0, 0, 0.2); background:#A8A8A8;} | |
#${_CONFIG_.vipBoxId} .vip_list2::-webkit-scrollbar-track{box-shadow:inset 0 0 5px rgba(0, 0, 0, 0.2); background:#F1F1F1;} | |
`); | |
GM_addStyle(` | |
/* 新增按钮的样式 */ | |
#${_CONFIG_.vipBoxId} .img_box#save_playback, | |
#${_CONFIG_.vipBoxId} .img_box#load_playback { | |
background-color: #28a745; /* 绿色背景 */ | |
margin: 5px 0; | |
} | |
`); | |
if (_CONFIG_.isMobile) { | |
GM_addStyle(` | |
#${_CONFIG_.vipBoxId} {top:300px;} | |
#${_CONFIG_.vipBoxId} .vip_list {width:300px;} | |
`); | |
} | |
let type_1_str = ""; | |
let type_2_str = ""; | |
let type_3_str = ""; | |
_CONFIG_.videoParseList.forEach((item, index) => { | |
if (item.type.includes("1")) { | |
type_1_str += `<li class="nq-li" title="${item.name}1" data-index="${index}">${item.name}</li>`; | |
} | |
if (item.type.includes("2")) { | |
type_2_str += `<li class="tc-li" title="${item.name}" data-index="${index}">${item.name}</li>`; | |
} | |
if (item.type.includes("3")) { | |
type_3_str += `<li class="tc-li" title="${item.name}" data-index="${index}">${item.name}</li>`; | |
} | |
}); | |
let autoPlay = !!GM_getValue(_CONFIG_.autoPlayerKey, null) ? "开" : "关"; | |
$(container).append(` | |
<div id="${_CONFIG_.vipBoxId}"> | |
<div class="vip_icon"> | |
<div class="img_box" title="选择解析源" style="color:white;font-size:16px;font-weight:bold;border-radius:5px;"><span style="color: red;">VIP</span></div> | |
<div class="vip_list"> | |
<div> | |
<h3 style="color:#1c84c6; font-weight: bold; font-size: 16px; padding:5px 0px;">[内嵌播放]</h3> | |
<ul> | |
${type_1_str} | |
<div style="clear:both;"></div> | |
</ul> | |
</div> | |
<div> | |
<h3 style="color:#1c84c6; font-weight: bold; font-size: 16px; padding:5px 0px;">[弹窗播放带选集]</h3> | |
<ul> | |
${type_2_str} | |
<div style="clear:both;"></div> | |
</ul> | |
</div> | |
<div> | |
<h3 style="color:#1c84c6; font-weight: bold; font-size: 16px; padding:5px 0px;">[弹窗播放不带选集]</h3> | |
<ul> | |
${type_3_str} | |
<div style="clear:both;"></div> | |
</ul> | |
</div> | |
<div style="text-align:left;color:#FFF;font-size:10px;padding:0px 10px;margin-top:10px;"> | |
<b>自动解析功能说明:</b> | |
<br> 1、自动解析功能默认关闭(自动解析只支持内嵌播放源) | |
<br> 2、开启自动解析,网页打开后脚本将根据当前选中的解析源自动解析视频。如解析失败,请手动选择不同的解析源尝试 | |
<br> 3、没有选中解析源将随机选取一个 | |
<br> 4、如某些网站有会员可以关闭自动解析功能 | |
</div> | |
</div> | |
</div> | |
<div class="img_box" id="vip_auto" style="color:white;font-size:16px;font-weight:bold;border-radius:5px;" title="是否打开自动解析。若自动解析失败,请手动选择其它接口尝试!!">${autoPlay}</div> | |
<!-- 新增保存和加载按钮 --> | |
<div class="img_box" id="save_playback" title="保存当前播放记录">保存</div> | |
<div class="img_box" id="load_playback" title="加载已保存的播放记录">加载</div> | |
</div> | |
</div>`); | |
return new Promise((resolve, reject) => resolve(container)); | |
} | |
bindEvent(container) { | |
const vipBox = $(`#${_CONFIG_.vipBoxId}`); | |
if (_CONFIG_.isMobile) { | |
vipBox.find(".vip_icon").on("click", () => vipBox.find(".vip_list").toggle()); | |
vipBox.find(".money").on("click", () => vipBox.find(".vip_list2").toggle()); | |
} else { | |
vipBox.find(".vip_icon").on("mouseover", () => vipBox.find(".vip_list").show()); | |
vipBox.find(".vip_icon").on("mouseout", () => vipBox.find(".vip_list").hide()); | |
vipBox.find(".money").on("mouseover", () => vipBox.find(".vip_list2").show()); | |
vipBox.find(".money").on("mouseout", () => vipBox.find(".vip_list2").hide()); | |
} | |
let _this = this; | |
vipBox.find(".vip_list .nq-li").each((liIndex, item) => { | |
item.addEventListener("click", () => { | |
const index = parseInt($(item).attr("data-index")); | |
GM_setValue(_CONFIG_.autoPlayerVal, index); | |
GM_setValue(_CONFIG_.flag, "true"); | |
_this.showPlayerWindow(_CONFIG_.videoParseList[index]); | |
vipBox.find(".vip_list li").removeClass("selected"); | |
$(item).addClass("selected"); | |
}); | |
}); | |
vipBox.find(".vip_list .tc-li").each((liIndex, item) => { | |
item.addEventListener("click", () => { | |
const index = parseInt($(item).attr("data-index")); | |
const videoObj = _CONFIG_.videoParseList[index]; | |
let url = videoObj.url + window.location.href; | |
GM_openInTab(url, { | |
active: true, | |
insert: true, | |
setParent: true | |
}); | |
}); | |
}); | |
//右键移动位置 | |
vipBox.mousedown(function (e) { | |
if (e.which !== 3) { | |
return; | |
} | |
e.preventDefault() | |
vipBox.css("cursor", "move"); | |
const positionDiv = $(this).offset(); | |
let distenceX = e.pageX - positionDiv.left; | |
let distenceY = e.pageY - positionDiv.top; | |
$(document).mousemove(function (e) { | |
let x = e.pageX - distenceX; | |
let y = e.pageY - distenceY; | |
const windowWidth = $(window).width(); | |
const windowHeight = $(window).height(); | |
if (x < 0) { | |
x = 0; | |
} else if (x > windowWidth - vipBox.outerWidth(true) - 100) { | |
x = windowWidth - vipBox.outerWidth(true) - 100; | |
} | |
if (y < 0) { | |
y = 0; | |
} else if (y > windowHeight - vipBox.outerHeight(true)) { | |
y = windowHeight - vipBox.outerHeight(true); | |
} | |
vipBox.css("left", x); | |
vipBox.css("top", y); | |
}); | |
$(document).mouseup(function () { | |
$(document).off('mousemove'); | |
vipBox.css("cursor", "pointer"); | |
}); | |
$(document).contextmenu(function (e) { | |
e.preventDefault(); | |
}) | |
}); | |
// 绑定保存播放记录按钮的点击事件 | |
vipBox.find("#save_playback").on("click", () => this.savePlayback()); | |
// 绑定加载播放记录按钮的点击事件 | |
vipBox.find("#load_playback").on("click", () => this.loadPlayback()); | |
return new Promise((resolve, reject) => resolve(container)); | |
} | |
autoPlay(container) { | |
const vipBox = $(`#${_CONFIG_.vipBoxId}`); | |
vipBox.find("#vip_auto").on("click", function () { | |
if (!!GM_getValue(_CONFIG_.autoPlayerKey, null)) { | |
GM_setValue(_CONFIG_.autoPlayerKey, null); | |
$(this).html("关"); | |
$(this).attr("title", "是否打开自动解析。若自动解析失败,请手动选择其它接口尝试!!"); | |
} else { | |
GM_setValue(_CONFIG_.autoPlayerKey, "true"); | |
$(this).html("开"); | |
} | |
setTimeout(function () { | |
window.location.reload(); | |
}, 200); | |
}); | |
if (!!GM_getValue(_CONFIG_.autoPlayerKey, null)) { | |
this.selectPlayer(container); | |
} | |
return new Promise((resolve, reject) => resolve(container)); | |
} | |
selectPlayer(container) { | |
let index = GM_getValue(_CONFIG_.autoPlayerVal, 2); | |
let autoObj = _CONFIG_.videoParseList[index]; | |
let _th = this; | |
if (autoObj.type.includes("1")) { | |
setTimeout(function () { | |
_th.showPlayerWindow(autoObj); | |
const vipBox = $(`#${_CONFIG_.vipBoxId}`); | |
vipBox.find(`.vip_list [title="${autoObj.name}1"]`).addClass("selected"); | |
$(container).find("#vip_auto").attr("title", `自动解析源:${autoObj.name}`); | |
}, 2500); | |
} | |
} | |
showPlayerWindow(videoObj) { | |
util.findTargetEle(_CONFIG_.currentPlayerNode.container) | |
.then((container) => { | |
const type = videoObj.type; | |
let url = videoObj.url + window.location.href; | |
if (type.includes("1")) { | |
util.reomveVideo(); | |
$(container).empty(); | |
$(container).empty(); | |
let iframeDivCss = "width:100%;height:100%;z-index:999999;"; | |
if (_CONFIG_.isMobile) { | |
iframeDivCss = "width:100%;height:220px;z-index:999999;"; | |
} | |
if (_CONFIG_.isMobile && window.location.href.indexOf("iqiyi.com") !== -1) { | |
iframeDivCss = "width:100%;height:220px;z-index:999999;margin-top:-56.25%;"; | |
} | |
$(container).append(`<div style="${iframeDivCss}"><iframe id="iframe-player-4a5b6c" src="${url}" style="border:none;" allowfullscreen="true" width="100%" height="100%"></iframe></div>`); | |
} | |
}); | |
} | |
postHandle(container) { | |
if (!!GM_getValue(_CONFIG_.autoPlayerKey, null)) { | |
util.urlChangeReload(); | |
} else { | |
let oldHref = window.location.href; | |
let interval = setInterval(() => { | |
let newHref = window.location.href; | |
if (oldHref !== newHref) { | |
oldHref = newHref; | |
if (!!GM_getValue(_CONFIG_.flag, null)) { | |
clearInterval(interval); | |
window.location.reload(); | |
} | |
} | |
}, 1000); | |
} | |
} | |
// 保存播放记录的方法 | |
savePlayback() { | |
const seriesId = this.getSeriesId(); // 获取电视剧的唯一标识 | |
const currentEpisode = this.getCurrentEpisode(); // 获取当前播放的剧集号 | |
if (seriesId && currentEpisode) { | |
GM_setValue(`playback_${seriesId}`, currentEpisode); | |
GM_log(`已保存播放记录:第${currentEpisode}集`); | |
GM_notification({ text: `已保存播放记录:第${currentEpisode}集`,timeout:2000 }); | |
} else { | |
GM_log("无法获取当前播放信息,请确保正在播放电视剧。"); | |
} | |
} | |
// 加载播放记录的方法 | |
loadPlayback() { | |
const seriesId = this.getSeriesId(); // 获取电视剧的唯一标识 | |
const savedEpisode = GM_getValue(`playback_${seriesId}`, null); | |
if (savedEpisode) { | |
this.jumpToEpisode(savedEpisode); | |
} | |
} | |
// 获取电视剧的唯一标识(需根据不同网站实现) | |
getSeriesId() { | |
const host = window.location.host; | |
if (host.includes("v.qq.com")) { | |
// 腾讯视频:从URL中提取系列ID | |
const match = window.location.pathname.match(/\/cover\/([^\/]+)/); | |
return match ? match[1] : null; | |
} else if (host.includes("iqiyi.com")) { | |
// 爱奇艺:从URL中提取系列ID | |
const match = window.location.pathname.match(/\/v_([^\/]+)/); | |
return match ? match[1] : null; | |
} | |
// 其他网站的实现 | |
return null; | |
} | |
// 获取当前播放的剧集号(需根据不同网站实现) | |
getCurrentEpisode() { | |
const host = window.location.host; | |
if (host.includes("v.qq.com")) { | |
// 腾讯视频:从页面中提取当前剧集号 | |
const episodeElement = document.querySelector(".txp_videos_container .current"); | |
return episodeElement ? parseInt(episodeElement.textContent.match(/\d+/)[0]) : null; | |
} else if (host.includes("iqiyi.com")) { | |
// 爱奇艺:从页面中提取当前剧集号 | |
const episodeElement = document.querySelector(".episode-list .current"); | |
return episodeElement ? parseInt(episodeElement.textContent.match(/\d+/)[0]) : null; | |
} | |
// 其他网站的实现 | |
return null; | |
} | |
// 跳转到指定剧集(需根据不同网站实现) | |
jumpToEpisode(episode) { | |
const host = window.location.host; | |
if (host.includes("v.qq.com")) { | |
// 腾讯视频:模拟点击指定剧集 | |
const episodeElement = document.querySelector(`.txp_videos_container [data-episode="${episode}"]`); | |
if (episodeElement) episodeElement.click(); | |
} else if (host.includes("iqiyi.com")) { | |
// 爱奇艺:模拟点击指定剧集 | |
const episodeElement = document.querySelector(`.episode-list [data-episode="${episode}"]`); | |
if (episodeElement) episodeElement.click(); | |
} | |
// 其他网站的实现 | |
} | |
} | |
class DefaultConsumer extends BaseConsumer { } | |
class BilibiliConsumer extends BaseConsumer { | |
// 获取电视剧的唯一标识(season_id) | |
getSeriesId() { | |
const mediaInfoElement = document.querySelector('[class*="mediainfo_mediaInfoWrap"]'); | |
if (mediaInfoElement) { | |
const mrShow = mediaInfoElement.getAttribute('mr-show'); | |
if (mrShow) { | |
try { | |
const data = JSON.parse(mrShow); | |
return data.msg.season_id; // 返回 season_id | |
} catch (error) { | |
console.error("解析 mr-show 属性失败:", error); | |
} | |
} | |
} | |
return null; | |
} | |
// 获取当前播放的剧集号(ep_id) | |
getCurrentEpisode() { | |
const mediaInfoElement = document.querySelector('[class*="mediainfo_mediaInfoWrap"]'); | |
if (mediaInfoElement) { | |
const mrShow = mediaInfoElement.getAttribute('mr-show'); | |
if (mrShow) { | |
try { | |
const data = JSON.parse(mrShow); | |
return data.msg.ep_id; // 返回 ep_id | |
} catch (error) { | |
console.error("解析 mr-show 属性失败:", error); | |
} | |
} | |
} | |
return null; | |
} | |
// 跳转到指定剧集 | |
jumpToEpisode(episode) { | |
// 构建目标剧集的 URL | |
const targetUrl = __NEXT_DATA__.page.replace('[videoId]', `ep${episode}`); | |
window.location.href = targetUrl; // 跳转到目标 URL | |
} | |
} | |
class QQConsumer extends BaseConsumer { | |
/* constructor() { | |
super(); | |
util.findTargetEle('.preview-mini-player') | |
.then((container) => container.remove()); | |
} */ | |
// 从URL中提取SeriesId(如mcv8hkc8zk8lnov) | |
getSeriesId() { | |
const pathParts = window.location.pathname.split('/'); | |
// 预期URL结构:/x/cover/SeriesId/EpId.html | |
if (pathParts.length >= 5 && pathParts[1] === 'x' && pathParts[2] === 'cover') { | |
return pathParts[3]; // 返回SeriesId | |
} | |
console.error("无法从URL中提取SeriesId,请检查URL结构"); | |
return null; | |
} | |
// 从URL中提取当前剧集ID(如v0048tkd15x) | |
getCurrentEpisode() { | |
const pathParts = window.location.pathname.split('/'); | |
if (pathParts.length >= 5 && pathParts[1] === 'x' && pathParts[2] === 'cover') { | |
const epPart = pathParts[4]; | |
// 去除末尾的.html后缀 | |
return epPart.replace(/\.html$/, ''); | |
} | |
console.error("无法从URL中提取当前剧集ID,请检查URL结构"); | |
return null; | |
} | |
// 跳转到指定剧集 | |
jumpToEpisode(episode) { | |
const pathParts = window.location.pathname.split('/'); | |
if (pathParts.length >= 5 && pathParts[1] === 'x' && pathParts[2] === 'cover') { | |
// 替换EpId并保留其他路径部分 | |
pathParts[4] = `${episode}.html`; | |
const newUrl = new URL(window.location.origin + pathParts.join('/')); | |
window.location.href = newUrl.href; | |
} else { | |
console.error("当前页面URL结构不符合要求,跳转失败"); | |
} | |
} | |
} | |
return { | |
start: () => { | |
GM_setValue(_CONFIG_.flag, null); | |
let mallCase = 'Default'; | |
let playerNode = _CONFIG_.playerContainers.filter(value => value.host === window.location.host); | |
if (playerNode === null || playerNode.length <= 0) { | |
console.warn(window.location.host + "该网站暂不支持,请联系作者,作者将会第一时间处理(注意:请记得提供有问题的网址)"); | |
return; | |
} | |
_CONFIG_.currentPlayerNode = playerNode[0]; | |
mallCase = _CONFIG_.currentPlayerNode.name; | |
const targetConsumer = eval(`new ${mallCase}Consumer`); | |
targetConsumer.parse(); | |
} | |
} | |
})(); | |
(function () { | |
superVip.start(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment