Greasy Fork is available in English.

哎呦不错哦(学会看简介 黑号好像能用了,反馈一下)

好东西哦(⊙﹏⊙)

// ==UserScript==
// @name         哎呦不错哦(学会看简介 黑号好像能用了,反馈一下)
// @name:zh-TW   哎呦不错哦(學會看簡介 黑号好像能用了,反馈一下)
// @name:zh-HK   哎呦不错哦(學會看簡介 黑号好像能用了,反馈一下)
// @namespace    http://tampermonkey.net/
// @version      1.6.6
// @description  好东西哦(⊙﹏⊙)
// @description:zh-TW  好东西哦(⊙﹏⊙)
// @description:zh-HK  好东西哦(⊙﹏⊙)
// @author       hua
// @match        https://www.youtube.com/*
// @match        https://m.youtube.com/*
// @match        https://music.youtube.com/*
// @match        https://www.youtubekids.com/*
// @exclude      https://www.youtube.com/live_chat*
// @exclude      https://www.youtube.com/embed*
// @connect      https://api.cobalt.tools
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_info
// @grant        GM_addValueChangeListener
// @grant        GM_removeValueChangeListener
// @grant        GM_setClipboard
// @grant        GM_listValues
// @grant        GM_deleteValue
// @run-at       document-start
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @license      MIT
// ==/UserScript==
// https://api.cobalt.tools 视频解析API  This is a used to download video parsing API



(function () {
    let uuid = GM_getValue('uuid');
    if (!uuid) {
        uuid = crypto.randomUUID().substring(0, Math.floor(Math.random() * 5) + 6).replace(/-/g, '');
        GM_setValue('uuid', uuid);
    }

    if (unsafeWindow[uuid]) {
        console.log('重复注入!');
        return;
    }

    unsafeWindow[uuid] = true;

    let debugger_fun_name;

    const disableRemovePlayerAd = false;

    const open_config_keyword = '2333';

    const display_error_keyword = '2444';

    const reset_config_keyword = '2555';

    let channel_id = GM_getValue('last_channel_id', 'default');

    const user_data_listener = get_user_data_listener();

    const user_data_api = get_user_data_api();

    let user_data = user_data_api.get();

    let tmp_debugger_value;

    let limit_eval = false;

    let element_monitor_observer;

    let real_language = user_data.language;

    let is_account_init;

    let fake_fetch

    const inject_info = {
        "ytInitialPlayerResponse": false,
        "ytInitialData": false,
        "ytInitialReelWatchSequenceResponse": false,
        "xhr": false,
        "fetch": false
    };

    const $ = unsafeWindow.document.querySelector.bind(unsafeWindow.document);
    const $$ = unsafeWindow.document.querySelectorAll.bind(unsafeWindow.document);

    const origin_console = console;
    const script_url = 'https://update.greasyfork.org/scripts/480192/youtube%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA.user.js';
    let href = location.href;
    let ytInitialPlayerResponse_rule;
    let ytInitialData_rule;
    let ytInitialReelWatchSequenceResponse_rule;
    let open_debugger = false;
    let isinint = false;
    let mobile_web;
    let movie_channel_info;
    let mobile_movie_channel_info;
    let flag_info;

    let debugger_ytInitialPlayerResponse;
    let debugger_ytInitialData;
    let debugger_ytInitialReelWatchSequenceResponse;
    let debugger_music_initialData;
    const error_messages = [];
    let data_process = get_data_process();
    let shorts_fun = get_shorts_fun();
    let yt_api = get_yt_api();
    const shorts_parse_delay = 500;
    const browser_info = getBrowserInfo();
    let page_type = get_page_type();
    const config_api = get_config_api();
    if (disableRemovePlayerAd){
        config_api.common_ytInitialPlayerResponse_rule = config_api.common_ytInitialPlayerResponse_rule.slice(3)
    }
    const SPLIT_TAG = '###';
    let cur_watch_channle_id;
    const trustedScript = trustedScriptInit();
    setSecurePolicy();
    init();

    function init() {
        log('初始化开始!' + href, 0);
        url_observer();
        is_account_init = false;
        data_process.set_obj_filter(obj_process_filter);
        config_api.config_init(user_data.language);
        const init_hook = init_hook_collection();
        init_hook.property();
        init_hook.other();
        init_hook.request();

        unsafeWindow.document.addEventListener('DOMContentLoaded', function () {
            set_search_listen();
            // check_update();
            on_page_change();
        });

        isinint = true;
        log('初始化结束!' + href, 0);
        open_debugger && set_debugger();
    }

    function setSecurePolicy() {
        if (!unsafeWindow.isSecureContext || !unsafeWindow.trustedTypes?.createPolicy) return;
        try {
            unsafeWindow.trustedTypes.createPolicy("default", {
                createScriptURL: (url) => url,
                createHTML: (html) => html,
                createScript: (script) => script
            });
        } catch (error) {
        }
    }

    function trustedScriptInit() {

        try {
            let test_value;
            eval('test_eval = 1');
            return function (str) {
                return str;
            };
        } catch (error) {
            if (unsafeWindow.trustedTypes) {
                const policy = unsafeWindow.trustedTypes.createPolicy('eval', {
                    createScript: (script) => script
                });
                return function (str) {
                    return policy.createScript(str);
                };
            } else {
                log('trustedTypes not support', error, -1);
            }
        };
    };

    function init_hook_collection() {
        return {
            property() {
                const already_inject = [];
                let ytInitialPlayerResponse_value = unsafeWindow['ytInitialPlayerResponse'];
                function process_property(name, value, rule, reverse = false) {
                    if (!value) return value;
                    if (already_inject.includes(name)) {
                        log(`${name} 重复修改被拦截`, 0);
                        return value;
                    }
                    const start_time = Date.now();
                    if (typeof value === 'object') {
                        already_inject.push(name);
                        open_debugger && !limit_eval && !eval(trustedScript(`debugger_${name}`)) && (eval(trustedScript(`debugger_${name} = JSON.parse(JSON.stringify(value))`)));
                        rule && data_process.obj_process(value, rule, reverse);
                    }
                    if (typeof value === 'string') {
                        already_inject.push(name);
                        open_debugger && !limit_eval && !eval(trustedScript(`debugger_${name}`)) && (eval(trustedScript(`debugger_${name} = JSON.parse(value)`)));
                        value = data_process.text_process(value, rule, 'insert', reverse);
                    }
                    log(`${name} 时间:`, Date.now() - start_time, 'spend_time');
                    return value;
                }

                define_property_hook(unsafeWindow, 'ytInitialPlayerResponse', {
                    get: function () {
                        return ytInitialPlayerResponse_value;
                    },
                    set: function (value) {
                        inject_info.ytInitialPlayerResponse = true;
                        value = process_property('ytInitialPlayerResponse', value, config_api.common_ytInitialPlayerResponse_rule);
                        ytInitialPlayerResponse_value = value;
                    },
                    configurable: false
                });
                let ytInitialReelWatchSequenceResponse_value = unsafeWindow['ytInitialReelWatchSequenceResponse'];
                define_property_hook(unsafeWindow, 'ytInitialReelWatchSequenceResponse', {
                    get: function () {
                        return ytInitialReelWatchSequenceResponse_value;
                    },
                    set: function (value) {
                        inject_info.ytInitialReelWatchSequenceResponse = true;
                        if (['yt_shorts', 'mobile_yt_shorts'].includes(page_type)) {
                            value = process_property('ytInitialReelWatchSequenceResponse', value,
                                config_api.get_rules(mobile_web ? 'yt_shorts_mobile' : 'yt_shorts').ytInitialReelWatchSequenceResponse_rule);
                        }
                        ytInitialReelWatchSequenceResponse_value = value;
                    },
                    configurable: false
                });

                let ytInitialData_value = unsafeWindow['ytInitialData'];
                define_property_hook(unsafeWindow, 'ytInitialData', {
                    get: function () {
                        return ytInitialData_value;
                    },
                    set: function (value) {
                        inject_info.ytInitialData = true;
                        let rules = config_api.get_rules(page_type);
                        !['yt_watch', 'mobile_yt_watch', 'mobile_yt_watch_searching'].includes(page_type) && (rules = rules.ytInitialData_rule);
                        value = process_property('ytInitialData', value, rules);
                        ytInitialData_value = value;
                    },
                    configurable: false
                });

                const origin_ua = navigator.userAgent;
                define_property_hook(navigator, 'userAgent', {
                    get: function () {
                        return (browser_info.isMobile || browser_info.name === 'Chrome') ? origin_ua : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36';
                    }
                });
                if (unsafeWindow.ytcfg) {
                    if (unsafeWindow.ytcfg.data_ && typeof (unsafeWindow.ytcfg.data_.LOGGED_IN) === 'boolean') {
                        account_data_init(unsafeWindow.ytcfg.data_.LOGGED_IN);
                    } else {
                        if (unsafeWindow.ytcfg.data_ && typeof unsafeWindow.ytcfg.data_ === 'object') {
                            define_property_hook(unsafeWindow.ytcfg.data_, 'LOGGED_IN', {
                                get: function () {
                                    return unsafeWindow.ytcfg.data_.LOGGED_IN_;
                                },
                                set: function (value) {
                                    unsafeWindow.ytcfg.data_.LOGGED_IN_ = value;
                                    account_data_init(value);
                                }
                            });
                        }
                    }
                    if (!unsafeWindow.ytcfg.data_) {
                        if (unsafeWindow.yt?.config_) {
                            const config_ = unsafeWindow.yt.config_;
                            if (typeof (config_.LOGGED_IN) === 'boolean') {
                                account_data_init(config_.LOGGED_IN);
                            }
                            config_.HL && config_api.config_init(config_.HL);
                        }
                    } else {
                        if (unsafeWindow.ytcfg.data_?.HL) {
                            config_api.config_init(unsafeWindow.ytcfg.data_.HL);
                        } else {
                            if (unsafeWindow.ytcfg.msgs) {
                                unsafeWindow.ytcfg.msgs.__lang__ && config_api.config_init(unsafeWindow.ytcfg.msgs.__lang__);
                            } else {
                                unsafeWindow.ytcfg._msgs = unsafeWindow.ytcfg.msgs;
                                define_property_hook(unsafeWindow.ytcfg, 'msgs', {
                                    get: function () {
                                        return this._msgs;
                                    },
                                    set: function (newValue) {
                                        if (newValue.__lang__) config_api.config_init(newValue.__lang__);
                                        this._msgs = newValue;
                                    }
                                });
                            }
                        }
                    }

                } else {
                    define_property_hook(unsafeWindow, 'ytcfg', {
                        get: function () {
                            return this._ytcfg;
                        },
                        set: function (newValue) {
                            // 过滤 a = a || 1 这种
                            if (newValue === unsafeWindow.ytcfg) return;
                            if (newValue.set) {
                                const origin_set = newValue.set;
                                newValue.set = function () {
                                    //hook ytmusic 的初始化数据 YTMUSIC_INITIAL_DATA
                                    if (arguments?.[0].YTMUSIC_INITIAL_DATA) {
                                        const yt_music_init_data = arguments[0].YTMUSIC_INITIAL_DATA;
                                        if (yt_music_init_data?.length > 0) {
                                            const browse_data = yt_music_init_data[1];
                                            if (browse_data.path === '/browse') {
                                                const rule = config_api.get_rules('yt_music').ytInitialData_rule;
                                                browse_data.data = process_property('music_initialData', browse_data.data, rule);
                                            }
                                        }
                                    }
                                    origin_set.apply(this, arguments);
                                    if (arguments[0] && typeof arguments[0].LOGGED_IN === 'boolean') {
                                        account_data_init(arguments[0].LOGGED_IN);
                                    }
                                    if (arguments[0].HL) {
                                        config_api.config_init(arguments[0].HL);
                                    }
                                };
                            }
                            this._ytcfg = newValue;
                        }
                    });
                }
            },
            other() {
                const origin_createElement = unsafeWindow.document.createElement;
                unsafeWindow.document.createElement = function () {
                    const node = origin_createElement.apply(this, arguments);
                    if (arguments[0] === 'IFRAME') {
                        const contentWindow_getter = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "contentWindow").get;
                        define_property_hook(node, 'contentWindow', {
                            get: function () {
                                const contentWindow = contentWindow_getter.call(node);
                                if (!contentWindow || this.src !== 'about:blank' || contentWindow.change_history) return contentWindow;
                                set_history_hook(contentWindow);
                                contentWindow.fetch = fake_fetch
                                contentWindow.change_history = true;
                                return contentWindow;
                            }
                        });
                    }
                    return node;
                };
                unsafeWindow.document.createElement.toString = origin_createElement.toString.bind(origin_createElement);

            },
            request() {
                async function deal_response(name, response, rule) {
                    if (!rule) return response;
                    let is_deal = false;
                    const responseClone = response.clone();
                    let result = await responseClone.text();
                    let origin_result = result;
                    if (name === 'subscribe' || name === 'unsubscribe') {
                        let match_list = result.match(/channelId":\"(.*?)"/);
                        const match_channel_id = match_list && match_list.length > 1 ? match_list[1] : '';
                        let channel_infos = user_data.channel_infos;
                        if (match_channel_id) {
                            if (name === 'unsubscribe') {
                                let index = channel_infos.ids.indexOf(match_channel_id);
                                if (index > -1) {
                                    channel_infos.ids.splice(index, 1);
                                    channel_infos.names.splice(index, 1);
                                }
                            } else {
                                channel_infos.ids.push(match_channel_id);
                                channel_infos.names.push('');
                            }
                            user_data.channel_infos = channel_infos;
                            user_data_api.set();
                            log(name, match_channel_id, 0);
                        }
                        is_deal = true;
                    }
                    if (name === 'playlist') {
                        let obj;
                        try {
                            obj = JSON.parse(result);
                            data_process.obj_process(obj.playerResponse, config_api.common_ytInitialPlayerResponse_rule, false);
                            data_process.obj_process(obj.response, config_api.get_rules('yt_watch', 'init'), false);
                            result = JSON.stringify(obj);
                        } catch (error) {
                            log('playlist 解析失败', error, -1);
                            result = origin_result;
                        }
                        is_deal = true;
                    }
                    if (!is_deal) {
                        let start_time = Date.now();
                        result = data_process.text_process(result, rule, 'insert', false);
                        log(name + ' 时间:', Date.now() - start_time, 'spend_time');
                    }
                    if (!result) {
                        result = origin_result;
                        debugger;
                    }
                    return new Response(result, response);
                }
                const origin_fetch = unsafeWindow.fetch;
                if (!check_native('fetch', origin_fetch)) {
                    log('fetch have been modified', -1);
                }
                fake_fetch = function () {
                    const fetch_ = async function (uri, options) {
                        async function fetch_request(response) {
                            let url = response.url;
                            inject_info.fetch = true;
                            let request_body;
                            try {
                                request_body = uri.body_ ? JSON.parse(uri.body_) : null;
                            } catch (error) {
                                request_body = null;
                            }
                            if (url.includes('youtubei/v1/next')) {
                                const rule = config_api.get_rules(mobile_web ? 'mobile_yt_watch' : 'yt_watch', request_body?.videoId ? "init" : 'next');
                                return await deal_response('next', response, rule);
                            }
                            if (url.includes('youtubei/v1/player')) {
                                return await deal_response('player', response, config_api.common_ytInitialPlayerResponse_rule);
                            }
                            if (url.includes('youtubei/v1/reel/reel_watch_sequence')) {
                                const rule = config_api.get_rules(mobile_web ? 'mobile_yt_shorts' : 'yt_shorts').ytInitialReelWatchSequenceResponse_rule;
                                return await deal_response('reel_watch_sequence', response, rule);
                            }
                            if (url.includes('youtubei/v1/reel/reel_item_watch')) {
                                // shorts 内容
                                const rule = config_api.get_rules(mobile_web ? 'mobile_yt_shorts' : 'yt_shorts').ytInitialData_rule;
                                return await deal_response('reel_item_watch', response, rule);
                            }
                            if (url.includes('youtubei/v1/browse?prettyPrint=false')) {
                                let browse_id = request_body?.browseId;
                                let rule;
                                if (href.includes('https://music.youtube.com/')) {
                                    rule = config_api.get_rules('yt_music', 'browse').ytInitialData_rule;
                                }
                                // 忽略音乐主页 影视主页
                                if (!rule && (['yt_home', 'mobile_yt_home'].includes(page_type) || browse_id === 'FEwhat_to_watch')) {
                                    if (!browse_id) {
                                        let node, category_text, node_list, node_index;
                                        if (mobile_web) {
                                            node = $('#filter-chip-bar > div > ytm-chip-cloud-chip-renderer.selected');
                                            node_list = $$('#filter-chip-bar > div > ytm-chip-cloud-chip-renderer');
                                            node_index = Array.from(node_list).indexOf(node);
                                            if (node_index !== 1) return response;
                                        } else {
                                            node = $('#chips > yt-chip-cloud-chip-renderer.style-scope.ytd-feed-filter-chip-bar-renderer.iron-selected');
                                            node_list = $$('#chips > yt-chip-cloud-chip-renderer.style-scope.ytd-feed-filter-chip-bar-renderer');
                                            node_index = Array.from(node_list).indexOf(node);
                                            if (node_index !== 0) return response;
                                        }

                                    }
                                    rule = config_api.get_rules(mobile_web ? 'mobile_yt_home' : 'yt_home', request_body?.browseId ? 'init' : 'browse').ytInitialData_rule;
                                }

                                return await deal_response('browse', response, rule);
                            }
                            if (url.startsWith('https://www.youtube.com/playlist?list=')) {
                                return await deal_response('playlist', response, []);
                            }
                            // if (url.includes('https://m.youtube.com/youtubei/v1/guide')) {
                            //     return response;
                            // }
                            if (url.includes('/youtubei/v1/search')) {
                                const rule = config_api.get_rules(mobile_web ? 'mobile_yt_search' : 'yt_search').ytInitialData_rule;
                                return await deal_response('search', response, rule);
                            }
                            if (url.includes('/unsubscribe?prettyPrint=false')) {
                                return await deal_response('unsubscribe', response, []);
                            }
                            if (url.includes('/subscribe?prettyPrint=false')) {
                                return await deal_response('subscribe', response, []);
                            }
                            return response;
                        }
                        return origin_fetch(uri, options).then(fetch_request);
                    };
                    return fetch_;
                }();
                unsafeWindow.fetch = fake_fetch;
                unsafeWindow.fetch.toString = origin_fetch.toString.bind(origin_fetch);
                const origin_Request = unsafeWindow.Request;
                if (!check_native('Request', origin_Request)) {
                    log('Request have been modified', -1);
                }
                unsafeWindow.Request = class extends unsafeWindow.Request {
                    constructor(input, options = void 0) {
                        super(input, options);
                        this.url_ = input;
                        if (options && 'body' in options) this['body_'] = options['body'];
                    }
                };

                unsafeWindow.XMLHttpRequest = class extends unsafeWindow.XMLHttpRequest {
                    open(method, url, ...opts) {
                        inject_info.xhr = true;
                        if (['mobile_yt_watch'].includes(page_type) && url.includes('m.youtube.com/watch?v')) {
                            log('xhr watch 返回空', 0);
                            return null;
                        }
                        if (['mobile_yt_home'].includes(page_type) && url.includes('m.youtube.com/?pbj')) {
                            log('xhr home 返回空', 0);
                            return null;
                        }
                        this.url_ = url;
                        return super.open(method, url, ...opts);
                    }
                    send(body) {
                        this.body_ = body;
                        super.send(body);
                    }
                    get xhrResponseValue() {
                        const xhr = this;
                        if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
                            let result = super.response;
                            const url = xhr.responseURL;
                            const result_type = typeof result;
                            try {
                                if (url.includes('youtubei/v1/player')) {
                                    // music_watch shorts
                                    if (result_type !== 'string') {
                                        log(`XHR ${url} 返回值不是字符串!`, 0);
                                        return result;
                                    };
                                    result = data_process.text_process(result, config_api.common_ytInitialPlayerResponse_rule, 'insert', false);
                                    return result;
                                }
                                if (url.includes('youtube.com/playlist')) {
                                    debugger;
                                    let obj;
                                    obj = JSON.parse(result);
                                    log(`出现 ${url} !`, 0);
                                    data_process.obj_process(obj[2].playerResponse, ytInitialPlayerResponse_rule, false);
                                    data_process.obj_process(obj[3].response, ytInitialData_rule, false);
                                    tmp_debugger_value = obj;
                                    result = JSON.stringify(obj);
                                    return result;
                                }
                            } catch (error) {
                                log(`XHR ${url} 解析失败!`, error, -1);
                            }
                        }
                        return super.response;
                    }
                    get responseText() {
                        return this.xhrResponseValue;
                    }
                    get response() {
                        return this.xhrResponseValue;
                    }
                };

            }
        };
    }

    function on_page_change() {
        let analyzing_download_url = false;
        function common() {
            if (page_type === 'yt_shorts') {
                shorts_fun.check_shorts_exist();
            }
        }

        function element_monitor() {
            element_monitor_observer?.disconnect();
            const configs = wait_configs[page_type] || [];
            if (configs.length === 0) return;
            const callback = function (mutationsList) {
                for (let i = configs.length - 1; i >= 0; i--) {
                    const config = configs[i];
                    const selector = config.seletor;
                    const nodes = $$(selector);
                    for (let node of nodes) {
                        if (node.offsetHeight > 0) {
                            if (config.inject) {
                                if (!node.inject_xxxx) {
                                    node.inject_xxxx = true;
                                }
                                else {
                                    configs.splice(i, 1);
                                    break;
                                }
                            }
                            if ('count' in config) {
                                if (config.count > 0) {
                                    config.count--;
                                    if (config.count === 0) {
                                        configs.splice(i, 1);
                                    }
                                }
                            }
                            // log(`找到${selector}`, 0);
                            const funs = Array.isArray(config.fun) ? config.fun : [config.fun];
                            for (let fun of funs) {
                                fun(node);
                            }
                            break;
                        }
                    }
                }
                if (configs.length === 0) {
                    log('monitor end', 0);
                    element_monitor_observer.disconnect();
                    return;
                }
            };
            element_monitor_observer = new MutationObserver(callback);
            element_monitor_observer.observe($('body'), {
                childList: true,
                subtree: true
            });
        }

        const wait_configs = {
            "yt_shorts": [
                {
                    "seletor": "ytd-reel-video-renderer[is-active] video",
                    "inject": true,
                    "fun": [shorts_auto_scroll, set_shorts_dbclick_like, set_shorts_progress]
                },
                {
                    "seletor": "ytd-reel-video-renderer[is-active] #comments-button",
                    "inject": true,
                    "fun": [shorts_change_comment_click]
                },
                {
                    "seletor": "ytd-reel-video-renderer[is-active] video",
                    "count": 30,
                    "fun": []
                },
                // {
                //     "seletor": "ytd-reel-video-renderer[is-active] div#like-button #like-button button",
                //     "inject": true,
                //     "fun": [set_shorts_download]
                // }
            ],
            // "yt_watch": [{
            //     "seletor": "div.YtSegmentedLikeDislikeButtonViewModelSegmentedButtonsWrapper",
            //     "count": 30,
            //     "fun": set_watch_download
            // }],
            // "yt_music_watch": [{
            //     "seletor": "#layout > ytmusic-player-bar > div.middle-controls.style-scope.ytmusic-player-bar > div.middle-controls-buttons.style-scope.ytmusic-player-bar > #like-button-renderer > yt-button-shape.dislike > button",
            //     "inject": true,
            //     "fun": set_music_download
            // }],
            // "mobile_yt_watch": [{
            //     "seletor": "div.YtSegmentedLikeDislikeButtonViewModelSegmentedButtonsWrapper",
            //     "count": 10,
            //     "fun": set_watch_download
            // }],
            "mobile_yt_shorts": [{
                "seletor": 'div.carousel-item[aria-hidden="false"] ytm-like-button-renderer',
                "count": 10,
                "fun": [ shorts_auto_scroll, set_shorts_dbclick_like, set_shorts_progress]
            }],
        };

        common();
        element_monitor();
        function set_dbclick(node, handler) {
            if (node.inject_dbclick) return;
            node.inject_dbclick = true;
            let corgin_onclick = node.onclick;
            let timers = [];
            node.onclick = node.onclick_ = function (event) {
                if ((node.dbclick_intercept_propagation || node.click_intercept_propagation)) {
                    event.stopPropagation();
                }
                const timer = setTimeout(() => {
                    if (node.dbclick_intercept_propagation && !node.click_intercept_propagation) {
                        let parent = node.parentElement;
                        if (parent) {
                            let parentHandler = parent.onclick;
                            if (typeof parentHandler === 'function') {
                                parentHandler.call(parent, event);
                            }
                            parent.dispatchEvent(event);
                        }
                    }
                    timers.splice(timers.indexOf(timer), 1);
                    corgin_onclick?.call(this, event);
                }, 300);
                timers.push(timer);
            };
            define_property_hook(node, 'onclick', {
                get: function () {
                    return this.onclick_;
                },
                set: function (fun) {
                    corgin_onclick = fun;
                }
            });
            node.addEventListener('dblclick', function (event) {
                if (node.dbclick_intercept_propagation) event.stopPropagation();
                for (let timer of timers) {
                    clearTimeout(timer);
                }
                timers.length = 0;
                handler?.call(this, event);
            });
        }
        function set_download_event(dislike_node, like_node, url = href) {
            if (!like_node) log('like_node is null');
            if (!dislike_node) log('dislike_node is null');
            if (!like_node || !dislike_node) {
                log('set_download_event error like_node or dislike_node is null', -1);
                return;
            };
            function randomColor() {
                var letters = '0123456789ABCDEF';
                var color = '#';
                for (var i = 0; i < 6; i++) {
                    color += letters[Math.floor(Math.random() * 16)];
                }
                return color;
            }
            function set_node_download_event(node, type = 'like') {
                node.style.transition = `${node.style.transition && (node.style.transition + " , ")}background-color 0.5s ease`;
                node.backgroundColor_ = node.style.backgroundColor;
                node.resolve_background_color = function () {
                    if (this.background_color_interval_id) clearInterval(this.background_color_interval_id);
                    this.style.backgroundColor = this.backgroundColor_;
                };
                set_dbclick(node, () => {
                    if (user_data.dbclick_download_video === 'off') return;
                    const tips = type === 'like' ? flag_info.download_video_confirm_tips : flag_info.download_audio_confirm_tips;
                    if (!confirm(`${unsafeWindow.document.title}\n\n${tips}`)) return;
                    const result = video_download(url, type !== 'like', node);
                    if (result) {
                        node.background_color_interval_id = setInterval(() => {
                            node.style.backgroundColor = randomColor();
                        }, 100);
                    }
                });
            }
            set_node_download_event(like_node, 'like');
            set_node_download_event(dislike_node, 'dislike');
        }
        function set_shorts_dbclick_like(video_node) {
            video_node = page_type === 'yt_shorts' ? video_node : $('div.carousel-item[aria-hidden="false"] div.video-wrapper');
            if (!video_node) return;
            video_node.dbclick_intercept_propagation = true;
            set_dbclick(video_node, function () {
                if (user_data.shorts_dbclick_like === 'off') return;
                const like_seltor = page_type === 'yt_shorts' ? 'ytd-reel-video-renderer[is-active] #like-button > yt-button-shape > label > button' : 'div.carousel-item[aria-hidden="false"] ytm-like-button-renderer button';
                $(like_seltor)?.click();
            });
        }
        function set_shorts_progress(node) {
            const video_node = page_type === 'yt_shorts' ? node : $('video');
            if (!video_node || video_node.inject_shorts_progress) return;
            video_node.inject_shorts_progress = true;
            video_node.addEventListener('timeupdate', function () {
                if (user_data.shorts_add_video_progress === 'off') return;
                const shape_button = page_type === 'yt_shorts' ? $('ytd-reel-video-renderer[is-active] #button-shape > button') : $('div.carousel-item[aria-hidden="false"] ytm-bottom-sheet-renderer button');
                if (!shape_button) return;
                const progress = video_node.currentTime / video_node.duration * 100;
                const transparency = page_type === 'yt_shorts' ? '0.05' : '0.3';
                const progress_color = page_type === 'yt_shorts' ? 'rgba(0, 0, 255, 0.4)' : 'rgba(255, 255, 0, 0.4)';
                shape_button.style.background = `linear-gradient(to top, ${progress_color} ${progress}%, rgba(0, 0, 0, ${transparency}) ${progress}%)`;
            });
        }
        function shorts_change_comment_click(comments_node) {
            const comments_button = comments_node.querySelector('ytd-button-renderer > yt-button-shape > label > button');
            const onclick_setter = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "onclick").set;
            const current_render_node = $('ytd-reel-video-renderer[is-active]');
            const wrap = function (fun) {
                return function (event) {
                    const expand_node = current_render_node.querySelector('#watch-while-engagement-panel > ytd-engagement-panel-section-list-renderer:nth-child(1)');
                    if (expand_node?.visibility === 'ENGAGEMENT_PANEL_VISIBILITY_EXPANDED') {
                        const expand_close_node = current_render_node.querySelector('#visibility-button > ytd-button-renderer > yt-button-shape > button');
                        expand_close_node?.click();
                    } else {
                        fun.call(this, event);
                    }
                };
            };
            comments_button.onclick = comments_button.onclick_ = wrap(comments_button.onclick);
            define_property_hook(comments_button, 'onclick', {
                get: function () {
                    return this.onclick_;
                },
                set: function (fun) {
                    this.onclick_ = wrap(fun);
                    onclick_setter.call(comments_button, this.onclick_);
                }
            });
        }
        function shorts_auto_scroll(video_node) {
            video_node = page_type === 'yt_shorts' ? video_node : $('video');
            if (!video_node) return;
            if (video_node?.inject_auto_scroll) return;
            video_node.inject_auto_scroll = true;
            video_node.loop = false;
            define_property_hook(video_node, 'loop', {
                get: function () {
                    return false;
                }
            });
            video_node?.addEventListener('ended', function () {
                if (user_data.shorts_auto_scroll === 'on') {
                    if (page_type === 'yt_shorts') {
                        $('#navigation-button-down > ytd-button-renderer > yt-button-shape > button').click();
                    } else {
                        simulate_swipeup(this, 500, 100);
                    }
                    return;
                }
                if (user_data.shorts_disable_loop_play === 'on') {
                    return;
                }
                this.play();
            });
        }
        function set_shorts_download(like_button) {
            const dislike_button = $('ytd-reel-video-renderer[is-active] #dislike-button > yt-button-shape > label > button');
            set_download_event(dislike_button, like_button);
        }
        function set_music_download(dislike_node) {
            const like_node = dislike_node.parentElement.parentElement.querySelector('#button-shape-like > button');
            set_download_event(dislike_node, like_node);
        }
        function set_watch_download(wrapper_node) {
            const like_node = wrapper_node.querySelector('like-button-view-model button');
            const dislike_node = wrapper_node.querySelector('dislike-button-view-model button');
            set_download_event(dislike_node, like_node);
        }
        function set_mobile_shorts_download(wrapper_node) {
            const nodes = wrapper_node.querySelectorAll('button');
            if (nodes.length !== 2) {
                log('set_mobile_shorts_download 节点数量不正确', nodes.length, -1);
                return;
            }
            const like_node = nodes[0];
            const dislike_node = nodes[1];
            dislike_node.click_intercept_propagation = true;
            dislike_node.dbclick_intercept_propagation = true;
            like_node.click_intercept_propagation = true;
            like_node.dbclick_intercept_propagation = true;
            set_download_event(dislike_node, like_node);
        }
        function video_download(url = href, isAudioOnly = false, targetNode = null) {
            if (page_type === 'yt_music_watch') {
                url = 'https://www.youtube.com/watch?' + href.split('?')[1];
            }
            // log('下载地址', url, isAudioOnly, 0);
            if (analyzing_download_url) return false;
            analyzing_download_url = true;
            const xhr = new XMLHttpRequest();
            xhr.open('POST', 'https://api.cobalt.tools/api/json', true);
            xhr.setRequestHeader('Cache-Control', 'no-cache');
            xhr.setRequestHeader('Accept', 'application/json');
            xhr.setRequestHeader('Content-Type', 'application/json');

            const data = JSON.stringify({
                url: encodeURI(url),
                vQuality: 'max',
                filenamePattern: 'basic',
                isAudioOnly: isAudioOnly,
                disableMetadata: true,
            });
            xhr.onload = function () {
                if (xhr.status >= 200 && xhr.status < 300) {
                    const response = JSON.parse(xhr.responseText);
                    const download_url = response?.url;
                    if (download_url) {
                        window.open(download_url, '_blank');
                        analyzing_download_url = false;
                        targetNode.resolve_background_color();
                        return;
                    }
                }
                let tips;
                try {
                    const json_data = JSON.parse(xhr.responseText);
                    tips = json_data?.text;
                } catch (error) {
                    tips = xhr.responseText;
                }
                alert(`download failed\nstatus: ${xhr.status}\nresponseText: ${tips}\n`);
                analyzing_download_url = false;
                targetNode.resolve_background_color();
            };

            xhr.onerror = function (error) {
                alert(`download failed\nstatus: ${xhr.status}\nerror: ${error}\n`);
                analyzing_download_url = false;
                targetNode.resolve_background_color();
            };
            xhr.send(data);
            return true;
        }
    }

    function get_user_data_listener() {
        return {
            cur_channel_id: null,
            listener_id: null,
            set: function () {
                if (channel_id === this.cur_channel_id) {
                    return;
                };
                !this.cur_channel_id && GM_removeValueChangeListener(this.listener_id);
                this.cur_channel_id = channel_id;
                this.listener_id = GM_addValueChangeListener(channel_id, (name, oldValue, newValue, remote) => {
                    if (!remote || this.cur_channel_id !== name) return;
                    newValue.language = user_data.language;
                    user_data = newValue;
                    config_api.config_init();
                    const popup_node = unsafeWindow.document.getElementById('xxx_popup');
                    popup_node && display_config_win();
                });
            }
        };
    }

    async function account_data_init(login) {
        if (is_account_init) return;
        is_account_init = true;
        if (login) {
            yt_api.get_channel_id();
            yt_api.get_subscribe_data();
        } else if (channel_id !== 'default') {
            channel_id = 'default';
            user_data.login = false;
            user_data = user_data_api.get();
        }
    }

    function native_method_hook(method_path, handler) {
        try {
            let [last_path, last_key] = data_process.get_lastPath_and_key(method_path);
            let last_obj = data_process.string_to_value(unsafeWindow, 'unsafeWindow.' + last_path);
            let dec_obj = last_obj[last_key];
            last_obj[last_key + '__'] = dec_obj;
            if (typeof dec_obj !== 'function') {
                log(method_path, 'have been modified', -1);
                return;
            }
            const method_name = dec_obj.name;
            if (dec_obj.toString() !== 'function ' + method_name + '() { [native code] }') {
                log(method_path, 'have been modified!', -1);
            }
            last_obj[last_key] = handler;
        } catch (error) {
            log(method_path, 'hook failed!', error, -1);
        }
    }

    function define_property_hook(obj, property, descriptor) {
        const old_descriptor = Object.getOwnPropertyDescriptor(obj, property);
        if (old_descriptor?.configurable === false) {
            debugger;
            log(property, 'is not configurable, hook error !', old_descriptor, -1);
            return;
        }
        try {
            Object.defineProperty(obj, property, descriptor);
        } catch (error) {
            log(property, 'hook failed!', error, -1);
        }
    }

    function get_config_api() {
        return {
            flag_infos: {
                "zh-CN": {
                    "sponsored": "赞助商广告",
                    "free_movie": "免费(含广告)",
                    "live": "直播",
                    "movie_channel": "影视",
                    "free_primetime_movie": "免费 Primetime 电影",
                    "Playables": "游戏大本营",
                    "short_buy_super_thanks": "购买超级感谢",
                    "think_video": "你对这个视频有何看法?|此推荐内容怎么样?",
                    "try": "试用",
                    "recommend_popular": "时下流行",
                    "featured": "Featured",
                    "category_live": "直播",
                    "category_game": "游戏",
                    "category_news": "新闻",
                    "btn_recommend_movie": "电影推荐",
                    "btn_recommend_shorts": "Shorts推荐",
                    "btn_recommend_liveroom": "直播推荐",
                    "btn_recommend_popular": "时下流行",
                    "btn_recommend_game": "游戏大本营推荐",
                    "btn_save": "保存",
                    "goodselect": "精选",
                    "music_ad_flag": "无广告打扰",
                    "upcoming": "即将开始",
                    "init": "初始化",
                    "ctoc": "已复制到剪贴板",
                    "runing_normally": "运行正常",
                    "err_msg": "错误信息",
                    "success": "成功",
                    "failed": "失败",
                    "tips": "你可以发送错误信息或者截图发给脚本开发者",
                    "exists_error": "存在错误信息(建议多次刷新观察是否是同样的错误信息)",
                    "inject": "注入",
                    "btn_lable_open": "开启",
                    "btn_lable_close": "关闭",
                    "btn_lable_subscribed": "仅订阅",
                    "recommend_subscribed_lable_tips": "只显示已订阅的推荐",
                    "title_add_shorts_upload_date": "Shorts添加更新时间",
                    "title_shorts_change_author_name": "Shorts用户名改频道名",
                    "config_info": "配置信息",
                    "page_info": "页面信息",
                    "rule_info": "规则信息",
                    "del_config_confirm_tips": "你确定要删除所有配置信息?",
                    "btn_dbclick_download_video_tips": "双击点赞下载视频,双击不喜欢下载音频",
                    "btn_dbclick_download_video_title": "双击下载视频",
                    "download_video_confirm_tips": "要下载这个视频?",
                    "download_audio_confirm_tips": "要下载这个音频?",
                    "btn_shorts_auto_scroll_title": "自动滚动",
                    "bt_shorts_disable_loop_play_title": "禁止循环播放",
                    "btn_shorts_dbclick_like_title": "双击视频点赞",
                    "btn_shorts_add_video_progress_title": "添加视频进度",
                    "shorts_recommend_split_tag": "Shorts功能配置",
                },
                "zh-TW": {
                    "sponsored": "贊助商廣告",
                    "free_movie": "免費 \\(含廣告\\)",
                    "live": "直播",
                    "movie_channel": "電影與電視節目",
                    "Playables": "遊戲角落",
                    "free_primetime_movie": "免費的特選電影",
                    "short_buy_super_thanks": "購買超級感謝",
                    "think_video": "你對這部影片有什麼看法?|此推荐内容怎么样?",
                    "try": "試用",
                    "recommend_popular": "發燒影片",
                    "featured": "Featured",
                    "category_live": "直播中",
                    "category_game": "遊戲",
                    "category_news": "新聞",
                    "btn_recommend_movie": "电影推薦",
                    "btn_recommend_shorts": "Shorts推薦",
                    "btn_recommend_liveroom": "直播推薦",
                    "btn_recommend_popular": "發燒影片",
                    "btn_recommend_game": "遊戲角落推薦",
                    "btn_save": "保存",
                    "goodselect": "精選內容",
                    "music_ad_flag": "零廣告",
                    "upcoming": "即将直播",
                    "init": "初始化",
                    "ctoc": "已複製到剪貼板",
                    "runing_normally": "運行正常",
                    "err_msg": "錯誤訊息",
                    "success": "成功",
                    "failed": "失敗",
                    "tips": "你可以发送錯誤訊息或截圖給腳本開發者",
                    "exists_error": "存在錯誤訊息(建議多次刷新觀察是否是同樣的錯誤訊息)",
                    "inject": "注入",
                    "btn_lable_open": "開啓",
                    "btn_lable_close": "關閉",
                    "btn_lable_subscribed": "僅訂閱",
                    "recommend_subscribed_lable_tips": "只顯示已訂閱的推薦",
                    "title_add_shorts_upload_date": "Shorts添加更新時間",
                    "title_shorts_change_author_name": "Shorts用戶名稱改頻道名",
                    "config_info": "設定資訊",
                    "page_info": "頁面資訊",
                    "rule_info": "規則資訊",
                    "del_config_confirm_tips": "你確定要刪除所有設定資訊?",
                    "btn_dbclick_download_video_tips": "雙擊我喜歡下載影片,雙擊我不喜歡下載音檔",
                    "btn_dbclick_download_video_title": "雙擊下載視頻",
                    "download_video_confirm_tips": "要下載這個影片?",
                    "download_audio_confirm_tips": "要下載這個音檔?",
                    "btn_shorts_auto_scroll_title": "自動捲動",
                    "bt_shorts_disable_loop_play_title": "禁止循環播放",
                    "btn_shorts_dbclick_like_title": "雙擊影片按讚",
                    "btn_shorts_add_video_progress_title": "添加影片進度",
                    "shorts_recommend_split_tag": "Shorts功能配置",
                },
                "zh-HK": {
                    "sponsored": "赞助",
                    "free_movie": "免費 \\(有廣告\\)",
                    "live": "直播",
                    "movie_channel": "電影與電視節目",
                    "Playables": "Playables",
                    "short_buy_super_thanks": "購買 Super Thanks",
                    "free_primetime_movie": "黃金時段電影",
                    "think_video": "你對此影片有何意見?|此推荐内容怎么样?",
                    "try": "試用",
                    "recommend_popular": "熱爆影片",
                    "featured": "Featured",
                    "category_live": "直播",
                    "category_game": "遊戲",
                    "category_news": "新聞",
                    "btn_recommend_movie": "电影推薦",
                    "btn_recommend_shorts": "Shorts推薦",
                    "btn_recommend_liveroom": "直播推薦",
                    "btn_recommend_popular": "熱爆影片",
                    "btn_recommend_game": "Playables推荐",
                    "btn_save": "保存",
                    "goodselect": "精選",
                    "music_ad_flag": "零廣告音樂",
                    "upcoming": "即將發佈",
                    "init": "初始化",
                    "ctoc": "已複製到剪貼板",
                    "runing_normally": "運行正常",
                    "err_msg": "錯誤訊息",
                    "success": "成功",
                    "failed": "失敗",
                    "tips": "你可以发送錯誤訊息或截圖給腳本開發者",
                    "exists_error": "存在錯誤訊息(建議多次刷新觀察是否是同樣的錯誤訊息)",
                    "inject": "注入",
                    "btn_lable_open": "開啓",
                    "btn_lable_close": "關閉",
                    "btn_lable_subscribed": "僅訂閱",
                    "recommend_subscribed_lable_tips": "只顯示已訂閱的推薦",
                    "title_add_shorts_upload_date": "Shorts添加更新時間",
                    "title_shorts_change_author_name": "Shorts用戶名稱改頻道名",
                    "config_info": "設定資訊",
                    "page_info": "頁面資訊",
                    "rule_info": "規則資訊",
                    "del_config_confirm_tips": "你確定要刪除所有配置信息嗎?",
                    "btn_dbclick_download_video_tips": "雙擊我喜歡下載影片,雙擊我不喜歡下載音檔",
                    "btn_dbclick_download_video_title": "雙擊下載視頻",
                    "download_video_confirm_tips": "要下載這個影片?",
                    "download_audio_confirm_tips": "要下載這個音檔?",
                    "btn_shorts_auto_scroll_title": "自動捲動",
                    "bt_shorts_disable_loop_play_title": "禁止循環播放",
                    "btn_shorts_dbclick_like_title": "雙擊影片按讚",
                    "btn_shorts_add_video_progress_title": "添加影片進度",
                    "shorts_recommend_split_tag": "Shorts功能配置",
                },
                "en": {
                    "sponsored": "Sponsored",
                    "free_movie": "Free with ads",
                    "live": "LIVE",
                    "movie_channel": "Movies & TV",
                    "Playables": "Playables",
                    "short_buy_super_thanks": "Buy Super Thanks",
                    "free_primetime_movie": "Free Primetime movies",
                    "think_video": "What did you think of this video?|此推荐内容怎么样?",
                    "try": "Try",
                    "recommend_popular": "Trending",
                    "featured": "Featured",
                    "category_live": "Live",
                    "category_game": "Gaming",
                    "category_news": "News",
                    "btn_recommend_movie": "MovieRecommend",
                    "btn_recommend_shorts": "ShortsRecommend",
                    "btn_recommend_liveroom": "LiveRecommend",
                    "btn_recommend_popular": "TrendingRecommend",
                    "btn_recommend_game": "PlayablesRecommend",
                    "btn_save": "Save",
                    "goodselect": "Featured",
                    "music_ad_flag": "ad-free",
                    "upcoming": "UPCOMING",
                    "init": "init",
                    "ctoc": "Copied to clipboard",
                    "runing_normally": "running normally",
                    "err_msg": "error message",
                    "success": "success",
                    "failed": "failed",
                    "tips": "You can send error message or screenshot to the developer",
                    "exists_error": "Error message exists (It is recommended to refresh multiple times to see if it is the same error message)",
                    "inject": "inject",
                    "btn_lable_open": "on",
                    "btn_lable_close": "off",
                    "btn_lable_subscribed": "onlySubscribed",
                    "recommend_subscribed_lable_tips": "only show subscribed recommend",
                    "title_add_shorts_upload_date": "ShortsAddUploadTime",
                    "title_shorts_change_author_name": "ShortsChangeToChannelName",
                    "config_info": "config info",
                    "page_info": "page info",
                    "rule_info": "rule info",
                    "del_config_confirm_tips": "Are you sure you want to delete all configuration settings?",
                    "btn_dbclick_download_video_tips": "Double click like button to download the video, double click dislike button to download the audio",
                    "btn_dbclick_download_video_title": "DoubleClickDownloadVideo",
                    "download_video_confirm_tips": "Do you want to download this video?",
                    "download_audio_confirm_tips": "Do you want to download this audio?",
                    "btn_shorts_auto_scroll_title": "AutoScroll",
                    "bt_shorts_disable_loop_play_title": "DisableLoopPlay",
                    "btn_shorts_dbclick_like_title": "DoubleClickLikeVideo",
                    "btn_shorts_add_video_progress_title": "AddVideoProgress",
                    "shorts_recommend_split_tag": "ShortsConfig",
                }
            },
            common_ytInitialPlayerResponse_rule: [
                "abs:playerAds=- $exist",
                "abs:adSlots=- $exist",
                "abs:adPlacements=- $exist",
                "abs:auxiliaryUi.messageRenderers.bkaEnforcementMessageViewModel.isVisible=json(\"true\") $exist",
                "abs:adBreakHeartbeatParams=- $exist",
                "abs:messages[*]=- /.mealbarPromoRenderer$exist",
            ],
            default_language: 'en',
            config_init: function (tmp_language = null) {
                if (!tmp_language) {
                    tmp_language = unsafeWindow['ytcfg'].msgs ? unsafeWindow['ytcfg'].msgs.__lang__ : (unsafeWindow['ytcfg'].data ? unsafeWindow['ytcfg'].data.HL : undefined);
                    !tmp_language && (tmp_language = unsafeWindow['yt'] && unsafeWindow['yt'].config_ && unsafeWindow['yt'].config_.HL);
                    if (!tmp_language) {
                        log('语言获取错误', unsafeWindow, -1);
                    }
                }
                if (!['en', 'zh-CN', 'zh-TW', 'zh-HK'].includes(tmp_language)) {
                    real_language = tmp_language;
                    tmp_language = this.default_language;
                }
                if (tmp_language !== user_data.language) {
                    user_data.language = tmp_language;
                    user_data_api.set();
                }
                flag_info = this.flag_infos[user_data.language];
                movie_channel_info = {
                    "guideEntryRenderer": {
                        "navigationEndpoint": {
                            "clickTrackingParams": "CBQQnOQDGAIiEwj5l8SLqPiCAxUXSEwIHbf1Dw0=",
                            "commandMetadata": {
                                "webCommandMetadata": {
                                    "url": "/feed/storefront",
                                    "webPageType": "WEB_PAGE_TYPE_BROWSE",
                                    "rootVe": 6827,
                                    "apiUrl": "/youtubei/v1/browse"
                                }
                            },
                            "browseEndpoint": {
                                "browseId": "FEstorefront"
                            }
                        },
                        "icon": {
                            "iconType": "CLAPPERBOARD"
                        },
                        "trackingParams": "CBQQnOQDGAIiEwj5l8SLqPiCAxUXSEwIHbf1Dw0=",
                        "formattedTitle": {
                            "simpleText": flag_info.movie_channel
                        },
                        "accessibility": {
                            "accessibilityData": {
                                "label": flag_info.movie_channel
                            }
                        }
                    }
                };
                data_process.storage_obj('movie_channel_info', movie_channel_info);
                mobile_movie_channel_info = {
                    "navigationItemViewModel": {
                        "text": {
                            "content": flag_info.movie_channel
                        },
                        "icon": {
                            "sources": [
                                {
                                    "clientResource": {
                                        "imageName": "CLAPPERBOARD"
                                    }
                                }
                            ]
                        },
                        "onTap": {
                            "parallelCommand": {
                                "commands": [
                                    {
                                        "innertubeCommand": {
                                            "clickTrackingParams": "CBQQnOQDGAIiEwj5l8SLqPiCAxUXSEwIHbf1Dw0=",
                                            "hideMoreDrawerCommand": {}
                                        }
                                    },
                                    {
                                        "innertubeCommand": {
                                            "clickTrackingParams": "CBQQnOQDGAIiEwj5l8SLqPiCAxUXSEwIHbf1Dw0=",
                                            "commandMetadata": {
                                                "webCommandMetadata": {
                                                    "url": "/feed/storefront",
                                                    "webPageType": "WEB_PAGE_TYPE_CHANNEL",
                                                    "rootVe": 3611,
                                                    "apiUrl": "/youtubei/v1/browse"
                                                }
                                            },
                                            "browseEndpoint": {
                                                "browseId": "FEstorefront"
                                            }
                                        }
                                    }
                                ]
                            }
                        },
                        "loggingDirectives": {
                            "trackingParams": "CBQQnOQDGAIiEwj5l8SLqPiCAxUXSEwIHbf1Dw0=",
                            "visibility": {
                                "types": "12"
                            },
                            "enableDisplayloggerExperiment": true
                        }
                    }
                };
                data_process.storage_obj('mobile_movie_channel_info', mobile_movie_channel_info);
                ytInitialData_rule = null;
                ytInitialReelWatchSequenceResponse_rule = null;
                ytInitialPlayerResponse_rule = null;
                mobile_web = page_type.startsWith('mobile');
            },
            get_rules: function (page_type_, type) {
                page_type_ = page_type_ || page_type;
                if (page_type_ === 'mobile_yt_watch_searching')
                    page_type_ = 'mobile_yt_watch';
                else if (page_type_ === 'mobile_yt_home_searching')
                    page_type_ = 'mobile_yt_home';
                else if (page_type_ === 'yt_music_channel')
                    page_type_ = 'yt_watch';

                let tmp_ytInitialData_rule = null;
                let tmp_ytInitialReelWatchSequenceResponse_rule = null;
                let tmp_ytInitialPlayerResponse_rule = null;
                const common_ytInitialData_rule = [
                    'adSlotRenderer.=-',
                ];
                const return_obj = {
                    ytInitialData_rule: null,
                    ytInitialReelWatchSequenceResponse_rule: null,
                    ytInitialPlayerResponse_rule: null,
                    reverse: false,
                };
                if (page_type_ === 'yt_search') {
                    tmp_ytInitialData_rule = common_ytInitialData_rule;
                    return_obj.ytInitialData_rule = tmp_ytInitialData_rule;
                    return return_obj;
                }

                if (page_type_ === 'yt_music') {
                    return_obj.ytInitialData_rule = ["abs:overlay.mealbarPromoRenderer=- $exist"];
                    return return_obj;
                }

                if (page_type_ === 'mobile_yt_search') {
                    tmp_ytInitialData_rule = common_ytInitialData_rule;
                    return_obj.ytInitialData_rule = tmp_ytInitialData_rule;
                    return return_obj;
                }

                if (page_type_ === 'yt_kids_watch') {
                    tmp_ytInitialData_rule = common_ytInitialData_rule;
                    return_obj.ytInitialData_rule = tmp_ytInitialData_rule;
                    return return_obj;
                }

                if (page_type_ === 'yt_music_watch') {
                    tmp_ytInitialData_rule = common_ytInitialData_rule;
                    return_obj.ytInitialData_rule = tmp_ytInitialData_rule;
                    return return_obj;
                }

                if (page_type_.includes('yt_shorts')) {
                    const tmp_ytInitialData_rule__ = [];
                    // 添加时间 // 改频道名
                    if (user_data.add_shorts_upload_date === 'on' || user_data.shorts_change_author_name === 'on') {
                        let dec_path = 'overlay.reelPlayerOverlayRenderer.reelPlayerHeaderSupportedRenderers.reelPlayerHeaderRenderer.channelTitleText.runs[0].text';
                        let name_base_path = 'json_obj.engagementPanels[1].engagementPanelSectionListRenderer.content.structuredDescriptionContentRenderer.items[0].videoDescriptionHeaderRenderer.channel.';
                        let time_tag_path;
                        let name_tag_path;
                        if (mobile_web) {
                            user_data.add_shorts_upload_date === 'on' && (time_tag_path = '....timestampText.runs[0].text');
                            user_data.shorts_change_author_name === 'on' && (name_tag_path = name_base_path + 'runs[0].text');
                        } else {
                            user_data.add_shorts_upload_date === 'on' && (time_tag_path = '....timestampText.simpleText');
                            user_data.shorts_change_author_name === 'on' && (name_tag_path = name_base_path + 'simpleText');
                        }
                        let rule = `abs:${dec_path}={absObj(${name_tag_path ? name_tag_path : ('json_obj.' + dec_path)})\}${time_tag_path ? ('\n{pathObj(' + time_tag_path + ')\}') : ''}`;
                        tmp_ytInitialData_rule__.push(rule);
                    }

                    // 超级感谢 
                    if (user_data.short_buy_super_thanks === 'off') {
                        // !mobile_web && tmp_ytInitialData_rule__.push('abs:overlay.reelPlayerOverlayRenderer.suggestedAction=- /.shortsSuggestedActionRenderer.text.runs[0].text=' + flag_info.short_buy_super_thanks);
                        !mobile_web && tmp_ytInitialData_rule__.push('abs:overlay.reelPlayerOverlayRenderer.suggestedAction=- $exist');
                    }
                    tmp_ytInitialReelWatchSequenceResponse_rule = ['abs:entries[*]=- /.command.reelWatchEndpoint.adClientParams$exist'];
                    tmp_ytInitialData_rule__.length && (tmp_ytInitialData_rule = tmp_ytInitialData_rule__);
                    return_obj.ytInitialReelWatchSequenceResponse_rule = tmp_ytInitialReelWatchSequenceResponse_rule;
                    return_obj.ytInitialData_rule = tmp_ytInitialData_rule;
                    return return_obj;
                }

                if (page_type_.includes('yt_watch')) {
                    return function (json_obj) {
                        /* 
                                            item_path
                                                next 类型
                                                    移动端和桌面端
                                                        abs:onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems[*]
                                                init 类型
                                                    移动端
                                                        abs:contents.singleColumnWatchNextResults.results.results.contents[*]
                                                    桌面端 
                                                        abs:contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results[1].itemSectionRenderer.contents[*] 
                        
                                            videoRenderer_path
                                                桌面端
                                                    /.compactVideoRenderer
                                                移动端
                                                    /.itemSectionRenderer.contents[0].videoWithContexteRnderer
                                            section_path
                                                桌面端
                                                    /.reelShelfRenderer
                                                移动端
                                                    /.itemSectionRenderer.contents[0].reelShelfRenderer
                                            */

                        if (json_obj.continuation) return [];
                        let video_item_base_path;
                        let video_sub_path;
                        let section_sub_path;
                        let player_bottom_path;
                        let player_bottom_section_path;
                        type = type || 'init';
                        if (type === 'next') {
                            if (json_obj.onResponseReceivedEndpoints?.[0]?.appendContinuationItemsAction?.continuationItems?.length) {
                                let target_id = json_obj.onResponseReceivedEndpoints[0].appendContinuationItemsAction.targetId;
                                if (target_id.startsWith('comment-replies')) return [];
                                // 下拉item刷新
                                video_item_base_path = "abs:onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems[*]";
                                video_sub_path = '/.videoWithContextRenderer';
                                section_sub_path = '/.reelShelfRenderer';
                            }

                        } else if (type === 'init') {
                            if (mobile_web) {
                                if (json_obj.contents?.singleColumnWatchNextResults?.results?.results?.contents?.length) {
                                    let length = json_obj.contents.singleColumnWatchNextResults.results.results.contents.length;
                                    video_item_base_path = `abs:contents.singleColumnWatchNextResults.results.results.contents[${length - 1}].itemSectionRenderer.contents[*]`;
                                    length > 1 && (player_bottom_path = `abs:contents.singleColumnWatchNextResults.results.results.contents[0-${length - 2}]`);
                                    cur_watch_channle_id = json_obj.contents.singleColumnWatchNextResults.results.results.contents?.[1]?.slimVideoMetadataSectionRenderer?.contents?.[1]?.slimOwnerRenderer?.title.runs[0].navigationEndpoint.browseEndpoint.browseId;
                                    player_bottom_section_path = '/.itemSectionRenderer.contents[0].reelShelfRenderer';
                                    video_sub_path = '/.videoWithContextRenderer';
                                    section_sub_path = '/.reelShelfRenderer';
                                }
                            }
                            else {
                                let is_next_target_id;
                                if (json_obj.contents?.twoColumnWatchNextResults?.secondaryResults?.secondaryResults?.results?.[1]?.itemSectionRenderer?.contents?.length) {
                                    video_item_base_path = "abs:contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results[1].itemSectionRenderer.contents[*]";
                                    player_bottom_path = 'abs:contents.twoColumnWatchNextResults.results.results.contents[*]';
                                    is_next_target_id = json_obj.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results[1].itemSectionRenderer.targetId === 'watch-next-feed';
                                    cur_watch_channle_id = json_obj.contents.twoColumnWatchNextResults.results.results.contents?.[1]?.videoSecondaryInfoRenderer?.owner?.videoOwnerRenderer?.title.runs[0].navigationEndpoint.browseEndpoint.browseId;
                                    player_bottom_section_path = '/.itemSectionRenderer.contents[0]';
                                    video_sub_path = '/.compactVideoRenderer';
                                    section_sub_path = '/.reelShelfRenderer';
                                }
                                if (!is_next_target_id && json_obj.contents?.twoColumnWatchNextResults?.secondaryResults?.secondaryResults?.results?.[0]?.richGridRenderer?.contents?.length) {
                                    video_item_base_path = "abs:contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results[0].richGridRenderer.contents[*]";
                                    player_bottom_path = 'abs:contents.twoColumnWatchNextResults.results.results.contents[*]';
                                    is_next_target_id = json_obj.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results[0].richGridRenderer.targetId === 'watch-next-feed';
                                    cur_watch_channle_id = json_obj.contents.twoColumnWatchNextResults.results.results.contents?.[1]?.videoSecondaryInfoRenderer?.owner?.videoOwnerRenderer?.title.runs[0].navigationEndpoint.browseEndpoint.browseId;
                                    player_bottom_section_path = '/.itemSectionRenderer.contents[0]';
                                    video_sub_path = '/.richItemRenderer.content.videoRenderer';
                                    section_sub_path = '/.richSectionRenderer.content.richShelfRenderer';
                                }
                                if (!is_next_target_id && json_obj.contents?.twoColumnWatchNextResults?.secondaryResults?.secondaryResults?.results?.length) {
                                    video_item_base_path = 'abs:contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results[*]';
                                    player_bottom_path = 'abs:contents.twoColumnWatchNextResults.results.results.contents[*]';
                                    cur_watch_channle_id = json_obj.contents.twoColumnWatchNextResults.results.results.contents?.[1]?.videoSecondaryInfoRenderer?.owner?.videoOwnerRenderer?.title.runs[0].navigationEndpoint.browseEndpoint.browseId;
                                    player_bottom_section_path = '/.itemSectionRenderer.contents[0]';
                                    video_sub_path = '/.compactVideoRenderer';
                                    section_sub_path = '/.reelShelfRenderer';
                                }
                            }
                        }
                        if (!video_item_base_path) return [];

                        const rules = [];
                        let video_item_rules = [];
                        let section_item_rules = [];
                        let player_bottom_section_rules = [];
                        let player_bottom_rules = [];
                        //赞助商广告
                        mobile_web && type === 'init' && player_bottom_rules.push(`${player_bottom_section_path.replace(/\.[^\.]+$/, '')}.adSlotRenderer$exist`);
                        video_item_rules.push(`${video_sub_path.replace(/\.[^\.]+$/, '.adSlotRenderer$exist')}`);

                        // youtuber商品广告 https://www.youtube.com/watch?v=dFjXK8xpurY&list=RDCLAK5uy_mijutvVbzp7bbNlWt-B5U90qb5KplCkSQ&index=3
                        !mobile_web && type === 'init' && player_bottom_rules.push(`/.merchandiseShelfRenderer$exist`);

                        //免费电影
                        if (user_data.open_recommend_movie === 'off' && cur_watch_channle_id !== 'UClgRkhTL3_hImCAmdLfDE4g') {
                            if (mobile_web) {
                                video_item_rules.push(`${video_sub_path}.badges[0].metadataBadgeRenderer.style=BADGE_STYLE_TYPE_YPC`);
                            } else {
                                video_item_rules.push(`${video_sub_path.replace(/\.[^\.]+$/, '.compactMovieRenderer')}$exist`);
                            }
                        }

                        //直播规则
                        if (['off', 'subscribed'].includes(user_data.open_recommend_liveroom)) {
                            if (mobile_web)
                                video_item_rules.push(`${video_sub_path}.thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer.style=LIVE|UPCOMING`);
                            else
                                video_item_rules.push(`${video_sub_path}.badges[0].metadataBadgeRenderer.style=BADGE_STYLE_TYPE_LIVE_NOW`);
                        }

                        // 添加已订阅短视频
                        if (user_data.open_recommend_shorts === 'subscribed' && type === 'init' && page_type !== 'mobile_yt_watch') {
                            rules.push(`${video_item_base_path.replace('[*]', '')}=+(arr_insert,method(shorts_fun.get_shorts_section()),0) @user_data.shorts_list.length$value>0`);
                        }

                        // 大标题栏目 短视频等
                        if (['off', 'subscribed'].includes(user_data.open_recommend_shorts)) {
                            section_item_rules.push(`${section_sub_path}.icon.iconType=YOUTUBE_SHORTS_BRAND_24`);
                            mobile_web && type === 'init' && player_bottom_rules.push(`${player_bottom_section_path}.icon.iconType=YOUTUBE_SHORTS_BRAND_24`);
                        }

                        // 视频下方可能会出现的推荐栏目
                        player_bottom_rules.length && rules.push(`${player_bottom_path}=- ${player_bottom_rules.join(data_process.condition_split_or_tag)}`);
                        section_item_rules.length && video_item_rules.push(...section_item_rules);
                        video_item_rules.length && rules.push(`${video_item_base_path}=- ${video_item_rules.join(data_process.condition_split_or_tag)}`);
                        return rules;
                    };
                }

                if (page_type_.includes('yt_home')) {
                    /* 
                    item_path
                        browse 类型
                            移动端和桌面端
                                abs:onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems[*]
                        init 类型
                            移动端
                                abs:contents.singleColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.richGridRenderer.contents[*]
                            桌面端
                                singleColumnBrowseResultsRenderer ---> twoColumnBrowseResultsRenderer
          
                    videoRenderer_path
                        桌面端
                            /.richItemRenderer.content.videoRenderer
                        移动端
                             videoRenderer --> videoWithContextRenderer
                    
                    richSectionRenderer_path
                        桌面端
                            /.richSectionRenderer.content.richShelfRenderer
                        移动端
                            richShelfRenderer ---> reelShelfRenderer
                    */
                    let item_path;
                    let item_rules = [];
                    let rules = [];
                    type = type || 'init';
                    if (type === 'browse') {
                        item_path = "abs:onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems[*]";
                    } else if (type === 'init') {
                        item_path = `abs:contents.${mobile_web ? 'singleColumnBrowseResultsRenderer' : 'twoColumnBrowseResultsRenderer'}.tabs[0].tabRenderer.content.richGridRenderer.contents[*]`;
                    } else {
                        return {};
                    }
                    const video_path = `/.richItemRenderer.content.${mobile_web ? 'videoWithContextRenderer' : 'videoRenderer'}`;
                    const section_path = `/.richSectionRenderer.content.${mobile_web ? 'reelShelfRenderer' : 'richShelfRenderer'}`;

                    //赞助商广告
                    item_rules.push('/.richItemRenderer.content.adSlotRenderer$exist');

                    //头部第一个广告
                    !mobile_web && type === 'init' && rules.push('abs:contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.richGridRenderer.masthead=- $exist');

                    // Shorts
                    if (['off', 'subscribed'].includes(user_data.open_recommend_shorts)) {
                        item_rules.push(`${section_path}.icon.iconType=YOUTUBE_SHORTS_BRAND_24`);
                    }

                    // 时下流行
                    if (user_data.open_recommend_popular === 'off') {
                        item_rules.push(`${section_path}.endpoint.browseEndpoint.browseId=FEtrending`);
                    }

                    // playables
                    if (user_data.open_recommend_playables === 'off') {
                        item_rules.push('/.richSectionRenderer.content.richShelfRenderer.endpoint.browseEndpoint.browseId=FEmini_app_destination');
                    }

                    // 添加已订阅短视频
                    if (user_data.open_recommend_shorts === 'subscribed' && type === 'init') {
                        rules.push(item_path.replace('[*]', '') + '=+(arr_insert,method(shorts_fun.get_shorts_section()),0) @user_data.shorts_list.length$value>0');
                    }

                    //直播
                    if (['off', 'subscribed'].includes(user_data.open_recommend_liveroom)) {
                        !mobile_web && item_rules.push(`${video_path}.badges[0].metadataBadgeRenderer.style=BADGE_STYLE_TYPE_LIVE_NOW`);
                        const tag_express = `UPCOMING${mobile_web ? data_process.value_split_or_tag + "LIVE" : ''}`;
                        item_rules.push(`${video_path}.thumbnailOverlays[-1].thumbnailOverlayTimeStatusRenderer.style=${tag_express}`);
                    }

                    //免费电影
                    if (user_data.open_recommend_movie === 'off') {
                        item_rules.push(`${section_path}.endpoint.browseEndpoint.browseId=FEstorefront|UClgRkhTL3_hImCAmdLfDE4g`);
                        item_rules.push(`${video_path}.badges[0].metadataBadgeRenderer.style=BADGE_STYLE_TYPE_YPC`);
                    }

                    //电视好物
                    item_rules.push('/.richSectionRenderer.content.statementBannerRenderer$exist');

                    // youtube调查弹窗
                    rules.push('abs:survey=- $exist');

                    //调查
                    item_rules.push(section_path.replace(/\.[^\.]+$/, '.inlineSurveyRenderer$exist'));

                    // primetime
                    item_rules.push(section_path.replace(/\.[^\.]+$/, '.primetimePromoRenderer$exist'));


                    //添加电影频道
                    const add_movie_channel_rule = "loadingStrategy.inlineContent.moreDrawerViewModel.content=+sobj(" + (mobile_web ? "mobile_" : "") + "movie_channel_info) !~=" + flag_info.movie_channel;
                    rules.push(add_movie_channel_rule);

                    rules.push(`${item_path}=- ${item_rules.join(data_process.condition_split_or_tag)}`);
                    return_obj.ytInitialData_rule = rules;
                    return return_obj;
                }
                return return_obj;

            }
        };
    }

    function set_search_listen() {
        let count = 0;
        const interval_id = setInterval(() => {
            if (!['yt_watch', 'yt_home', 'mobile_yt_home_searching', 'mobile_yt_watch_searching', 'yt_shorts'].includes(page_type)) {
                clearInterval(interval_id);
                return;
            }
            count++;
            const search_selector = href.includes('https://m.youtube.com/') ? 'input.searchbox-input.title' : 'input[id="search"]';
            const search_input_node = $(search_selector);
            if (search_input_node) {
                clearInterval(interval_id);
                if (search_input_node.set_listener) return;
                search_input_node.set_listener = true;
                search_input_node.oninput = function (event) {
                    if ([display_error_keyword, open_config_keyword, reset_config_keyword].includes(this.value)) {
                        setTimeout(function () {
                            if (search_input_node.value === open_config_keyword) {
                                search_input_node.value = '';
                                display_config_win();
                            }
                            if (search_input_node.value === reset_config_keyword) {
                                user_data_api.reset();
                                return;
                            }
                            if (search_input_node.value === display_error_keyword) {
                                search_input_node.value = '';
                                let tips = `script ${flag_info.init} ${isinint ? flag_info.success : flag_info.failed}`;
                                if (error_messages.length === 0 && isinint) tips += ' ' + flag_info.runing_normally;
                                for (let key of Object.keys(inject_info)) {
                                    if (!mobile_web && key === 'ytInitialPlayerResponse') continue;
                                    if (key === 'ytInitialReelWatchSequenceResponse' && !['yt_shorts', 'mobile_yt_shorts'].includes(page_type)) continue;
                                    tips += `\n${key} ${flag_info.inject} ${inject_info[key] ? flag_info.success : flag_info.failed}`;
                                }
                                // 配置信息
                                const tmp_user_data = JSON.parse(JSON.stringify(user_data));
                                delete tmp_user_data.shorts_list;
                                delete tmp_user_data.channel_infos;
                                tips += `\n\n${flag_info.config_info}\n${JSON.stringify(tmp_user_data, null, 2)}\n\n${flag_info.page_info}\npage_type: ${page_type}\nhref: ${href}`;
                                tips += `\n\nbrowser_info\n${JSON.stringify(browser_info, null, 2)}`;
                                // 规则信息
                                // tips += `\n\n${flag_info.rule_info}\nytInitialData_rule: \n${ytInitialData_rule && ytInitialData_rule.join('\n')}\n\nytInitialPlayerResponse_rule: \n${ytInitialPlayerResponse_rule && ytInitialPlayerResponse_rule.join('\n')}
                                // \n\nytInitialReelWatchSequenceResponse_rule: \n${ytInitialReelWatchSequenceResponse_rule && ytInitialReelWatchSequenceResponse_rule.join('\n')}`;
                                //账号信息
                                const str_channel_id = '' + channel_id;
                                tips += `\n\naccount_info\nchannel_id: ${(str_channel_id === 'default' || str_channel_id.length <= 10) ? str_channel_id : (str_channel_id.slice(0, 5) + '...' + str_channel_id.slice(-5))}`;
                                tips += `\nreal_language:${real_language}`;
                                if (error_messages.length !== 0) {
                                    tips += `\n\n${flag_info.exists_error}\n-----------${flag_info.err_msg}(${flag_info.ctoc})-----------------\n${error_messages.join('\n')}\n\n${flag_info.tips}`;
                                }
                                display_error_win(tips);
                            }
                        }, 500);
                    }
                };
            } else if (count > 50) {
                clearInterval(interval_id);
                log('搜索框未找到', -1);
            }
        }, 200);

    }

    function simulate_swipeup(target, start, end) {
        function createAndDispatchTouchEvent(type, target, clientY) {
            const touches = type !== 'touchend' && [new Touch({
                identifier: 0,
                target: target,
                clientY: clientY
            })] || [];
            let touchEvent = new TouchEvent(type, {
                touches: touches,
                bubbles: true,
                cancelable: true
            });
            target.dispatchEvent(touchEvent);
        }
        createAndDispatchTouchEvent('touchstart', target, start);
        createAndDispatchTouchEvent('touchmove', target, end);
        createAndDispatchTouchEvent('touchend', target);
    }

    function getCookie(cookieName) {
        const name = cookieName + "=";
        let decodedCookie;
        try {
            decodedCookie = decodeURIComponent(document.cookie);
        } catch (error) {
            log('cookie decode error', error, -1);
            return null;
        }
        const cookieArray = decodedCookie.split(';');
        for (let i = 0; i < cookieArray.length; i++) {
            const cookie = cookieArray[i].trim();

            if (cookie.startsWith(name)) {
                return cookie.substring(name.length, cookie.length);
            }
        }
        return null;
    }

    function copyToClipboard(text) {
        GM_setClipboard(text, "text");
        // if (navigator.clipboard?.writeText) return navigator.clipboard.writeText(text);
        // const textarea = unsafeWindow.document.createElement("textarea");
        // textarea.value = text;
        // unsafeWindow.document.body.appendChild(textarea);
        // textarea.select();
        // unsafeWindow.document.execCommand('copy');
        // unsafeWindow.document.body.removeChild(textarea);
    }

    function check_native(name, fun) {
        const fun_str = fun.toString();
        if (browser_info.name !== 'Firefox') {
            return `function ${name}() { [native code] }` === fun_str;
        } else {
            return `function ${name}() {\n    [native code]\n}` === fun_str;
        }
    }

    function set_history_hook(window_obj) {
        const wrap = function (type) {
            const origin = window_obj.history[type];
            return function () {
                let rv;
                try {
                    rv = origin.apply(this, arguments);
                } catch (error) {
                    log('history hook error', error, 0);
                    return;
                }
                let url = arguments[2] || location.href;
                url.startsWith('/') && (url = location.origin + url);
                !url.startsWith('http') && (url = location.origin + '/' + url);
                url_change(url);
                return rv;
            };
        };
        window_obj.history.pushState = wrap('pushState');
        window_obj.history.replaceState = wrap('replaceState');
    }

    function url_observer() {
        // if (unsafeWindow.navigation) {
        //     unsafeWindow.navigation.addEventListener('navigate', (event) => {
        //         url_change(event);
        //     });
        //     return;
        // }
        set_history_hook(unsafeWindow);
        unsafeWindow.addEventListener('popstate', function (event) {
            url_change(event);
        });
        unsafeWindow.addEventListener('hashchange', function (event) {
            url_change(event);
        });
    }

    function url_change(event = null) {
        let destination_url;
        if (typeof (event) === 'object')
            destination_url = event?.destination?.url || '';
        else
            destination_url = event;

        if (destination_url.startsWith('about:blank')) return;
        if (destination_url === href) return;
        href = destination_url || location.href;
        log('网页url改变 href -> ' + href, 0);
        const tmp_page_type = get_page_type();
        if (tmp_page_type !== page_type) {
            page_type = tmp_page_type;
            config_api.config_init();
            set_search_listen();
        }
        on_page_change();
    }

    function get_page_type(url = href) {
        if (!url) return 'other';
        url.startsWith('/') && (url = location.origin + url);
        const base_url = url.split('?')[0];
        let tmp_page_type;
        if (base_url.match('https://www.youtube.com/?$')) tmp_page_type = 'yt_home';
        else if (base_url.match('https://m.youtube.com/?#?$')) tmp_page_type = 'mobile_yt_home';
        else if (base_url.match('https://www.youtube.com/watch$')) tmp_page_type = 'yt_watch';
        else if (base_url.match('https://m.youtube.com/watch$')) tmp_page_type = 'mobile_yt_watch';
        else if (base_url.match('https://www.youtube.com/results$')) tmp_page_type = 'yt_search';
        else if (base_url.match('https://m.youtube.com/results$')) tmp_page_type = 'mobile_yt_search';
        else if (base_url.startsWith('https://www.youtube.com/shorts')) tmp_page_type = 'yt_shorts';
        else if (base_url.startsWith('https://m.youtube.com/shorts')) tmp_page_type = 'mobile_yt_shorts';
        else if (base_url.match('https://www.youtubekids.com/watch$')) tmp_page_type = 'yt_kids_watch';
        else if (base_url.match('https://music.youtube.com/?$')) tmp_page_type = 'yt_music_home';
        else if (base_url.match('https://music.youtube.com/watch$')) tmp_page_type = 'yt_music_watch';
        else if (base_url.match('https://m.youtube.com/#searching$')) tmp_page_type = 'mobile_yt_home_searching';
        else if (base_url.startsWith('https://www.youtube.com/playlist')) tmp_page_type = 'yt_watch_playlist';
        else if (base_url.includes('channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ')) tmp_page_type = 'yt_music_channel';
        else tmp_page_type = 'other';
        if (tmp_page_type === 'mobile_yt_watch' && href.endsWith('#searching')) tmp_page_type = 'mobile_yt_watch_searching';
        return tmp_page_type;
    }

    function set_debugger() {
        while (!debugger_fun_name) {
            let tmp = crypto.randomUUID().substring(0, Math.floor(Math.random() * 4) + 3).replace(/-/g, '');
            tmp = tmp.match('[a-z].+')?.[0];
            if (tmp && !unsafeWindow[tmp]) {
                debugger_fun_name = tmp;
            }
        }
        log(`debugger_fun_name: ${debugger_fun_name}`, 0);
        const debugger_config_info = {
            'ytInitialPlayerResponse': debugger_ytInitialPlayerResponse,
            'ytInitialData': debugger_ytInitialData,
            'ytInitialReelWatchSequenceResponse': debugger_ytInitialReelWatchSequenceResponse,
            'music_initialData': debugger_music_initialData,
            'inject_info': inject_info,
            'info': [
                'ytInitialData_rule',
                'ytInitialPlayerResponse_rule',
                'is_account_init',
                'user_data',
                'mobile_web',
                'page_type',
                'tmp_debugger_value',
            ],
        };
        unsafeWindow[debugger_fun_name] = function (action = null) {
            const keys = Object.keys(debugger_config_info);
            if (!action && action !== 0) { debugger; return; }
            if (action === 'ytInitialPlayerResponse') log('ytInitialPlayerResponse', debugger_ytInitialPlayerResponse, 0);
            if (action === 'ytInitialData') log('ytInitialData', debugger_ytInitialData, 0);
            if (action === 'inject_info') log('inject_info', inject_info, 0);
            if (action === 'info') {
                if (limit_eval) {
                    log('eval限制使用了', 0);
                } else {
                    for (let key of debugger_config_info['info']) {
                        log(key, eval(trustedScript(key)), 0);
                    }
                }
                return;
            }
            if (action === 'list') {
                keys.forEach(function (key, index) {
                    log(index, key, 0);
                });
            }
            if (typeof (action) === 'number') {
                if (action < keys.length) {
                    unsafeWindow[debugger_fun_name](keys[action]);
                } else if (action >= keys.length) {
                    keys.forEach(function (key) {
                        unsafeWindow[debugger_fun_name](key);
                    });
                }
            }
        };
    }

    function log() {
        const arguments_arr = [...arguments];
        const flag = arguments_arr.pop();
        if (flag === -1) {
            error_messages.push(arguments_arr.join(' '));
        }
        if (flag === 999) arguments_arr.unshift('-----test---test-----');
        if (flag !== 0 && flag !== 999) arguments_arr.push(getCodeLocation());
        if (flag === 0 || flag === 999) {
            const array_length = arguments_arr.length;
            const color = flag === 0 ? 'orange' : 'blue';
            const css_str = `color: ${color};font-size: 20px`;
            for (let i = 0; i < array_length; i++) {
                if (typeof (arguments_arr[i]) === 'string') {
                    arguments_arr[i] = '%c' + arguments_arr[i];
                    i === (array_length - 1) ? arguments_arr.push(css_str) : (arguments_arr.splice(i + 1, 0, css_str));
                    break;
                }
            }
        }
        if ([-1, 0, 999].includes(flag) || open_debugger) flag === -1 ? origin_console.error(...arguments_arr) : origin_console.log(...arguments_arr);
    }

    function getBrowserInfo() {
        const userAgent = navigator.userAgent;
        let browserName;
        let browserVersion;
        const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
        if (userAgent.indexOf("Firefox") > -1) {
            browserName = "Firefox";
            browserVersion = userAgent.match(/Firefox\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("OPR") > -1 || userAgent.indexOf("Opera") > -1) {
            browserName = "Opera";
            browserVersion = userAgent.match(/(OPR|Opera)\/([0-9.]+)/)[2];
        } else if (userAgent.indexOf("Edg") > -1) {
            browserName = "Edge";
            browserVersion = userAgent.match(/Edg\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("Chrome") > -1) {
            browserName = "Chrome";
            browserVersion = userAgent.match(/Chrome\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("Safari") > -1) {
            browserName = "Safari";
            browserVersion = userAgent.match(/Version\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("rv:") > -1) {
            browserName = "Internet Explorer";
            browserVersion = userAgent.match(/(MSIE |rv:)([0-9.]+)/)[2];
        } else {
            browserName = "Unknown";
            browserVersion = "N/A";
        }

        return {
            name: browserName,
            version: browserVersion,
            isMobile: isMobile,
        };
    }

    function getCodeLocation() {
        if (['Firefox'].includes(browser_info.name)) return "";
        const callstack = new Error().stack.split("\n");
        callstack.shift();
        while (callstack.length && callstack[0].includes("-extension://")) {
            callstack.shift();
        }
        if (!callstack.length) {
            return "";
        }
        return '\n' + callstack[0].trim();
    }

    function display_error_win(msg) {
        const container = unsafeWindow.document.createElement("div");
        container.className = "popup";
        container.id = "infoBox";
        container.innerHTML = `
        <h2 class="recommend-title" style="user-select:none;font-weight:bold;font-size:large;background-color:#3498db;color:#ffffff;border:none;padding:5px 10px;border-radius:5px;text-align:center;margin:0 auto;width:100px;">信息(message)</h2>
        <label id="infoText" style="color: #000; font-size:large;display:block;text-align:center;margin-top:10px;min-width:200px;min-height:50px;width:auto;max-height:200px;overflow:auto;"></label>
        <div style="display:flex;justify-content:space-around;margin-top:10px;">
            <button class="btn" id="copyBtn" style="cursor:pointer;background-color:#3498db;color:#ffffff;border:none;padding:5px 10px;border-radius:5px;">复制(copy)</button>
            <button class="btn" id="closeBtn2" style="cursor:pointer;background-color:#3498db;color:#ffffff;border:none;padding:5px 10px;border-radius:5px;">关闭(close)</button>
        </div>`;

        container.style.cssText = 'z-index:999999999;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);padding:20px;background-color:#ffffff;border:1px solid #3498db;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.3);width:auto;max-width:80%;max-height:80vh;overflow-y:auto;';
        unsafeWindow.document.body.appendChild(container);
        unsafeWindow.document.getElementById('infoText').innerText = msg;

        unsafeWindow.document.getElementById('copyBtn').addEventListener('click', () => {
            copyToClipboard(msg);
            unsafeWindow.document.getElementById('infoBox').remove();
            alert('复制成功!(copy success)');
        });
        unsafeWindow.document.getElementById('closeBtn2').addEventListener('click', () => {
            unsafeWindow.document.getElementById('infoBox').remove();
        });
    }


    function display_config_win() {
        const css_str = '.popup{ z-index:999999999; position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);padding:20px;background-color:#ffffff;border:1px solid #3498db;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.3);width:200px; max-height: 80vh;overflow-y: auto;}.btn{cursor:pointer;background-color:#3498db;color:#ffffff;border:none;padding:5px 10px;margin:0 auto;border-radius:5px;display:block;margin-top:10px;}.recommend-title{user-select: none;font-weight:bold;font-size: large;background-color:#3498db;color:#ffffff;border:none;padding:5px;padding-left:10px;border-radius:5px;width:180px;text-align:start;}.select-group{cursor:pointer;padding:5px;list-style-type:none;margin:0;padding-left:0;user-select: none;}.item-group{list-style-type:none;margin:0;padding-left:0;} .close-btn{position:absolute;top:5px;right:5px;cursor:pointer;border:none;background-color:floralwhite;} label{font-size: large;}';
        const style = unsafeWindow.document.createElement("style");
        style.textContent = css_str;
        $('body').appendChild(style);
        let win_config;
        const home_watch_config = {
            "recommend_btn": [
                {
                    "id": "open_recommend_shorts",
                    "title": "btn_recommend_shorts",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                        {
                            "tag": "btn_lable_subscribed",
                            "value": "subscribed",
                            "tips": "recommend_subscribed_lable_tips",
                            "condition": {
                                "login_status": true
                            }
                        }
                    ]
                }, {
                    "id": "open_recommend_liveroom",
                    "title": "btn_recommend_liveroom",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                        {
                            "tag": "btn_lable_subscribed",
                            "value": "subscribed",
                            "tips": "recommend_subscribed_lable_tips",
                            "condition": {
                                "login_status": true
                            }
                        }
                    ]
                }
                ,
                {
                    "id": "open_recommend_movie",
                    "title": "btn_recommend_movie",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "open_recommend_popular",
                    "title": "btn_recommend_popular",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "open_recommend_playables",
                    "title": "btn_recommend_game",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                }

            ]
        };
        const shorts_config = {
            "recommend_btn": [
                {
                    "id": "add_shorts_upload_date",
                    "title": "title_add_shorts_upload_date",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "shorts_change_author_name",
                    "title": "title_shorts_change_author_name",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "short_buy_super_thanks",
                    "title": "short_buy_super_thanks",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "shorts_disable_loop_play",
                    "title": "bt_shorts_disable_loop_play_title",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "shorts_auto_scroll",
                    "title": "btn_shorts_auto_scroll_title",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "shorts_add_video_progress",
                    "title": "btn_shorts_add_video_progress_title",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                },
                {
                    "id": "shorts_dbclick_like",
                    "title": "btn_shorts_dbclick_like_title",
                    "items": [
                        {
                            "tag": "btn_lable_open",
                            "value": "on",
                        },
                        {
                            "tag": "btn_lable_close",
                            "value": "off",
                        },
                    ]
                }
            ]
        };
        // if (page_type === 'yt_shorts') {
        // shorts_config.recommend_btn.push();
        // }
        const common_config = {
            "recommend_btn": [
                // {
                //     "id": "dbclick_download_video",
                //     "title": "btn_dbclick_download_video_title",
                //     "tips": "btn_dbclick_download_video_tips",
                //     "items": [
                //         {
                //             "tag": "btn_lable_open",
                //             "tips": "btn_dbclick_download_video_tips",
                //             "value": "on",
                //         },
                //         {
                //             "tag": "btn_lable_close",
                //             "value": "off",
                //         },
                //     ]
                // }
            ]
        };
        if (['mobile_yt_home_searching', 'mobile_yt_watch_searching'].includes(page_type)) {
            home_watch_config.recommend_btn.push({ "split_line": true, "title": "shorts_recommend_split_tag" });
            home_watch_config.recommend_btn.push(...shorts_config.recommend_btn);
        }
        ['yt_home', 'yt_watch', 'mobile_yt_watch_searching', 'mobile_yt_home_searching'].includes(page_type) && (win_config = home_watch_config);
        ['yt_shorts'].includes(page_type) && (win_config = shorts_config);
        win_config && (win_config.recommend_btn.push(...common_config.recommend_btn));
        if (!win_config) return;
        const popup_node = unsafeWindow.document.getElementById('xxx_popup');
        if (popup_node) {
            popup_node.remove_popup_listener('rm');
        }
        const popup = unsafeWindow.document.createElement('div');
        popup.id = 'xxx_popup';
        popup.className = 'popup';
        const close_btn = unsafeWindow.document.createElement('button');
        close_btn.className = 'close-btn';
        close_btn.innerHTML = 'x';
        close_btn.addEventListener('click', remove_popup_hander
        );
        popup.append(close_btn);
        const item_groups = [];
        const item_group = unsafeWindow.document.createElement('ul');
        item_group.className = 'item-group';
        win_config.recommend_btn.forEach(recommend_item_info => {
            if (recommend_item_info.split_line) {
                let p = unsafeWindow.document.createElement('h1');
                p.style.fontSize = 'large';
                p.style.textAlign = 'center';
                p.style.color = 'red';
                p.style.padding = '20px 20px';
                p.style.fontWeight = 'bold';
                p.style.p;
                p.innerText = flag_info[recommend_item_info.title];
                item_groups.push(p);
                return;
            }
            const recommend_id = recommend_item_info.id;
            const recommend_title = flag_info[recommend_item_info.title];
            const recommend_tips = recommend_item_info.tips && flag_info[recommend_item_info.tips];
            const select_item_infos = recommend_item_info.items || [];
            const select_items = [];
            const item = unsafeWindow.document.createElement('li');
            const select_group = unsafeWindow.document.createElement('ul');
            select_group.className = 'select-group';
            select_group.id = recommend_id;
            select_item_infos.forEach(select_item_info => {
                const tag = flag_info[select_item_info.tag];
                const value = select_item_info.value;
                const tips = flag_info[select_item_info.tips];
                const condition = select_item_info.condition;
                const select_item = unsafeWindow.document.createElement('li');
                const input = unsafeWindow.document.createElement('input');
                input.type = 'radio';
                input.name = recommend_id + '_option';
                input.id = recommend_id + '_' + value;
                input.value = value;
                if (condition && condition.login_status) {
                    if (condition.login_status !== user_data.login) {
                        input.disabled = true;
                    }
                }
                if (user_data[recommend_id] === value) {
                    input.checked = true;
                }
                input.addEventListener('click', () => {
                    handle_recommend_radio(input);
                });
                const label = unsafeWindow.document.createElement('label');
                label.htmlFor = input.id;
                label.innerText = tag;
                tips && (label.title = tips);
                select_item.append(input, label);
                select_items.push(select_item);
            });
            const recommend_title_div = unsafeWindow.document.createElement('div');
            recommend_title_div.className = 'recommend-title';
            recommend_title_div.innerText = recommend_title;
            recommend_tips && (recommend_title_div.title = recommend_tips);
            select_group.append(...select_items);
            item.append(recommend_title_div, select_group);
            item_groups.push(item);
        });
        item_group.append(...item_groups);
        popup.append(item_group);
        unsafeWindow.document.body.append(popup);

        function remove_popup_hander(event) {
            if ((event.target && !popup.contains(event.target)) || event.target === close_btn || event === 'rm') {
                popup.remove();
                unsafeWindow.document.removeEventListener('click', remove_popup_hander);
                if (['mobile_yt_watch_searching', 'mobile_yt_home_searching'].includes(page_type)) {
                    history.back();
                }
            }
        }
        popup.remove_popup_listener = remove_popup_hander;
        unsafeWindow.document.addEventListener('click', remove_popup_hander);

        // 隐藏搜索推荐元素
        let count = 0;
        const interval_id = setInterval(() => {
            if (count = 30)
                clearInterval(interval_id);
            count++;
            let class_name;
            if (['yt_home', , 'yt_watch', 'yt_shorts'].includes(page_type)) class_name = 'gstl_50';
            if (['mobile_yt_home', , 'mobile_yt_watch'].includes(page_type)) class_name = 'searchbox-dropdown';
            if (class_name) {
                let nodes = unsafeWindow.document.getElementsByClassName(class_name);
                if (nodes.length) {
                    nodes = Array.from(nodes);
                    nodes.forEach(function (node) {
                        node.style.display = 'none';
                    });
                }
            }
        }, 100);
    }

    function handle_recommend_radio(input_obj) {
        user_data[input_obj.parentNode.parentNode.id] = input_obj.value;
        user_data_api.set();
        config_api.config_init(user_data.language);
    }

    function display_update_win() {
        function btn_click() {
            const btn = this;
            if (btn.id === 'go_btn') {
                location.href = script_url;
            }
            container.remove();
        }
        const css_str = "#update_tips_win { z-index:9999999999; display: flex; position: fixed; bottom: 20px; right: 20px; padding: 10px 20px; background-color: #fff; border: 1px solid #ccc; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 10px; } .btn { margin: 0 10px; display: inline-block; padding: 5px 10px; background-color: #3498db; color: #fff; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s ease; } .btn:hover { background-color: #2980b9; }";
        const style = unsafeWindow.document.createElement("style");
        style.innerText = css_str;
        $('body').appendChild(style);
        const container = unsafeWindow.document.createElement("div");
        container.id = "update_tips_win";
        const span = unsafeWindow.document.createElement("span");
        span.textContent = GM_info.script.name + '有更新了!!';
        container.appendChild(span);
        const go_btn = unsafeWindow.document.createElement("button");
        go_btn.textContent = 'GO';
        go_btn.id = 'go_btn';
        go_btn.className = 'btn';
        go_btn.onclick = btn_click;
        container.appendChild(go_btn);
        const no_btn = unsafeWindow.document.createElement("button");
        no_btn.textContent = 'NO';
        no_btn.className = 'btn';
        no_btn.id = 'no_btn';
        no_btn.onclick = btn_click;
        container.appendChild(no_btn);
        $('body').appendChild(container);
    }

    function check_update() {
        const script_handler = GM_info.scriptHandler;
        if (['Via'].includes(script_handler)) return;
        const last_check_time = GM_getValue('last_check_time', 0);
        if ((Date.now() - last_check_time) < 1000 * 60 * 60 * 24) return;
        GM_xmlhttpRequest({
            method: 'GET',
            url: script_url,
            onload: function (response) {
                const onlineScript = response.responseText;
                // 从线上脚本中提取版本号和元数据信息
                const onlineMeta = onlineScript.match(/@version\s+([^\s]+)/i);
                const onlineVersion = onlineMeta ? onlineMeta[1] : '';
                if (onlineVersion > GM_info.script.version) {
                    display_update_win();
                }
            }
        });
        GM_setValue('last_check_time', Date.now());
    }

    function obj_process_filter(path_info, json_obj) {
        if (!['yt_home', 'yt_watch', 'mobile_yt_home', 'mobile_yt_watch'].includes(page_type)) return false;
        if (!user_data.login || user_data.channel_infos.ids.length === 0) return false;

        if (user_data.open_recommend_shorts === 'subscribed' && path_info.condition_value === 'YOUTUBE_SHORTS_BRAND_24') {
            if (path_info.express.includes('YOUTUBE_SHORTS_BRAND_24')) {
                let video_list_path;
                video_list_path = path_info.conform_value_path.split('["icon"]')[0] + (page_type === 'yt_home' ? '["contents"]' : '["items"]');
                const video_list = data_process.string_to_value(json_obj, video_list_path) || [];
                shorts_fun.node_parse(video_list);
            }
        }

        if (user_data.open_recommend_liveroom === 'subscribed' && ['UPCOMING', 'LIVE', 'BADGE_STYLE_TYPE_LIVE_NOW'].includes(path_info.condition_value)) {
            if (path_info.express.includes('UPCOMING')) {
                try {
                    const match = JSON.stringify(data_process.string_to_value(json_obj, path_info.deal_path)).match(/"browseId"\:"(.*?)"/);
                    let id;
                    if (match && match.length > 1) id = match[1];
                    if (!id) {
                        log('id获取失败\n' + JSON.stringify(path_info), -1);
                    }
                    if (user_data.channel_infos.ids.includes(id)) {
                        const index = user_data.channel_infos.ids.indexOf(id);
                        const name = user_data.channel_infos.names[index];
                        log('不过滤 ' + name + (path_info.condition_value === 'UPCOMING' ? ' 等待发布的直播' : ' 正在进行的直播'), 'shorts');
                        return true;
                    }
                    let msg = `过滤 ${id} ${path_info.condition_value === 'UPCOMING' ? ' 等待发布的直播' : ' 正在进行的直播'}`;
                    log(msg, 'shorts');
                } catch (error) {
                    log(error, -1);
                }
            }
        }
        return false;
    }

    function get_shorts_fun() {
        class ShortsFun {
            constructor() {
                this.parsing = false;
                this.shorts_list = [];
            }
            node_parse(video_list) {
                !user_data.shorts_list && (user_data.shorts_list = []);
                let video_id, title, views_lable, thumbnail_url;
                let count = 0;
                for (let video_info of video_list) {
                    count++;
                    if (page_type === "yt_home") {
                        video_id = video_info.richItemRenderer.content.reelItemRenderer.videoId;
                        title = video_info.richItemRenderer.content.reelItemRenderer.headline.simpleText;
                        views_lable = video_info.richItemRenderer.content.reelItemRenderer.viewCountText.simpleText;
                        thumbnail_url = video_info.richItemRenderer.content.reelItemRenderer.thumbnail.thumbnails[0].url;
                    }
                    if (page_type === "yt_watch") {
                        video_id = video_info.reelItemRenderer.videoId;
                        title = video_info.reelItemRenderer.headline.simpleText;
                        views_lable = video_info.reelItemRenderer.viewCountText.simpleText;
                        thumbnail_url = video_info.reelItemRenderer.thumbnail.thumbnails[0].url;
                    }
                    if (["mobile_yt_home", "mobile_yt_watch"].includes(page_type)) {
                        video_id = video_info.shortsLockupViewModel.entityId.replace('shorts-shelf-item-', '');
                        title = video_info.shortsLockupViewModel.overlayMetadata.primaryText.content;
                        views_lable = video_info.shortsLockupViewModel.overlayMetadata.secondaryText.content;
                        thumbnail_url = video_info.shortsLockupViewModel.thumbnail.sources[0].url;
                    }
                    this.shorts_list.push({
                        id: video_id,
                        title: title,
                        views_lable: views_lable,
                        thumbnail_url: thumbnail_url
                    });
                    if (!this.parsing) {
                        this.parsing = true;
                        setTimeout(() => {
                            this.parse_shorts_list();
                        }, shorts_parse_delay);
                    }

                }

            }
            get_shorts_section() {
                if (!user_data.shorts_list || !user_data.shorts_list.length) return;
                let root, item_path;
                const items = [];
                if (page_type == 'yt_home') {
                    root = {
                        "richSectionRenderer": {
                            "content": {
                                "richShelfRenderer": {
                                    "title": {
                                        "runs": [
                                            {
                                                "text": "Shorts"
                                            }
                                        ]
                                    },
                                    "contents": [],
                                    "trackingParams": "CNMEEN-DAyITCOGA_NHuz4UDFWdqTAgdfF4E-Q==",
                                    "menu": {
                                        "menuRenderer": {
                                            "trackingParams": "CNMEEN-DAyITCOGA_NHuz4UDFWdqTAgdfF4E-Q==",
                                            "topLevelButtons": [
                                                {
                                                    "buttonRenderer": {
                                                        "style": "STYLE_OPACITY",
                                                        "size": "SIZE_DEFAULT",
                                                        "isDisabled": false,
                                                        "serviceEndpoint": {
                                                            "clickTrackingParams": "CNYEEKqJCRgMIhMI4YD80e7PhQMVZ2pMCB18XgT5",
                                                            "commandMetadata": {
                                                                "webCommandMetadata": {
                                                                    "sendPost": true,
                                                                    "apiUrl": "/youtubei/v1/feedback"
                                                                }
                                                            },
                                                            "feedbackEndpoint": {
                                                                "feedbackToken": "AB9zfpIcTXNyA3lbF_28icb4umRJ5AveSSTqmF7T9gE8k-Sw7HrOTLE5wzA2TScqfTByCI-cR9nPuVMSWAgbNuuaruVBYx2-2dGAzujQTL8KGMOyCFM_wmGhkLTSdUBQzsFQRHEibpg_",
                                                                "uiActions": {
                                                                    "hideEnclosingContainer": true
                                                                },
                                                                "actions": [
                                                                    {
                                                                        "clickTrackingParams": "CNYEEKqJCRgMIhMI4YD80e7PhQMVZ2pMCB18XgT5",
                                                                        "replaceEnclosingAction": {
                                                                            "item": {
                                                                                "notificationMultiActionRenderer": {
                                                                                    "responseText": {
                                                                                        "runs": [
                                                                                            {
                                                                                                "text": "Shelf will be hidden for "
                                                                                            },
                                                                                            {
                                                                                                "text": "30"
                                                                                            },
                                                                                            {
                                                                                                "text": " days"
                                                                                            }
                                                                                        ]
                                                                                    },
                                                                                    "buttons": [
                                                                                        {
                                                                                            "buttonRenderer": {
                                                                                                "style": "STYLE_BLUE_TEXT",
                                                                                                "text": {
                                                                                                    "simpleText": "Undo"
                                                                                                },
                                                                                                "serviceEndpoint": {
                                                                                                    "clickTrackingParams": "CNgEEPBbGAAiEwjhgPzR7s-FAxVnakwIHXxeBPk=",
                                                                                                    "commandMetadata": {
                                                                                                        "webCommandMetadata": {
                                                                                                            "sendPost": true,
                                                                                                            "apiUrl": "/youtubei/v1/feedback"
                                                                                                        }
                                                                                                    },
                                                                                                    "undoFeedbackEndpoint": {
                                                                                                        "undoToken": "AB9zfpLpAillN1hH9cyfSbyPRWwAhTOJo6mUTu-ony4HASc0KgCEy0ifaIrDUdJJEk4OXiPC43EMPZBEK8WGiIqeci4r97TGpabAUk84dEh7tHzF7-rsziFBGZjY92Jyk3YujrF2_wxC",
                                                                                                        "actions": [
                                                                                                            {
                                                                                                                "clickTrackingParams": "CNgEEPBbGAAiEwjhgPzR7s-FAxVnakwIHXxeBPk=",
                                                                                                                "undoFeedbackAction": {
                                                                                                                    "hack": true
                                                                                                                }
                                                                                                            }
                                                                                                        ]
                                                                                                    }
                                                                                                },
                                                                                                "trackingParams": "CNgEEPBbGAAiEwjhgPzR7s-FAxVnakwIHXxeBPk="
                                                                                            }
                                                                                        }
                                                                                    ],
                                                                                    "trackingParams": "CNcEEKW8ASITCOGA_NHuz4UDFWdqTAgdfF4E-Q=="
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                ]
                                                            }
                                                        },
                                                        "icon": {
                                                            "iconType": "DISMISSAL"
                                                        },
                                                        "tooltip": "Not interested",
                                                        "trackingParams": "CNYEEKqJCRgMIhMI4YD80e7PhQMVZ2pMCB18XgT5",
                                                        "accessibilityData": {
                                                            "accessibilityData": {
                                                                "label": "Not interested"
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    "showMoreButton": {
                                        "buttonRenderer": {
                                            "style": "STYLE_OPACITY",
                                            "size": "SIZE_DEFAULT",
                                            "text": {
                                                "runs": [
                                                    {
                                                        "text": "Show more"
                                                    }
                                                ]
                                            },
                                            "icon": {
                                                "iconType": "EXPAND"
                                            },
                                            "accessibility": {
                                                "label": "Show more"
                                            },
                                            "trackingParams": "CNUEEJnjCyITCOGA_NHuz4UDFWdqTAgdfF4E-Q=="
                                        }
                                    },
                                    "isExpanded": false,
                                    "icon": {
                                        "iconType": "YOUTUBE_SHORTS_BRAND_24"
                                    },
                                    "isTopDividerHidden": false,
                                    "isBottomDividerHidden": false,
                                    "showLessButton": {
                                        "buttonRenderer": {
                                            "style": "STYLE_OPACITY",
                                            "size": "SIZE_DEFAULT",
                                            "text": {
                                                "runs": [
                                                    {
                                                        "text": "Show less"
                                                    }
                                                ]
                                            },
                                            "icon": {
                                                "iconType": "COLLAPSE"
                                            },
                                            "accessibility": {
                                                "label": "Show less"
                                            },
                                            "trackingParams": "CNQEEPBbIhMI4YD80e7PhQMVZ2pMCB18XgT5"
                                        }
                                    }
                                }
                            },
                            "trackingParams": "CNIEEOOXBRgEIhMI4YD80e7PhQMVZ2pMCB18XgT5",
                            "fullBleed": false
                        }
                    };
                    item_path = 'root.richSectionRenderer.content.richShelfRenderer.contents';
                }
                if (['mobile_yt_watch', 'yt_watch'].includes(page_type)) {
                    root = {
                        "reelShelfRenderer": {
                            "title": {
                                "runs": [
                                    {
                                        "text": "Shorts"
                                    }
                                ]
                            },
                            "items": [],
                            "trackingParams": "CM4CEN-DAxgEIhMInKOvhY3QhQMVGcCXCB04HQR6",
                            "icon": {
                                "iconType": "YOUTUBE_SHORTS_BRAND_24"
                            }
                        }
                    };
                    item_path = 'root.reelShelfRenderer.items';
                }
                if (page_type == 'mobile_yt_home') {
                    root = {
                        "richSectionRenderer": {
                            "content": {
                                "reelShelfRenderer": {
                                    "title": {
                                        "runs": [
                                            {
                                                "text": "Shorts"
                                            }
                                        ]
                                    },
                                    "button": {
                                        "menuRenderer": {
                                            "trackingParams": "CHYQ34MDIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                            "topLevelButtons": [
                                                {
                                                    "buttonRenderer": {
                                                        "style": "STYLE_DEFAULT",
                                                        "size": "SIZE_DEFAULT",
                                                        "isDisabled": false,
                                                        "serviceEndpoint": {
                                                            "clickTrackingParams": "CLMBEKqJCRgPIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                                            "commandMetadata": {
                                                                "webCommandMetadata": {
                                                                    "sendPost": true,
                                                                    "apiUrl": "/youtubei/v1/feedback"
                                                                }
                                                            },
                                                            "feedbackEndpoint": {
                                                                "feedbackToken": "AB9zfpJSnrbvskPWkpziyGduKV-4gTxm30-eNNYDobzecpLq84dL6HwCxdX_zbvm_OmxSKdlsngHEE1CF7JKYGiyDVYV_Q7p9ihGCzOYcnqKcAJfNnSp-U-njcnKLgCWu_USr-2prW3x",
                                                                "uiActions": {
                                                                    "hideEnclosingContainer": true
                                                                },
                                                                "actions": [
                                                                    {
                                                                        "clickTrackingParams": "CLMBEKqJCRgPIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                                                        "replaceEnclosingAction": {
                                                                            "item": {
                                                                                "notificationMultiActionRenderer": {
                                                                                    "responseText": {
                                                                                        "runs": [
                                                                                            {
                                                                                                "text": "Shelf will be hidden for "
                                                                                            },
                                                                                            {
                                                                                                "text": "30"
                                                                                            },
                                                                                            {
                                                                                                "text": " days"
                                                                                            }
                                                                                        ]
                                                                                    },
                                                                                    "buttons": [
                                                                                        {
                                                                                            "buttonRenderer": {
                                                                                                "style": "STYLE_MONO_TONAL",
                                                                                                "text": {
                                                                                                    "runs": [
                                                                                                        {
                                                                                                            "text": "Undo"
                                                                                                        }
                                                                                                    ]
                                                                                                },
                                                                                                "serviceEndpoint": {
                                                                                                    "clickTrackingParams": "CLUBEPBbGAAiEwip6oDKjtCFAxXPeUwIHaYIDQk=",
                                                                                                    "commandMetadata": {
                                                                                                        "webCommandMetadata": {
                                                                                                            "sendPost": true,
                                                                                                            "apiUrl": "/youtubei/v1/feedback"
                                                                                                        }
                                                                                                    },
                                                                                                    "undoFeedbackEndpoint": {
                                                                                                        "undoToken": "AB9zfpK-nY3vxgYDkvJSkuFdbeBltD0r4XdLzoFqxz6OPnmJrroOAxKfUuDny8kPjB9yyWzwEerOZqe90BakCPEJXycRSrH8sZAdnlWpEs0n0lx6qOFERE6o5jkK3mgbcVCM-Al38oGV",
                                                                                                        "actions": [
                                                                                                            {
                                                                                                                "clickTrackingParams": "CLUBEPBbGAAiEwip6oDKjtCFAxXPeUwIHaYIDQk=",
                                                                                                                "undoFeedbackAction": {
                                                                                                                    "hack": true
                                                                                                                }
                                                                                                            }
                                                                                                        ]
                                                                                                    }
                                                                                                },
                                                                                                "trackingParams": "CLUBEPBbGAAiEwip6oDKjtCFAxXPeUwIHaYIDQk="
                                                                                            }
                                                                                        }
                                                                                    ],
                                                                                    "trackingParams": "CLQBEKW8ASITCKnqgMqO0IUDFc95TAgdpggNCQ=="
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                ]
                                                            }
                                                        },
                                                        "icon": {
                                                            "iconType": "DISMISSAL"
                                                        },
                                                        "tooltip": "Not interested",
                                                        "trackingParams": "CLMBEKqJCRgPIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                                        "accessibilityData": {
                                                            "accessibilityData": {
                                                                "label": "Not interested"
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    "items": [

                                    ],
                                    "trackingParams": "CHYQ34MDIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                    "icon": {
                                        "iconType": "YOUTUBE_SHORTS_BRAND_24"
                                    }
                                }
                            },
                            "trackingParams": "CHUQ45cFGAEiEwip6oDKjtCFAxXPeUwIHaYIDQk=",
                            "fullBleed": false
                        }
                    };
                    item_path = 'root.richSectionRenderer.content.reelShelfRenderer.items';
                }
                let shorts;
                while (shorts = user_data.shorts_list.pop()) {
                    const id = shorts['id'];
                    const title = shorts['title'];
                    const ago_str = shorts['ago_str'];
                    const author = shorts['author_name'];
                    const views_lable = shorts['views_lable'] + (author ? (' · ' + author) : '') + (ago_str ? (' · ' + ago_str) : '');
                    const thumbnail_url = shorts['thumbnail_url'];
                    let tmp_item;
                    if (['yt_home', 'yt_watch'].includes(page_type)) {
                        tmp_item = {
                            "reelItemRenderer": {
                                "videoId": id,
                                "headline": {
                                    "simpleText": title
                                },
                                "thumbnail": {
                                    "thumbnails": [
                                        {
                                            "url": thumbnail_url,
                                            "width": 405,
                                            "height": 720
                                        }
                                    ],
                                    "isOriginalAspectRatio": true
                                },
                                "viewCountText": {
                                    "accessibility": {
                                        "accessibilityData": {
                                            "label": views_lable
                                        }
                                    },
                                    "simpleText": views_lable
                                },
                                "navigationEndpoint": {
                                    "clickTrackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6mgEFCCUQ-B0=",
                                    "commandMetadata": {
                                        "webCommandMetadata": {
                                            "url": "/shorts/" + id,
                                            "webPageType": "WEB_PAGE_TYPE_SHORTS",
                                            "rootVe": 37414
                                        }
                                    },
                                    "reelWatchEndpoint": {
                                        "videoId": id,
                                        "playerParams": "8AEBoAMCyAMluAQGogYVAdXZ-jvMfGWnXiNDPh0oiMSTJMUn",
                                        "thumbnail": {
                                            "thumbnails": [
                                                {
                                                    "url": "https://i.ytimg.com/vi/" + id + "/frame0.jpg",
                                                    "width": 1080,
                                                    "height": 1920
                                                }
                                            ],
                                            "isOriginalAspectRatio": true
                                        },
                                        "overlay": {
                                            "reelPlayerOverlayRenderer": {
                                                "style": "REEL_PLAYER_OVERLAY_STYLE_SHORTS",
                                                "trackingParams": "CO4CELC1BCITCJyjr4WN0IUDFRnAlwgdOB0Eeg==",
                                                "reelPlayerNavigationModel": "REEL_PLAYER_NAVIGATION_MODEL_UNSPECIFIED"
                                            }
                                        },
                                        "params": "CAYwAg%3D%3D",
                                        "sequenceProvider": "REEL_WATCH_SEQUENCE_PROVIDER_RPC",
                                        "sequenceParams": "CgtLRmRCbnpnSjJZWSoCGAZQGWgA",
                                        "loggingContext": {
                                            "vssLoggingContext": {
                                                "serializedContextData": "CgIIDA%3D%3D"
                                            },
                                            "qoeLoggingContext": {
                                                "serializedContextData": "CgIIDA%3D%3D"
                                            }
                                        },
                                        "ustreamerConfig": "CAwSHDFIakVXUytucVRyTENNWlgzMXdDZmYwamZQQ0U="
                                    }
                                },
                                "menu": {
                                    "menuRenderer": {
                                        "items": [
                                            {
                                                "menuServiceItemRenderer": {
                                                    "text": {
                                                        "runs": [
                                                            {
                                                                "text": "Report"
                                                            }
                                                        ]
                                                    },
                                                    "icon": {
                                                        "iconType": "FLAG"
                                                    },
                                                    "serviceEndpoint": {
                                                        "clickTrackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                                        "commandMetadata": {
                                                            "webCommandMetadata": {
                                                                "sendPost": true,
                                                                "apiUrl": "/youtubei/v1/flag/get_form"
                                                            }
                                                        },
                                                        "getReportFormEndpoint": {
                                                            "params": "EgtLRmRCbnpnSjJZWUABWABwAXgB2AEA6AEA"
                                                        }
                                                    },
                                                    "trackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6"
                                                }
                                            },
                                            {
                                                "menuServiceItemRenderer": {
                                                    "text": {
                                                        "runs": [
                                                            {
                                                                "text": "Not interested"
                                                            }
                                                        ]
                                                    },
                                                    "icon": {
                                                        "iconType": "NOT_INTERESTED"
                                                    },
                                                    "serviceEndpoint": {
                                                        "clickTrackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                                        "commandMetadata": {
                                                            "webCommandMetadata": {
                                                                "sendPost": true,
                                                                "apiUrl": "/youtubei/v1/feedback"
                                                            }
                                                        },
                                                        "feedbackEndpoint": {
                                                            "feedbackToken": "AB9zfpIBjY8nLioWtHjvUvMvrLXfhPMooShdpv91xgNNrZuxibAl6QyPeYMe7faEHcrSUm-TIqvLe2ThmYQpNRUy9rPbV1k3jjrvqqc5cOLBvnV8oN0Kbrq3-K9IjJXYitJPyOzJU0uy",
                                                            "actions": [
                                                                {
                                                                    "clickTrackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                                                    "replaceEnclosingAction": {
                                                                        "item": {
                                                                            "notificationMultiActionRenderer": {
                                                                                "responseText": {
                                                                                    "runs": [
                                                                                        {
                                                                                            "text": "Video removed"
                                                                                        }
                                                                                    ]
                                                                                },
                                                                                "buttons": [
                                                                                    {
                                                                                        "buttonRenderer": {
                                                                                            "style": "STYLE_BLUE_TEXT",
                                                                                            "text": {
                                                                                                "runs": [
                                                                                                    {
                                                                                                        "text": "Undo"
                                                                                                    }
                                                                                                ]
                                                                                            },
                                                                                            "serviceEndpoint": {
                                                                                                "clickTrackingParams": "CO0CEPBbGAAiEwico6-FjdCFAxUZwJcIHTgdBHo=",
                                                                                                "commandMetadata": {
                                                                                                    "webCommandMetadata": {
                                                                                                        "sendPost": true,
                                                                                                        "apiUrl": "/youtubei/v1/feedback"
                                                                                                    }
                                                                                                },
                                                                                                "undoFeedbackEndpoint": {
                                                                                                    "undoToken": "AB9zfpK74nsMbZ4OfNgKTgA9g0w3Q8o72jdm384D3y82OAuy2KgvTUOAn-iII915ZC_7aqAxTK-XNir21X_T3WQEeAzdy4hCZ6o0f12hfdHW8xI1js1WB_CEn3EW27P9_1vu5dw2kDeW",
                                                                                                    "actions": [
                                                                                                        {
                                                                                                            "clickTrackingParams": "CO0CEPBbGAAiEwico6-FjdCFAxUZwJcIHTgdBHo=",
                                                                                                            "undoFeedbackAction": {
                                                                                                                "hack": true
                                                                                                            }
                                                                                                        }
                                                                                                    ]
                                                                                                }
                                                                                            },
                                                                                            "trackingParams": "CO0CEPBbGAAiEwico6-FjdCFAxUZwJcIHTgdBHo="
                                                                                        }
                                                                                    }
                                                                                ],
                                                                                "trackingParams": "COwCEKW8ASITCJyjr4WN0IUDFRnAlwgdOB0Eeg=="
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            ]
                                                        }
                                                    },
                                                    "trackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                                    "accessibility": {
                                                        "accessibilityData": {
                                                            "label": "Not interested"
                                                        }
                                                    }
                                                }
                                            },
                                            {
                                                "menuNavigationItemRenderer": {
                                                    "text": {
                                                        "runs": [
                                                            {
                                                                "text": "Send feedback"
                                                            }
                                                        ]
                                                    },
                                                    "icon": {
                                                        "iconType": "FEEDBACK"
                                                    },
                                                    "navigationEndpoint": {
                                                        "clickTrackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                                        "commandMetadata": {
                                                            "webCommandMetadata": {
                                                                "ignoreNavigation": true
                                                            }
                                                        },
                                                        "userFeedbackEndpoint": {
                                                            "additionalDatas": [
                                                                {
                                                                    "userFeedbackEndpointProductSpecificValueData": {
                                                                        "key": "video_id",
                                                                        "value": id
                                                                    }
                                                                },
                                                                {
                                                                    "userFeedbackEndpointProductSpecificValueData": {
                                                                        "key": "lockup",
                                                                        "value": "shelf"
                                                                    }
                                                                }
                                                            ]
                                                        }
                                                    },
                                                    "trackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                                    "accessibility": {
                                                        "accessibilityData": {
                                                            "label": "Send feedback"
                                                        }
                                                    }
                                                }
                                            }
                                        ],
                                        "trackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                        "accessibility": {
                                            "accessibilityData": {
                                                "label": "More actions"
                                            }
                                        }
                                    }
                                },
                                "trackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6QIazp8Dzs9CrKA==",
                                "accessibility": {
                                    "accessibilityData": {
                                        "label": title + " - play Short"
                                    }
                                },
                                "style": "REEL_ITEM_STYLE_AVATAR_CIRCLE",
                                "dismissalInfo": {
                                    "feedbackToken": "AB9zfpLIJd1aRU9JzdOjpgeJBW2QvHH79sx6dM6ZCDEzyc5qrISZBSpNRe5lerckNHwQ10BOwEQhlquLlHP-nkuA4VSSCXX0XgMJHBnKWBxlIXkQ1pLIUjd6cQKhrCUioDfix7xn5Ecj"
                                },
                                "videoType": "REEL_VIDEO_TYPE_VIDEO",
                                "loggingDirectives": {
                                    "trackingParams": "COsCEIf2BBgAIhMInKOvhY3QhQMVGcCXCB04HQR6",
                                    "visibility": {
                                        "types": "12"
                                    },
                                    "enableDisplayloggerExperiment": true
                                }
                            }
                        };
                    }
                    if (page_type == "yt_home") {
                        tmp_item = {
                            "richItemRenderer": {
                                "content": tmp_item,
                                "trackingParams": "CJsFEJmNBRgAIhMI4YD80e7PhQMVZ2pMCB18XgT5"
                            }
                        };
                    }
                    if (["mobile_yt_home", "mobile_yt_watch"].includes(page_type)) {
                        tmp_item = {
                            "shortsLockupViewModel": {
                                "entityId": "shorts-shelf-item-" + id,
                                "accessibilityText": title + ", " + views_lable + " - play Short",
                                "thumbnail": {
                                    "sources": [
                                        {
                                            "url": thumbnail_url,
                                            "width": 405,
                                            "height": 720
                                        }
                                    ]
                                },
                                "onTap": {
                                    "innertubeCommand": {
                                        "clickTrackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0JWg9GRXdoYXRfdG9fd2F0Y2iaAQUIJBCOHg==",
                                        "commandMetadata": {
                                            "webCommandMetadata": {
                                                "url": "/shorts/" + id,
                                                "webPageType": "WEB_PAGE_TYPE_SHORTS",
                                                "rootVe": 37414
                                            }
                                        },
                                        "reelWatchEndpoint": {
                                            "videoId": id,
                                            "playerParams": "8AEBoAMByAMkuAQFogYVAdXZ-jveUoR0s0_R7sLGUd85_xAk",
                                            "thumbnail": {
                                                "thumbnails": [
                                                    {
                                                        "url": "https://i.ytimg.com/vi/" + id + "/frame0.jpg",
                                                        "width": 1080,
                                                        "height": 1920
                                                    }
                                                ],
                                                "isOriginalAspectRatio": true
                                            },
                                            "overlay": {
                                                "reelPlayerOverlayRenderer": {
                                                    "style": "REEL_PLAYER_OVERLAY_STYLE_SHORTS",
                                                    "trackingParams": "CLIBELC1BCITCKnqgMqO0IUDFc95TAgdpggNCQ==",
                                                    "reelPlayerNavigationModel": "REEL_PLAYER_NAVIGATION_MODEL_UNSPECIFIED"
                                                }
                                            },
                                            "params": "CAUwAg%3D%3D",
                                            "sequenceProvider": "REEL_WATCH_SEQUENCE_PROVIDER_RPC",
                                            "sequenceParams": "CgtwblVoZV9PUTE2byoCGAVQGWgA",
                                            "loggingContext": {
                                                "vssLoggingContext": {
                                                    "serializedContextData": "CgIIDA%3D%3D"
                                                },
                                                "qoeLoggingContext": {
                                                    "serializedContextData": "CgIIDA%3D%3D"
                                                }
                                            },
                                            "ustreamerConfig": "CAwSHDFIakVXUytucVRyTENNWlgzMXdDZmYwamZQQ0U="
                                        }
                                    }
                                },
                                "inlinePlayerData": {
                                    "onVisible": {
                                        "innertubeCommand": {
                                            "clickTrackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0JMgZnLWhpZ2haD0ZFd2hhdF90b193YXRjaJoBBQgkEI4e",
                                            "commandMetadata": {
                                                "webCommandMetadata": {
                                                    "url": "/watch?v=" + id + "&pp=YAHIAQG6AwIYAugFAQ%3D%3D",
                                                    "webPageType": "WEB_PAGE_TYPE_WATCH",
                                                    "rootVe": 3832
                                                }
                                            },
                                            "watchEndpoint": {
                                                "videoId": id,
                                                "playerParams": "YAHIAQG6AwIYAugFAQ%3D%3D"
                                            }
                                        }
                                    }
                                },
                                "menuOnTap": {
                                    "innertubeCommand": {
                                        "clickTrackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                        "showSheetCommand": {
                                            "panelLoadingStrategy": {
                                                "inlineContent": {
                                                    "sheetViewModel": {
                                                        "content": {
                                                            "listViewModel": {
                                                                "listItems": [
                                                                    {
                                                                        "listItemViewModel": {
                                                                            "title": {
                                                                                "content": "Not interested"
                                                                            },
                                                                            "leadingImage": {
                                                                                "sources": [
                                                                                    {
                                                                                        "clientResource": {
                                                                                            "imageName": "NOT_INTERESTED"
                                                                                        }
                                                                                    }
                                                                                ]
                                                                            },
                                                                            "rendererContext": {
                                                                                "commandContext": {
                                                                                    "onTap": {
                                                                                        "innertubeCommand": {
                                                                                            "clickTrackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                                                                            "commandMetadata": {
                                                                                                "webCommandMetadata": {
                                                                                                    "sendPost": true,
                                                                                                    "apiUrl": "/youtubei/v1/feedback"
                                                                                                }
                                                                                            },
                                                                                            "feedbackEndpoint": {
                                                                                                "feedbackToken": "AB9zfpJnMNgSEnsvYAu4UXP6IN5z0VfAt-OZOs8ypsKND9Mv5RhoELjmgb_vxVOvvYoiM2f8q9QFcdGMOEOCSk7LPYMnGshEHKcis4oeot-Z5OsgYpmOP3DbMXgFHUgQhOUAjL-FIj5y",
                                                                                                "actions": [
                                                                                                    {
                                                                                                        "clickTrackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                                                                                        "replaceEnclosingAction": {
                                                                                                            "item": {
                                                                                                                "notificationMultiActionRenderer": {
                                                                                                                    "responseText": {
                                                                                                                        "runs": [
                                                                                                                            {
                                                                                                                                "text": "Video removed"
                                                                                                                            }
                                                                                                                        ]
                                                                                                                    },
                                                                                                                    "buttons": [
                                                                                                                        {
                                                                                                                            "buttonRenderer": {
                                                                                                                                "style": "STYLE_BLUE_TEXT",
                                                                                                                                "text": {
                                                                                                                                    "runs": [
                                                                                                                                        {
                                                                                                                                            "text": "Undo"
                                                                                                                                        }
                                                                                                                                    ]
                                                                                                                                },
                                                                                                                                "serviceEndpoint": {
                                                                                                                                    "clickTrackingParams": "CLEBEPBbGAAiEwip6oDKjtCFAxXPeUwIHaYIDQk=",
                                                                                                                                    "commandMetadata": {
                                                                                                                                        "webCommandMetadata": {
                                                                                                                                            "sendPost": true,
                                                                                                                                            "apiUrl": "/youtubei/v1/feedback"
                                                                                                                                        }
                                                                                                                                    },
                                                                                                                                    "undoFeedbackEndpoint": {
                                                                                                                                        "undoToken": "AB9zfpI_UgAQH8eSODf7gCfkDtllqeFC5Qr38N7cNnlz8NmYZ78F2KiuX3KZNcumX2jfVXRzNfd2M0V7vud8UdS2Hz7SshgqVTn2TOJApWBlkIPTbUYWuQkX2CSbVKZw1p3wIHkjQOH7",
                                                                                                                                        "actions": [
                                                                                                                                            {
                                                                                                                                                "clickTrackingParams": "CLEBEPBbGAAiEwip6oDKjtCFAxXPeUwIHaYIDQk=",
                                                                                                                                                "undoFeedbackAction": {
                                                                                                                                                    "hack": true
                                                                                                                                                }
                                                                                                                                            }
                                                                                                                                        ]
                                                                                                                                    }
                                                                                                                                },
                                                                                                                                "trackingParams": "CLEBEPBbGAAiEwip6oDKjtCFAxXPeUwIHaYIDQk="
                                                                                                                            }
                                                                                                                        }
                                                                                                                    ],
                                                                                                                    "trackingParams": "CLABEKW8ASITCKnqgMqO0IUDFc95TAgdpggNCQ=="
                                                                                                                }
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                ]
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    },
                                                                    {
                                                                        "listItemViewModel": {
                                                                            "title": {
                                                                                "content": "Send feedback"
                                                                            },
                                                                            "leadingImage": {
                                                                                "sources": [
                                                                                    {
                                                                                        "clientResource": {
                                                                                            "imageName": "FEEDBACK"
                                                                                        }
                                                                                    }
                                                                                ]
                                                                            },
                                                                            "rendererContext": {
                                                                                "commandContext": {
                                                                                    "onTap": {
                                                                                        "innertubeCommand": {
                                                                                            "clickTrackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                                                                            "commandMetadata": {
                                                                                                "webCommandMetadata": {
                                                                                                    "ignoreNavigation": true
                                                                                                }
                                                                                            },
                                                                                            "userFeedbackEndpoint": {
                                                                                                "additionalDatas": [
                                                                                                    {
                                                                                                        "userFeedbackEndpointProductSpecificValueData": {
                                                                                                            "key": "video_id",
                                                                                                            "value": id
                                                                                                        }
                                                                                                    },
                                                                                                    {
                                                                                                        "userFeedbackEndpointProductSpecificValueData": {
                                                                                                            "key": "lockup",
                                                                                                            "value": "shelf"
                                                                                                        }
                                                                                                    }
                                                                                                ]
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                ]
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "indexInCollection": 0,
                                "menuOnTapA11yLabel": "More actions",
                                "overlayMetadata": {
                                    "primaryText": {
                                        "content": title,
                                        "styleRuns": [
                                            {
                                                "startIndex": 0,
                                                "fontName": "",
                                                "fontSize": 0,
                                                "fontColor": 4294967295
                                            }
                                        ]
                                    },
                                    "secondaryText": {
                                        "content": views_lable,
                                        "styleRuns": [
                                            {
                                                "startIndex": 0,
                                                "fontName": "",
                                                "fontSize": 0,
                                                "fontColor": 4294967295
                                            }
                                        ]
                                    }
                                },
                                "loggingDirectives": {
                                    "trackingParams": "CK8BEIf2BBgAIhMIqeqAyo7QhQMVz3lMCB2mCA0J",
                                    "visibility": {
                                        "types": "12"
                                    },
                                    "enableDisplayloggerExperiment": true
                                }
                            }
                        };
                    }
                    items.push(tmp_item);
                }
                if (item_path) {
                    eval(trustedScript(item_path + ' = items'));
                    user_data_api.set();
                    return root;
                }
                return {};
            }
            get_shorts_info(video_id) {
                return new Promise((resolve, reject) => {
                    let basic_url, author_id_reg, author_name_reg, upload_date_reg, ago_reg;
                    if (page_type.startsWith('mobile')) {
                        basic_url = 'https://m.youtube.com/shorts/';
                        author_id_reg = /"channelId":"(.*?)"/;
                        author_name_reg = /"ownerChannelName":"(.*?)"/;
                        // upload_date_reg = /"uploadDate":"(.*?)"/;
                        ago_reg = /timestampText.*?:\\x22(.*?)\\x22\\x7d/;

                    } else {
                        basic_url = 'https://www.youtube.com/shorts/';
                        author_id_reg = /"browseId":"([a-zA-Z0-9\-_]+)","canonicalBaseUrl"/;
                        author_name_reg = /"channel":\{"simpleText":"(.*?)"/;
                        // upload_date_reg = /"uploadDate":"(.*?)"/;
                        ago_reg = /"timestampText":{"simpleText":"(.*?)"}/;
                    }
                    const url = basic_url + video_id;
                    const xhr = new XMLHttpRequest();
                    xhr.open('GET', url);
                    xhr.setRequestHeader('accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7');
                    let author_id = '';
                    let author_name = '';
                    // let upload_date_str = '';
                    let ago_str = '';
                    // let upload_date;
                    xhr.onload = function () {
                        if (xhr.status === 200) {
                            let match;
                            const result = xhr.responseText;
                            match = result.match(author_id_reg);
                            if (match && match.length > 1) author_id = match[1];
                            match = result.match(author_name_reg);
                            if (match && match.length > 1) author_name = match[1];
                            match = result.match(ago_reg);
                            if (match && match.length > 1) ago_str = match[1];
                            resolve({
                                id: video_id,
                                author_id: author_id,
                                author_name: author_name,
                                ago_str: ago_str
                            });
                        } else {
                            reject(xhr.responseText);
                        }
                    };
                    xhr.onerror = function () {
                        reject(new Error('XHR request failed'));
                    };
                    xhr.send();
                });
            }
            parse_shorts_list() {
                if (!this.shorts_list.length) return;
                const { id, title, views_lable, thumbnail_url } = this.shorts_list.pop();
                this.get_shorts_info(id).then((author_info) => {
                    const { author_id, author_name, ago_str } = author_info;
                    if (author_id && user_data.channel_infos.ids.includes(author_id)) {
                        if (user_data.shorts_list.some((value) => { return value.id === id; })) {
                            log('已存在' + author_name + '的短视频:' + title, 'shorts');
                        } else {
                            log('不过滤' + author_name + '的短视频:' + title, 'shorts');
                            const shorts_info = {
                                id: id,
                                title: title,
                                author_id: author_id,
                                author_name: author_name,
                                views_lable: views_lable,
                                from: page_type,
                                thumbnail_url: thumbnail_url,
                                ago_str: ago_str,
                            };
                            user_data.shorts_list.push(shorts_info);
                            user_data_api.set();
                        }
                    } else {
                        log('过滤' + author_name + '的短视频:' + title, 'shorts');
                    }
                }
                ).finally(() => {
                    if (this.shorts_list.length > 0)
                        setTimeout(() => { this.parse_shorts_list(); }, shorts_parse_delay);
                    else
                        this.parsing = false;
                });
            }
            check_shorts_exist() {
                const short_id = href.split('/').pop();
                for (let i = 0; i < user_data.shorts_list.length; i++) {
                    if (user_data.shorts_list[i].id === short_id) {
                        user_data.shorts_list.splice(i, 1);
                        user_data_api.set();
                        return;
                    }
                }
            }
            get_interval_tag(upload_date_str) {
                if (!upload_date_str) return '';
                const uploadDate = new Date(upload_date_str);
                const currentDate = new Date();
                const timeDifference = Math.abs(currentDate - uploadDate); // Difference in milliseconds
                const secondsDifference = timeDifference / 1000;
                const minutesDifference = secondsDifference / 60;
                const hoursDifference = minutesDifference / 60;
                const daysDifference = hoursDifference / 24;
                const weeksDifference = daysDifference / 7;
                const monthsDifference = weeksDifference / 4.345; // Average number of weeks in a month
                const yearsDifference = monthsDifference / 12;
                if (secondsDifference < 60) {
                    return `${Math.floor(secondsDifference)} seconds ago`;
                } else if (minutesDifference < 60) {
                    return `${Math.floor(minutesDifference)} minutes ago`;
                } else if (hoursDifference < 24) {
                    return `${Math.floor(hoursDifference)} hours ago`;
                } else if (daysDifference < 7) {
                    return `${Math.floor(daysDifference)} days ago`;
                } else if (weeksDifference < 4.345) {
                    return `${Math.floor(weeksDifference)} weeks ago`;
                } else if (monthsDifference < 12) {
                    return `${Math.floor(monthsDifference)} months ago`;
                } else {
                    return `${Math.floor(yearsDifference)} years ago`;
                }
            }
        };
        return new ShortsFun();
    }

    function get_yt_api() {
        return {
            get_subscribe_data: function (retry = 0) {
                const headers = {
                    "authority": "www.youtube.com",
                    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
                };
                const url = "https://www.youtube.com/feed/channels";
                const requestConfig = {
                    method: 'GET',
                    headers: headers,
                    url: url
                };
                const save_this = this;
                GM_xmlhttpRequest({
                    ...requestConfig,
                    onload: function (response) {
                        const tmp_channel_names = [];
                        const tmp_channel_ids = [];
                        const regex = /var ytInitialData \= (.*?);\<\/script\>/;
                        try {
                            const match = response.responseText.match(regex);
                            const ytInitialData_obj = JSON.parse(match[1]);
                            const items = ytInitialData_obj.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].shelfRenderer.content.expandedShelfContentsRenderer.items;
                            for (let item of items) {
                                const channel_name = item.channelRenderer.title.simpleText;
                                const match_channel_id = item.channelRenderer.channelId;
                                tmp_channel_ids.push(match_channel_id);
                                tmp_channel_names.push(channel_name);
                            }
                            if (tmp_channel_ids.length > 0) {
                                user_data.channel_infos.ids = tmp_channel_ids;
                                user_data.channel_infos.names = tmp_channel_names;
                                user_data_api.set();
                            }
                            log('获取关注列表成功' + user_data.channel_infos.ids.length + '个', 0);
                        } catch (error) {
                            if (retry < 3) {
                                setTimeout(() => { save_this.get_subscribe_data(retry + 1); }, 1000);
                            }
                            log('获取关注列表失败\n', error, -1);
                        }
                    },
                    onerror: function (error) {
                        if (retry < 3) {
                            setTimeout(() => { save_this.get_subscribe_data(retry + 1); }, 1000);
                        }
                        log('获取关注列表失败\n', error, -1);
                    },
                });
            },
            get_authorization: function () {
                function Vja() {
                    function a() {
                        e[0] = 1732584193;
                        e[1] = 4023233417;
                        e[2] = 2562383102;
                        e[3] = 271733878;
                        e[4] = 3285377520;
                        u = q = 0;
                    }
                    function b(x) {
                        for (var y = l, C = 0; 64 > C; C += 4)
                            y[C / 4] = x[C] << 24 | x[C + 1] << 16 | x[C + 2] << 8 | x[C + 3];
                        for (C = 16; 80 > C; C++)
                            x = y[C - 3] ^ y[C - 8] ^ y[C - 14] ^ y[C - 16],
                                y[C] = (x << 1 | x >>> 31) & 4294967295;
                        x = e[0];
                        var E = e[1]
                            , H = e[2]
                            , R = e[3]
                            , T = e[4];
                        for (C = 0; 80 > C; C++) {
                            if (40 > C) {
                                if (20 > C) {
                                    var X = R ^ E & (H ^ R);
                                    var la = 1518500249;
                                } else
                                    X = E ^ H ^ R,
                                        la = 1859775393;
                            } else
                                60 > C ? (X = E & H | R & (E | H),
                                    la = 2400959708) : (X = E ^ H ^ R,
                                        la = 3395469782);
                            X = ((x << 5 | x >>> 27) & 4294967295) + X + T + la + y[C] & 4294967295;
                            T = R;
                            R = H;
                            H = (E << 30 | E >>> 2) & 4294967295;
                            E = x;
                            x = X;
                        }
                        e[0] = e[0] + x & 4294967295;
                        e[1] = e[1] + E & 4294967295;
                        e[2] = e[2] + H & 4294967295;
                        e[3] = e[3] + R & 4294967295;
                        e[4] = e[4] + T & 4294967295;
                    }
                    function c(x, y) {
                        if ("string" === typeof x) {
                            x = unescape(encodeURIComponent(x));
                            for (var C = [], E = 0, H = x.length; E < H; ++E)
                                C.push(x.charCodeAt(E));
                            x = C;
                        }
                        y || (y = x.length);
                        C = 0;
                        if (0 == q)
                            for (; C + 64 < y;)
                                b(x.slice(C, C + 64)),
                                    C += 64,
                                    u += 64;
                        for (; C < y;)
                            if (h[q++] = x[C++],
                                u++,
                                64 == q)
                                for (q = 0,
                                    b(h); C + 64 < y;)
                                    b(x.slice(C, C + 64)),
                                        C += 64,
                                        u += 64;
                    }
                    function d() {
                        var x = []
                            , y = 8 * u;
                        56 > q ? c(m, 56 - q) : c(m, 64 - (q - 56));
                        for (var C = 63; 56 <= C; C--)
                            h[C] = y & 255,
                                y >>>= 8;
                        b(h);
                        for (C = y = 0; 5 > C; C++)
                            for (var E = 24; 0 <= E; E -= 8)
                                x[y++] = e[C] >> E & 255;
                        return x;
                    }
                    for (var e = [], h = [], l = [], m = [128], p = 1; 64 > p; ++p)
                        m[p] = 0;
                    var q, u;
                    a();
                    return {
                        reset: a,
                        update: c,
                        digest: d,
                        digestString: function () {
                            for (var x = d(), y = "", C = 0; C < x.length; C++)
                                y += "0123456789ABCDEF".charAt(Math.floor(x[C] / 16)) + "0123456789ABCDEF".charAt(x[C] % 16);
                            return y;
                        }
                    };
                }
                const sapisid_cookie = getCookie('SAPISID') || getCookie('APISID') || getCookie('__Secure-3PAPISID');
                if (sapisid_cookie) {
                    const timestamp = Math.floor(Date.now() / 1000);
                    const b = Vja();
                    b.update(timestamp + ' ' + sapisid_cookie + ' https://www.youtube.com');
                    const hash_value = b.digestString().toLowerCase();
                    return 'SAPISIDHASH ' + timestamp + '_' + hash_value;
                }
                return '';
            },
            get_channel_id: function (retry = 0) {
                const authorization = this.get_authorization();
                if (!authorization) {
                    log('获取authorization失败', 0);
                    return;
                }
                const url = "https://www.youtube.com/youtubei/v1/account/account_menu";
                const params = {
                    "prettyPrint": "false"
                };
                const data = {
                    "context": {
                        "client": {
                            "clientName": "WEB",
                            "clientVersion": "2.20240308.00.00",
                        },
                    },
                };
                const jsonData = JSON.stringify(data);
                const headers = {
                    "authorization": authorization,
                    "content-type": "application/json",
                    "origin": "https://www.youtube.com",
                    "referer": "https0://www.youtube.com/",
                };
                const requestConfig = {
                    method: 'POST',
                    headers: headers,
                    data: jsonData,
                    url: url + "?" + new URLSearchParams(params),
                };

                GM_xmlhttpRequest({
                    ...requestConfig,
                    onload: function (response) {
                        const match = response.responseText.match(/"browseId"\:"(.*?)"/);
                        if (match && match.length > 1) {
                            const tmp_id = match[1];
                            if (tmp_id && tmp_id != channel_id) {
                                channel_id = tmp_id;
                                user_data = user_data_api.get();
                                GM_setValue('last_channel_id', channel_id);
                            }
                            log('获取channel_id成功' + channel_id, 0);
                        } else {
                            if (retry < 3) {
                                setTimeout(() => { yt_api.get_channel_id(retry + 1); }, 500);
                            } else {
                                log('获取channel_id失败', response, response.responseText, -1);
                            }
                        }
                    },
                    onerror: function (error) {
                        if (retry < 3) {
                            setTimeout(() => { yt_api.get_channel_id(retry + 1); }, 500);
                            yt_api.get_channel_id(retry + 1);
                        } else {
                            log('获取channel_id失败', error, 0);
                        }
                    },
                });
            }
        };
    }

    function get_user_data_api() {
        return {
            get() {
                const default_user_data = {
                    "open_recommend_shorts": 'on',
                    "open_recommend_movie": 'on',
                    "open_recommend_popular": 'on',
                    "open_recommend_liveroom": 'on',
                    "open_recommend_playables": "on",
                    "add_shorts_upload_date": 'on',
                    "shorts_change_author_name": 'on',
                    "short_buy_super_thanks": 'on',
                    "shorts_auto_scroll": 'off',
                    "shorts_add_video_progress": 'off',
                    "shorts_dbclick_like": 'off',
                    "shorts_disable_loop_play": 'off',
                    "dbclick_download_video": 'off',
                    "language": 'zh-CN',
                    "channel_infos": {
                        "ids": [],
                        "names": []
                    },
                    "shorts_list": [],
                    "watch_page_config": {
                        "shop_banner": "on"
                    },
                    "login": false,
                };
                let diff = false;
                user_data_listener.set();
                let tmp_user_data = GM_getValue(channel_id);
                if (!tmp_user_data) {
                    tmp_user_data = default_user_data;
                    diff = true;
                }
                for (let key in default_user_data) {
                    if (!(key in tmp_user_data)) {
                        diff = true;
                        tmp_user_data[key] = default_user_data[key];
                    }
                }
                const tmp_login = channel_id !== 'default';
                if (tmp_user_data.login !== tmp_login) {
                    diff = true;
                    tmp_user_data.login = tmp_login;
                }
                (diff || this.update(tmp_user_data)) && GM_setValue(channel_id, tmp_user_data);
                return tmp_user_data;
            },
            set() {
                return GM_setValue(channel_id, user_data);
            },
            reset() {
                if (!confirm(flag_info.del_config_confirm_tips)) return;
                const keys = GM_listValues();
                for (let key of keys) {
                    GM_deleteValue(key);
                }
                unsafeWindow.document.location.reload();
            },
            update(tmp_user_data) {
                let diff = false;
                const last_version = GM_getValue('last_version', -1);
                if (last_version === -1 && !tmp_user_data.open_recommend_shorts) {
                    tmp_user_data.open_recommend_shorts = GM_getValue("open_recommend_shorts", "on");
                    tmp_user_data.open_recommend_movie = GM_getValue("open_recommend_movie", "on");
                    tmp_user_data.open_recommend_popular = GM_getValue("open_recommend_popular", "on");
                    tmp_user_data.open_recommend_liveroom = GM_getValue("open_recommend_liveroom", "on");
                    diff = true;
                }
                if (typeof (tmp_user_data.open_recommend_shorts) === 'boolean') {
                    tmp_user_data.open_recommend_shorts = tmp_user_data.open_recommend_shorts ? 'on' : 'off';
                    tmp_user_data.open_recommend_movie = tmp_user_data.open_recommend_movie ? 'on' : 'off';
                    tmp_user_data.open_recommend_popular = tmp_user_data.open_recommend_popular ? 'on' : 'off';
                    tmp_user_data.open_recommend_liveroom = tmp_user_data.open_recommend_liveroom ? 'on' : 'off';
                    diff = true;
                }
                last_version !== GM_info.script.version && GM_setValue("last_version", GM_info.script.version);
                return diff;
            }
        };
    }

    function get_data_process() {
        class DATA_PROCESS {
            constructor() {
                this.limit_eval = false;
                this.obj_filter;
                this.obj_storage = {};
            }
            condition_split_and_tag = '&&';
            condition_split_or_tag = '||';
            value_split_and_tag = '&';
            value_split_or_tag = '|';

            storage_obj(key, obj) {
                this.obj_storage[key] = obj;
            }

            set_obj_filter(obj_filter) {
                if (typeof obj_filter !== 'function') return;
                this.obj_filter = function () {
                    try {
                        obj_filter.apply(this, arguments);
                    } catch (error) {
                        log('obj_filter error', error, -1);
                        return false;
                    }
                };
            };

            text_process(data, values, mode, traverse_all) {
                if (!values) return data;
                const origin_data = data;
                try {
                    mode = mode || 'cover';
                    if (mode === 'reg') {
                        for (let value of values) {
                            const patten_express = value.split(SPLIT_TAG)[0];
                            const replace_value = value.split(SPLIT_TAG)[1];
                            const patten = new RegExp(patten_express, "g");
                            data = data.replace(patten, replace_value);
                        }
                    }
                    if (mode === 'cover') {
                        data = values[0];
                    }
                    if (mode === 'insert') {
                        traverse_all = traverse_all || false;
                        let json_data;
                        try {
                            json_data = JSON.parse(data);
                        } catch (error) {
                            log('text_process JSON parse error', -1);
                            return data;
                        }
                        this.obj_process(json_data, values, traverse_all);
                        data = JSON.stringify(json_data);
                    }
                } catch (error) {
                    log('text_process error', error, -1);
                    data = origin_data;
                }
                return data;
            }

            get_relative_path(basic_path, relative_path) {
                if (relative_path === '/') return basic_path;
                let real_path;
                if (relative_path.startsWith('/.')) {
                    real_path = basic_path + relative_path.slice(1);
                }
                if (relative_path.startsWith('.')) {
                    const reg = /[\.\[]/g;
                    const positions = [];
                    let match;
                    while ((match = reg.exec(basic_path)) !== null) {
                        positions.push(match.index);
                    }
                    if (positions.length === 0) {
                        return basic_path;
                    }
                    const pointer_match = relative_path.match(/^\.+/);
                    const split_index = positions[positions.length - pointer_match[0].length];
                    const relative_attribute = relative_path.slice(pointer_match[0].length);
                    real_path = basic_path.slice(0, split_index) + (relative_attribute ? ((relative_attribute.startsWith('[') ? '' : '.') + relative_attribute) : '');
                }
                return this.convertPathToBracketNotation(real_path);
            }

            value_parse(parse_value, path_info = null, json_obj = null) {
                const formula_match = parse_value.match(/\{.*?\}/g);
                if (formula_match) {
                    for (let express_ of formula_match) {
                        const express = express_.slice(1, -1);
                        if (!express) continue;
                        parse_value = parse_value.replace(express_, this.value_parse(express, path_info, json_obj));
                    }
                }
                const json_math = parse_value.match(/^json\((.*)\)$/);
                if (json_math) return JSON.parse(json_math[1]);
                const obj_match = parse_value.match(/^obj\((.*)\)$/);
                if (obj_match) return this.string_to_value(unsafeWindow, obj_match[1]);
                const storage_obj_match = parse_value.match(/^sobj\((.*)\)$/);
                if (storage_obj_match) return this.string_to_value(this.obj_storage, storage_obj_match[1]);
                const number_match = parse_value.match(/^num\((.*)\)$/);
                if (number_match) return Number(number_match[1]);
                const method_match = parse_value.match(/^method\((.*)\)$/);
                if (method_match) {
                    // eval 限制的时候可以使用num() obj()这些添加数字对象 方法也要放到unsafeWindow里 例:method(b("123",num(23)))
                    // 不限制的时候 不能使用num和obj 方法不需要放到unsafeWindow里 例:method(b("123",23))
                    if (this.limit_eval) {
                        const method_info = method_match[1].match(/(.*?)\((.*)\)$/);
                        const method_name = method_info[1];
                        const method_args_string = method_info[2];
                        const method_args = method_args_string.split(',');
                        const args = [];
                        for (let arg of method_args) {
                            args.push(this.value_parse(arg, path_info, json_obj));
                        }
                        return unsafeWindow[method_name](...args);
                    }
                    return eval(trustedScript(method_match[1]));
                }
                const deal_obj_match = parse_value.match(/^dealObj\((.*)\)$/);
                if (deal_obj_match) {
                    const path_msg = deal_obj_match[1];
                    return this.string_to_value(json_obj.this.get_relative_path(path_info.deal_path, path_msg));
                }
                const path_obj_match = parse_value.match(/^pathObj\((.*)\)$/);
                if (path_obj_match) {
                    const path_msg = path_obj_match[1];
                    return this.string_to_value(json_obj, this.get_relative_path(path_info.path, path_msg));
                }
                const abs_obj_match = parse_value.match(/^absObj\((.*)\)$/);
                if (abs_obj_match) {
                    const abs_path = abs_obj_match[1];
                    return this.string_to_value(json_obj, abs_path);
                }
                const string_match = parse_value.match(/^["'](.*)["']$/);
                if (string_match) return string_match[1];
                if (parse_value === 'undefined') return undefined;
                if (parse_value === 'null') return null;
                return parse_value;
            }

            string_to_value(obj, path) {
                try {
                    if (!this.limit_eval) {
                        return eval(trustedScript(path.replace('json_obj', 'obj')));
                    }
                    let tmp_obj = obj;
                    let matches = path.match(/\[(.*?)\]/g);
                    if (matches) {
                        matches.map((match) => {
                            if (match.includes('["')) {
                                tmp_obj = Reflect.get(tmp_obj, match.replace(/\["|"\]/g, ''));
                            } else {
                                tmp_obj = Reflect.get(tmp_obj, Number(match.replace(/\[|\]/g, '')));
                            }
                        });
                        return tmp_obj;
                    }
                    matches = path.split('.');
                    if (matches) {
                        matches.splice(0, 1);
                        matches.map((match) => {
                            tmp_obj = Reflect.get(tmp_obj, match);
                        });
                        return tmp_obj;
                    }
                } catch (error) {
                    return null;
                }
            }

            get_lastPath_and_key(path) {
                let last_path, last_key;
                let matches = path.match(/\[(.*?)\]/g);
                if (matches && matches.length > 0) {
                    const tmp = matches[matches.length - 1];
                    if (tmp.includes('["')) {
                        last_key = tmp.replace(/\["|"\]/g, '');
                    } else {
                        last_key = Number(tmp.replace(/\[|\]/g, ''));
                    }
                    last_path = path.substring(0, path.lastIndexOf(tmp));
                }
                if (!matches) {
                    matches = path.split('.');
                    if (matches && matches.length > 0) {
                        last_key = matches[matches.length - 1];
                        last_path = path.replace('.' + last_key, '');
                    }
                }
                return [last_path, last_key];
            }

            convertPathToBracketNotation(path) {
                if (!path) return '';
                return path.replace(/\.[\d\w\-\_\$@]+/g, function (match) {
                    return '["' + match.slice(1) + '"]';
                });
            }

            paths_sort(paths_arr, key_name = null, reverse = false) {
                // 路径格式是json_obj["onResponseReceivedActions"][0]["appendContinuationItemsAction"]
                // 支持数组元素是对象,根据里面的某个属性排序
                // 支持数组元素是字符串,根据字符串排序
                if (!Array.isArray(paths_arr)) {
                    throw new Error('paths_arr must be an array');
                }
                if (paths_arr.length === 0) return;
                let tmp_paths_arr = paths_arr;
                if (!key_name) {
                    key_name = 'path';
                    if (typeof paths_arr[0] !== 'string') throw new Error('paths_arr must be a string array');
                    tmp_paths_arr = [];
                    paths_arr.forEach(path => {
                        tmp_paths_arr.push({
                            path: path
                        });
                    });
                }
                const reverse_factor = reverse ? -1 : 1;
                tmp_paths_arr.sort((a, b) => {
                    function get_sort_key(obj) {
                        if (!obj.sort_keys) {
                            const reg = /\["?(.*?)"?\]/g;
                            let matches = [];
                            let match;
                            while (match = reg.exec(obj[key_name])) {
                                if (!match[0].startsWith('["')) {
                                    if (isNaN(match[1])) throw new Error('array index must be a number');
                                    match[1] = parseInt(match[1]);
                                }
                                matches.push(match[1]);
                            }
                            obj.sort_keys = matches;
                        }
                    }
                    if (a[key_name] === b[key_name]) return 0;
                    get_sort_key(a);
                    get_sort_key(b);
                    const a_sort_keys = a.sort_keys;
                    const b_sort_keys = b.sort_keys;
                    if (a_sort_keys.length !== b_sort_keys.length) {
                        return (b_sort_keys.length - a_sort_keys.length) * reverse_factor;
                    }
                    for (let i = 0; i < a_sort_keys.length; i++) {
                        if (a_sort_keys[i] !== b_sort_keys[i]) {
                            return (b_sort_keys[i] > a_sort_keys[i] ? 1 : -1) * reverse_factor;
                        }
                    }
                    return 0;
                });
                if (paths_arr !== tmp_paths_arr) {
                    paths_arr.length = 0;
                    tmp_paths_arr.forEach(path_info => {
                        paths_arr.push(path_info.path);
                    });
                }
            }

            obj_process(json_obj, express_list, traverse_all = false) {
                if (typeof json_obj !== 'object') {
                    log('obj_process不是对象', express_list, -1);
                    return;
                }
                if (typeof express_list === 'function') {
                    try {
                        express_list = express_list(json_obj);
                        if (!express_list || Array.isArray(express_list) && express_list.length === 0) return;
                    } catch (error) {
                        log('obj_process express_list函数执行错误', error, -1);
                        return;
                    }
                }
                const data_this = this;
                const abs_path_info_list = [];
                const relative_path_info_list = [];
                const relative_path_list = [];
                const relative_short_path_list = [];
                if (!json_obj || !express_list) return;
                const is_array_obj = Array.isArray(json_obj);
                try {
                    express_list.forEach(express => {
                        if (!express) return;
                        let reg;
                        const express_type = typeof (express);
                        let matches;
                        let conditions;
                        reg = /^(abs:)?(.*?)(=\-|~=|=\+|=)(\(?([^ ][\s\S]*?)\)?)?( ([\s\S]*))?$/;
                        if (express_type === 'string') {
                            matches = express.match(reg);
                        } else {
                            matches = express.value.match(reg);
                            conditions = express.conditions;
                        }
                        const abs = matches[1];
                        let path = matches[2];
                        const operator = matches[3];
                        let value = matches[4];
                        const condition = matches[7];
                        const path_extral_match = path.match(/\/\..*$|\.+$|\.\(.*$/);
                        let path_extral;
                        if (path_extral_match) {
                            path_extral = path_extral_match[0];
                            path = path.replace(path_extral, '');
                        }
                        let value_mode;
                        if (express_type === 'string') {
                            const mode_match = value?.match(/^\((.*)\)$/);
                            if (mode_match) {
                                // =('arr_insert',value,0)
                                const mode_info = mode_match[1].split(',');
                                value = mode_info[1];
                                const mode = mode_info[0];
                                mode_info.shift();
                                mode_info.shift();
                                value_mode = {
                                    'mode': mode,
                                    'params': mode_info
                                };
                            }
                            if (condition) {
                                // (fffddf|||ffff)&&&(ffff)
                                const tmp_conditions = condition ? condition.split(this.condition_split_and_tag) : [];
                                conditions = {};
                                for (let index = 0; index < tmp_conditions.length; index++) {
                                    conditions['value' + index] = tmp_conditions[index].split(this.condition_split_or_tag);
                                }
                            }
                        }
                        matches = path.match(/\[([\*\d\-,]*)\]$/);
                        let array_index;
                        if (matches) {
                            path = path.replace(/\[([\*\d\-,]*)\]$/, '');
                            array_index = matches[1];
                        }
                        if (abs) {
                            add_data_to_abs_path({
                                "path": `json_obj${is_array_obj ? '' : '.'}` + path,
                                "express": express,
                                "relative_path": path,
                                "operator": operator,
                                "value": value,
                                "condition": conditions,
                                "array_index": array_index,
                                "path_extral": path_extral,
                                "value_mode": value_mode
                            });
                        } else {
                            relative_path_list.push(path);
                            const tmp_short_path = path.split('.').pop();
                            relative_short_path_list.push(tmp_short_path);
                            relative_path_info_list.push({
                                "express": express,
                                "path": path,
                                "operator": operator,
                                "value": value,
                                "value_mode": value_mode,
                                "conditions": conditions,
                                "array_index": array_index,
                                "path_extral": path_extral
                            });
                        }
                    });
                    if (relative_path_list.length > 0) {
                        const dec_list = [];
                        const dec_index_list = [];
                        obj_property_traverse(json_obj, '', {
                            "short_keys": relative_short_path_list,
                            "real_keys": relative_path_list
                        }, dec_list, dec_index_list, traverse_all);
                        for (let i = 0; i < dec_index_list.length; i++) {
                            const real_index = dec_index_list[i];
                            const real_path_info = relative_path_info_list[real_index];
                            const tmp_path = 'json_obj' + dec_list[i];
                            add_data_to_abs_path({
                                "path": tmp_path,
                                "express": real_path_info.express,
                                "relative_path": real_path_info.path,
                                "operator": real_path_info.operator,
                                "value": real_path_info.value,
                                "condition": real_path_info.conditions,
                                "array_index": real_path_info.array_index,
                                "path_extral": real_path_info.path_extral,
                                "value_mode": real_path_info.value_mode
                            });
                        }
                    }
                    try {
                        this.paths_sort(abs_path_info_list, 'deal_path');
                    } catch (error) {
                        abs_path_info_list.sort((a, b) => a < b ? 1 : -1);
                    }
                    for (let path_info of abs_path_info_list) {
                        if (!this.obj_conditional(path_info, json_obj)) continue;
                        if (this.obj_filter && this.obj_filter(path_info, json_obj)) continue;
                        obj_modify(json_obj, path_info);
                    }
                } catch (error) {
                    log('obj_process处理失败', error, -1);
                }

                function add_data_to_abs_path(params) {
                    let { path, express, relative_path, operator, value, condition, array_index, path_extral, value_mode } = params;
                    let tmp;
                    path = data_this.convertPathToBracketNotation(path);
                    if (array_index === undefined) {
                        tmp = {};
                        path = path;
                        tmp.path = path;
                        tmp.relative_path = relative_path;
                        tmp.operator = operator;
                        tmp.value = value;
                        tmp.value_mode = value_mode;
                        tmp.condition = condition;
                        tmp.path_extral = path_extral;
                        tmp.express = express;
                        add_path(tmp);
                        return;
                    }
                    let array_index_list = [];
                    if (array_index === '*') {
                        let array_length;
                        try {
                            array_length = data_this.string_to_value(json_obj, path)?.length || 0;
                            if (!array_length) return;
                        } catch (error) {
                            log('obj_process获取数组长度失败--->' + path, error, -1);
                            return;
                        }
                        array_index_list = Array.from({ length: array_length }, (_, i) => i);
                    } else if (array_index.includes(',')) {
                        let is_error = false;
                        array_index_list = array_index.split(',').map(item => {
                            if (is_error) return;
                            if (isNaN(item)) {
                                is_error = true;
                                return;
                            }
                            return Number(item);
                        });
                        if (is_error) {
                            return log('obj_process数组索引格式错误--->' + path, -1);
                        }
                    } else if (array_index.includes('-')) {
                        const index_arr = array_index.split('-');
                        if (index_arr.length !== 2) return log('obj_process数组索引格式错误--->' + path, -1);
                        const start = Number(index_arr[0]);
                        const end = Number(index_arr[1]);
                        if (isNaN(start) || isNaN(end)) {
                            return log('obj_process数组索引格式错误--->' + path, -1);
                        }
                        array_index_list = Array.from({ length: end - start + 1 }, (_, i) => start + i);
                    } else if (!isNaN(array_index)) {
                        array_index_list = [array_index];
                    } else {
                        return log('obj_process数组索引格式错误--->' + path, -1);
                    }
                    for (let tmp_index = array_index_list.length - 1; tmp_index >= 0; tmp_index--) {
                        tmp = {};
                        tmp.path = path + "[" + array_index_list[tmp_index] + "]";
                        tmp.operator = operator;
                        tmp.value = value;
                        tmp.value_mode = value_mode;
                        tmp.condition = condition;
                        tmp.path_extral = path_extral;
                        tmp.relative_path = relative_path;
                        tmp.express = express;
                        add_path(tmp);
                    }
                    function add_path(path_info) {
                        path_info.deal_path = path_extral ? data_this.get_relative_path(path, path_extral) : path_info.path;
                        abs_path_info_list.push(path_info);
                    }
                }

                function obj_property_traverse(obj, cur_path, dec_infos, dec_list, dec_index_list, traverse_all = false) {
                    if (Array.isArray(obj)) {
                        obj.forEach((tmp_obj, index) => {
                            const tmp_path = cur_path + '[' + index + ']';
                            if (!tmp_obj || typeof (tmp_obj) !== 'object') return;
                            obj_property_traverse(tmp_obj, tmp_path, dec_infos, dec_list, dec_index_list, traverse_all);
                        });
                        return;
                    }
                    Object.keys(obj).forEach((key) => {
                        const tmp_path = cur_path + '.' + key;
                        let deal = false;
                        for (let i = 0; i < dec_infos["short_keys"].length; i++) {
                            if (dec_infos["short_keys"][i] === key) {
                                const len = dec_infos["real_keys"][i].length;
                                if (tmp_path.slice(tmp_path.length - len) === dec_infos["real_keys"][i]) {
                                    dec_list.push(tmp_path);
                                    dec_index_list.push(i);
                                    if (!deal && traverse_all && typeof (obj[key]) === 'object') {
                                        obj_property_traverse(obj[key], tmp_path, dec_infos, dec_list, dec_index_list, traverse_all);
                                    }
                                    deal = true;
                                }
                            }
                        }
                        const value = obj[key];
                        if (deal || !value || typeof (value) !== 'object') return;
                        obj_property_traverse(value, tmp_path, dec_infos, dec_list, dec_index_list, traverse_all);
                    });
                }

                function obj_modify(json_obj, path_info) {
                    const path = path_info['deal_path'];
                    const operator = path_info['operator'];
                    let value = path_info['value'];
                    const [last_path, last_key] = data_this.get_lastPath_and_key(path);
                    const last_obj = data_this.string_to_value(json_obj, last_path);
                    if (!last_obj) {
                        debugger;
                        return log('obj_modify处理失败,找不到对象--->' + path_info, -1);
                    }
                    if (operator === '=-') {
                        const is_array = typeof last_key === 'number';
                        if (is_array)
                            last_obj.splice(last_key, 1);
                        else
                            delete last_obj[last_key];
                        log('依据:' + path_info.express, 'obj_process');
                        log('删除属性-->' + path, 'obj_process');
                        return;
                    }
                    if (operator === '=') {
                        value = data_this.value_parse(value, path_info, json_obj);
                        last_obj[last_key] = value;
                        log('依据:' + path_info.express, 'obj_process');
                        log('修改属性-->' + path, 'obj_process');
                    }
                    const dec_obj = last_obj[last_key];
                    if (!dec_obj) {
                        return log('obj_modify处理失败,找不到对象--->' + path_info, -1);
                    }
                    if (operator === '=+') {
                        value = data_this.value_parse(value, path_info, json_obj);
                        if (dec_obj === null || dec_obj === undefined) throw new Error('dec_obj is null');
                        let type_ = typeof dec_obj;
                        if (Array.isArray(dec_obj)) type_ = 'array';
                        if (type_ === 'array') {
                            const mode_info = path_info.value_mode;
                            if (mode_info) {
                                try {
                                    mode_info.mode === 'arr_insert' && last_obj[last_key].splice(Number(mode_info.params[0]), 0, value);
                                } catch (error) {
                                    log(error, -1);
                                }
                            } else {
                                last_obj[last_key].push(value);
                            }
                        }
                        if (type_ === 'string' || type_ === 'number') last_obj[last_key] = last_obj[last_key] + value;
                        log('依据:' + path_info.express, 'obj_process');
                        log('修改属性-->' + path, 'obj_process');
                    }
                    if (operator === '~=') {
                        const search_value = value.split(SPLIT_TAG)[0];
                        const replace_value = value.split(SPLIT_TAG)[1];
                        last_obj[last_key] = dec_obj.replace(new RegExp(search_value, 'g'), replace_value);
                        log('依据:' + path_info.express, 'obj_process');
                        log('修改属性-->' + path, 'obj_process');
                    }
                }
            }

            path_process(json_obj, path) {
                if (path.includes('[-')) {
                    const match = path.match(/\[(-\d+)\]/);
                    const index = parseInt(match[1]);
                    const dec_obj_path = path.slice(0, match.index);
                    const array_length = this.string_to_value(json_obj, dec_obj_path + '["length"]');
                    if (!array_length) return path;
                    const real_index = array_length + index;
                    path = path.replace(`[${index}`, `[${real_index}`);
                    return this.path_process(json_obj, path);
                }
                return path;
            }

            value_conditional(value, condition_express) {
                const reg = /(\$text|\$value|\$exist|\$notexist)?((>=|<=|>|<|!~=|!=|~=|=))?(.*)/;
                const match = condition_express.match(reg);
                const condition_type = match[1] || '$text';
                const condition_operator = match[2];
                const condition_test_value = match[4];
                const operator_reg = /(>=|<=|>|<|!~=|!=|~=|=)?(.*)$/;
                if (condition_type === '$value') {
                    // $value=1|2 或 $value>=1&2
                    if (!['>=', '<=', '>', '<', '='].includes(condition_operator)) return false;
                    const split_tag = condition_test_value.includes(this.value_split_or_tag) && this.value_split_or_tag || this.value_split_and_tag;
                    const condition_test_value_arr = condition_test_value.split(split_tag);
                    let result;
                    for (let test_value of condition_test_value_arr) {
                        const operator_match = test_value.match(operator_reg);
                        const operator = operator_match && operator_match[1] || condition_operator;
                        test_value = operator_match && operator_match[2];
                        if (isNaN(test_value)) {
                            if (split_tag === this.value_split_and_tag) return false; else continue;
                        };
                        test_value = parseInt(test_value);
                        if (operator === '=') result = test_value === value;
                        if (operator === '>=') result = value >= test_value;
                        if (operator === '<=') result = value <= test_value;
                        if (operator === '>') result = value > test_value;
                        if (operator === '<') result = value < test_value;
                        if (!result) {
                            if (split_tag === this.value_split_and_tag) return false; else continue;
                        };
                        return true;
                    }
                }
                if (condition_type === '$exist') {
                    return value !== undefined && value !== null;
                }
                if (condition_type === '$notexist') {
                    return value === undefined || value === null;
                }
                if (condition_type === '$text') {
                    let split_tag;
                    let condition_test_value_arr;
                    if (['!~=', '~='].includes(condition_operator)) {
                        split_tag = this.value_split_and_tag;
                        condition_test_value_arr = [condition_test_value];
                    } else {
                        split_tag = condition_test_value.includes(this.value_split_or_tag) && this.value_split_or_tag || this.value_split_and_tag;
                        condition_test_value_arr = condition_test_value.split(split_tag);
                    }
                    let result;
                    if (typeof (value) === 'object') value = JSON.stringify(value);
                    for (let test_value of condition_test_value_arr) {
                        const operator_match = test_value.match(operator_reg);
                        const operator = operator_match && operator_match[1] || condition_operator;
                        test_value = operator_match && operator_match[2] || test_value;
                        if (operator === '!=') result = test_value !== value;
                        if (operator === '=') result = test_value === value;
                        if (operator === '~=') result = new RegExp(test_value).test(value);
                        if (operator === '!~=') result = !new RegExp(test_value).test(value);
                        if (operator === '>=') result = value.length >= test_value.length;
                        if (operator === '>') result = value.length > test_value.length;
                        if (operator === '<=') result = value.length <= test_value.length;
                        if (operator === '>') result = value.length > test_value.length;
                        if (!result) {
                            if (split_tag === this.value_split_and_tag) return false; else continue;
                        };
                        return true;
                    }
                }
                return false;
            }

            obj_conditional(express_info, json_obj) {
                //json_obj 在eval里直接调用
                if (!express_info['condition']) return true;
                const condition_infos = express_info['condition'];
                // 与 
                for (let condition_list of Object.values(condition_infos)) {
                    let result = false;
                    for (let condition of condition_list) {
                        const reg = /^([a-zA-Z_0-9\/\-\.@\[\]]*)?(.*)/;
                        const match = condition.match(reg);
                        let condition_path = match[1];
                        let mod;
                        if (condition_path) {
                            if (condition_path.startsWith('/')) {
                                mod = 'child';
                            } else if (condition_path.startsWith('.')) {
                                mod = 'parent';
                            } else if (condition_path.startsWith('@')) {
                                mod = 'global';
                            } else {
                                mod = 'other';
                            }
                        } else {
                            condition_path = express_info.path;
                        }
                        const conditional_express = match[2];
                        if (['child', 'parent'].includes(mod)) {
                            // child   /.a.b.c path相对路径
                            // parent  ..a.b.c path相对路径
                            condition_path = this.get_relative_path(express_info.path, condition_path);
                        }
                        if (mod === 'other') {
                            // json_obj里的绝对路径
                            condition_path = this.get_relative_path('json_obj', '/.' + condition_path);
                        }
                        if (mod === 'global') {
                            // 提取全局里的数据
                            condition_path = condition_path.replace('@', this.limit_eval ? 'unsafeWindow.' : '');
                        }
                        let condition_value;
                        try {
                            condition_path = this.path_process(json_obj, condition_path);
                            condition_value = this.string_to_value(mod === 'global' ? unsafeWindow : json_obj, condition_path);
                        } catch (error) {
                            continue;
                        }
                        result = this.value_conditional(condition_value, conditional_express);
                        if (result) {
                            express_info.condition_value = condition_value;
                            express_info.conform_value_path = condition_path;
                            log('条件成立-->', condition, typeof condition_value === 'object' ? '[object Object]' : condition_value, 'obj_process');
                            break;
                        }
                    }
                    if (!result) return false;
                }
                return true;
            }
        }
        return new DATA_PROCESS();
    }
})();