Greasy Fork 支持简体中文。

hookFetch

only hookFetch

目前為 2023-05-05 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/465483/1186059/hookFetch.js

  1. (() => {
  2. var contextWindow = window.unsafeWindow || document.defaultView || window;
  3. if (contextWindow['__hookRequest__'] != null) {
  4. return;
  5. }
  6. var globalVariable = new Map();
  7. var FetchMapList = new Map();
  8. var XhrMapList = new Map();
  9.  
  10. function deliveryTask(callbackList, _object, period) {
  11. let newObject = _object;
  12. for (let i = 0; i < callbackList.length; i++) {
  13. let tempObject = null;
  14. try {
  15. tempObject = callbackList[i](newObject, period);
  16. } catch (e) {
  17. new Error(e);
  18. }
  19. if (tempObject == null) {
  20. continue;
  21. }
  22. newObject = tempObject;
  23. }
  24. return newObject;
  25. }
  26.  
  27. function hookFetch() {
  28. const originalFetch = contextWindow.fetch;
  29. globalVariable.set('Fetch', originalFetch);
  30. contextWindow.fetch = (...args) => {
  31. let U = args[0];
  32. if (U.indexOf('http') == -1) {
  33. if (U[0] !== '/') {
  34. let pathname = new URL(location.href).pathname;
  35. U = pathname + U;
  36. }
  37. U = location.origin + U;
  38. }
  39. let apply = null;
  40. (() => {
  41. let url = new URL(U),
  42. pathname = url.pathname,
  43. callback = FetchMapList.get(pathname);
  44. if (callback == null) return;
  45. if (callback.length === 0) return;
  46. let newObject = deliveryTask(callback, { args }, 'preRequest');
  47. if (newObject && newObject.args) {
  48. args = newObject.args;
  49. }
  50. apply = originalFetch.apply(this, args);
  51. apply.then((response) => {
  52. let originalGetReader = response.body.getReader;
  53. response.body.getReader = function () {
  54. let originalReader = originalGetReader.apply(this, arguments);
  55. let originalRead = originalReader.read;
  56. originalReader.read = function () {
  57. return originalRead.apply(this, arguments).then(function (result) {
  58. let tempObject = deliveryTask(callback, { result, args }, 'doing');
  59. if (tempObject && tempObject.result) {
  60. result = tempObject.result;
  61. }
  62. return result;
  63. });
  64. };
  65. return originalReader;
  66. };
  67. let text = response.text,
  68. json = response.json;
  69. response.text = () => {
  70. return text.apply(response).then((text) => {
  71. let _object = deliveryTask(callback, { text, args }, 'done');
  72. if (_object && _object.text) {
  73. text = _object.text;
  74. }
  75. return text;
  76. });
  77. };
  78. response.json = () => {
  79. return json.apply(response).then((json) => {
  80. let text = JSON.stringify(json);
  81. let _object = deliveryTask(callback, { text, args }, 'done');
  82. if (_object && _object.text) {
  83. text = _object.text;
  84. return JSON.parse(text);
  85. }
  86. return json;
  87. });
  88. };
  89. });
  90. })();
  91. if (apply == null) {
  92. apply = originalFetch.apply(this, args);
  93. }
  94. return apply;
  95. };
  96. }
  97.  
  98. function hookXhr() {
  99. const XHRProxy = new Proxy(contextWindow.XMLHttpRequest, {
  100. construct(target, args) {
  101. const xhr = new target(...args);
  102. const originalOpen = xhr.open;
  103. const originalSend = xhr.send;
  104. const url = '';
  105. xhr.open = function () {
  106. url = arguments[1];
  107. return originalOpen.apply(xhr, arguments);
  108. };
  109. xhr.send = function () {
  110. let o = function (args) {
  111. return originalSend.apply(xhr, args);
  112. };
  113. let args = arguments;
  114. let U = xhr.responseURL == '' ? url : xhr.responseURL;
  115. if (U.indexOf('http') == -1) {
  116. if (U[0] !== '/') {
  117. let pathname = new URL(location.href).pathname;
  118. U = pathname + U;
  119. }
  120. U = location.origin + U;
  121. }
  122. let pathname = new URL(U).pathname;
  123. let callback = XhrMapList.get(pathname);
  124. if (callback == null) return o(args);
  125. if (callback.length === 0) return o(args);
  126. let newObject = deliveryTask(callback, { args }, 'preRequest');
  127. if (newObject && newObject.args) {
  128. args = newObject.args;
  129. }
  130. const onReadyStateChangeOriginal = xhr.onreadystatechange;
  131. xhr.onreadystatechange = function () {
  132. if (xhr.readyState === 4 && xhr.status === 200) {
  133. let text = xhr.responseText;
  134. let newObject = deliveryTask(callback, { text, args }, 'done');
  135. if (newObject && newObject.text) {
  136. xhr.responseText = newObject.text;
  137. }
  138. }
  139. onReadyStateChangeOriginal && onReadyStateChangeOriginal.apply(xhr, args);
  140. };
  141. return o(args);
  142. };
  143. return xhr;
  144. }
  145. });
  146. globalVariable.set('XMLHttpRequest', contextWindow.XMLHttpRequest);
  147. contextWindow.XMLHttpRequest = XHRProxy;
  148. }
  149.  
  150. (async () => {
  151. hookFetch();
  152. })();
  153. (async () => {
  154. hookXhr();
  155. })();
  156.  
  157. contextWindow['__hookRequest__'] = {
  158. FetchCallback: {
  159. add: (pathname, callback) => {
  160. let list = FetchMapList.get(pathname) || (FetchMapList.set(pathname, []), FetchMapList.get(pathname));
  161. list.push(callback);
  162. let index = list.length;
  163. return index;
  164. },
  165. del: (pathname, index) => {
  166. try {
  167. let list = FetchMapList.get(pathname);
  168. if (list == null) return false;
  169. list.splice(index - 1, 1);
  170. } catch (e) {
  171. new Error(e);
  172. return false;
  173. }
  174. return true;
  175. }
  176. },
  177. XhrCallback: {
  178. add: (pathname, callback) => {
  179. let list = XhrMapList.get(pathname) || (XhrMapList.set(pathname, []), XhrMapList.get(pathname));
  180. list.push(callback);
  181. let index = list.length;
  182. return index;
  183. },
  184. del: (pathname, index) => {
  185. try {
  186. let list = XhrMapList.get(pathname);
  187. if (list == null) return false;
  188. list.splice(index - 1, 1);
  189. } catch (e) {
  190. new Error(e);
  191. return false;
  192. }
  193. return true;
  194. }
  195. },
  196. globalVariable: {
  197. get: (key) => {
  198. return globalVariable.get(key);
  199. },
  200. getAll: () => {
  201. return globalVariable.entries();
  202. },
  203. set: (key, value) => {
  204. globalVariable.set(key, value);
  205. },
  206. getOrDrfault: (key, defaultValue) => {
  207. return globalVariable.get(key) || defaultValue;
  208. }
  209. }
  210. };
  211. })();