rsshub
Version:
Make RSS Great Again!
57 lines (56 loc) • 1.83 kB
JavaScript
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 };