VK Ads Fixes

This script applies several fixes to the adblock filter on VK, aiming to speed up site loading and enhance overall performance.

目前为 2024-07-06 提交的版本。查看 最新版本

// ==UserScript==
// @name         VK Ads Fixes
// @name:ru      Правки рекламы ВКонтакте
// @name:uk      Правки реклами ВКонтакте
// @namespace    https://vtosters.app/
// @version      1.6
// @description  This script applies several fixes to the adblock filter on VK, aiming to speed up site loading and enhance overall performance.
// @description:ru Этот скрипт вносит несколько исправлений в фильтр adblock в VK, чтобы ускорить загрузку сайта и повысить общую производительность.
// @description:uk Цей скрипт вносить кілька виправлень у фільтр adblock у VK, щоб прискорити завантаження сайту і підвищити загальну продуктивність.
// @author       gdlbo
// @match        https://vk.com/*
// @match        https://vk.ru/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    class InteractionListener {
        constructor() {
            this._listeners = [];
        }

        addListener(callback) {
            if (!this._listeners.includes(callback)) {
                this._listeners.push(callback);
            }
            return {
                remove: () => this.removeListener(callback),
            };
        }

        removeListener(callback) {
            const index = this._listeners.indexOf(callback);
            if (index !== -1) {
                this._listeners.splice(index, 1);
            }
        }

        get listeners() {
            return [...this._listeners];
        }
    }

    const interaction = new InteractionListener();

    const hookVK = async () => {
        let vkValue = window.vk;

        Object.defineProperty(window, "vk", {
            get: () => vkValue,
            set: (newVk) => {
                vkValue = newVk;
                for (const callback of interaction.listeners) {
                    try {
                        callback(vkValue);
                    } catch (e) {
                        console.error(e);
                    }
                }
                return true;
            },
            configurable: true,
        });
    };

    let inited = false;
    const onAddNewCallback = async (callback) => {
        if (inited) {
            // await waitVK();
        } else {
            inited = true;
            await hookVK();
        }

        callback(window.vk);
    };

    const onChangeVK = (callback) => {
        const listener = interaction.addListener(callback);

        onAddNewCallback(callback);

        return listener;
    };

    const createOnChangeVKField = (fieldName) => {
        const interaction = new InteractionListener();

        const hookField = (vkValue) => {
            let fieldValue = vkValue[fieldName];

            Object.defineProperty(vkValue, fieldName, {
                get: () => fieldValue,
                set: (newValue) => {
                    fieldValue = newValue;
                    for (const callback of interaction.listeners) {
                        try {
                            callback(fieldValue);
                        } catch (e) {
                            console.error(e);
                        }
                    }
                    return true;
                },
                configurable: true,
                enumerable: true,
            });
        };

        const hookFieldWithVK = async () => {
            let vkValue = window.vk;

            hookField(vkValue);

            onChangeVK((newVk) => {
                hookField(newVk);
            });
        };

        let inited = false;
        const onAddNewCallback = async (callback) => {
            if (!inited) {
                inited = true;
                await hookFieldWithVK();
            }
            callback(window.vk[fieldName]);
        };

        const onChangeField = (callback) => {
            const listener = interaction.addListener(callback);
            onAddNewCallback(callback);
            return listener;
        };

        return onChangeField;
    };

    const onChangeVKPart = createOnChangeVKField("pe");
    const onChangeAudioAdsConfig = createOnChangeVKField("audioAdsConfig");
    const onChangeErrorMonitoringConfig = createOnChangeVKField("cfg");

    const modifyVkPart = (vkParts) => {
        for (const key of [
            "send_user_info_stats",
            "force_send_user_info",
            "send_user_info_on_localhost",
            "send_navigation_stats_in_spa",
            "log_send_user_info_errors",
            "web_mytracker_collect_post_stats",
            "web_stats_device_id",
            "web_stats_reduce_debounce",
            "web_stats_send_beacon",
            "web_stats_send_on_events_limit",
            "web_stats_transport_story_view",
            "sentry_js_web_request_timeouts_feature",
            "sentry_js_web_request_timeouts_forwarding",
            "sentry_js_web_timeouts_forwarding",
            "sentry_js_web_verbose",
            "sentry_log_network_errors",
            "ads_app_form_link_redirect",
            "ads_autopromotion_web_geo",
            "ads_easy_promote_goods_new_create_api",
            "ads_light_methods_protection",
            "ads_market_autopromotion_bookmarks_stats",
            "ads_use_vk_community_video_portrait_4_5",
            "clips_web_my_tracker",
            "feed_post_track_code_client_web",
            "games_send_track_visitor_activity",
            "js_errors_no_write_uncaught_errors",
            "tgb_adblock_protection",
            "post_adblock_protection_promo",
            "eager_error_monitoring",
            "mini_apps_performance_close_app_empty_event",
            "mini_apps_performance_iframe_errors",
            "mini_apps_performance_web",
            "mini_apps_send_my_tracker_activity",
            "post_click_analytics_int_ext_link_click_web",
            "posting_track_event_count",
            "unique_adblock_users",
            "audio_my_tracker_web",
            "mini_apps_send_stat_arguments_bridge_events_sdk",
            "ajax_request_parse_html_error",
            "js_errors_no_write_uncaught_errors",
            "tns_track_sections",
            "tns_track_hosts",
            "geminus_counter",
            "ads_pixels_track_new_events_web_mvk",
            "web_navigation_handlers",
            "measure_module_navigation_stats",
            "group_join_track_event_count",
            "feed_content_events_open_post_event_web",
            "feed_posts_duration_stats_fix",
            "collect_unsupported_user_info_stats",
            "log_fetch_requests",
            "log_fetch_requests_get",
            "post_adguard_protection_promo",
            "extended_ajax_logging",
            "messenger_mediascope_stats_collect",
            "audio_player_stats_web"
        ]) {
            delete vkParts[key];
        }
    };

    const modifyAudioAdsConfig = (audioAdsConfig) => {
        if (audioAdsConfig) {
            Object.defineProperties(audioAdsConfig, {
                'enabled': {
                    value: false,
                    writable: false,
                    configurable: false,
                    enumerable: false
                },
                'day_limit_reached': {
                    value: false,
                    writable: false,
                    configurable: false,
                    enumerable: false
                },
            });
        }
    };

    const modifyErrorMonitoringConfig = (errorMonitoringConfig) => {
        Object.defineProperties(errorMonitoringConfig, {
            'dsn': {
                value: 'http://127.0.0.1',
                writable: false,
                configurable: false,
                enumerable: false
            },
        });
    };

    const modifyAdParams = (adParams) => {
        Object.defineProperties(adParams, {
            'ads_can_show': {
                value: 0,
                writable: false,
                configurable: false,
                enumerable: false
            },
            'leftads': {
                value: '',
                writable: false,
                configurable: false,
                enumerable: false
            },
            'wsTransport': {
                value: 'http://127.0.0.1',
                writable: false,
                configurable: false,
                enumerable: false
            },
            'ads_rotate_interval': {
                value: Number.MAX_SAFE_INTEGER,
                writable: false,
                configurable: false,
                enumerable: false
            }
        });
    };

    const modifyWindowProperties = () => {
        const properties = {
            noAds: true,
            noAdsAtAll: true,
            no_left_ads: true,
            no_ads: true,
            isNoAdsForce: true,
            hide_ad: true,
            ya_direct: false,
            yaDirectAdActive: false
        };

        for (const prop in properties) {
            if (!(prop in window)) {
                Object.defineProperty(window, prop, {
                    value: properties[prop],
                    writable: false,
                    configurable: false,
                    enumerable: false
                });
            }
        }
    };

    function decodeLink(link) {
        const httpOffset = link.search("http%3A%2F%2F");
        const httpsOffset = link.search("https%3A%2F%2F");
        const postOffset = link.search(/&post=/g);
        const ccKeyOffset = link.search(/&cc_key=/g);
        const offset = httpsOffset !== -1 ? httpsOffset : httpOffset;

        if (postOffset === -1 && ccKeyOffset === -1) {
            return decodeURIComponent(link.substring(offset));
        } else if (postOffset !== -1 && ccKeyOffset === -1) {
            return decodeURIComponent(link.substring(offset, postOffset));
        } else if (postOffset === -1 && ccKeyOffset !== -1) {
            return decodeURIComponent(link.substring(offset, ccKeyOffset));
        } else {
            const endOffset = Math.min(postOffset, ccKeyOffset);
            return decodeURIComponent(link.substring(offset, endOffset));
        }
    }

    function removeAway() {
        const links = document.getElementsByTagName("a");

        for (let i = 0; i < links.length; i++) {
            if (links[i].href.match(/away.php/)) {
                links[i].href = decodeLink(links[i].href);
            }
        }
    }

    function removeElementById(id) {
        const element = document.getElementById(id);
        if (element) {
            console.log(`Removing element with id: ${id}`);
            element.remove();
        }
    }

    function removeBlocks(blockClass) {
        const blocks = document.querySelectorAll(`div.${blockClass}`);
        blocks.forEach(block => {
            console.log(`Removing block with id: ${block.id}`);
            block.remove();
        });
    }

    function clearFunctions(obj) {
        for (const prop in obj) {
            if (typeof obj[prop] === 'function') {
                try {
                    Object.defineProperty(obj, prop, {
                        value: function () { },
                        writable: false,
                        configurable: false,
                        enumerable: false
                    });
                } catch (error) {
                    console.error(`Failed to clear function: ${prop}`, error);
                }
            }
        }
    }

    if (window.vk) {
        modifyVkPart(window.vk.pe);
        modifyAudioAdsConfig(window.vk.audioAdsConfig);
        modifyErrorMonitoringConfig(window.vk.cfg.error_monitoring_config);
        modifyAdParams(window.vk);
        modifyWindowProperties();

        onChangeVKPart(modifyVkPart);
        onChangeAudioAdsConfig(modifyAudioAdsConfig);
        onChangeErrorMonitoringConfig(modifyErrorMonitoringConfig);

        if (window.AdsLight) {
            clearFunctions(window.AdsLight);
        }

        window.__adsSet = function () { };
        window.__adsUpdate = function () { };
    }

    setInterval(() => {
        removeAway();
        removeBlocks('_ads_block_data_w');
        removeElementById('ads_left');
        if (window.AdsLight) {
            clearFunctions(window.AdsLight);
        }
    }, window.navigator?.hardwareConcurrency ? (30_000 / navigator.hardwareConcurrency) : 30_000);
})();

QingJ © 2025

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