fix(huya): 一号一设备补完 — hydevice 设备参数跟随账号画像 + 画像一致性字段下沉
用户实弹测试暴露两个缺口:
1. Hebe/GUID32 全空: 登录路径走 get_profile, 未经过 account_env 补字段
→ _enrich_profile 下沉到 get_profile (幂等, 存量账号自动补齐)
2. sdid 前缀跨账号同源 (0UnHUgv0_qmfD4KAKlwzh...): env.js 是静态设备仿真
(写死 M2102J2SC), 状态目录隔离只改了'存储', 没改'采集输入'
→ env.js makeEnv(overrides) 支持按画像覆盖 UA/屏幕/机型/Android版本;
runner 接收 device.json; get_huya_sdid(device_hint=画像);
下次登录每账号 hydevice 采集输入=各自绑定机型 → sdid 彻底分家
This commit is contained in:
@@ -1,17 +1,29 @@
|
||||
// Android WebView (M2102J2SC, 小米, Android 11) 环境仿真
|
||||
function makeEnv() {
|
||||
// Android WebView 环境仿真 (默认 M2102J2SC; 可传设备覆盖参数实现一号一设备)
|
||||
// overrides = {model, androidVer, vendor, appVer, screenWidth, screenHeight}
|
||||
function makeEnv(overrides) {
|
||||
const ov = overrides || {};
|
||||
const MODEL = ov.model || 'M2102J2SC';
|
||||
const ANDROID_VER = ov.androidVer || '11';
|
||||
const VENDOR = ov.vendor || 'xiaomi';
|
||||
const APP_VER = ov.appVer || '13.4.22';
|
||||
const UA = ov.userAgent || ('Mozilla/5.0 (Linux; Android ' + ANDROID_VER + '; ' + MODEL +
|
||||
' Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 ' +
|
||||
'Chrome/149.0.7827.159 Mobile Safari/537.36 huya adr/' + APP_VER + '/' + VENDOR + '/30');
|
||||
// 视口按物理分辨率/3 仿真 (393x851 ≈ 1080x2120 / 2.75)
|
||||
const VW = ov.screenWidth ? Math.round(ov.screenWidth / 2.75) : 393;
|
||||
const VH = ov.screenHeight ? Math.round(ov.screenHeight / 2.75) : 851;
|
||||
const W = globalThis;
|
||||
W.screen = {width:393, height:851, availWidth:393, availHeight:851,
|
||||
W.screen = {width:VW, height:VH, availWidth:VW, availHeight:VH,
|
||||
colorDepth:24, pixelDepth:24, availLeft:0, availTop:0, orientation:{type:'portrait-primary', angle:0}};
|
||||
W.devicePixelRatio = 2.75;
|
||||
W.innerWidth = 393; W.innerHeight = 737; W.outerWidth = 393; W.outerHeight = 851;
|
||||
W.innerWidth = VW; W.innerHeight = Math.max(VH - 114, 500); W.outerWidth = VW; W.outerHeight = VH;
|
||||
W.location = {href:'https://aq.huya.com/p/safe_auth/pt_auth.html', protocol:'https:', host:'aq.huya.com',
|
||||
hostname:'aq.huya.com', port:'', pathname:'/p/safe_auth/pt_auth.html', search:'', hash:'',
|
||||
origin:'https://aq.huya.com', toString(){return this.href}};
|
||||
W.history = {length:2, state:null, pushState(){}, replaceState(){}, back(){}, go(){}};
|
||||
const navProps = {
|
||||
userAgent:'Mozilla/5.0 (Linux; Android 11; M2102J2SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/149.0.7827.159 Mobile Safari/537.36 huya adr/13.4.22/xiaomi/30',
|
||||
appName:'Netscape', appVersion:'5.0 (Linux; Android 11; M2102J2SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/149.0.7827.159 Mobile Safari/537.36',
|
||||
userAgent: UA,
|
||||
appName:'Netscape', appVersion: UA.replace(/^Mozilla\//, ''),
|
||||
platform:'Linux armv8l', language:'zh-CN', languages:['zh-CN','zh','en'],
|
||||
cookieEnabled:true, doNotTrack:null, maxTouchPoints:5, hardwareConcurrency:8,
|
||||
deviceMemory:8, vendor:'Google Inc.', productSub:'20030107', webdriver:false,
|
||||
@@ -19,7 +31,7 @@ function makeEnv() {
|
||||
getBattery(){return Promise.resolve({charging:true, level:0.9})},
|
||||
userAgentData: {brands:[{brand:'Chromium',version:'149'},{brand:'Google Chrome',version:'149'},{brand:'Not?A_Brand',version:'24'}],
|
||||
mobile:true, platform:'Android',
|
||||
getHighEntropyValues(){return Promise.resolve({architecture:'arm', bitness:'64', model:'M2102J2SC', platformVersion:'11.0.0', uaFullVersion:'149.0.7827.159'})}},
|
||||
getHighEntropyValues(){return Promise.resolve({architecture:'arm', bitness:'64', model:MODEL, platformVersion:ANDROID_VER+'.0.0', uaFullVersion:'149.0.7827.159'})}},
|
||||
connection: {effectiveType:'4g', downlink:10, rtt:50, saveData:false},
|
||||
plugins: {length:0, item(){return null}, namedItem(){return null}},
|
||||
mimeTypes: {length:0},
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// hydevice 指纹运行器: 仿真 Android WebView 环境 -> 真实请求 df/token + df/collect -> 输出 sdid
|
||||
// argv: [stateDir, deviceJson] — deviceJson 为账号画像派生的设备覆盖参数 (一号一设备)
|
||||
process.on('uncaughtException', e => { console.error('[uncaught]', String(e && e.message).slice(0, 120)); });
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
|
||||
globalThis.window = globalThis;
|
||||
require(path.join(__dirname, 'env.js')).makeEnv();
|
||||
let _deviceOverrides = null;
|
||||
try { _deviceOverrides = JSON.parse(fs.readFileSync(process.argv[3] || '', 'utf8')); } catch (e) {}
|
||||
require(path.join(__dirname, 'env.js')).makeEnv(_deviceOverrides);
|
||||
|
||||
// ---- localStorage 持久化(设备稳定性) ----
|
||||
const stateDir = process.argv[2] || '.';
|
||||
|
||||
Reference in New Issue
Block a user