【魔术先生】VIP工具箱

🔥优化样式🔥:🎉 1、Vip视频解析;🎉 2、一站式音乐搜索解决方案;🎉 3、bilibili视频封面获取;🎉 4、bilibili视频下载(已支持分P下载);🎉 5、夸克网盘直链批量获取;🎉 6、CSDN页面、剪切板清理;🎉 7、页面自动展开(更多网站匹配中,欢迎提交想要支持的网站) 🎉 8、YouTube视频下载🎉 9、中间页自动跳转;🎉 10、搜索引擎快速跳转

// ==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工具箱加载失败,请检查控制台日志并反馈给作者!");
    }

}));

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址