Files
QZMusic_PC/amll-local/packages/lyric/test/eqrc.test.ts
lqtmcstudio 72f4510dc8 fork(fix): Clone AMLL 并修复 BUG
- 将AMLL Clone到本以地进行修复和优化(emm虽然这很不优雅但是暂时无时间做子模块和Fork)
- 修复在当前播放歌词行不可见的视口Seek会出现滚动偏移的问题
2026-06-07 00:02:14 +08:00

57 lines
1.9 KiB
TypeScript

import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
import { decryptQrcHex, encryptQrcHex } from "../src/formats/eqrc";
import { parseQrc } from "../src/formats/qrc";
function decodeXmlEntities(text: string): string {
return text
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&apos;/g, "'")
.replace(/&amp;/g, "&")
.replace(/&#10;/g, "\n")
.replace(/&#13;/g, "\r");
}
function extractQrcPayload(xmlLike: string): string {
const match = xmlLike.match(/<!\[CDATA\[([\s\S]*?)\]\]>/);
if (match?.[1]) return match[1].trim();
const attrMatch = xmlLike.match(/LyricContent="([^"]*)"/);
if (!attrMatch?.[1]) return "";
return decodeXmlEntities(attrMatch[1]).trim();
}
describe("eqrc", () => {
it("decrypts rust sample hex with stable output", () => {
const hexPath = resolve(__dirname, "eqrc.hex");
const hex = readFileSync(hexPath, "utf8").trim();
const decrypted = decryptQrcHex(hex);
const sha256 = createHash("sha256").update(decrypted).digest("hex");
const qrcText = extractQrcPayload(decrypted);
const lines = parseQrc(qrcText);
expect(hex.length).toBe(7136);
expect(decrypted.length).toBe(7188);
expect(sha256).toBe(
"f3bf2f3b5af01e9f21c5fc49e5ed9ab59370faa530f62b60a38df1881ea31f6a",
);
expect(decrypted).toContain("<QrcInfos>");
expect(decrypted).toContain('<LyricInfo LyricCount="1">');
expect(qrcText.length).toBeGreaterThan(0);
expect(lines.length).toBeGreaterThan(0);
});
it("keeps decrypt/encrypt/decrypt text stable for rust sample", () => {
const hexPath = resolve(__dirname, "eqrc.hex");
const hex = readFileSync(hexPath, "utf8").trim();
const decrypted = decryptQrcHex(hex);
const encryptedAgain = encryptQrcHex(decrypted);
const decryptedAgain = decryptQrcHex(encryptedAgain);
expect(decryptedAgain).toBe(decrypted);
});
});