UNPKG

rsshub

Version:
76 lines (60 loc) 2.03 kB
// Copied from https://github.com/huandu/heybox-url import { createHash } from 'node:crypto'; 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 & 0x80 ? 0xFF & ((v << 1) ^ 0x1B) : 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; export const calculate = (url, timestamp = 0, nonce = '') => { timestamp ||= Math.trunc(Date.now() / 1000); 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 % dict.length; c = Math.trunc(c / dict.length); 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.toString(); };