LINUX.ORG.RU

История изменений

Исправление Legioner, (текущая версия) :

Очередная итерация. Оказалось, что youtube засовывает рекламу прямо в страницу, чистить JSON-ответы не всегда достаточно. Сделал такой вариант, пока вроде работает.

(() => {
    "use strict";
    // remove JSON ads
    const originalJSONParse = JSON.parse;
    JSON.parse = function (text, reviver) {
        const obj = originalJSONParse.call(this, text, reviver);
        removeJSONAds(obj);
        return obj;
    };

    const originalResponsePrototypeJson = Response.prototype.json;
    Response.prototype.json = function () {
        return originalResponsePrototypeJson.call(this).then(obj => {
            removeJSONAds(obj);
            return obj;
        });
    };

    function removeJSONAds(obj) {
        if (obj == null || typeof obj !== "object") {
            return;
        }
        if (Array.isArray(obj)) {
            for (const item of obj) {
                // noinspection JSUnresolvedVariable
                delete item?.playerResponse?.adPlacements;
            }
        }
        // noinspection JSUnresolvedVariable
        delete obj.adPlacements;
        // noinspection JSUnresolvedVariable
        delete obj.playerResponse?.adPlacements;
    }

    // remove global object ads
    function defineProxyProperty(object, property, behaviour) {
        const value = object[property];
        const proxyHandler = getProxyHandler(behaviour);
        let proxyValue = value == null ? value : new Proxy(value, proxyHandler);
        Object.defineProperty(object, property, {
            enumerable: true,

            get() {
                return proxyValue;
            },

            set(newValue) {
                proxyValue = newValue == null ? newValue : new Proxy(newValue, proxyHandler);
            }
        });
    }

    function getProxyHandler(behaviour) {
        // noinspection JSUnusedGlobalSymbols
        return {
            get(target, property) {
                if (property in behaviour) {
                    const propertyBehaviour = behaviour[property];
                    if (propertyBehaviour == null) {
                        return propertyBehaviour;
                    }
                    const propertyValue = target[property];
                    if (propertyValue == null) {
                        return propertyValue;
                    }
                    return new Proxy(propertyValue, getProxyHandler(propertyBehaviour));
                } else {
                    return target[property];
                }
            },

            has(target, property) {
                if (property in behaviour) {
                    const propertyBehaviour = behaviour[property];
                    if (propertyBehaviour === undefined) {
                        return false;
                    }
                }
                return property in target;
            }
        };
    }

    defineProxyProperty(window, "ytInitialPlayerResponse", {adPlacements: undefined});
})();

Исходная версия Legioner, :

Очередная итерация. Оказалось, что youtube засовывает рекламу прямо в страницу, чистить JSON-ответы не всегда достаточно. Сделал такой вариант, пока вроде работает.

(() => {
    "use strict";
    console.log("youtube_script");
    // remove JSON ads
    const originalJSONParse = JSON.parse;
    JSON.parse = function (text, reviver) {
        const obj = originalJSONParse.call(this, text, reviver);
        removeJSONAds(obj);
        return obj;
    };

    const originalResponsePrototypeJson = Response.prototype.json;
    Response.prototype.json = function () {
        return originalResponsePrototypeJson.call(this).then(obj => {
            removeJSONAds(obj);
            return obj;
        });
    };

    function removeJSONAds(obj) {
        if (obj == null || typeof obj !== "object") {
            return;
        }
        if (Array.isArray(obj)) {
            for (const item of obj) {
                // noinspection JSUnresolvedVariable
                delete item?.playerResponse?.adPlacements;
            }
        }
        // noinspection JSUnresolvedVariable
        delete obj.adPlacements;
        // noinspection JSUnresolvedVariable
        delete obj.playerResponse?.adPlacements;
    }

    // remove global object ads
    function defineProxyProperty(object, property, behaviour) {
        const value = object[property];
        const proxyHandler = getProxyHandler(behaviour);
        let proxyValue = value == null ? value : new Proxy(value, proxyHandler);
        Object.defineProperty(object, property, {
            enumerable: true,

            get() {
                return proxyValue;
            },

            set(newValue) {
                proxyValue = newValue == null ? newValue : new Proxy(newValue, proxyHandler);
            }
        });
    }

    function getProxyHandler(behaviour) {
        // noinspection JSUnusedGlobalSymbols
        return {
            get(target, property) {
                if (property in behaviour) {
                    const propertyBehaviour = behaviour[property];
                    if (propertyBehaviour == null) {
                        return propertyBehaviour;
                    }
                    const propertyValue = target[property];
                    if (propertyValue == null) {
                        return propertyValue;
                    }
                    return new Proxy(propertyValue, getProxyHandler(propertyBehaviour));
                } else {
                    return target[property];
                }
            },

            has(target, property) {
                if (property in behaviour) {
                    const propertyBehaviour = behaviour[property];
                    if (propertyBehaviour === undefined) {
                        return false;
                    }
                }
                return property in target;
            }
        };
    }

    defineProxyProperty(window, "ytInitialPlayerResponse", {adPlacements: undefined});
})();