Track changes in YouTube's experiment flags
当前为
// ==UserScript==
// @name YouTube Flag Tracker
// @namespace Violentmonkey Scripts
// @version 1.2
// @description Track changes in YouTube's experiment flags
// @include http*://www.youtube.com/*
// @grant unsafeWindow
// @grant GM_setValue
// @grant GM_getValue
// @run-at document-end
// ==/UserScript==
function save(key, data) {
if (!Object.keys(data).length) {
return;
}
if (key === "changes") {
const changes = GM_getValue("changes", []);
changes.unshift(data);
data = changes;
}
GM_setValue(key, data);
}
// Comparison Cases: Boolean, Integer, Float, String, List.
function isEqual(a, b) {
// Primitive Types: Boolean, Integer, Float, String
if (a === b) {
return true;
}
// Array Type
if (Array.isArray(a) && Array.isArray(b)) {
return (
a.length === b.length &&
JSON.stringify(a) === JSON.stringify(b)
);
}
console.log("not equal");
return false; // Other Type
}
function diffChecker(prev = {}, curr = {}) {
let changes = {};
const allKeys = new Set([...Object.keys(prev), ...Object.keys(curr)]);
allKeys.forEach(key => {
const prevVal = prev[key];
const currVal = curr[key];
if (prevVal === undefined) {
changes[key] = { type: "added", value: currVal };
}
else if (currVal === undefined) {
changes[key] = { type: "removed" };
}
else if (!isEqual(prevVal, currVal)) {
changes[key] = { type: "modified", value: currVal };
}
});
return changes;
}
function updateStorage(curr) {
const prev = GM_getValue("flags", {});
const changes = diffChecker(prev, curr);
save("changes", changes);
save("flags", curr);
}
function observeFlags() {
const observer = new MutationObserver(() => {
const flags = unsafeWindow.yt?.config_?.EXPERIMENT_FLAGS;
if (flags) {
observer.disconnect();
console.log(flags);
updateStorage(flags);
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
observeFlags();