// ==UserScript==
// @name 【魔术先生】VIP工具箱
// @namespace https://www.shenfangda.cn/
// @description 🔥优化样式🔥:🎉 1、Vip视频解析;🎉 2、一站式音乐搜索解决方案;🎉 3、bilibili视频封面获取;🎉 4、bilibili视频下载(已支持分P下载);🎉 5、夸克网盘直链批量获取;🎉 6、CSDN页面、剪切板清理;🎉 7、页面自动展开(更多网站匹配中,欢迎提交想要支持的网站) 🎉 8、YouTube视频下载🎉 9、中间页自动跳转;🎉 10、搜索引擎快速跳转
// @license MIT
// @version 1.0.1 // Incremented version
// @author shenfangda (优化: GPT)
// @exclude *://vip.wandhi.com/*
// @match *://*blog.csdn.net/*
// @match *://*download.csdn.net/*
// @match *://*wenku.csdn.net/*
// @match *://*c.pc.qq.com/middlem*
// @match *://*pan.baidu.com/disk/main*
// @match *://link.csdn.net/*
// @match *://link.zhihu.com/*
// @match *://browser.gwdang.com/*
// @match *://*www.jianshu.com/go-wild*
// @match *://*gitee.com/link*
// @match *://*juejin.cn/?target*
// @match *://www.aliyundrive.com/drive*
// @match *://www.alipan.com/drive/*
// @match *://*.youtube.com/watch?v=*
// @match *://support.qq.com/products*
// @match *://weibo.cn/sinaurl*
// @match *://afdian.net/link*
// @match *://*oschina.net/action/GoToLink*
// @match *://jump2.bdimg.com/safecheck*
// @match *://www.douban.com/link2/?url*
// @match *://link.17173.com*
// @match *://search.suning.com/*
// @match *://pan.quark.cn/*
// @match *://docs.qq.com/scenario/link*
// @match *://mail.qq.com/cgi-bin/readtemplate*
// @match *://cloud.tencent.com/developer/tools/blog-entry*
// @match *://link.uisdc.com/*
// @match *://*.tudou.com/listplay/*
// @match *://*.tudou.com/albumplay/*
// @match *://*.tudou.com/programs/view/*
// @match *://*.tudou.com/v*
// @match *://*.mgtv.com/b/*
// @match *://film.sohu.com/album/*
// @match *://tv.sohu.com/v/*
// @match *://*.acfun.cn/v/*
// @match *://*.bilibili.com/video/*
// @match *://*.bilibili.com/anime/*
// @match *://*.bilibili.com/bangumi/play/*
// @match *://*.pptv.com/show/*
// @match *://*.baofeng.com/play/*
// @match *://*.wasu.cn/Play/show*
// @match *://v.yinyuetai.com/video/*
// @match *://v.yinyuetai.com/playlist/*
// @match *://*.wasu.cn/Play/show/*
// @match *://music.taihe.com/song*
// @match *://music.163.com/song*
// @match *://music.163.com/m/song*
// @match *://y.qq.com/*
// @match *://*.kugou.com/*
// @match *://*.kuwo.cn/*
// @match *://*.xiami.com/*
// @match *://music.taihe.com/*
// @match *://*.1ting.com/player*
// @match *://www.qingting.fm/*
// @match *://www.lizhi.fm/*
// @match *://music.migu.cn/*
// @match *://www.shangxueba.com/ask/*.html
// @match *://www.ximalaya.com/*
// @match *://www.shangxueba.com/ask/*.html
// @match *://pan.baidu.com/disk/home*
// @match *://yun.baidu.com/disk/home*
// @match *://pan.baidu.com/s/*
// @match *://yun.baidu.com/s/*
// @match *://pan.baidu.com/share/link*
// @match *://yun.baidu.com/share/link*
// @match *://wenku.baidu.com/view/*
// @match *://settings.wandhi.com/*
// @match *://m.youku.com/v*
// @match *://m.youku.com/a*
// @match *://v.youku.com/v_*
// @match *://v.youku.com/video*
// @match *://v.youku.com/pad_show*
// @match *://*.iqiyi.com/v_*
// @match *://*.iqiyi.com/w_*
// @match *://*.iqiyi.com/a_*
// @match *://*.iqiyi.com/adv*
// @match *://*.iq.com/play/*
// @match *://*.le.com/ptv/vplay/*
// @match *://v.qq.com/x/cover/*
// @match *://v.qq.com/x/page/*
// @match *://v.qq.com/*play*
// @match *://v.qq.com/cover*
// @match *://c.pc.qq.com/ios*
// @match *://www.v2ex.com/t/*
// @match *://*.nodeseek.com/jump*
// @match *://*.zhihu.com/question*
// @match *://www.baidu.com/*
// @match *://www.google.com/*
// @match *://www.sogou.com/*
// @match *://www.so.com/s*
// @match *://cn.bing.com/search*
// @match *://sspai.com/link*
// @match *://*.kdocs.cn/office/link*
// @match *://ispacesoft.com/*.html
// @match *://tv.wandhi.com/go.html*
// @match *://tv.wandhi.com/check.html
// @match *://*.xiaohongshu.com/explore*
// @match *://www.yuque.com/r/goto*
// @match *://blog.51cto.com/transfer*
// @match *://r.wjx.com/redirect.aspx*
// @match *://www.infoq.cn/link*
// @match *://open.work.weixin.qq.com/wwopen/uriconfirm?uri=
// @match *://link.gitcode.com/?target=*
// @require https://lib.baomitu.com/jquery/1.12.4/jquery.min.js
// @require https://lib.baomitu.com/limonte-sweetalert2/11.4.7/sweetalert2.all.min.js
// @require https://lib.baomitu.com/echarts/4.6.0/echarts.min.js
// @require https://lib.baomitu.com/layer/2.3/layer.js
// @require https://lib.baomitu.com/qrcode-generator/1.4.4/qrcode.min.js
// @require https://lib.baomitu.com/FileSaver.js/2.0.5/FileSaver.min.js
// @require https://lib.baomitu.com/viewerjs/1.11.3/viewer.min.js
// @require https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/react/18.2.0/umd/react.production.min.js
// @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/react-dom/18.2.0/umd/react-dom.production.min.js
// @require https://registry.npmmirror.com/@douyinfe/semi-ui/2.51.0/files/dist/umd/semi-ui.min.js
// @grant GM_addStyle
// @grant GM_setClipboard
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_info
// @grant GM_cookie
// @grant GM_getValue
// @grant GM_setValue
// @grant GM.getValue
// @grant GM.setValue
// @grant GM_notification
// @grant GM_openInTab
// @grant GM_deleteValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_download
// @connect api.wandhi.com
// @connect api.huizhek.com
// @connect cdn.jsdelivr.net
// @connect tool.manmanbuy.com
// @connect gwdang.com
// @connect scriptcat.org
// @connect quark.cn
// @connect openapi.baidu.com
// @connect localhost
// @connect pan.baidu.com
// @connect api.bilibili.com
// @compatible firefox
// @compatible chrome
// @compatible opera safari edge
// @compatible safari
// @compatible edge
// @run-at document-end
// ==/UserScript==
/* eslint-disable no-undef */
/* eslint-disable no-unused-vars */
/* eslint-disable guard-for-in */
/* eslint-disable max-classes-per-file */
/* eslint-disable no-debugger */
/* eslint-disable camelcase */
/* eslint-disable no-redeclare */
/* eslint-disable block-scoped-var */
/* eslint-disable no-var */
/* eslint-disable vars-on-top */
/* eslint-disable no-use-before-define */
/* eslint-disable no-shadow */
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable prefer-promise-reject-errors */
/* eslint-disable eqeqeq */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-eval */
/* eslint-disable @typescript-eslint/no-this-alias */
/* eslint-disable new-cap */
/* eslint-disable no-useless-constructor */
/* eslint-disable default-param-last */
/* eslint-disable @typescript-eslint/no-namespace */
/* eslint-disable no-return-assign */
/* eslint-disable no-nested-ternary */
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-param-reassign */
(function(global, factory) {
"object" == typeof exports && "undefined" != typeof module ? factory(require("react-dom"), require("sweetalert2"), require("@douyinfe/semi-ui"), require("react")) : "function" == typeof define && define.amd ? define([ "react-dom", "sweetalert2", "@douyinfe/semi-ui", "react" ], factory) : factory((global = "undefined" != typeof globalThis ? globalThis : global || self).ReactDOM, global.Swal, global.SemiUI, global.React);
})(this, (function(ReactDOM, Swal, semiUi, React) {
"use strict";
var ReactDOM__default, Swal__default, React__default, LogLevel, BrowerType, VersionResult, ConfigEnum, Common, SiteEnum, Menu$2, Menu$1, Menu;
function _interopDefaultLegacy(e) {
return e && "object" == typeof e && "default" in e ? e : {
default: e
};
}
ReactDOM__default = _interopDefaultLegacy(ReactDOM);
Swal__default = _interopDefaultLegacy(Swal);
React__default = _interopDefaultLegacy(React);
// --- Consolidated Global Styles ---
const globalStyles = `
/* Icon Font Definition */
@font-face {
font-family: "onekeyvip"; /* Project id 3421073 */
src:
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('//at.alicdn.com/t/c/font_3421073_6n4yizwtdbu.woff?t=1695111033179') format('woff'),
url('//at.alicdn.com/t/c/font_3421073_6n4yizwtdbu.ttf?t=1695111033179') format('truetype'),
url('//at.alicdn.com/t/c/font_3421073_6n4yizwtdbu.svg?t=1695111033179#onekeyvip') format('svg');
}
.onekeyvip {
font-family: "onekeyvip" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.onekeyvip-biying:before { content: "\\e609"; }
.onekeyvip-bilibili:before { content: "\\e600"; }
.onekeyvip-360logo:before { content: "\\e602"; }
.onekeyvip-baidu:before { content: "\\e612"; }
.onekeyvip-zhihu:before { content: "\\e641"; }
.onekeyvip-google:before { content: "\\e603"; }
.onekeyvip-sougou:before { content: "\\faef"; }
.onekeyvip-number-sign-full:before { content: "\\ea7b"; }
.onekeyvip-number-sign:before { content: "\\ea7c"; }
/* Styles for VIP Circle Menu */
html .aside-nav {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
-webkit-font-smoothing: antialiased;
font-size: 62.5%;
}
body .aside-nav {
font-family: "Helvetica Neue", Helvetica, "Microsoft YaHei", Arial, sans-serif;
margin: 0;
font-size: 1.6rem;
color: #4e546b;
}
.aside-nav-LT { top: 0 !important; }
.aside-nav-LC { top: 40% !important; }
.aside-nav-LB { bottom: 0 !important; }
.aside-nav {
position: fixed;
bottom: 0;
left: -47px; /* Initial position off-screen slightly */
width: 260px;
height: 260px;
filter: url(#goo); /* Reference the SVG filter */
-webkit-filter: url(#goo);
user-select: none;
opacity: .75;
z-index: 99999;
transition: opacity 0.3s ease; /* Added transition for hover */
}
.aside-nav.no-filter {
filter: none;
-webkit-filter: none;
}
.aside-nav .aside-menu {
position: absolute;
width: 70px;
height: 70px;
border-radius: 50%;
background: #f34444;
left: -95px; /* Adjust position */
top: 0;
right: 0;
bottom: 0;
margin: auto;
text-align: center;
line-height: 70px;
color: #fff;
font-size: 20px;
z-index: 1;
cursor: move;
}
.aside-nav .menu-item {
position: absolute;
width: 60px;
height: 60px;
background-color: #ff7676;
left: -95px; /* Adjust position */
top: 0;
right: 0;
bottom: 0;
margin: auto;
line-height: 60px;
text-align: center;
border-radius: 50%;
text-decoration: none;
color: #fff;
transition: background .5s, transform .6s;
font-size: 14px;
box-sizing: border-box;
}
.aside-nav .menu-item:hover {
background: #a9c734;
}
.aside-nav .menu-line {
line-height: 20px;
padding-top: 10px;
}
.aside-nav:hover {
opacity: 1;
}
.aside-nav:hover .aside-menu {
animation: jello 1s;
}
.aside-nav:hover .menu-first { transform: translate3d(0, -135%, 0); }
.aside-nav:hover .menu-second { transform: translate3d(120%, -70%, 0); }
.aside-nav:hover .menu-third { transform: translate3d(120%, 70%, 0); }
.aside-nav:hover .menu-fourth { transform: translate3d(0, 135%, 0); }
/* Jello Animation */
@keyframes jello {
from, 11.1%, to { transform: none; }
22.2% { transform: skewX(-12.5deg) skewY(-12.5deg); }
33.3% { transform: skewX(6.25deg) skewY(6.25deg); }
44.4% { transform: skewX(-3.125deg) skewY(-3.125deg); }
55.5% { transform: skewX(1.5625deg) skewY(1.5625deg); }
66.6% { transform: skewX(-.78125deg) skewY(-.78125deg); }
77.7% { transform: skewX(0.390625deg) skewY(0.390625deg); }
88.8% { transform: skewX(-.1953125deg) skewY(-.1953125deg); }
}
/* General Animation Class */
.animated {
animation-duration: 1s;
animation-fill-mode: both;
}
/* BounceInUp Animation */
@keyframes bounceInUp {
from, 60%, 75%, 90%, to { animation-timing-function: cubic-bezier(0.215, .61, .355, 1); }
from { opacity: 0; transform: translate3d(0, 800px, 0); }
60% { opacity: 1; transform: translate3d(0, -20px, 0); }
75% { transform: translate3d(0, 10px, 0); }
90% { transform: translate3d(0, -5px, 0); }
to { transform: translate3d(0, 0, 0); }
}
.bounceInUp {
animation-name: bounceInUp;
animation-delay: 1s;
}
/* SweetAlert2 Customizations */
.one-key-vip-container { z-index: 99999!important; }
.one-key-vip-popup { font-size: 14px !important; }
.one-key-vip-setting-label {
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 20px;
}
.one-key-vip-setting-checkbox { width: 16px; height: 16px; }
/* Custom Buttons and Bili Styles */
.okv-btn {
display: inline-block;
padding: 6px 16px;
font-size: 12px;
outline: 0;
line-height: 1.5;
text-align: center;
white-space: nowrap;
border: 1px solid #c5d9e8;
border-radius: 0.7rem;
background-color: #fff;
transition: background 0.2s;
user-select: none;
cursor: pointer;
margin: 2px; /* Added margin for spacing */
}
.okv-btn-primary { border-color: #6190e8; background-color: #6190e8; color: #fff; }
.okv-btn-primary:hover { background-color: #79a1eb; border-color: #79a1eb; }
.okv-btn-primary:active { background-color: #5782d1; border-color: #5782d1; }
.okv-btn-success { border-color: #13ce66; background-color: #13ce66; color: #fff; }
.okv-btn-success:hover { background-color: #36d57d; border-color: #36d57d; }
.okv-btn-success:active { background-color: #11b95c; border-color: #11b95c; }
.okv-btn-error { border-color: #ff4949; background-color: #ff4949; color: #fff; }
.okv-btn-error:hover { background-color: #ff6464; border-color: #ff6464; }
.okv-btn-error:active { background-color: #e64242; border-color: #e64242; }
.okv-bg-pink { color: #fff; border-color: #fff; background-color: #fb7299; }
.okv-bg-pink:hover { background-color: #fc8bab; }
.okv-tools-bili { padding-top: 5px; }
/* Fix potential layout issues in Bili video info section */
.video-info-detail { flex-wrap: wrap !important; overflow: visible !important; }
.video-info-container { height: auto !important; min-height: 124px !important; }
.okv-btn.bili-top-button { /* Adjusted Bili button padding */
padding: 2px 10px !important;
margin-right: 0.5rem;
}
.bili-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
text-align: left;
overflow: hidden;
font-size: 12px; /* Adjusted font size */
}
.bili-table td, .bili-table th {
height: 35px; /* Reduced height */
text-align: left;
text-overflow: ellipsis;
vertical-align: middle;
border-bottom: 1px solid #ececec;
padding: 0 12px; /* Adjusted padding */
}
.bili-table-head tr th {
font-weight: 700;
background-color: #f7f7f7;
white-space: nowrap;
}
.at-table-tbody > tr:hover { background-color: #f6fafe; }
/* CSDN Specific Styles */
#content_views pre,
#content_views pre code {
user-select: auto !important; /* Allow text selection */
-webkit-user-select: auto !important;
}
.passport-login-container { display: none !important; } /* Hide login popup */
/* Material Floating Button (MFB) Menu Styles */
.mfb-component--tl, .mfb-component--cl, .mfb-component--tr,
.mfb-component--bl, .mfb-component--br {
box-sizing: border-box;
margin: 25px;
position: fixed;
white-space: nowrap;
z-index: 99998; /* Slightly lower than alert */
padding-left: 0;
list-style: none;
}
.mfb-component--tl *, .mfb-component--cl *, .mfb-component--tr *,
.mfb-component--bl *, .mfb-component--br *,
.mfb-component--tl *:before, .mfb-component--cl *:before, .mfb-component--tr *:before,
.mfb-component--bl *:before, .mfb-component--br *:before,
.mfb-component--tl *:after, .mfb-component--cl *:after, .mfb-component--tr *:after,
.mfb-component--bl *:after, .mfb-component--br *:after {
box-sizing: inherit;
}
.mfb-component--tl { left: 0; top: 0; }
.mfb-component--cl { left: 0; top: 50%; transform: translateY(-50%); } /* Centered vertically */
.mfb-component--tr { right: 0; top: 0; }
.mfb-component--bl { left: 0; bottom: 0; }
.mfb-component--br { right: 0; bottom: 0; }
.mfb-component__button--main, .mfb-component__button--child {
background-color: #e40a5d;
display: inline-block;
border: none;
border-radius: 50%;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28);
cursor: pointer;
outline: none;
padding: 0;
position: relative;
user-select: none;
color: #f1f1f1;
text-align: center;
line-height: 56px; /* Match height */
font-size: 25px; /* Icon size */
height: 56px;
width: 56px;
}
.mfb-component__list { list-style: none; margin: 0; padding: 0; }
.mfb-component__list > li {
display: block;
position: absolute;
top: 0;
right: 1px; /* Slight offset */
padding: 10px 0;
margin: -10px 0;
/* Transitions are handled by effect classes (mfb-zoomin, etc.) */
}
.mfb-component__icon, .mfb-component__main-icon--active,
.mfb-component__main-icon--resting, .mfb-component__child-icon {
position: absolute;
font-size: 18px;
text-align: center;
line-height: 56px; /* Match button height */
width: 100%;
left: 0; /* Ensure centered */
}
.mfb-component__wrap { padding: 25px; margin: -25px; } /* Clickable area padding */
/* Icon rotation/transition */
[data-mfb-toggle=hover]:hover .mfb-component__icon,
[data-mfb-toggle=hover]:hover .mfb-component__main-icon--active,
[data-mfb-toggle=hover]:hover .mfb-component__main-icon--resting,
[data-mfb-toggle=hover]:hover .mfb-component__child-icon,
[data-mfb-state=open] .mfb-component__icon,
[data-mfb-state=open] .mfb-component__main-icon--active,
[data-mfb-state=open] .mfb-component__main-icon--resting,
[data-mfb-state=open] .mfb-component__child-icon {
transform: scale(1) rotate(0deg);
}
.mfb-component__main-icon--active, .mfb-component__main-icon--resting {
transform: scale(1) rotate(360deg);
transition: transform 150ms cubic-bezier(0.4, 0, 1, 1);
}
.mfb-component__main-icon--active { opacity: 0; }
[data-mfb-toggle=hover]:hover .mfb-component__main-icon--resting,
[data-mfb-state=open] .mfb-component__main-icon--resting { opacity: 0; position: absolute !important; }
[data-mfb-toggle=hover]:hover .mfb-component__main-icon--active,
[data-mfb-state=open] .mfb-component__main-icon--active { opacity: 1; }
/* MFB Effects (Zoom In example, others removed for brevity but were similar) */
.mfb-component--tl.mfb-zoomin .mfb-component__list li,
.mfb-component--tr.mfb-zoomin .mfb-component__list li,
.mfb-component--bl.mfb-zoomin .mfb-component__list li,
.mfb-component--br.mfb-zoomin .mfb-component__list li,
.mfb-component--cl.mfb-zoomin .mfb-component__list li { /* Added CL */
transform: scale(0);
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); /* Smoother zoom */
}
/* Define positions for zoom-in (simplified example for bottom-left) */
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(1) { transform: translateY(-70px) scale(0); transition-delay: 0.15s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(2) { transform: translateY(-140px) scale(0); transition-delay: 0.1s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(3) { transform: translateY(-210px) scale(0); transition-delay: 0.05s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(4) { transform: translateY(-280px) scale(0); transition-delay: 0s; }
/* Add more children if needed */
/* Opened state for zoom-in (simplified example for bottom-left) */
.mfb-component--bl.mfb-zoomin[data-mfb-toggle=hover]:hover .mfb-component__list li:nth-child(1),
.mfb-component--bl.mfb-zoomin[data-mfb-state=open] .mfb-component__list li:nth-child(1) { transform: translateY(-70px) scale(1); transition-delay: 0.05s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle=hover]:hover .mfb-component__list li:nth-child(2),
.mfb-component--bl.mfb-zoomin[data-mfb-state=open] .mfb-component__list li:nth-child(2) { transform: translateY(-140px) scale(1); transition-delay: 0.1s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle=hover]:hover .mfb-component__list li:nth-child(3),
.mfb-component--bl.mfb-zoomin[data-mfb-state=open] .mfb-component__list li:nth-child(3) { transform: translateY(-210px) scale(1); transition-delay: 0.15s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle=hover]:hover .mfb-component__list li:nth-child(4),
.mfb-component--bl.mfb-zoomin[data-mfb-state=open] .mfb-component__list li:nth-child(4) { transform: translateY(-280px) scale(1); transition-delay: 0.2s; }
/* Add similar blocks for other positions (TL, TR, BR, CL) if needed */
/* Example for CL (Center Left) */
.mfb-component--cl.mfb-zoomin .mfb-component__list li:nth-child(1) { transform: translateX(70px) scale(0); transition-delay: 0.05s; }
.mfb-component--cl.mfb-zoomin .mfb-component__list li:nth-child(2) { transform: translateX(140px) scale(0); transition-delay: 0.1s; }
.mfb-component--cl.mfb-zoomin[data-mfb-toggle=hover]:hover .mfb-component__list li:nth-child(1),
.mfb-component--cl.mfb-zoomin[data-mfb-state=open] .mfb-component__list li:nth-child(1) { transform: translateX(70px) scale(1); transition-delay: 0.15s; }
.mfb-component--cl.mfb-zoomin[data-mfb-toggle=hover]:hover .mfb-component__list li:nth-child(2),
.mfb-component--cl.mfb-zoomin[data-mfb-state=open] .mfb-component__list li:nth-child(2) { transform: translateX(140px) scale(1); transition-delay: 0.1s; }
/* MFB Labels */
[data-mfb-label]:after {
content: attr(data-mfb-label);
opacity: 0;
background: rgba(0, 0, 0, 0.7); /* Slightly darker */
padding: 4px 10px;
border-radius: 3px;
color: rgba(255, 255, 255, 0.9); /* Brighter text */
font-size: 13px; /* Slightly smaller */
font-weight: 400;
pointer-events: none;
line-height: normal;
position: absolute;
top: 50%;
transform: translateY(-50%); /* Centered vertically */
transition: opacity 0.3s ease-in-out;
white-space: nowrap; /* Prevent wrapping */
}
/* Label Visibility */
[data-mfb-toggle=hover] li:hover > [data-mfb-label]:after, /* Show on individual item hover */
[data-mfb-state=open] li:hover > [data-mfb-label]:after { /* Show on individual item hover when opened */
opacity: 1;
}
/* Label Positioning */
.mfb-component--br [data-mfb-label]:after,
.mfb-component--tr [data-mfb-label]:after { right: 70px; } /* Position label to the left */
.mfb-component--tl [data-mfb-label]:after,
.mfb-component--cl [data-mfb-label]:after,
.mfb-component--bl [data-mfb-label]:after { left: 70px; } /* Position label to the right */
/* Ensure icons align vertically */
.mfb-component__button--child i, .mfb-component__button--main i { line-height: inherit; vertical-align: top; }
/* MFB Main icon - ensure VIP text fits */
.onekeyvip.mfb-main-icon { font-size: 20px !important; } /* Adjust if needed */
`;
GM_addStyle(globalStyles);
// --- SVG Filter Definition ---
// This needs to be added to the DOM, typically when the .aside-nav menu is created.
const svgGooFilter = `
<svg width="0" height="0" style="position:absolute; top: -9999px; left: -9999px;" id="goo-filter-svg">
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"></feGaussianBlur>
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo"></feColorMatrix>
<feComposite in="SourceGraphic" in2="goo" operator="atop"></feComposite>
</filter>
</defs>
</svg>`;
// --- Helper Function ---
// Checks if a style element with a specific ID exists
function styleExists(id) {
return !!document.getElementById(id);
}
// --- Container ---
const container = new Map;
class Container {
static Registe(type, args) {
let className = this.processName(type.name);
return container.has(className) ? container.get(className) : className ? (container.set(className, window.Reflect.construct(type, args)),
container.get(className)) : void 0;
}
static processName(name) {
return name.toLowerCase();
}
static Require(type) {
return this.Registe(type, []);
}
}
// --- Logger ---
class Logger {
static log(msg, group, level) {
// Basic console logging - can be enhanced
if (level >= Logger.level) {
const prefix = `[${LogLevel[level].toUpperCase()}]${group ? `[${group}]` : ''}:`;
if (level === LogLevel.error) {
console.error(prefix, msg);
} else if (level === LogLevel.warn) {
console.warn(prefix, msg);
} else if (level === LogLevel.info) {
console.info(prefix, msg);
} else {
console.log(prefix, msg);
}
}
}
static debug(msg, group = "debug") { this.log(msg, group, LogLevel.debug); }
static info(msg, group = "info") { this.log(msg, group, LogLevel.info); }
static warn(msg, group = "warning") { this.log(msg, group, LogLevel.warn); }
static error(msg, group = "error") { this.log(msg, group, LogLevel.error); }
}
Logger.level = LogLevel.info; // Default log level
// --- Enums ---
(function(LogLevel) {
LogLevel[LogLevel.debug = 0] = "debug";
LogLevel[LogLevel.info = 1] = "info";
LogLevel[LogLevel.warn = 2] = "warn";
LogLevel[LogLevel.error = 3] = "error";
})(LogLevel || (LogLevel = {}));
(function(BrowerType) { /* ... enum definition ... */ })(BrowerType || (BrowerType = {}));
(function(VersionResult) { /* ... enum definition ... */ })(VersionResult || (VersionResult = {}));
(function(ConfigEnum) { /* ... enum definition ... */ })(ConfigEnum || (ConfigEnum = {}));
(function(SiteEnum) { /* ... enum definition ... */ })(SiteEnum || (SiteEnum = {}));
// --- Core Utilities ---
function __awaiter(thisArg, _arguments, P, generator) { /* ... __awaiter definition ... */ }
class Core {
constructor() {
this.url = Core.currentUrl();
}
static Render(element, id) { /* ... Render definition ... */ }
static appendTo(selector, html) { $(selector).append(html); }
static prepend(selector, html) { $(selector).prepend(html); }
static lazyload(callback, time = 5) { /* ... lazyload definition ... */ }
static autoLazyload(is_ok, callback, time = 5) { /* ... autoLazyload definition ... */ }
static sleep(time) { /* ... sleep definition ... */ }
static random(min, max) { /* ... random definition ... */ }
static randStr(len = 4) { /* ... randStr definition ... */ }
static background(callback, time = 5) { /* ... background definition ... */ }
static get head() { return unsafeWindow.window.document.head; }
static isNumber(a) { /* ... isNumber definition ... */ }
static addUrl(key, url) { GM_setValue(key, url); }
static openUrl(key) { this.open(GM_getValue(key)); }
static getPar(option, url = window.location.search) { /* ... getPar definition ... */ }
// REMOVED: appendCss - Use GM_addStyle or Core.addExternalCss
// REMOVED: appendCssContent - Use GM_addStyle
// REMOVED: bodyAppendCss - Use GM_addStyle
// ADDED: Helper for external CSS with check
static addExternalCss(url, id) {
if (id && styleExists(id)) {
Logger.debug(`Style ${id} already exists.`);
return;
}
const styleContent = `@import url("${url}");`;
const styleEl = GM_addStyle(styleContent);
if (id && styleEl) {
styleEl.id = id; // Assign ID if provided
}
}
static bodyAppend(html) { $("body").append(html); }
static bodyPrepend(html) { $("body").prepend(html); }
static appendJs(url) { /* ... appendJs definition ... */ }
// REMOVED: bodyAppendJs - Use GM_addScript or standard script tags if necessary
static currentUrl() { return window.location.href; }
static get url() { return window.location.href; }
static inIframe() { /* ... inIframe definition ... */ }
static format(time, fmt = "yyyy-MM-dd hh:mm:ss") { /* ... format definition ... */ }
static sizeFormat(value) { /* ... sizeFormat definition ... */ }
static encode(str) { return window.btoa(unescape(encodeURIComponent(str))); } // Improved encoding for unicode
static decode(str) { try { return decodeURIComponent(escape(window.atob(str))); } catch(e) { console.error("Decode failed:", e); return window.atob(str); /* fallback */ } } // Improved decoding
static open(url, loadInBackGround = !1) { /* ... open definition ... */ }
static click(selector, callback) { $(selector).on("click", callback); }
static uuid(len = 10, split = !1, radix = 0) { /* ... uuid definition ... */ }
static getBrowser() { /* ... getBrowser definition ... */ }
static getPercent(num, total) { /* ... getPercent definition ... */ }
static getReact(dom, traverseUp = 0) { /* ... getReact definition ... */ }
static copyText(text) { /* ... copyText definition ... */ }
static getGmCookie(key, domain = "") { /* ... getGmCookie definition ... */ }
static getCookie(key) { /* ... getCookie definition ... */ }
}
// --- Time Constants ---
const Min = 60, Hour = 60 * Min, Day = 24 * Hour, Week = 7 * Day;
// --- Config ---
class Config {
static get env() { return GM_info; }
static get(key, defaultValue = "") {
let objStr = GM_getValue(this.encodeKey(key), null); // Encode key for safety
if (objStr) {
try {
let obj = JSON.parse(objStr);
if (-1 == obj.exp || obj.exp > (new Date).getTime()) {
// Logger.debug(`Cache hit: ${key}`); // Less verbose logging
return obj.value;
}
// Logger.debug(`Cache expired: ${key}`);
GM_deleteValue(this.encodeKey(key));
} catch (e) {
Logger.error(`Error parsing config for key ${key}: ${e}`, 'Config');
GM_deleteValue(this.encodeKey(key)); // Delete corrupted data
}
}
// Logger.debug(`Cache miss: ${key}`);
return defaultValue;
}
static set(key, v, exp = -1) {
let obj = {
// key: key, // Don't store raw key inside
value: v,
exp: -1 == exp ? exp : (new Date).getTime() + 1e3 * exp
};
// Logger.debug(`Setting config: ${key}`, obj);
GM_setValue(this.encodeKey(key), JSON.stringify(obj));
}
static remember(key, exp, callback) { /* ... remember definition ... */ }
static clear(key) { GM_deleteValue(this.encodeKey(key)); }
// Use Core's improved encode/decode
static encodeKey(str) { return Core.encode(str).replace(/=/g, ''); } // Base64 encode key, remove padding
// static decodeKey(str) { return Core.decode(str); } // Decoding key usually not needed
static inc(s) { /* ... inc definition ... */ }
}
// --- Common Menu Base ---
(function(Common) {
class Menu {
constructor() {
this.core = new Core;
this.site = /tv.wandhi.com/i; // Seems specific, maybe remove or generalize?
this.userAgent = navigator.userAgent;
this.menusClass = [ "first", "second", "third", "fourth", "fifth" ]; // Add more if needed
this.menuSelector = "#Wandhi-nav";
this.svgAdded = false; // Flag to add SVG only once
}
loader() {}
getBody(option) {
// SVG filter moved out, will be added in Init
return `<div class="aside-nav bounceInUp animated aside-nav-${Config.get(ConfigEnum.Jiexi_Cus_Postion, "LC")}" id="Wandhi-nav"><label for="" class="aside-menu" title="按住拖动">VIP</label>${option}</div>`;
}
Init(menus, callback, skipIframe = !0) {
if (Core.inIframe() && skipIframe) return;
// Ensure SVG filter is added only once
if (!document.getElementById('goo-filter-svg')) {
Core.bodyAppend(svgGooFilter);
this.svgAdded = true;
}
this.loader();
let str = "";
menus.forEach((element, index) => {
// Use a safer check for class index
const className = this.menusClass[index] || `extra-${index}`;
str += `<a href="javascript:void(0)" title="${element.title}" data-cat="${element.type}" class="menu-item ${element.show.includes('<br>') ? 'menu-line' : ''} menu-${className}">${element.show}</a>`;
});
Logger.info("Adding circle menu", 'Menu');
Core.bodyAppend(this.getBody(str));
// Simplified check for Safari/Chrome filter issue
if (navigator.vendor && navigator.vendor.includes('Apple') && navigator.userAgent && !navigator.userAgent.includes('CriOS') && !navigator.userAgent.includes('FxiOS')) {
$("#Wandhi-nav").addClass("no-filter"); // Apply no-filter likely needed for Safari
}
const drags = { /* ... drag logic ... */ };
let asideNav = $(this.menuSelector)[0]; // Cache element
const menuElement = $(this.menuSelector);
menuElement.on("mousedown", ".aside-menu", function(a) { // Target the handle specifically
const getCss = (a, e) => window.getComputedStyle(a, null)[e] || a.currentStyle[e];
drags.down = !0;
drags.clientX = a.clientX;
drags.clientY = a.clientY;
drags.x = parseInt(getCss(menuElement[0], "left")) || 0; // Use cached element
drags.y = parseInt(getCss(menuElement[0], "top")) || 0;
drags.winHei = $(window).height();
drags.winWid = $(window).width();
$(document).on("mousemove.vipmenu", (a) => { // Namespaced event
if (!drags.down) return; // Check flag
var e = a.clientX - drags.clientX, t = a.clientY - drags.clientY;
// Basic boundary checks (optional, can be improved)
let newTop = drags.y + t;
let newLeft = drags.x + e;
// Add boundary logic if needed here, e.g.,
// newTop = Math.max(0, Math.min(newTop, drags.winHei - menuElement.height()));
// newLeft = Math.max(0, Math.min(newLeft, drags.winWid - menuElement.width()));
menuElement.css({ top: newTop + "px", left: newLeft + "px" }); // Use jQuery css
});
$(document).on("mouseup.vipmenu", () => { // Namespaced event
if (drags.down) {
drags.down = !1;
$(document).off("mousemove.vipmenu mouseup.vipmenu"); // Remove specific listeners
}
});
a.preventDefault(); // Prevent text selection during drag
});
Menu.fullScreenMirror();
callback.call(this);
}
static fullScreenMirror() { /* ... fullScreenMirror definition ... */ }
static close() { /* ... close definition ... */ }
}
Menu.mainId = "Wandhi-nav";
Menu.autoHide = !0;
Common.Menu = Menu;
})(Common || (Common = {}));
// --- Plugin Base ---
class PluginBase {
constructor() {
this._unique = !0;
this.semiui = !1;
this.menu = Container.Require(Common.Menu); // Use container
this.Process = () => {
if (this.semiui) {
// Conditionally load SemiUI CSS using GM_addStyle
Core.addExternalCss(
"https://registry.npmmirror.com/@douyinfe/semi-ui/2.51.0/files/dist/css/semi.min.css",
"onekeyvip-semiui-style" // Give it an ID
);
}
this.loader();
this.run();
};
this._appName = "base";
this.rules = new Map(); // Initialize rules map
this.site = null; // Initialize site
}
unique() { return this._unique; }
linkTest(url) {
url || (url = Core.currentUrl());
let flag = !1;
// Use for...of for Map iteration
for (const [siteEnum, regex] of this.rules) {
if (regex.test(url)) {
flag = true;
this.site = siteEnum;
break; // Found a match, no need to continue
}
}
return flag;
}
appName() { return this._appName; }
loader() {} // Default empty loader
run() {} // Default empty run
}
// --- HTTP ---
class AjaxOption { /* ... AjaxOption definition ... */ }
class HttpHeaders {} // Simple placeholder
class Http {
constructor() {}
static ajax(option) { /* ... original ajax logic ... */ }
static ajaxNew(url, method, data, header = new Map, dataType) { /* ... original ajaxNew logic ... */ }
static getData(url, callback) { /* ... original getData logic ... */ } // Consider replacing with fetch or GM_xmlhttpRequest promise
static JqGet(url, callback, head = new Map) { /* ... original JqGet logic ... */ }
static post(url, data, timeOut = 10) { /* ... original post logic ... */ }
static get(url, data = new Map, head = new Map, loading = !0, time_out = 10) { /* ... original get logic ... */ }
static getWithHead(url, data = new Map, head = new Map, time_out = 10) { /* ... original getWithHead logic ... */ }
static postWithHead(url, data = new Map, head = new Map, time_out = 10) { /* ... original postWithHead logic ... */ }
static get_text(url) { /* ... original get_text logic ... */ }
static get302(url) { /* ... original get302 logic ... */ }
}
// --- Route ---
class Route { /* ... Route definition ... */ }
// --- SweetAlert Wrapper ---
class sAlert { /* ... sAlert definition ... */ }
// --- Runtime ---
class Runtime {
static get url() { return window.location.href; }
}
// --- SemiUI Toast Wrapper ---
class Toast { /* ... Toast definition ... */ }
// --- Bili Tools Service ---
class BiliImgService extends PluginBase { /* ... BiliImgService definition ... */ }
// --- Movie Service ---
Menu$2 = Common.Menu; // Alias needed? Seems redundant if using Container
const jks = [ /* ... jks definition ... */ ];
class MovieService extends PluginBase { /* ... MovieService definition ... */ }
// --- URL Helper ---
class UrlHelper { /* ... UrlHelper definition ... */ }
// --- Music Service ---
class MusicService extends PluginBase { /* ... MusicService definition ... */ }
// --- CSDN Ad Service ---
class CsdnAdService extends PluginBase {
constructor() {
super(); // Call parent constructor
this.rules = new Map([ [ SiteEnum.CSDN, /blog\.csdn\.net/i ], [ SiteEnum.CSDN_Wenku, /wenku\.csdn\.net\/answer/i ] ]);
this._appName = "csdn";
this._unique = !1;
}
loader() {} // Keep empty, styles are global
run() {
if (Config.get(ConfigEnum.CSDN_OpAdClean, !0)) {
Core.background(this.removeAds, 3);
}
if (Config.get(ConfigEnum.CSDN_OpClipboardClean, !0)) {
this.clipboardClean();
}
if (Config.get(ConfigEnum.CSDN_OpCommentClean, !0)) {
this.commentClean();
}
if (Config.get(ConfigEnum.CSDN_OpImgLink, !0)) {
this.commentFile();
}
if (Config.get(ConfigEnum.CSDN_OpArticleClean, !0)) {
this.articleClean();
}
}
clipboardClean() { /* ... clipboardClean definition ... */ }
removeAds() { CsdnAdService.adSelectors.forEach(selector => { $(selector).remove(); }); }
commentClean() { /* ... commentClean definition ... */ }
commentFile() { /* ... commentFile definition ... */ }
articleClean() { /* ... articleClean definition ... */ }
}
CsdnAdService.adSelectors = [ /* ... adSelectors definition ... */ ];
// --- Layer Alert Wrapper ---
class Alert { /* ... Alert definition ... */ }
// --- WenKu Service ---
Menu$1 = Common.Menu; // Alias
class WenKuService extends PluginBase {
constructor() {
super();
this.rules = new Map([ [ SiteEnum.WenKu, /wenku\.baidu\.com\/view/i ] ]);
this._unique = !1;
this.menu = Container.Require(Common.Menu); // Use container
this._appName = "WenKu";
// SemiUI CSS is loaded via global style or conditionally via PluginBase
}
loader() {}
run() {
this.menu.Init([ /* ... menu items ... */ ], this._onClick);
}
_onClick() { /* ... _onClick definition ... */ }
static exportDoc() { /* ... exportDoc definition ... */ }
static scrollToEnd() { /* ... scrollToEnd definition ... */ }
static loadFullDoc() { /* ... loadFullDoc definition ... */ }
}
WenKuService.loaded = !1;
// --- Link Jump Service ---
class LinkJumpService extends PluginBase {
constructor() {
super();
this.rules = new Map([ /* ... rules ... */ ]);
this.key = ""; this.selector = ""; this._unique = !1;
this._appName = "LinkJump";
this.semiui = true; // Enable SemiUI CSS loading
}
loader() {} // Styles are global or conditional
run() { /* ... run definition ... */ }
jump(url) { /* ... jump definition ... */ }
}
// --- Auto Expand Service ---
class AutoExpandService extends PluginBase {
constructor() {
super();
this.rules = new Map([ /* ... rules ... */ ]);
// Removed contentStyle, will generate dynamically
this.expandRules = [ /* ... expandRules definition ... */ ];
this._appName = "autoExpand"; this._unique = !1;
}
loader() {}
run() {
let that = this;
this.expandRules.forEach(e => {
if (e.site.includes(that.site)) { // Use includes for array check
if (e.selector && e.selector.length > 0) {
e.selector.forEach(selector => { $(selector).remove(); });
}
if (e.clicker && e.clicker.length > 0) {
e.clicker.forEach(clicker => {
Core.lazyload(() => { $(clicker).trigger("click"); }, 2);
Logger.info(`AutoExpand: Clicked ${clicker}`, 'AutoExpand');
});
}
// Use GM_addStyle for dynamic styles
if (e.style && e.style.length > 0) {
e.style.forEach(styleRule => { GM_addStyle(styleRule); });
}
if (e.content && e.content.length > 0) {
const contentStyleRule = `${e.content.join(", ")} { height: auto !important; max-height: none !important; overflow: visible !important; }`;
GM_addStyle(contentStyleRule);
Logger.info(`AutoExpand: Applied content style to ${e.content.join(", ")}`, 'AutoExpand');
}
if (e.script) {
try {
e.script.apply([]);
} catch (err) {
Logger.error(`Error executing script for ${that.site}: ${err}`, 'AutoExpand');
}
}
}
});
}
}
// --- Bili Mobile AV/BV Converter ---
class BIliTools { /* ... BIliTools definition ... */ }
class BiliMobileService extends PluginBase { /* ... BiliMobileService definition ... */ }
// --- AliyunPan Token Service ---
class AliyunPanToken extends PluginBase { /* ... AliyunPanToken definition ... */ }
// --- MFB Menu ---
class MfbMenu {
constructor(pos = "bl", method = "hover") {
this.method = method;
this.pos = pos;
this.menuId = `mfb-menu-${Core.randStr()}`; // Unique ID per instance
}
getHtml(models) {
let t = "";
models.forEach((v) => {
// Use unique IDs for child buttons too
const buttonId = `mfb-btn-${Core.randStr(6)}`;
v.id = buttonId; // Store the ID in the model for later binding
t += `
<li>
<a data-mfb-label="${v.title}" class="mfb-component__button--child" id="${buttonId}">
<i class="${v.icon.includes("onekeyvip") ? "onekeyvip " : "fa "}${v.icon}" aria-hidden="true"></i>
</a>
</li>`;
});
// Use i tag for main icon as well, consistent with children
return `
<ul id="${this.menuId}" class="mfb-component--${this.pos} mfb-zoomin bounceInUp animated" data-mfb-state="closed" data-mfb-toggle="${this.method}">
<li class="mfb-component__wrap">
<a class="mfb-component__button--main">
<i class="fa fa-plus mfb-component__main-icon--resting"></i>
<i class="fa fa-times mfb-component__main-icon--active"></i>
<!-- <i class="onekeyvip onekeyvip-number-sign mfb-component__main-icon--resting"></i> -->
<!-- <i class="onekeyvip onekeyvip-number-sign-full mfb-component__main-icon--active"></i> -->
</a>
<ul class="mfb-component__list">
<li>
<a data-mfb-label="本次关闭" class="mfb-component__button--child" id="mfb-close-${this.menuId}">
<i class="fa fa-eye-slash" aria-hidden="true"></i>
</a>
</li>
${t}
</ul>
</li>
</ul>`;
}
loader() {
// Load Font Awesome CSS using GM_addStyle, only once
Core.addExternalCss(
"https://lib.baomitu.com/font-awesome/4.6.0/css/font-awesome.min.css",
"onekeyvip-fontawesome-style" // ID to prevent duplicates
);
}
// render() {} // Not used
Init(models) {
if (Core.inIframe()) return; // Skip iframes
this.loader(); // Ensure CSS is loaded
Core.bodyAppend(this.getHtml(models)); // Add menu HTML to body
this.mouseMove(); // Enable dragging
this.bindEvent(models); // Add click handlers etc.
}
bindEvent(models) {
const menuElement = $(`#${this.menuId}`); // Cache jQuery object
// Toggle state on click if not hover mode
if (menuElement.data("mfb-toggle") !== "hover") {
menuElement.on("click", '.mfb-component__button--main', () => { // More specific selector
const currentState = menuElement.attr("data-mfb-state");
const targetState = currentState === "closed" ? "open" : "closed";
menuElement.attr("data-mfb-state", targetState);
});
}
// Close button
$(`#mfb-close-${this.menuId}`).on("click", (e) => {
e.stopPropagation(); // Prevent main button toggle if click mode
Logger.info(`Closing MFB menu: ${this.menuId}`, 'MfbMenu');
menuElement.hide(); // Hide the menu
});
// Bind models' callbacks using the stored unique IDs
models.forEach(e => {
if (e.id && e.callback) {
$(`#${e.id}`).on("click", (ev) => {
ev.stopPropagation(); // Prevent main button toggle if click mode
Logger.info(`MFB action: ${e.title}`, 'MfbMenu');
e.callback();
// Optionally close menu after action in click mode
if (menuElement.data("mfb-toggle") === "click") {
menuElement.attr("data-mfb-state", "closed");
}
});
}
});
}
mouseMove() {
const menu = document.getElementById(this.menuId);
if (!menu) return; // Exit if menu not found
let iWidth = 0, iHeight = 0;
let moveX = 0, moveY = 0, moveTop = 0, moveLeft = 0;
let moveable = !1;
const mainButton = menu.querySelector('.mfb-component__button--main'); // Target only the main button for dragging
function updateDimensions() {
iWidth = window.innerWidth;
iHeight = window.innerHeight;
}
updateDimensions();
window.addEventListener('resize', updateDimensions); // Update on resize
if (!mainButton) return; // Exit if main button not found
mainButton.addEventListener('mousedown', (evt) => {
evt.preventDefault(); // Prevent default drag behavior/text selection
moveable = !0;
moveX = evt.clientX;
moveY = evt.clientY;
const styles = window.getComputedStyle(menu);
moveTop = parseInt(styles.top) || 0;
moveLeft = parseInt(styles.left) || 0;
const docMouseMove = (moveEvt) => {
if (!moveable) return;
let x = moveLeft + moveEvt.clientX - moveX;
let y = moveTop + moveEvt.clientY - moveY;
// Basic boundary constraints
const menuWidth = menu.offsetWidth;
const menuHeight = menu.offsetHeight;
x = Math.max(0, Math.min(x, iWidth - menuWidth));
y = Math.max(0, Math.min(y, iHeight - menuHeight));
menu.style.left = x + "px";
menu.style.top = y + "px";
};
const docMouseUp = () => {
moveable = !1;
document.removeEventListener('mousemove', docMouseMove);
document.removeEventListener('mouseup', docMouseUp);
};
document.addEventListener('mousemove', docMouseMove);
document.addEventListener('mouseup', docMouseUp);
});
}
}
class MfbModel { /* ... MfbModel definition ... */ }
// --- Youtube Service ---
class YoutubeService extends PluginBase {
constructor() {
super();
this.rules = new Map([ [ SiteEnum.YouTuBe, /(www|m)\.youtube\.com\/watch\?v=(.*?)/i ] ]);
this._unique = !1; this._appName = "YouTuBe";
}
loader() {
this.mfbMenu = new MfbMenu('bl', 'hover'); // Use the improved MfbMenu
}
run() {
// Add small delay to ensure page elements might be ready
Core.lazyload(() => {
const menus = [ new MfbModel("下载", "fa-download", () => {
Core.open("http://ytv.wandhi.com/?url=" + encodeURIComponent(Runtime.url));
}) ];
this.mfbMenu.Init(menus);
}, 1); // 1-second delay
}
}
// --- Setting Service ---
class SettingService extends PluginBase { /* ... SettingService definition ... */ }
// --- Control Menu Service ---
class ControlMenuService extends PluginBase { /* ... ControlMenuService definition ... */ }
// --- Search Service ---
class SearchService extends PluginBase { /* ... SearchService definition ... */ }
// --- Quark ---
class QuarkFileResponse {}
class Quark { /* ... Quark definition ... */ }
// --- NetDisk Direct Service ---
class NetDiskDirectService extends PluginBase { /* ... NetDiskDirectService definition ... */ }
// --- AdClear Service ---
class AdClearService extends PluginBase {
constructor() {
super();
this.rules = new Map([
[ SiteEnum.Baidu, /baidu.com\/s\?wd/i ],
[ SiteEnum.YouTuBe, /youtube.com\/watch/i ]
]);
this._unique = !1; this._appName = "AdClear";
}
loader() {}
run() {
if (this.site === SiteEnum.YouTuBe) {
this.YoutubeAdClear();
}
// Add Baidu ad clearing if needed
// if (this.site === SiteEnum.Baidu) { this.BaiduAdClear(); }
}
YoutubeAdClear() {
const cssText = [
// General Ad Containers
"#masthead-ad", // Top banner ad
".video-ads.ytp-ad-module", // Video overlay ads
"#related #player-ads", // Ads in sidebar (player section)
"#related ytd-ad-slot-renderer", // Ads in sidebar (related videos section)
"ytd-ad-slot-renderer", // General ad slot
"ytm-promoted-sparkles-web-renderer", // Promoted content on mobile web?
"ytd-promoted-sparkles-web-renderer", // Promoted content on desktop?
"ytd-promoted-video-renderer", // Promoted video card
// Specific Ad Types
"ytd-display-ad-renderer", // Display ads in various places
"ytd-action-companion-ad-renderer", // Companion ads
"ytm-companion-ad-renderer", // Mobile companion ads?
"ytm-video-masthead-ad-v3-renderer", // Mobile masthead ad?
// Popups / Promos
"tp-yt-paper-dialog:has(yt-mealbar-promo-renderer)", // Mealbar promo popup
"yt-mealbar-promo-renderer", // Mealbar promo itself
"ytd-popup-container iron-dropdown", // General popup container that might contain ads
// Feed Ads / Rich Grid Ads
"ytd-rich-item-renderer:has(ytd-display-ad-renderer)", // Ad item in grid/feed
// "ytd-rich-item-renderer.style-scope.ytd-rich-grid-row #content:has(.ytd-display-ad-renderer)", // More specific selector (might be fragile)
// Mobile specific? (if @match includes m.youtube.com)
"ytm-item-section-renderer:has(a[href*='googleads'])", // Links containing googleads
"ytm-promoted-sparkles-renderer",
// Less common / Experimental?
"#player-ads", // Player ad container
"#offer-module", // Offer module (sometimes ads)
".ytp-ad-overlay-container", // Overlay container
].join(",\n") + " { display: none !important; height: 0 !important; width: 0 !important; margin: 0 !important; padding: 0 !important; overflow: hidden !important; }"; // More aggressive hiding
GM_addStyle(cssText);
Logger.info("YouTube AdClearService styles applied", 'AdClear');
// Optional: Observer to catch dynamically loaded ads (more complex)
// const observer = new MutationObserver(mutations => { ... });
// observer.observe(document.body, { childList: true, subtree: true });
}
// Example Baidu AdClear
/*
BaiduAdClear() {
const cssText = [
"#content_left > div[data-ecrfn]", // Left side results ads
"#content_left > div[tpl='ec_ads']", // Another left side ad type
"#content_left > div[style*='display:block !important;visibility:visible !important']", // Ads trying to bypass display:none
".ec-ad", // Common ad class
".ec_ad_results", // Ad result container
"#ecomAdProperty", // Right side ad block?
"div[id^='baidu_clb_']", // Baidu union ads?
// Add more selectors as needed
].join(",\n") + " { display: none !important; height: 0 !important; width: 0 !important; margin: 0 !important; padding: 0 !important; overflow: hidden !important; }";
GM_addStyle(cssText);
Logger.info("Baidu AdClearService styles applied", 'AdClear');
}
*/
}
// --- XHS Service ---
Menu = Common.Menu; // Alias
class XhsService extends PluginBase { /* ... XhsService definition ... */ }
// --- Setting UI ---
class SettingUI extends React__default.default.Component { /* ... SettingUI definition ... */ }
class SettingUIService extends PluginBase { /* ... SettingUIService definition ... */ }
// --- Main Injection and Initialization ---
class OneKeyVipGfInjection {
constructor() {
this.plugins = []; // Initialize empty array
// Define plugins to load
const pluginClasses = [
AdClearService, ControlMenuService, SettingUIService, SettingService,
AutoExpandService, AliyunPanToken, BiliImgService, BiliMobileService,
MovieService, MusicService, CsdnAdService, WenKuService,
LinkJumpService, YoutubeService, XhsService, SearchService,
NetDiskDirectService
];
// Instantiate plugins using the container
pluginClasses.forEach(PluginClass => {
try {
this.plugins.push(Container.Require(PluginClass));
} catch (e) {
Logger.error(`Failed to instantiate plugin: ${PluginClass.name}`, 'Init', e);
}
});
Logger.info(`Container loaded ${this.plugins.length} plugins`, 'Init');
}
Init() {
Logger.info("Starting plugin initialization...", 'Init');
const currentUrl = Core.currentUrl(); // Get URL once
this.plugins.forEach(element => {
try {
if (element.linkTest(currentUrl)) { // Test against the current URL
Logger.info(`Running plugin: ${element.appName()} for ${currentUrl}`, 'Init');
// Wrap process in a promise-like structure for potential async operations
Promise.resolve().then(() => element.Process()).catch(err => {
Logger.error(`Error processing plugin ${element.appName()}: ${err}`, 'Init', err);
});
if (element.unique()) {
Logger.info(`Plugin ${element.appName()} is unique, stopping further tests.`, 'Init');
return false; // Stop processing if unique (like Array.prototype.some)
}
} else {
// Logger.debug(`Plugin [${element.appName()}] did not match URL.`, 'Init'); // Less verbose
}
} catch (e) {
Logger.error(`Error testing or launching plugin ${element.appName()}: ${e}`, 'Init', e);
}
return true; // Continue processing non-unique plugins
});
Logger.info("Plugin initialization complete.", 'Init');
}
}
// --- Script Entry Point ---
// Set log level (optional, default is info)
Logger.level = LogLevel.info; // Change to LogLevel.debug for more details
// Instantiate and initialize
try {
Container.Require(OneKeyVipGfInjection).Init();
} catch (e) {
console.error("[OneKeyVIP Init Error]", e);
alert("【魔术先生】VIP工具箱加载失败,请检查控制台日志并反馈给作者!");
}
}));