// 解析 app.asar 找 skills_json 消费逻辑 const fs = require('fs'); const path = require('path'); const asarPath = 'C:/Users/maidou/AppData/Local/Programs/WorkBuddy/resources/app.asar'; const buf = fs.readFileSync(asarPath); // 新版 asar 多重 pickle 头:@0=4, @4=headerSize+4, @8=headerSize, @12=JSON长度, @16=JSON const headerLen = buf.readUInt32LE(12); let pos = 16; const header = JSON.parse(buf.slice(pos, pos + headerLen).toString('utf8')); // 遍历文件树找含 skills_json 的 js 文件(全量,不限目录) const hits = []; function walk(node, prefix) { if (!node.files) return; for (const name of Object.keys(node.files)) { const f = node.files[name]; const full = prefix + '/' + name; if (f.files) { walk(f, full); } else if (/\.(js|cjs|mjs|ts)$/.test(name)) { hits.push({ full, offset: f.offset, size: f.size }); } } } walk(header, ''); // 逐个读取含 skills_json 的文件片段 const TARGET = Buffer.from('skills_json'); const results = []; for (const h of hits) { const start = pos + h.offset; const chunk = buf.slice(start, start + h.size); if (chunk.includes(TARGET)) { // 找出 skills_json 前后各 400 字符上下文 let idx = 0; while ((idx = chunk.indexOf(TARGET, idx)) !== -1) { const from = Math.max(0, idx - 500); const to = Math.min(chunk.length, idx + 700); results.push({ file: h.full, ctx: chunk.slice(from, to).toString('utf8') }); idx += TARGET.length; if (results.length > 40) break; } } if (results.length > 40) break; } console.log('含 skills_json 的文件数:', new Set(results.map(r=>r.file)).size); console.log('片段数:', results.length); // 只输出含读写逻辑的片段(排除 DDL/列定义) const interesting = results.filter(r => /INSERT|SELECT|UPDATE|JSON\.parse|=>|function|await|\.map\(|\.filter\(|include\(|find\(|query|execute/i.test(r.ctx) && !/CREATE TABLE|ALTER TABLE|addSql|statement-breakpoint|"name",\s*$/.test(r.ctx)); console.log('读写逻辑片段数:', interesting.length); interesting.slice(0, 25).forEach((r, i) => { console.log('\n########## ' + r.file + ' [' + i + '] ##########'); console.log(r.ctx.replace(/[ \t]+/g, ' ').slice(0, 1600)); });