CWSS

Complete WebSocket Sniffer

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

  1. // ==UserScript==
  2. // @license MIT
  3. // @name CWSS
  4. // @version 2.7.1
  5. // @description Complete WebSocket Sniffer
  6. // @author 0vC4
  7. // @match http://*/*
  8. // @match https://*/*
  9. // @grant none
  10. // @run-at document-start
  11. // @namespace https://greasyfork.org/users/670183
  12. // ==/UserScript==
  13.  
  14.  
  15.  
  16.  
  17.  
  18. const CWSS = (() => {
  19. const CWSS = window.CWSS || {};
  20. if (CWSS.ws) return CWSS;
  21. const proto = WebSocket.prototype;
  22. const def = Object.defineProperty;
  23. const rebase = (obj, key, list) => def(obj, key, {
  24. configurable: true,
  25. enumerable: true,
  26. set: func => list.push(func)
  27. });
  28. const native = (obj, value) => {
  29. obj.toString = function() {
  30. return Function.toString.call(value, ...arguments);
  31. };
  32. };
  33. const pipe = (type, ...next) => async function() {
  34. for (const hook of CWSS.hooks.sort((a, b) => b.priority - a.priority)) {
  35. if (!hook[type]) continue;
  36. if (!arguments) break;
  37. arguments = await hook[type].call(this, ...arguments);
  38. }
  39. if (!arguments) return;
  40. next.flat().forEach(func => func.call(this, ...arguments));
  41. };
  42. const pipeSync = type => function() {
  43. for (const hook of CWSS.hooks.sort((a, b) => b.priority - a.priority)) {
  44. if (!hook[type]) continue;
  45. if (!arguments) break;
  46. arguments = hook[type].call(this, ...arguments);
  47. }
  48. return arguments;
  49. };
  50. CWSS.ws = window.WebSocket;
  51. CWSS.send = proto.send;
  52. CWSS.addList = proto.addEventListener;
  53. CWSS.sockets = [];
  54. CWSS.hooks = [];
  55. CWSS.setHook = hook => {
  56. CWSS.hooks.push(hook);
  57. return CWSS;
  58. };
  59. CWSS.setHooks = (...hooks) => {
  60. CWSS.hooks.push(...hooks.flat());
  61. return CWSS;
  62. };
  63. proto.send = pipe('send', CWSS.send);
  64. proto.addEventListener = function() {
  65. const type = arguments[0];
  66. const func = arguments[1];
  67. const list = this.listeners[type];
  68. if (list) list.push(func);
  69. else CWSS.addList.call(this, ...arguments);
  70. };
  71. window.WebSocket = function() {
  72. arguments = pipeSync('args').call(this, ...arguments);
  73. const ws = new CWSS.ws(...arguments);
  74. for (const hook of CWSS.hooks.sort((a, b) => b.priority - a.priority))
  75. Object.assign(hook, {
  76. ws,
  77. async sendServer(data) {
  78. CWSS.send.call(ws, data);
  79. },
  80. async sendClient(data) {
  81. ws.listeners.message
  82. .forEach(func =>
  83. func.call(ws, {data})
  84. );
  85. },
  86. });
  87. CWSS.sockets.push(ws);
  88. pipe('init').call(ws);
  89. ws.listeners = {};
  90. for (const key of ['open', 'message', 'close']) {
  91. const list = ws.listeners[key] = [];
  92. CWSS.addList.call(ws, key, pipe(key, list));
  93. rebase(ws, 'on'+key, list);
  94. }
  95. return ws;
  96. };
  97. for (const k in CWSS.ws)
  98. if (k != 'prototype')
  99. window.WebSocket[k] = CWSS.ws[k];
  100. for (const k in proto)
  101. if (k != 'constructor')
  102. try {
  103. window.WebSocket.prototype[k] = proto[k];
  104. } catch (e) {};
  105. native(proto.send, CWSS.send);
  106. native(proto.addEventListener, CWSS.addList);
  107. native(window.WebSocket, CWSS.ws);
  108. window.CWSS = CWSS;
  109. return CWSS;
  110. })();
  111. // 0vC4#7152