小鹅通 通用m3u8获取

获取某鹅通m3u8内容 重新拼装真实ts地址和解密真实密钥 发送给扩展

目前为 2023-04-02 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 小鹅通 通用m3u8获取
  3. // @namespace https://94cat.com/
  4. // @version 0.1
  5. // @description 获取某鹅通m3u8内容 重新拼装真实ts地址和解密真实密钥 发送给扩展
  6. // @author mz
  7. // @match https://*/*
  8. // @match http://*/*
  9. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  10. // @grant none
  11. // @run-at document-start
  12. // @license GPL v3
  13. // ==/UserScript==
  14. (function () {
  15. 'use strict';
  16.  
  17. const _JSONparse = JSON.parse;
  18. JSON.parse = function () {
  19. let data = _JSONparse.apply(this, arguments);
  20. findMedia(data);
  21. return data;
  22. }
  23. JSON.parse.toString = function () {
  24. return _JSONparse.toString();
  25. }
  26. async function findMedia(data, raw = undefined, depth = 0) {
  27. for (let key in data) {
  28. if (typeof data[key] == "object") {
  29. if (depth > 25) { continue; }
  30. if (!raw) { raw = data; }
  31. findMedia(data[key], raw, ++depth);
  32. continue;
  33. }
  34. if (typeof data[key] == "string" && key == "video_urls" && data[key].slice(-4) == "__ba") {
  35. let base64 = data[key].replace("__ba", "");
  36. base64 = base64.replaceAll("@", "1").replaceAll("#", "2").replaceAll("$", "3").replaceAll("%", "4");
  37. let json = _JSONparse(atob(base64));
  38. if (!json) { return }
  39. for (let obj of json) {
  40. fetch(obj.url).then(response => response.text())
  41. .then(m3u8 => {
  42. const lines = m3u8.split('\n');
  43. let keyFlag = false;
  44. for (let i = 0; i < lines.length; i++) {
  45. if (!keyFlag && lines[i].includes("#EXT-X-KEY:METHOD=AES-128,URI=")) {
  46. const match = lines[i].match(/URI="([^"]*)"/);
  47. if (match && match[1]) {
  48. keyFlag = true;
  49. getKey(match[1] + "&uid=" + window.__user_id);
  50. }
  51. continue;
  52. }
  53. if (lines[i][0] != "#") {
  54. lines[i] = `${obj.ext.host}/${obj.ext.path}/${lines[i]}&${obj.ext.param}`;
  55. }
  56. }
  57. m3u8 = lines.join('\n');
  58. let url = URL.createObjectURL(new Blob([new TextEncoder("utf-8").encode(m3u8)]));
  59. window.postMessage({ action: "catCatchAddMedia", url: url, href: location.href, ext: "m3u8" });
  60. });
  61. }
  62. }
  63. }
  64. }
  65. function uid2byte(uid) {
  66. const byteArray = new Array;
  67. for (let i = 0; i < uid.length; i++) {
  68. let temp = uid.charCodeAt(i);
  69. if (temp >= 65536 && temp <= 1114111) {
  70. byteArray.push(temp >> 18 & 7 | 240);
  71. byteArray.push(temp >> 12 & 63 | 128);
  72. byteArray.push(temp >> 6 & 63 | 128);
  73. byteArray.push(63 & temp | 128);
  74. } else if (temp >= 2048 && temp <= 65535) {
  75. byteArray.push(temp >> 12 & 15 | 224);
  76. byteArray.push(temp >> 6 & 63 | 128);
  77. byteArray.push(63 & temp | 128);
  78. } else if (temp >= 128 && temp <= 2047) {
  79. byteArray.push(temp >> 6 & 31 | 192);
  80. byteArray.push(63 & temp | 128);
  81. } else {
  82. byteArray.push(255 & temp);
  83. }
  84. }
  85. return byteArray;
  86. }
  87. function getKey(url) {
  88. fetch(url).then(response => response.arrayBuffer())
  89. .then(buffer => {
  90. let newKey = [];
  91. buffer = new Uint8Array(buffer);
  92. const uidByte = uid2byte(window.__user_id);
  93. for (let i in buffer) {
  94. newKey.push(buffer[i] ^ uidByte[i]);
  95. }
  96. window.postMessage({ action: "catCatchAddKey", key: newKey, href: location.href });
  97. });
  98. }
  99. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址