YouTube Flag Tracker

Track changes in YouTube's experiment flags

目前为 2024-11-02 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Flag Tracker
  3. // @namespace Violentmonkey Scripts
  4. // @version 1.2
  5. // @description Track changes in YouTube's experiment flags
  6. // @include http*://www.youtube.com/*
  7. // @grant unsafeWindow
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @run-at document-end
  11. // ==/UserScript==
  12.  
  13. function save(key, data) {
  14.  
  15. if (!Object.keys(data).length) {
  16. return;
  17. }
  18.  
  19. if (key === "changes") {
  20. const changes = GM_getValue("changes", []);
  21. changes.unshift(data);
  22. data = changes;
  23. }
  24.  
  25. GM_setValue(key, data);
  26. }
  27.  
  28. // Comparison Cases: Boolean, Integer, Float, String, List.
  29. function isEqual(a, b) {
  30.  
  31. // Primitive Types: Boolean, Integer, Float, String
  32. if (a === b) {
  33. return true;
  34. }
  35.  
  36. // Array Type
  37. if (Array.isArray(a) && Array.isArray(b)) {
  38. return (
  39. a.length === b.length &&
  40. JSON.stringify(a) === JSON.stringify(b)
  41. );
  42. }
  43.  
  44. console.log("not equal");
  45. return false; // Other Type
  46. }
  47.  
  48. function diffChecker(prev = {}, curr = {}) {
  49.  
  50. let changes = {};
  51.  
  52. const allKeys = new Set([...Object.keys(prev), ...Object.keys(curr)]);
  53.  
  54. allKeys.forEach(key => {
  55.  
  56. const prevVal = prev[key];
  57. const currVal = curr[key];
  58.  
  59. if (prevVal === undefined) {
  60. changes[key] = { type: "added", value: currVal };
  61. }
  62.  
  63. else if (currVal === undefined) {
  64. changes[key] = { type: "removed" };
  65. }
  66.  
  67. else if (!isEqual(prevVal, currVal)) {
  68. changes[key] = { type: "modified", value: currVal };
  69. }
  70. });
  71.  
  72. return changes;
  73. }
  74.  
  75. function updateStorage(curr) {
  76.  
  77. const prev = GM_getValue("flags", {});
  78. const changes = diffChecker(prev, curr);
  79.  
  80. save("changes", changes);
  81. save("flags", curr);
  82. }
  83.  
  84. function observeFlags() {
  85.  
  86. const observer = new MutationObserver(() => {
  87.  
  88. const flags = unsafeWindow.yt?.config_?.EXPERIMENT_FLAGS;
  89.  
  90. if (flags) {
  91. observer.disconnect();
  92. console.log(flags);
  93. updateStorage(flags);
  94. }
  95. });
  96.  
  97. observer.observe(document.body, { childList: true, subtree: true });
  98. }
  99.  
  100.  
  101. observeFlags();