Advertisement
Guest User

YTBetter v1.2

a guest
Aug 24th, 2021
19,502
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.90 KB | None | 0 0
  1. // ==UserScript==
  2. // @name YTBetter
  3. // @namespace YTBetter
  4. // @match https://*.youtube.com/*
  5. // @run-at document-start
  6. // @grant none
  7. // @version 1.2
  8. // @author hop-step-pokosan
  9. // @description Patches YouTube to bypass some limitations
  10. // ==/UserScript==
  11.  
  12. (() => {
  13. const _DEBUG = false;
  14. const debug = (...msg) => {
  15. if (_DEBUG) {
  16. console.log("[YTBetter]", ...msg);
  17. }
  18. }
  19.  
  20. const PatchPlayerResponse = (playerResponse) => {
  21. try {
  22. // Patch to allow DVR to work on all streams
  23. if (playerResponse.videoDetails) {
  24. playerResponse.videoDetails.isLiveDvrEnabled = true;
  25. }
  26. } catch (err) {
  27. debug("Failed to patch playerResponse", err);
  28. }
  29. };
  30.  
  31. const GetPlayerResponse = (videoInfo) => {
  32. return videoInfo.raw_player_response || videoInfo.embedded_player_response || videoInfo.player_response;
  33. };
  34.  
  35. const TrapLoadVideoByPlayerVars = (value) => new Proxy(value, {
  36. apply: (target, thisArg, argumentsList) => {
  37. (() => {
  38. if (argumentsList.length !== 5) {
  39. return;
  40. }
  41.  
  42. let videoInfo = argumentsList[0];
  43. let playerResponse = GetPlayerResponse(videoInfo);
  44. if (typeof playerResponse === "undefined") {
  45. return;
  46. }
  47.  
  48. if (typeof playerResponse === "string") {
  49. playerResponse = JSON.parse(playerResponse);
  50. delete videoInfo.player_response;
  51. delete videoInfo.embedded_player_response;
  52. }
  53.  
  54. PatchPlayerResponse(playerResponse);
  55. })();
  56. debug("TrapLoadVideoByPlayerVars", thisArg, argumentsList);
  57. return Reflect.apply(target, thisArg, argumentsList);
  58. },
  59. });
  60.  
  61. const TrapConstructorPrototype = (value) => new Proxy(value, {
  62. defineProperty: (target, property, descriptor) => {
  63.  
  64. (() => {
  65. if (property !== "loadVideoByPlayerVars") {
  66. return;
  67. }
  68.  
  69. descriptor.value = TrapLoadVideoByPlayerVars(descriptor.value);
  70. })();
  71. return Reflect.defineProperty(target, property, descriptor);
  72. },
  73. });
  74.  
  75. const TrapConstructorCreate = (value) => new Proxy(value, {
  76. apply: (target, thisArg, argumentsList) => {
  77. (() => {
  78. if (argumentsList.length !== 3) {
  79. return;
  80. }
  81.  
  82. let videoInfo = argumentsList[1].args;
  83. let playerResponse = GetPlayerResponse(videoInfo);
  84. if (typeof playerResponse === "undefined") {
  85. return;
  86. }
  87.  
  88. if (typeof playerResponse === "string") {
  89. playerResponse = JSON.parse(playerResponse);
  90. delete videoInfo.player_response;
  91. delete videoInfo.embedded_player_response;
  92. }
  93.  
  94. PatchPlayerResponse(playerResponse);
  95. })();
  96. debug("TrapConstructorCreate", thisArg, argumentsList);
  97. return Reflect.apply(target, thisArg, argumentsList);
  98. },
  99. });
  100.  
  101. const TrapVideoConstructor = (value) => new Proxy(value, {
  102. defineProperty: (target, property, descriptor) => {
  103. (() => {
  104. switch (property) {
  105. case "prototype":
  106. descriptor.value = TrapConstructorPrototype(descriptor.value);
  107. case "create":
  108. descriptor.value = TrapConstructorCreate(descriptor.value);
  109. default:
  110. return;
  111. }
  112.  
  113. descriptor.value = TrapConstructorPrototype(descriptor.value);
  114. })();
  115. return Reflect.defineProperty(target, property, descriptor);
  116. },
  117. });
  118.  
  119. const TrapUpdateVideoInfo = (value) => new Proxy(value, {
  120. apply: (target, thisArg, argumentsList) => {
  121. (() => {
  122. if (argumentsList.length !== 3) {
  123. return;
  124. }
  125.  
  126. let videoInfo = argumentsList[1];
  127. let playerResponse = GetPlayerResponse(videoInfo);
  128. if (typeof playerResponse === "undefined") {
  129. return;
  130. }
  131.  
  132. if (typeof playerResponse === "string") {
  133. playerResponse = JSON.parse(playerResponse);
  134. delete videoInfo.player_response;
  135. delete videoInfo.embedded_player_response;
  136. }
  137.  
  138. PatchPlayerResponse(playerResponse);
  139. })();
  140. debug("TrapUpdateVideoInfo", thisArg, argumentsList);
  141. return Reflect.apply(target, thisArg, argumentsList);
  142. },
  143. });
  144.  
  145. const TrapYTPlayer = (value) => {
  146. const VideoConstructorFuncRegex = /this.webPlayerContextConfig=/;
  147. const UpdateVideoInfoRegex = /a.errorCode=null/;
  148.  
  149. let FoundVideoConstructor = false;
  150. let FoundUpdateVideoInfo = false;
  151.  
  152. return new Proxy(value, {
  153. defineProperty: (target, property, descriptor) => {
  154. (() => {
  155. if (typeof descriptor.value !== "function") {
  156. return;
  157. }
  158.  
  159. if (!FoundUpdateVideoInfo) {
  160. if (UpdateVideoInfoRegex.test(descriptor.value.toString())) {
  161. // UpdateVideoInfo is used for embeded videos, we need to trap
  162. // it to enable DVR on embeds.
  163. debug("Found UpdateVideoInfo func", property, descriptor.value);
  164. descriptor.value = TrapUpdateVideoInfo(descriptor.value);
  165. FoundUpdateVideoInfo = true;
  166. return;
  167. }
  168. }
  169.  
  170. if (!FoundVideoConstructor) {
  171. if (VideoConstructorFuncRegex.test(descriptor.value.toString())) {
  172. // VideoConstructor func is the constructor for videos,
  173. // we use it to patch some data when new videos are loaded.
  174. debug("Found VideoConstructor func", property, descriptor.value);
  175. descriptor.value = TrapVideoConstructor(descriptor.value);
  176. FoundVideoConstructor = true;
  177. return;
  178. }
  179. }
  180. })();
  181.  
  182. return Reflect.defineProperty(target, property, descriptor);
  183. },
  184. });
  185. }
  186.  
  187. debug("Script start");
  188.  
  189. Object.defineProperty(window, "_yt_player", {
  190. value: TrapYTPlayer({}),
  191. });
  192. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement