// ==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...
})();