utils.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*
  2. * @File : utils.js
  3. * @Author : jade
  4. * @Date : 2024/1/25 15:01
  5. * @Email : jadehh@1ive.com
  6. * @Software : Samples
  7. * @Desc :
  8. */
  9. import {Crypto} from "./cat.js";
  10. import {TextDecoder} from "./TextDecoder.js";
  11. import {TextEncoder} from "./TextEncoder.js";
  12. // import {TextDecoder} from "text-decoding";
  13. const deviceBrands = ['Huawei', 'Xiaomi'];
  14. const deviceModels = [
  15. ['MHA-AL00', 'HUAWEI Mate 9', 'MHA-TL00', 'HUAWEI Mate 9', 'LON-AL00', 'HUAWEI Mate 9 Pro', 'ALP-AL00', 'HUAWEI Mate 10', 'ALP-TL00', 'HUAWEI Mate 10', 'BLA-AL00', 'HUAWEI Mate 10 Pro', 'BLA-TL00', 'HUAWEI Mate 10 Pro', 'HMA-AL00', 'HUAWEI Mate 20', 'HMA-TL00', 'HUAWEI Mate 20', 'LYA-AL00', 'HUAWEI Mate 20 Pro', 'LYA-AL10', 'HUAWEI Mate 20 Pro', 'LYA-TL00', 'HUAWEI Mate 20 Pro', 'EVR-AL00', 'HUAWEI Mate 20 X', 'EVR-TL00', 'HUAWEI Mate 20 X', 'EVR-AN00', 'HUAWEI Mate 20 X', 'TAS-AL00', 'HUAWEI Mate 30', 'TAS-TL00', 'HUAWEI Mate 30', 'TAS-AN00', 'HUAWEI Mate 30', 'TAS-TN00', 'HUAWEI Mate 30', 'LIO-AL00', 'HUAWEI Mate 30 Pro', 'LIO-TL00', 'HUAWEI Mate 30 Pro', 'LIO-AN00', 'HUAWEI Mate 30 Pro', 'LIO-TN00', 'HUAWEI Mate 30 Pro', 'LIO-AN00m', 'HUAWEI Mate 30E Pro', 'OCE-AN10', 'HUAWEI Mate 40', 'OCE-AN50', 'HUAWEI Mate 40E', 'OCE-AL50', 'HUAWEI Mate 40E', 'NOH-AN00', 'HUAWEI Mate 40 Pro', 'NOH-AN01', 'HUAWEI Mate 40 Pro', 'NOH-AL00', 'HUAWEI Mate 40 Pro', 'NOH-AL10', 'HUAWEI Mate 40 Pro', 'NOH-AN50', 'HUAWEI Mate 40E Pro', 'NOP-AN00', 'HUAWEI Mate 40 Pro', 'CET-AL00', 'HUAWEI Mate 50', 'CET-AL60', 'HUAWEI Mate 50E', 'DCO-AL00', 'HUAWEI Mate 50 Pro', 'TAH-AN00', 'HUAWEI Mate X', 'TAH-AN00m', 'HUAWEI Mate Xs', 'TET-AN00', 'HUAWEI Mate X2', 'TET-AN10', 'HUAWEI Mate X2', 'TET-AN50', 'HUAWEI Mate X2', 'TET-AL00', 'HUAWEI Mate X2', 'PAL-AL00', 'HUAWEI Mate Xs 2', 'PAL-AL10', 'HUAWEI Mate Xs 2', 'EVA-AL00', 'HUAWEI P9', 'EVA-AL10', 'HUAWEI P9', 'EVA-TL00', 'HUAWEI P9', 'EVA-DL00', 'HUAWEI P9', 'EVA-CL00', 'HUAWEI P9', 'VIE-AL10', 'HUAWEI P9 Plus', 'VTR-AL00', 'HUAWEI P10', 'VTR-TL00', 'HUAWEI P10', 'VKY-AL00', 'HUAWEI P10 Plus', 'VKY-TL00', 'HUAWEI P10 Plus', 'EML-AL00', 'HUAWEI P20', 'EML-TL00', 'HUAWEI P20', 'CLT-AL00', 'HUAWEI P20 Pro', 'CLT-AL01', 'HUAWEI P20 Pro', 'CLT-AL00l', 'HUAWEI P20 Pro', 'CLT-TL00', 'HUAWEI P20 Pro', 'CLT-TL01', 'HUAWEI P20 Pro', 'ELE-AL00', 'HUAWEI P30', 'ELE-TL00', 'HUAWEI P30', 'VOG-AL00', 'HUAWEI P30 Pro', 'VOG-AL10', 'HUAWEI P30 Pro', 'VOG-TL00', 'HUAWEI P30 Pro', 'ANA-AL00', 'HUAWEI P40', 'ANA-AN00', 'HUAWEI P40', 'ANA-TN00', 'HUAWEI P40', 'ELS-AN00', 'HUAWEI P40 Pro', 'ELS-TN00', 'HUAWEI P40 Pro', 'ELS-AN10', 'HUAWEI P40 Pro', 'ELS-TN10', 'HUAWEI P40 Pro', 'ABR-AL00', 'HUAWEI P50', 'ABR-AL80', 'HUAWEI P50', 'ABR-AL60', 'HUAWEI P50E', 'ABR-AL90', 'HUAWEI P50E', 'JAD-AL00', 'HUAWEI P50 Pro', 'JAD-AL80', 'HUAWEI P50 Pro', 'JAD-AL50', 'HUAWEI P50 Pro', 'JAD-AL60', 'HUAWEI P50 Pro', 'BAL-AL00', 'HUAWEI P50 Pocket', 'BAL-AL60', 'HUAWEI Pocket S', 'PIC-AL00', 'HUAWEI nova 2', 'PIC-TL00', 'HUAWEI nova 2', 'BAC-AL00', 'HUAWEI nova 2 Plus', 'BAC-TL00', 'HUAWEI nova 2 Plus', 'HWI-AL00', 'HUAWEI nova 2s', 'HWI-TL00', 'HUAWEI nova 2s', 'ANE-AL00', 'HUAWEI nova 3e', 'ANE-TL00', 'HUAWEI nova 3e', 'PAR-AL00', 'HUAWEI nova 3', 'PAR-TL00', 'HUAWEI nova 3', 'INE-AL00', 'HUAWEI nova 3i', 'INE-TL00', 'HUAWEI nova 3i', 'VCE-AL00', 'HUAWEI nova 4', 'VCE-TL00', 'HUAWEI nova 4', 'MAR-AL00', 'HUAWEI nova 4e', 'MAR-TL00', 'HUAWEI nova 4e', 'SEA-AL00', 'HUAWEI nova 5', 'SEA-TL00', 'HUAWEI nova 5', 'SEA-AL10', 'HUAWEI nova 5 Pro', 'SEA-TL10', 'HUAWEI nova 5 Pro', 'GLK-AL00', 'HUAWEI nova 5i', 'GLK-TL00', 'HUAWEI nova 5i', 'GLK-LX1U', 'HUAWEI nova 5i', 'SPN-TL00', 'HUAWEI nova 5i Pro', 'SPN-AL00', 'HUAWEI nova 5z', 'WLZ-AL10', 'HUAWEI nova 6', 'WLZ-AN00', 'HUAWEI nova 6', 'JNY-AL10', 'HUAWEI nova 6 SE', 'JNY-TL10', 'HUAWEI nova 6 SE', 'JEF-AN00', 'HUAWEI nova 7', 'JEF-AN20', 'HUAWEI nova 7', 'JEF-TN00', 'HUAWEI nova 7', 'JEF-TN20', 'HUAWEI nova 7', 'JER-AN10', 'HUAWEI nova 7 Pro', 'JER-AN20', 'HUAWEI nova 7 Pro', 'JER-TN10', 'HUAWEI nova 7 Pro', 'JER-TN20', 'HUAWEI nova 7 Pro', 'CDY-AN00', 'HUAWEI nova 7 SE', 'CDY-AN20', 'HUAWEI nova 7 SE', 'CDY-TN00', 'HUAWEI nova 7 SE', 'CDY-TN20', 'HUAWEI nova 7 SE', 'ANG-AN00', 'HUAWEI nova 8', 'BRQ-AN00', 'HUAWEI nova 8 Pro', 'BRQ-AL00', 'HUAWEI nova 8 Pro', 'JSC-AN00', 'HUAWEI nova 8 SE', 'JSC-TN00', 'HUAWEI nova 8 SE', 'JSC-AL50', 'HUAWEI nova 8 SE', 'NAM-AL00', 'HUAWEI nova 9', 'RTE-AL00', 'HUAWEI nova 9 Pro', 'JLN-AL00', 'HUAWEI nova 9 SE', 'NCO-AL00', 'HUAWEI nova 10', 'GLA-AL00', 'HUAWEI nova 10 Pro', 'CHA-AL80', 'HUAWEI nova 10z'],
  16. ['M2001J2C', 'Xiaomi 10', 'M2001J2G', 'Xiaomi 10', 'M2001J2I', 'Xiaomi 10', 'M2011K2C', 'Xiaomi 11', 'M2011K2G', 'Xiaomi 11', '2201123C', 'Xiaomi 12', '2201123G', 'Xiaomi 12', '2112123AC', 'Xiaomi 12X', '2112123AG', 'Xiaomi 12X', '2201122C', 'Xiaomi 12 Pro', '2201122G', 'Xiaomi 12 Pro'],
  17. ];
  18. var charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
  19. let CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36";
  20. const MOBILEUA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1';
  21. let RESOURCEURL = "https://gh.con.sh/https://raw.githubusercontent.com/jadehh/TV/js"
  22. function isSub(ext) {
  23. return ext === "srt" || ext === "ass" || ext === "ssa";
  24. }
  25. function isNumeric(str) {
  26. return !isNaN(parseInt(str));
  27. }
  28. function getSize(size) {
  29. if (size <= 0) return "";
  30. if (size > 1024 * 1024 * 1024 * 1024.0) {
  31. size /= (1024 * 1024 * 1024 * 1024.0);
  32. return size.toFixed(2) + "TB";
  33. } else if (size > 1024 * 1024 * 1024.0) {
  34. size /= (1024 * 1024 * 1024.0);
  35. return size.toFixed(2) + "GB";
  36. } else if (size > 1024 * 1024.0) {
  37. size /= (1024 * 1024.0);
  38. return size.toFixed(2) + "MB";
  39. } else {
  40. size /= 1024.0;
  41. return size.toFixed(2) + "KB";
  42. }
  43. }
  44. function removeExt(text) {
  45. return text.indexOf('.') > -1 ? text.substring(0, text.lastIndexOf(".")) : text;
  46. }
  47. async function log(str) {
  48. console.debug(str);
  49. }
  50. function isVideoFormat(url) {
  51. var RULE = /http((?!http).){12,}?\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)\?.*|http((?!http).){12,}\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)|http((?!http).)*?video\/tos*/;
  52. if (url.indexOf("url=http") > -1 || url.indexOf(".js") > -1 || url.indexOf(".css") > -1 || url.indexOf(".html") > -1) {
  53. return false;
  54. }
  55. return RULE.test(url);
  56. }
  57. function jsonParse(input, json) {
  58. var jsonPlayData = JSON.parse(json);
  59. var url = jsonPlayData.url;
  60. if (url.startsWith("//")) {
  61. url = "https:" + url;
  62. }
  63. if (!url.startsWith("http")) {
  64. return null;
  65. }
  66. if (url === input) {
  67. if (!isVideoFormat(url)) {
  68. return null;
  69. }
  70. }
  71. var headers = {};
  72. var ua = jsonPlayData["user-agent"] || "";
  73. if (ua.trim().length > 0) {
  74. headers["User-Agent"] = " " + ua;
  75. }
  76. var referer = jsonPlayData.referer || "";
  77. if (referer.trim().length > 0) {
  78. headers["Referer"] = " " + referer;
  79. }
  80. var taskResult = {
  81. header: headers, url: url
  82. };
  83. return taskResult;
  84. }
  85. function debug(obj) {
  86. for (var a in obj) {
  87. if (typeof (obj[a]) == "object") {
  88. debug(obj[a]); //递归遍历
  89. } else {
  90. console.debug(a + "=" + obj[a]);
  91. }
  92. }
  93. }
  94. function objectToStr(params = null, isBase64Encode = false) {
  95. let params_str_list = []
  96. if (params !== null) {
  97. for (const key of Object.keys(params)) {
  98. if (isBase64Encode) {
  99. params_str_list.push(`${key}=${encodeURIComponent(params[key])}`)
  100. } else {
  101. params_str_list.push(`${key}=${params[key]}`)
  102. }
  103. }
  104. }
  105. return params_str_list.join("&")
  106. }
  107. function sleep(delay) {
  108. const start = (new Date()).getTime();
  109. while ((new Date()).getTime() - start < delay * 1000) {
  110. continue;
  111. }
  112. }
  113. function getStrByRegex(pattern, str) {
  114. let matcher = pattern.exec(str);
  115. if (matcher !== null) {
  116. if (matcher.length >= 1) {
  117. if (matcher.length >= 1) return matcher[1]
  118. }
  119. }
  120. return "";
  121. }
  122. function getStrByRegexDefault(pattern, str) {
  123. let matcher = pattern.exec(str);
  124. if (matcher !== null) {
  125. if (matcher.length >= 1) {
  126. if (matcher.length >= 1) return matcher[1]
  127. }
  128. }
  129. return str;
  130. }
  131. function base64Encode(text) {
  132. return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text));
  133. }
  134. function base64Decode(text) {
  135. return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
  136. }
  137. function unescape(code) {
  138. return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " ");
  139. }
  140. function decode(buffer, encode_type) {
  141. let decoder = new TextDecoder(encode_type)
  142. return decoder.decode(buffer)
  143. }
  144. function encode(buffer, encode_type) {
  145. let encoder = new TextEncoder(encode_type)
  146. return encoder.encode(buffer)
  147. }
  148. function getHost(url) {
  149. let url_list = url.split("/")
  150. return url_list[0] + "//" + url_list[2]
  151. }
  152. function unquote(str) {
  153. return str.replace(/^"(.*)"$/, '$1');
  154. }
  155. function md5Encode(text) {
  156. return Crypto.MD5(Crypto.enc.Utf8.parse(text)).toString();
  157. }
  158. function getUUID() {
  159. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
  160. let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
  161. return v.toString(16);
  162. }) + "-" + new Date().getTime().toString(16)
  163. }
  164. function objToList(list, key, split_value = "*") {
  165. let value_list = []
  166. for (const dic of list) {
  167. value_list.push(dic[key])
  168. }
  169. return value_list.join(split_value)
  170. }
  171. function getPropertiesAndMethods(obj) {
  172. let str = ""
  173. for (let key in obj) {
  174. if (typeof obj[key] === 'function') {
  175. str = str + "方法名:" + key + '()' + "\n";
  176. } else {
  177. str = str + "属性名:" + (key + ': ' + obj[key]) + "\n";
  178. }
  179. }
  180. return str
  181. }
  182. function formatPlayUrl(src, name) {
  183. return name
  184. .trim()
  185. .replaceAll(src, '')
  186. .replace(/<|>|《|》/g, '')
  187. .replace(/\$|#/g, ' ')
  188. .trim();
  189. }
  190. function rand(min, max) {
  191. return Math.floor(Math.random() * (max - min + 1)) + min;
  192. }
  193. function randDevice() {
  194. let brandIdx = rand(0, deviceBrands.length - 1);
  195. let brand = deviceBrands[brandIdx];
  196. let modelIdx = rand(0, deviceModels[brandIdx].length / 2 - 1);
  197. let model = deviceModels[brandIdx][modelIdx * 2 + 1];
  198. let release = rand(8, 13);
  199. let buildId = randStr(3, false).toUpperCase() + rand(11, 99) + randStr(1, false).toUpperCase();
  200. return {
  201. brand: brand,
  202. model: model,
  203. release: release,
  204. buildId: buildId,
  205. };
  206. }
  207. function randStr(len, withNum, onlyNum) {
  208. let _str = '';
  209. let containsNum = withNum === undefined ? true : withNum;
  210. for (let i = 0; i < len; i++) {
  211. let idx = onlyNum ? rand(charStr.length - 10, charStr.length - 1) : rand(0, containsNum ? charStr.length - 1 : charStr.length - 11);
  212. _str += charStr[idx];
  213. }
  214. return _str;
  215. }
  216. function randDeviceWithId(len) {
  217. let device = randDevice();
  218. device['id'] = randStr(len);
  219. return device;
  220. }
  221. function randUUID() {
  222. return randStr(8).toLowerCase() + '-' + randStr(4).toLowerCase() + '-' + randStr(4).toLowerCase() + '-' + randStr(4).toLowerCase() + '-' + randStr(12).toLowerCase();
  223. }
  224. function formatUrl(url) {
  225. if (url.indexOf("https:////") > -1) {
  226. url = "https://" + url.replaceAll("https:////", "")
  227. }
  228. if (url.indexOf("http:////") > -1) {
  229. url = "http://" + url.replaceAll("http:////", "")
  230. }
  231. return url
  232. }
  233. function formatContent(content) {
  234. return content.replaceAll('&amp;', '&')
  235. .replaceAll('&lt;', '<')
  236. .replaceAll('&gt;', '>')
  237. .replaceAll('&quot;', '\"')
  238. .replaceAll(/<\/?[^>]+>/g, '');
  239. }
  240. /**
  241. * 字符串相似度匹配
  242. * @returns
  243. */
  244. function lcs(str1, str2) {
  245. if (!str1 || !str2) {
  246. return {
  247. length: 0,
  248. sequence: '',
  249. offset: 0,
  250. };
  251. }
  252. var sequence = '';
  253. var str1Length = str1.length;
  254. var str2Length = str2.length;
  255. var num = new Array(str1Length);
  256. var maxlen = 0;
  257. var lastSubsBegin = 0;
  258. for (var i = 0; i < str1Length; i++) {
  259. var subArray = new Array(str2Length);
  260. for (var j = 0; j < str2Length; j++) {
  261. subArray[j] = 0;
  262. }
  263. num[i] = subArray;
  264. }
  265. var thisSubsBegin = null;
  266. for (i = 0; i < str1Length; i++) {
  267. for (j = 0; j < str2Length; j++) {
  268. if (str1[i] !== str2[j]) {
  269. num[i][j] = 0;
  270. } else {
  271. if (i === 0 || j === 0) {
  272. num[i][j] = 1;
  273. } else {
  274. num[i][j] = 1 + num[i - 1][j - 1];
  275. }
  276. if (num[i][j] > maxlen) {
  277. maxlen = num[i][j];
  278. thisSubsBegin = i - num[i][j] + 1;
  279. if (lastSubsBegin === thisSubsBegin) {
  280. // if the current LCS is the same as the last time this block ran
  281. sequence += str1[i];
  282. } else {
  283. // this block resets the string builder if a different LCS is found
  284. lastSubsBegin = thisSubsBegin;
  285. sequence = ''; // clear it
  286. sequence += str1.substr(lastSubsBegin, i + 1 - lastSubsBegin);
  287. }
  288. }
  289. }
  290. }
  291. }
  292. return {
  293. length: maxlen,
  294. sequence: sequence,
  295. offset: thisSubsBegin,
  296. };
  297. }
  298. let patternAli = /(https:\/\/www\.aliyundrive\.com\/s\/[^"]+|https:\/\/www\.alipan\.com\/s\/[^"]+)/
  299. let patternQuark = /(https:\/\/pan\.quark\.cn\/s\/[^"]+)/
  300. export {
  301. isSub,
  302. getSize,
  303. removeExt,
  304. log,
  305. isVideoFormat,
  306. jsonParse,
  307. debug,
  308. CHROME,
  309. objectToStr,
  310. sleep,
  311. getStrByRegex,
  312. RESOURCEURL,
  313. base64Encode,
  314. base64Decode,
  315. patternAli,
  316. patternQuark,
  317. unescape,
  318. decode,
  319. MOBILEUA,
  320. isNumeric,
  321. getHost,
  322. unquote,
  323. md5Encode,
  324. getStrByRegexDefault,
  325. getUUID,
  326. objToList,
  327. getPropertiesAndMethods,
  328. formatPlayUrl,
  329. randDeviceWithId,
  330. randStr,
  331. randUUID,
  332. formatContent,
  333. formatUrl,
  334. encode,
  335. lcs
  336. };