YouTube Perferred Settings for Private Mode

Save the setting permanently

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         YouTube Perferred Settings for Private Mode
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Save the setting permanently
// @author       CY Fung
// @icon         data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='189' height='140' viewBox='0 0 270 200' %3E%3Crect x='0' y='0' width='270' height='200'%3E%3C/rect%3E%3Cpath d='m106 190c-27.3-.6-48.3-1.5-60.6-3-7.2-.9-9.9-1.5-13.2-2.7-8.1-2.4-15-8.7-18.9-16.2-2.7-5.7-4.5-15.3-5.7-30.6-2.4-26.4-2.4-49.2 0-75.9 1.2-13.8 3-23.1 5.4-28.5 3.9-7.8 11.1-14.4 19.2-16.8 9.6-3 32.7-4.8 76.2-5.7 35.4-.6 81.3.3 105.9 2.4 20.4 1.5 27.6 3.9 34.8 11.1 7.5 7.5 9.9 15 12 37.2 1.2 12.9 1.5 22.5 1.5 39 0 25.8-1.5 46.5-4.5 59.7-1.5 6.9-4.2 12-9 16.5-7.2 7.5-14.1 9.6-34.8 11.4-24.6 1.8-71.7 3-108.3 2.1z' fill='%23018000'/%3E%3Cpath d='M110 66 178 104 110 142Z' fill='%23fff'/%3E%3C/svg%3E
// @license     MIT
// @match     https://www.youtube.com/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/js-cookie/3.0.1/js.cookie.min.js
// @noframes
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const gmKey = 'yps-r';
    const cookieDomain ='youtube.com';
    const STORE_VERSION = 1.1;
    /*

        this.j = g.N("ALT_PREF_COOKIE_NAME", "PREF");
        this.u = g.N("ALT_PREF_COOKIE_DOMAIN", "youtube.com");
    */

    /*global Cookies*/

    console.assert(typeof Cookies === "object");

    const skipKeys = ['SIDCC','CONSISTENCY'];


    const isPassiveArgSupport = (typeof IntersectionObserver === 'function');
    // https://caniuse.com/?search=observer
    // https://caniuse.com/?search=addEventListener%20passive

    const bubblePassive = isPassiveArgSupport ? { capture: false, passive: true } : false;
    const capturePassive = isPassiveArgSupport ? { capture: true, passive: true } : true;


    let registerH = 0;



    let navigationCheckPromiseResolve = null;
    const navigationCheckPromise = new Promise(r=>{
        navigationCheckPromiseResolve=r;
    });

    let _beginCookie = null;
    function regBegin(){

        if(registerH>0){
            GM_unregisterMenuCommand(registerH);
        }
    registerH = GM_registerMenuCommand("Setting Record Begin", begin, "b");
    }
    function regEnd(){

        if(registerH>0){
            GM_unregisterMenuCommand(registerH);
        }
        registerH = GM_registerMenuCommand("Setting Record End", end, "e");
    }
    function begin() {
        _beginCookie = Cookies.get();
        regEnd();
        let elm = document.querySelector('ytd-app');
        if(elm) elm.classList.add('yps-recording');
    }

    function end() {
        regBegin();
        const beginCookie = _beginCookie;
        if (!beginCookie) return alert('Recording was not started.')
        _beginCookie = null;


        let elm = document.querySelector('ytd-app');
        if(elm) elm.classList.remove('yps-recording');

        let endCookie = Cookies.get();
        let removed = [];
        let added = [];
        let keysBegin = Object.keys(beginCookie)
        let keysEnd = Object.keys(endCookie)

        let changed = [];
        for (const key of keysBegin) {

            if (keysEnd.includes(key)) {
                if (beginCookie[key] !== endCookie[key] && !skipKeys.includes(key)) {

                    changed.push({
                        key: key,
                        preValue: beginCookie[key],
                        newValue: endCookie[key],
                        changed: true
                    })
                }
                endCookie[key] = null;
                continue;
            }
            removed.push({
                key: key,
                prevValue: beginCookie[key],
                removed: true
            })
        }

        for (const key of keysEnd) {

            if (endCookie[key] === null) continue;
            added.push({
                key: key,
                newValue: endCookie[key],
                added: true
            })
        }

        if (removed.length > 0 || added.length > 0 || changed.length > 0) {

            let ret = prompt(
                [
                    `The recorded changes are as follows:`,
                    `Removed keys: ${JSON.stringify(removed, null, 2)},`,
                    `Added keys: ${JSON.stringify(added, null, 2)},`,
                    `Changed keys: ${JSON.stringify(changed, null, 2)},`,
                    `If you want to save these changes permanently, please type 'confirm'.`
                ].join('\n')
                , "confirm");


                async function goSave(req){

                    let gmValue = null;
                    try{
                        gmValue = await GM.getValue(gmKey);
                    }catch(e){}
                    if(!gmValue || typeof gmValue !=='string'){
                        gmValue = '{}';
                    }
                    let pObj = null;
                    try{
                        pObj = JSON.parse(gmValue)
                    }catch(e){

                    }
                    if(!pObj || pObj.version !== STORE_VERSION){
                        pObj = {
                            version: STORE_VERSION,
                            cookies:{

                            }
                        };
                    }

                    const cookies = pObj.cookies;

                    for(const {key} of req.removed){

                        cookies[key]={
                            v: null
                        }
                    }
                    for(const {key, newValue} of req.added){

                        cookies[key]={
                            v: newValue
                        }
                    }
                    for(const {key, newValue} of req.changed){

                        cookies[key]={
                            v: newValue
                        }
                    }


                    let success = true;
                    try{
                        let gmValue = JSON.stringify(pObj);
                        await GM.setValue(gmKey, gmValue);
                    }catch(e){
                        console.warn(e);
                        success = false;
                    }

                    if(success){
                        alert('The settings have been saved.')
                    }



                }


                if(ret.toLowerCase()==='confirm'){
                    goSave({
                        version: STORE_VERSION,
                        removed: removed,
                        added: added,
                        changed: changed
                    })
                }
        } else {
            alert('No changes can be recorded.')
        }


    }

    regBegin();

    async function init(){
        
        let _cookie = document.cookie||''
        if(_cookie.indexOf('CONSISTENCY')>=0) return;
        if(_cookie.indexOf('SIDCC')>=0) return;
         

        let gmValue = null;
        try{
           gmValue = await GM.getValue(gmKey);
        }catch(e){}
        if(!gmValue) return;

        let pObj = null;
        try{
            pObj = JSON.parse(gmValue)
        }catch(e){
        }

        if(!pObj || pObj.version !== STORE_VERSION){
            pObj = {
                version: STORE_VERSION,
                cookies:{
                }
            };
            return;
        }

        if(!pObj.cookies) return;

        await Promise.resolve(0);

        const cookies = pObj.cookies;


        for (const key in cookies) {
            if(cookies[key].v===null){
                Cookies.remove(key);
            }else if(typeof cookies[key].v ==='string'){
                Cookies.set(key, cookies[key].v, { domain: cookieDomain} )
            }
        }

        if(typeof navigationCheckPromiseResolve === 'function'){
            navigationCheckPromiseResolve();
        }


    }
    init();



    async function updateRecord(){
        return;

        let gmValue = null;
        try{
           gmValue = await GM.getValue(gmKey);
        }catch(e){}
        if(!gmValue) return;

        let pObj = null;
        try{
            pObj = JSON.parse(gmValue)
        }catch(e){
        }

        if(!pObj || pObj.version !== STORE_VERSION){
            pObj = {
                version: STORE_VERSION,
                cookies:{
                }
            };
            return;
        }

        if(!pObj.cookies) return;

        await Promise.resolve(0);

        const cookies = pObj.cookies;

        let overrided = 0;

        for (const key in cookies) {


            if(cookies[key].v===null){
                if(typeof Cookies.get(key) ==='string'){
                    delete cookies[key];
                    overrided++;
                }
            }else if(typeof cookies[key].v ==='string'){

                if(Cookies.get(key)!==cookies[key].v){
                    delete cookies[key];
                    overrided++;
                }
            }

        }

        if(overrided>0){

            let success = true;
            try{
                let gmValue = JSON.stringify(pObj);
                await GM.setValue(gmKey, gmValue);
            }catch(e){
                console.warn(e);
                success = false;
            }

            if(success){
                console.log('The perferred settings have been overrided.')
            }



        }




    }


    document.addEventListener('yt-navigate-finish', function(){

        navigationCheckPromise.then(()=>{
           // updateRecord();

        })

    }, bubblePassive)


    let keyupDT = 0;

    document.addEventListener('keyup', function(evt){

        if(evt.shiftKey && evt.code ==='KeyR'){


        }else{
            if(keyupDT>0 && evt.code ==='KeyR'){

            }else{

                keyupDT = 0;
                return;
            }
        }

        let t = Date.now();
        if(keyupDT>0){
            if(t - keyupDT <300){
                console.log('Shift-R-R')

                if(!_beginCookie){
                    begin();
                }else{
                    end();
                }
            }
            keyupDT = 0;
        }
        keyupDT = t;


    }, bubblePassive);

    GM_addStyle(
        `ytd-app.yps-recording{
            filter:brightness(0.7);
        }`
    );


    // Your code here...
})();