This commit is contained in:
bietiaop 2024-08-16 12:00:25 +08:00
parent 4a54442fae
commit 14f24bbd4d
4 changed files with 150 additions and 27 deletions

86
apps/user.js Normal file
View file

@ -0,0 +1,86 @@
import { ZZZPlugin } from '../lib/plugin.js';
import render from '../lib/render.js';
import { rulePrefix } from '../lib/common.js';
import { getPanelList, refreshPanel, getPanel } from '../lib/avatar.js';
import settings from '../lib/settings.js';
import _ from 'lodash';
export class Panel extends ZZZPlugin {
constructor() {
super({
name: '[ZZZ-Plugin]User',
dsc: 'zzzuser',
event: 'message',
priority: _.get(settings.getConfig('priority'), 'user', 70),
rule: [
{
reg: `${rulePrefix}绑定设备$`,
fnc: 'bindDevice',
},
],
});
}
async bindDevice() {
const uid = await this.getUID();
if (!uid) {
this.reply('未绑定UID');
}
this.setContext('toBindDevice');
await this.reply(
`为UID ${uid}绑定设备,请发送设备信息,或者发送“取消”取消绑定`,
false,
{ at: true, recallMsg: 100 }
);
}
async toBindDevice() {
const uid = await this.getUID();
if (!uid) {
this.reply('未绑定UID');
this.finish('toBindDevice');
return false;
}
const msg = this.e.msg.trim();
if (!msg) {
this.reply('请发送设备信息', false, { at: true, recallMsg: 100 });
return false;
}
if (msg.includes('取消')) {
await this.reply('已取消', false, { at: true, recallMsg: 100 });
this.finish('toBindDevice');
return false;
}
try {
const info = JSON.parse(msg);
if (!info) {
this.reply('设备信息格式错误', false, { at: true, recallMsg: 100 });
return false;
}
if (
!'deviceName' in info ||
!'deviceBoard' in info ||
!'deviceModel' in info ||
!'oaid' in info ||
!'deviceFingerprint' in info ||
!'deviceProduct' in info
) {
this.reply('设备信息格式错误', false, { at: true, recallMsg: 100 });
return false;
}
await redis.del(`ZZZ:DEVICE_FP:${uid}:FP`);
await redis.set(`ZZZ:DEVICE_FP:${uid}:BIND`, JSON.stringify(info));
const { deviceFp } = await this.getAPI();
if (!deviceFp) {
await this.reply('绑定设备失败');
return false;
}
logger.debug(`[UID:${uid}]绑定设备成功deviceFp:${deviceFp}`);
await this.reply('绑定设备成功', false, { at: true, recallMsg: 100 });
} catch (error) {
this.reply('设备信息格式错误', false, { at: true, recallMsg: 100 });
return false;
} finally {
this.finish('toBindDevice');
return false;
}
}
}

View file

@ -110,6 +110,16 @@ export default class MysZZZApi extends MysApi {
if (this._device) {
headers['x-rpc-device_id'] = this._device;
}
if (data?.deviceInfo && data?.modelName) {
const deviceBrand = data.deviceInfo?.split('/')[0];
try {
headers['x-rpc-device_name'] = `${deviceBrand} ${data.modelName}`;
headers['x-rpc-device_model'] = data.modelName;
headers['x-rpc-csm_source'] = 'myself';
} catch (error) {
logger.error(`[ZZZ]设备信息解析失败:${error.message}`);
}
}
// 写入DS
switch (dsSalt) {
case 'web': {
@ -136,7 +146,6 @@ export default class MysZZZApi extends MysApi {
body = JSON.stringify(body);
}
}
logger.debug(`[mysapi]请求url${url}`);
// 返回请求参数
return { url, headers, body };
}
@ -237,20 +246,16 @@ export default class MysZZZApi extends MysApi {
break;
case 10102:
if (res.message === 'Data is not public for the user') {
this.e.reply(
`\nUID:${this.uid},米游社数据未公开`, false, { at: this.userId }
);
this.e.reply(`\nUID:${this.uid},米游社数据未公开`, false, {
at: this.userId,
});
} else {
this.e.reply(
`UID:${this.uid},请先去米游社绑定角色`
);
this.e.reply(`UID:${this.uid},请先去米游社绑定角色`);
}
break;
case 10041:
case 5003:
this.e.reply(
`UID:${this.uid},米游社账号异常,暂时无法查询`
);
this.e.reply(`UID:${this.uid},米游社账号异常,暂时无法查询`);
break;
case 10035:
case 1034: {
@ -274,20 +279,14 @@ export default class MysZZZApi extends MysApi {
logger.mark(
`[米游社zzz查询失败][UID:${this.uid}][qq:${this.userId}] 遇到验证码`
);
this.e.reply(
'米游社zzz查询遇到验证码请稍后再试'
);
this.e.reply('米游社zzz查询遇到验证码请稍后再试');
}
break;
}
default:
if (/(登录|login)/i.test(res.message)) {
logger.mark(
`[ck失效][UID:${this.uid}]`
);
this.e.reply(
`UID:${this.uid}米游社cookie已失效`
);
logger.mark(`[ck失效][UID:${this.uid}]`);
this.e.reply(`UID:${this.uid}米游社cookie已失效`);
} else {
this.e.reply(
`米游社接口报错,暂时无法查询:${res.message || 'error'}`
@ -311,6 +310,28 @@ export default class MysZZZApi extends MysApi {
* @param {boolean} cached
*/
async getFinalData(e, type, data = {}, cached = false) {
if (data.deviceFp) {
if (!data.headers) data.headers = {};
data.headers['x-rpc-device_fp'] = data.deviceFp;
}
const uid = this.uid;
let bindInfo = await redis.get(`ZZZ:DEVICE_FP:${uid}:BIND`);
if (bindInfo) {
try {
bindInfo = JSON.parse(bindInfo);
data = {
...data,
productName: bindInfo?.deviceProduct,
deviceType: bindInfo?.deviceName,
modelName: bindInfo?.deviceModel,
oaid: bindInfo?.oaid,
deviceInfo: bindInfo?.deviceFingerprint,
board: bindInfo?.deviceBoard,
};
} catch (error) {
bindInfo = null;
}
}
const result = await this.getData(type, data, cached);
const _data = await this.checkCode(e, result, type, {});
if (!_data || _data.retcode !== 0) return false;

View file

@ -1,4 +1,4 @@
import { generateSeed } from '../../utils/data.js';
import { generateSeed, randomString } from '../../utils/data.js';
import crypto from 'crypto';
/**
* derived from miao-yunzai
@ -73,6 +73,15 @@ export default class ZZZApiTool {
}
getUrlMap = (data = {}) => {
const {
productName = 'J9110',
deviceType = 'J9110',
modelName = 'Sony',
oaid = 'e3ba65d61709d17074a306072a7c3a2ec70e6d374ca6d29eb6b1b965cbb68e23',
deviceInfo = `Sony\/J9110\/J9110:11\/55.2.A.4.332\/055002A004033203408384484:user\/release-keys`,
board = 'msmnile',
} = data;
const deviceBrand = deviceInfo.split('/')[0];
let urlMap = {
zzz: {
...(['prod_gf_cn'].includes(this.server)
@ -82,9 +91,13 @@ export default class ZZZApiTool {
body: {
seed_id: `${generateSeed(13)}`,
device_id: data.deviceId,
platform: '1',
platform: '2',
seed_time: new Date().getTime() + '',
ext_fields: `{"romRemain":"16357","romCapacity":"121947","osVersion":"15.7.1","ramCapacity":"3662","ramRemain":"62","appUpdateTimeDiff":"1722253089969","isJailBreak":"0","cpuCores":"6","magnetometer":"-205.693817x20.642471x-103.278427","vendor":"中国电信","networkType":"WIFI","gyroscope":"0.371554x0.804200x-0.526751","appMemory":"82","packageName":"com.miHoYo.mhybbs","model":"iPhone13,2","hasVpn":"1","appInstallTimeDiff":"1722253055560","screenBrightness":"0.063","cpuType":"CPU_TYPE_ARM64","chargeStatus":"1","packageVersion":"2.20.1","IDFV":"${data.deviceId.toUpperCase()}","deviceName":"navel","buildTime":"1719312801323","accelerometer":"0.044586x-0.842255x-0.624100","screenSize":"390×844","proxyStatus":"1","isPushEnabled":"0","isSimInserted":"1","batteryStatus":"46"}`,
ext_fields: `{"cpuType":"arm64-v8a","romCapacity":"512","productName":"${productName}","romRemain":"422","manufacturer":"${deviceBrand}","appMemory":"512","hostname":"dg02-pool03-kvm87","screenSize":"1264x2640","osVersion":"13","aaid":"${randomString(
64
)}","vendor":"中国联通","accelerometer":"0.44027936x7.256833x6.422336","buildTags":"release-keys","model":"${modelName}","brand":"XiaoMi","oaid":"${oaid}","hardware":"qcom","deviceType":"${deviceType}","devId":"REL","serialNumber":"unknown","buildTime":"1687848011000","buildUser":"root","ramCapacity":"469679","magnetometer":"20.081251x-27.487501x2.1937501","display":"${modelName}_13.1.0.181(CN01)","ramRemain":"215344","deviceInfo":"${deviceInfo}","gyroscope":"0.030226856x0.014647375x0.010652636","vaid":"${randomString(
64
)}","buildType":"user","sdkVersion":"33","board":"${board}"}`,
bbs_device_id: data.deviceId,
app_name: 'bbs_cn',
device_fp: '38d7fc717dc22',
@ -101,7 +114,7 @@ export default class ZZZApiTool {
hoyolab_device_id: `${this.uuid}`,
platform: '2',
seed_time: new Date().getTime() + '',
ext_fields: `{"proxyStatus":1,"isRoot":1,"romCapacity":"512","deviceName":"Xperia 1","productName":"J9110","romRemain":"483","hostname":"BuildHost","screenSize":"1096x2434","isTablet":0,"model":"J9110","brand":"Sony","hardware":"qcom","deviceType":"J9110","devId":"REL","serialNumber":"unknown","sdCapacity":107433,"buildTime":"1633631032000","buildUser":"BuildUser","simState":1,"ramRemain":"98076","appUpdateTimeDiff":1716545162858,"deviceInfo":"Sony\/J9110\/J9110:11\/55.2.A.4.332\/055002A004033203408384484:user\/release-keys","buildType":"user","sdkVersion":"30","ui_mode":"UI_MODE_TYPE_NORMAL","isMockLocation":0,"cpuType":"arm64-v8a","isAirMode":0,"ringMode":2,"app_set_id":"${this.uuid}","chargeStatus":1,"manufacturer":"Sony","emulatorStatus":0,"appMemory":"512","adid":"${this.uuid}","osVersion":"11","vendor":"unknown","accelerometer":"-0.9233304x7.574181x6.472585","sdRemain":97931,"buildTags":"release-keys","packageName":"com.mihoyo.hoyolab","networkType":"WiFi","debugStatus":1,"ramCapacity":"107433","magnetometer":"-9.075001x-27.300001x-3.3000002","display":"55.2.A.4.332","appInstallTimeDiff":1716489549794,"packageVersion":"","gyroscope":"0.027029991x-0.04459185x0.032222193","batteryStatus":45,"hasKeyboard":0,"board":"msmnile"}`,
ext_fields: `{"proxyStatus":1,"isRoot":1,"romCapacity":"512","deviceName":"Xperia 1","productName":"${productName}","romRemain":"483","hostname":"BuildHost","screenSize":"1096x2434","isTablet":0,"model":"${modelName}","brand":"${deviceBrand}","hardware":"qcom","deviceType":"${deviceType}","oaid":"${oaid}","devId":"REL","serialNumber":"unknown","sdCapacity":107433,"buildTime":"1633631032000","buildUser":"BuildUser","simState":1,"ramRemain":"98076","appUpdateTimeDiff":1716545162858,"deviceInfo":"${deviceInfo}","buildType":"user","sdkVersion":"30","ui_mode":"UI_MODE_TYPE_NORMAL","isMockLocation":0,"cpuType":"arm64-v8a","isAirMode":0,"ringMode":2,"app_set_id":"${this.uuid}","chargeStatus":1,"manufacturer":"${deviceBrand}","emulatorStatus":0,"appMemory":"512","adid":"${this.uuid}","osVersion":"11","vendor":"unknown","accelerometer":"-0.9233304x7.574181x6.472585","sdRemain":97931,"buildTags":"release-keys","packageName":"com.mihoyo.hoyolab","networkType":"WiFi","debugStatus":1,"ramCapacity":"107433","magnetometer":"-9.075001x-27.300001x-3.3000002","display":"${modelName}","appInstallTimeDiff":1716489549794,"packageVersion":"","gyroscope":"0.027029991x-0.04459185x0.032222193","batteryStatus":45,"hasKeyboard":0,"board":"${board}"}`,
app_name: 'bbs_oversea',
device_fp: '38d7f2352506c',
},

View file

@ -56,7 +56,7 @@ export class ZZZPlugin extends plugin {
// 创建米游社 API 对象
const api = new MysZZZApi(uid, ck);
// 获取设备指纹
let deviceFp = await redis.get(`ZZZ:DEVICE_FP:${uid}`);
let deviceFp = await redis.get(`ZZZ:DEVICE_FP:${uid}:FP`);
if (!deviceFp) {
const sdk = api.getUrl('getFp');
const res = await fetch(sdk.url, {
@ -65,9 +65,10 @@ export class ZZZPlugin extends plugin {
body: sdk.body,
});
const fpRes = await res.json();
logger.debug(`[米游社][设备指纹]${JSON.stringify(fpRes)}`);
deviceFp = fpRes?.data?.device_fp;
if (deviceFp) {
await redis.set(`ZZZ:DEVICE_FP:${uid}`, deviceFp, {
await redis.set(`ZZZ:DEVICE_FP:${uid}:FP`, deviceFp, {
EX: 86400 * 7,
});
}
@ -86,10 +87,12 @@ export class ZZZPlugin extends plugin {
*/
async getPlayerInfo() {
// 获取 米游社 API
const { api, uid } = await this.getAPI();
const { api, uid, deviceFp } = await this.getAPI();
if (!api) return false;
// 获取用户信息
let userData = await api.getFinalData(this.e, 'zzzUser');
let userData = await api.getFinalData(this.e, 'zzzUser', {
deviceFp,
});
if (!userData) return false;
// 取第一个用户信息
userData =