import { readFileSync } from "node:fs"; import { pathToFileURL } from "node:url"; export function installBrowserStubs(cookie = "") { const g = globalThis; g.window = g; g.self = g; g.top = g; g.__assetsPath = "./"; Object.defineProperty(g, "navigator", { value: { userAgent: "Mozilla/5.0 (Linux; Android 16; PJZ110 Build/BP2A.250605.015; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/149.0.7827.164 Mobile Safari/537.36 ksNebula/14.5.50.11631", appVersion: "Android 16", language: "zh-CN", }, configurable: true, }); g.screen = { width: 1080, height: 2376, availWidth: 1080, availHeight: 2376 }; g.devicePixelRatio = 3; Object.defineProperty(g, "location", { value: { href: "https://nebula.kuaishou.com/nebula/task/earning?&layoutType=4&source=bottom_guide_first", search: "?layoutType=4&source=bottom_guide_first", origin: "https://nebula.kuaishou.com", pathname: "/nebula/task/earning", hash: "", hostname: "nebula.kuaishou.com", assign(v) { this.href = v; }, replace(v) { this.href = v; }, }, configurable: true, }); g.history = { state: null, length: 1, pushState() {}, replaceState() {}, back() {}, go() {} }; g.Event = class { constructor(type, opts = {}) { this.type = type; this.cancelable = !!opts.cancelable; this.defaultPrevented = false; } }; g.CustomEvent = g.Event; g.HTMLElement = class {}; g.Element = class {}; g.Node = class {}; const elem = (tag = "div") => { const e = { tagName: String(tag).toUpperCase(), nodeType: 1, style: {}, children: [], childNodes: [], parentNode: { removeChild() {} }, setAttribute() {}, getAttribute() { return null; }, appendChild(c) { this.children.push(c); this.childNodes.push(c); return c; }, insertBefore(c) { this.children.push(c); this.childNodes.push(c); return c; }, removeChild() {}, addEventListener() {}, removeEventListener() {}, dispatchEvent() { return true; }, href: "", rel: "", as: "", crossOrigin: "", cloneNode() { return elem(tag); }, getBoundingClientRect() { return { top: 0, left: 0, width: 1, height: 1, right: 1, bottom: 1 }; }, clientWidth: 1080, clientHeight: 2376, }; Object.setPrototypeOf(e, Element.prototype); return e; }; Object.defineProperty(g, "document", { value: { cookie, hidden: false, visibilityState: "visible", nodeType: 9, createElement: elem, createTextNode(text) { return { nodeType: 3, textContent: text, nodeValue: text, childNodes: [], children: [] }; }, createEvent(type) { return { type, initEvent(name, bubbles, cancelable) { this.type = name; this.bubbles = bubbles; this.cancelable = cancelable; }, preventDefault() { this.defaultPrevented = true; }, }; }, getElementsByTagName() { return []; }, querySelector() { return null; }, querySelectorAll() { return []; }, addEventListener() {}, removeEventListener() {}, dispatchEvent() { return true; }, }, configurable: true, }); document.documentElement = elem("html"); document.head = elem("head"); document.body = elem("body"); g.getComputedStyle = () => ({ display: "block", visibility: "visible", opacity: "1", width: "1px", height: "1px", getPropertyValue() { return ""; }, }); g.localStorage = { getItem() { return null; }, setItem() {}, removeItem() {}, clear() {} }; g.sessionStorage = g.localStorage; g.performance = { now: () => Date.now(), mark() {}, measure() {} }; g.requestAnimationFrame = (fn) => setTimeout(fn, 0); g.cancelAnimationFrame = (id) => clearTimeout(id); g.addEventListener = () => {}; g.removeEventListener = () => {}; g.dispatchEvent = () => true; g.MutationObserver = class { constructor() {} observe() {} disconnect() {} takeRecords() { return []; } }; g.XMLHttpRequest = class { open() {} setRequestHeader() {} send() { this.readyState = 4; this.status = 0; this.onreadystatechange && this.onreadystatechange(); } addEventListener() {} }; g.fetch = async () => ({ ok: false, status: 0, json: async () => ({}), text: async () => "" }); g.atob = (s) => Buffer.from(s, "base64").toString("binary"); g.btoa = (s) => Buffer.from(s, "binary").toString("base64"); Object.defineProperty(g, "crypto", { value: { getRandomValues(arr) { for (let i = 0; i < arr.length; i++) arr[i] = Math.floor(Math.random() * 256); return arr; }, }, configurable: true, }); } export async function loadVendor() { let src = readFileSync(new URL("./main-vendor-ox-x1_g5.mjs", import.meta.url), "utf8"); src = src.replace( 'import{_ as __vitePreload}from"./main-CZ3ZSK5w.js";', "const __vitePreload=(base,deps,importerUrl)=>base();", ); return import("data:text/javascript;base64," + Buffer.from(src).toString("base64")); } export function encodeWith(instance, signInput) { return new Promise((resolve, reject) => { instance.call("$encode", [ signInput, { suc(result, cInfo) { resolve({ result, cInfo }); }, err(error) { reject(error); }, }, ]); }); } async function main() { const signInput = process.argv[2] === "-" ? readFileSync(0, "utf8") : process.argv[2] || "sigCatVer=1"; const cookie = process.env.KS_COOKIE || ""; const exportName = process.env.KS_VENDOR_EXPORT || "f"; installBrowserStubs(cookie); const realConsole = { log: console.log, warn: console.warn, error: console.error }; if (!process.env.KS_VENDOR_DEBUG) { console.log = () => {}; console.warn = () => {}; console.error = () => {}; } const vendor = await loadVendor(); console.log = realConsole.log; console.warn = realConsole.warn; console.error = realConsole.error; const instance = vendor[exportName]; if (!instance || typeof instance.call !== "function") { throw new Error(`vendor export ${exportName} has no call()`); } const encoded = await encodeWith(instance, signInput); console.log(JSON.stringify({ exportName, signInput, ...encoded }, null, 2)); } if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { await main(); }