UNPKG

rsshub

Version:
57 lines (56 loc) 1.83 kB
import { createHash } from "node:crypto"; //#region lib/routes/xiaoheihe/util.ts const dict = "JKMNPQRTX1234OABCDFG56789H"; const md5 = (str) => { const h = createHash("md5"); h.update(str); return h.digest(); }; function c0(v) { return c1(v) ^ c2(v) ^ c3(v); } function c1(v) { return c2(c3(convertByte(v))); } function c2(v) { return c3(convertByte(v)); } function c3(v) { return convertByte(v) ^ v; } function convertByte(v) { return v & 128 ? 255 & (v << 1 ^ 27) : v << 1; } /** * Calculate checksum for a 4-byte data. * @param {number[]} data * @returns {number} */ const checksum = (data) => [ c0(data[0]) ^ c1(data[1]) ^ c2(data[2]) ^ c3(data[3]), c3(data[0]) ^ c0(data[1]) ^ c1(data[2]) ^ c2(data[3]), c2(data[0]) ^ c3(data[1]) ^ c0(data[2]) ^ c1(data[3]), c1(data[0]) ^ c2(data[1]) ^ c3(data[2]) ^ c0(data[3]) ].reduce((prev, value) => prev + value) % 100; const calculate = (url, timestamp = 0, nonce = "") => { timestamp ||= Math.trunc(Date.now() / 1e3); nonce ||= md5(Math.random().toString()).toString("hex").toUpperCase(); const { pathname } = new URL(url); const ts = timestamp + 1; const u = "/" + pathname.split("/").filter(Boolean).join("/") + "/"; let key = ""; const nonceHash = md5((nonce + dict).replaceAll(/\D/g, "")).toString("hex").toLowerCase(); const rnd = md5(ts + u + nonceHash).toString("hex").replaceAll(/\D/g, "").slice(0, 9).padEnd(9, "0"); for (let c = +rnd, i = 0; i < 5; i++) { const u = c % 26; c = Math.trunc(c / 26); key += dict[u]; } const suffix = checksum([...key].slice(-4).map((c) => c.codePointAt(0))).toString().padStart(2, "0"); const query = `hkey=${key}${suffix}&_time=${timestamp}&nonce=${nonce}`; const urlObj = new URL(url); urlObj.search += urlObj.search ? "&" + query : query; return urlObj.href; }; //#endregion export { calculate as t };