chore: initial commit - maqt-desktop v0.2
- Phase 1-5: UI framework, auth, weapon schemes, color filters, system optimization - Industrial/tech design style with Chinese localization - Points to gch3n.online/delta backend API - Hardware monitor, filter editor, and all module pages
This commit is contained in:
128
scripts/scrape_schemes.js
Normal file
128
scripts/scrape_schemes.js
Normal file
@@ -0,0 +1,128 @@
|
||||
// 改枪方案数据采集器
|
||||
// 在 Windows 上运行: node scrape_schemes.js
|
||||
// 原理: 加载原版 app 的解密模块来解密方案数据
|
||||
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// ========== 配置 ==========
|
||||
const API_BASE = 'maqt.top';
|
||||
const TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NDc5MTcsInVzZXJuYW1lIjoic2l4dGVlbnRoIiwidG9rZW5WZXJzaW9uIjozLCJpYXQiOjE3NzgyMTI0MDUsImV4cCI6MjA5Mzc4ODQwNX0.B_J0CDtaiiF2jJ592yKtD4RtQDIR3cDF_EYgn2UM2ko';
|
||||
const CATEGORIES = ['AR','SMG','SR','LMG','SG','Pistol','Launcher'];
|
||||
const OUR_API = 'http://100.105.17.52:3001'; // 导入到自建后端
|
||||
|
||||
// ========== 尝试多种 AES 密钥 ==========
|
||||
const KEYS_TO_TRY = [
|
||||
Buffer.from('maqt-encryption-key-32bytes!', 'utf-8'), // 28 bytes
|
||||
Buffer.from('maqt-encryption-key-32bytes!!', 'utf-8'), // 29 bytes
|
||||
Buffer.from('0123456789abcdef0123456789abcdef', 'utf-8'), // 32 bytes (HEX)
|
||||
Buffer.from('maqt-encryption-key-32byte!', 'utf-8'), // 27 bytes
|
||||
];
|
||||
|
||||
function aesDecrypt(ivHex, dataHex, key) {
|
||||
try {
|
||||
// Pad key to 32 bytes with zeros if needed
|
||||
const keyBuf = key.length === 32 ? key : Buffer.concat([key, Buffer.alloc(32 - key.length)]);
|
||||
const iv = Buffer.from(ivHex, 'hex');
|
||||
const encrypted = Buffer.from(dataHex, 'hex');
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', keyBuf, iv);
|
||||
let d = decipher.update(encrypted, undefined, 'utf-8');
|
||||
d += decipher.final('utf-8');
|
||||
return JSON.parse(d);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function fetch(url, postData) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const opts = {
|
||||
hostname: API_BASE, path: url,
|
||||
method: postData ? 'POST' : 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${TOKEN}`,
|
||||
'User-Agent': 'MaQiangTang/7.0.4',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
};
|
||||
if (postData) { opts.headers['Content-Type'] = 'application/json'; }
|
||||
const req = https.request(opts, res => {
|
||||
let d = '';
|
||||
res.on('data', c => d += c);
|
||||
res.on('end', () => {
|
||||
try { resolve(JSON.parse(d)); }
|
||||
catch { resolve({ error: 'parse', raw: d.slice(0,100) }); }
|
||||
});
|
||||
});
|
||||
req.on('error', reject);
|
||||
if (postData) req.write(JSON.stringify(postData));
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
function tryDecrypt(encrypted) {
|
||||
if (!encrypted.encrypted) return encrypted;
|
||||
for (const key of KEYS_TO_TRY) {
|
||||
const result = aesDecrypt(encrypted.iv, encrypted.data, key);
|
||||
if (result) {
|
||||
console.log(` ✅ 解密成功! 密钥: ${key.toString('utf-8')}`);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('=== 码枪堂方案数据采集器 ===\n');
|
||||
|
||||
// 1. 测试解密
|
||||
console.log('--- 获取测试数据 ---');
|
||||
const testData = await fetch('/api/schemes?sort=hot&page=1&limit=2&weaponCategory=AR');
|
||||
|
||||
if (testData.encrypted) {
|
||||
console.log(` 加密数据: iv=${testData.iv} data_len=${testData.data.length}`);
|
||||
const decrypted = tryDecrypt(testData);
|
||||
if (!decrypted) {
|
||||
console.log(' ❌ 所有密钥都不匹配');
|
||||
console.log(' 请从 deobfuscated main.js 中找到正确的密钥');
|
||||
console.log(' 或在原始应用中运行:');
|
||||
console.log(' require("crypto").createDecipheriv("aes-256-cbc", <key>, <iv>)');
|
||||
return;
|
||||
}
|
||||
fs.writeFileSync('decrypted_schemes.json', JSON.stringify(decrypted, null, 2));
|
||||
console.log(' 已保存到 decrypted_schemes.json');
|
||||
} else {
|
||||
console.log(' 明文响应:', JSON.stringify(testData).slice(0, 500));
|
||||
}
|
||||
|
||||
// 2. 如果解密成功,采集所有分类
|
||||
if (fs.existsSync('decrypted_schemes.json')) {
|
||||
console.log('\n--- 全量采集 ---');
|
||||
const allSchemes = [];
|
||||
|
||||
for (const cat of CATEGORIES) {
|
||||
console.log(`\n分类: ${cat}`);
|
||||
for (let page = 1; page <= 5; page++) {
|
||||
const data = await fetch(`/api/schemes?sort=hot&page=${page}&limit=12&weaponCategory=${encodeURIComponent(cat)}`);
|
||||
if (data.encrypted) {
|
||||
const decrypted = tryDecrypt(data);
|
||||
if (decrypted && Array.isArray(decrypted)) {
|
||||
allSchemes.push(...decrypted);
|
||||
console.log(` 第${page}页: ${decrypted.length} 条`);
|
||||
if (decrypted.length < 12) break;
|
||||
} else break;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n共采集 ${allSchemes.length} 条方案`);
|
||||
fs.writeFileSync('all_schemes.json', JSON.stringify(allSchemes, null, 2));
|
||||
}
|
||||
|
||||
console.log('\n完成');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user