- sdk/qs 平台模块(安卓参数指纹匿名搜索)+ sdk/apis/qs 取流: 匿名 30s 试听,登录态走签名 track_v2 + spade key AES-CTR 解密 - /login/qs/qr 抖音扫码登录(授权后 sessionid 解锁完整曲目) - /stream/qs/:id 解密流代理,/url 返回的相对地址按请求 host 补全 - 回归测试覆盖 kw 双通道(VIP 真音频/降级链)与 qs 试听;start.bat 去掉 SOURCE_ENABLED 直启
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import { hash } from "./index.ts";
|
|
import { getArgus } from "./argus.ts";
|
|
import { getLadon } from "./ladon.ts";
|
|
import { defaultUnidbgConfig, type UnidbgConfig } from "./unidbgconfig.ts";
|
|
|
|
export interface UnidbgHeaders extends Record<string, string> {
|
|
"x-argus": string;
|
|
"x-ladon": string;
|
|
"x-khronos": string;
|
|
}
|
|
|
|
export default async function generateHeaders(
|
|
rawQuery: string,
|
|
xssStub = "",
|
|
timestamp: number = Math.floor(Date.now() / 1000),
|
|
config: UnidbgConfig = defaultUnidbgConfig,
|
|
): Promise<UnidbgHeaders> {
|
|
const [argus, ladon] = await Promise.all([
|
|
getArgus(rawQuery, xssStub, timestamp, config),
|
|
getLadon(timestamp, config),
|
|
]);
|
|
|
|
return {
|
|
"x-argus": argus,
|
|
"x-ladon": ladon,
|
|
"x-khronos": String(timestamp),
|
|
};
|
|
}
|
|
|
|
export async function signRequest(
|
|
url: string,
|
|
body?: ArrayBuffer | Uint8Array<ArrayBuffer> | string,
|
|
config: UnidbgConfig = defaultUnidbgConfig,
|
|
): Promise<Record<string, string>> {
|
|
const rawQuery = new URL(url).search.replace(/^\?/, "");
|
|
|
|
const hasBody = typeof body === "string" ? body.length > 0 : (body?.byteLength ?? 0) > 0;
|
|
const xssStub = hasBody ? await hash.md5(body!) : "";
|
|
|
|
const now = Date.now();
|
|
const headers: Record<string, string> = await generateHeaders(
|
|
rawQuery,
|
|
xssStub,
|
|
Math.floor(now / 1000),
|
|
config,
|
|
);
|
|
headers["x-ss-req-ticket"] = String(now);
|
|
if (hasBody) {
|
|
headers["X-SS-STUB"] = xssStub;
|
|
}
|
|
return headers;
|
|
}
|
|
|
|
export { getArgus } from "./argus.ts";
|
|
export { getLadon } from "./ladon.ts";
|
|
export { defaultUnidbgConfig, type UnidbgConfig } from "./unidbgconfig.ts";
|