├── .gitignore ├── README.MD ├── package.json ├── .github └── workflows │ └── cron_read.yaml ├── main.js ├── pikpak.js └── tools.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore node modules 2 | node_modules/ -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | 2 | [逆向过程在这里](https://blog.zhx47.top/posts/25.html) 3 | 4 | 代码中获取邮箱验证码是使用了 [mail.tm](https://mail.tm/en/) 5 | 6 | 程序入口在 `main.js`。需要更改 `pikpak.js` 中的 `getVerificationCode()`,更改为自己的服务地址或者重写与自己垃圾邮件配套的程序。 7 | 8 | 哦,对了,代码中没有对限流做处理,大批量的注册刷取邀请还需要自己处理。 9 | 10 | 还有还有,`main.js` 中的邮箱主域名需要改成大家自己的。 11 | 12 | 使用就是 npm i 下载依赖 13 | node main.js 运行脚本 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@cemalgnlts/mailjs": "^3.0.1", 4 | "axios": "^1.6.8", 5 | "axios-cookiejar-support": "^5.0.0", 6 | "crypto": "^1.0.1", 7 | "randomstring": "^1.3.0", 8 | "tough-cookie": "^4.1.3", 9 | "uuid": "^9.0.1" 10 | }, 11 | "scripts": { 12 | "start": "node main.js" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/cron_read.yaml: -------------------------------------------------------------------------------- 1 | name: Scheduled Node.js CI 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | workflow_dispatch: # 添加这行以允许手动触发 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 10 # 设置作业超时时间为10分钟 12 | 13 | strategy: 14 | matrix: 15 | node-version: [20.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - name: Install dependencies 24 | run: npm install 25 | - name: Run a script 26 | run: node main.js -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const { PikPak } = require("./pikpak"); 2 | const randomstring = require("randomstring"); 3 | const axios = require("axios"); 4 | const Mailjs = require("@cemalgnlts/mailjs"); 5 | const mailjs = new Mailjs(); 6 | 7 | async function main() { 8 | const response = await mailjs.createOneAccount(); 9 | const username = response.data.username; 10 | const password = response.data.password; 11 | 12 | console.log(username, password); 13 | let pikPak = new PikPak(username, password, null, "35619652"); 14 | 15 | pikPak 16 | .authVerification() 17 | .then(() => pikPak.getVerificationCode(mailjs)) 18 | .then(() => pikPak.authVerificationVerify()) 19 | .then(() => pikPak.authSignup()) 20 | .then(() => pikPak.userMe()) 21 | .then(() => pikPak.activityInvite()) 22 | .then(() => pikPak.activityInviteCode()) 23 | .then(() => pikPak.activationCode()) 24 | .then(() => pikPak.printUserInfo()) 25 | .catch((e) => console.log(e)); 26 | 27 | // 登录 28 | // let pikPak = new PikPak('temp@temp.com', 'tempPassword', 'tempuuid'); 29 | // pikPak.signin() 30 | // .then(() => pikPak.userMe()) 31 | // .then(() => pikPak.printUserInfo()) 32 | // .catch(e => console.log(e)) 33 | } 34 | 35 | main(); 36 | -------------------------------------------------------------------------------- /pikpak.js: -------------------------------------------------------------------------------- 1 | 2 | const { CookieJar, Cookie } = require("tough-cookie"); 3 | const { wrapper } = require("axios-cookiejar-support"); 4 | const axios = require("axios"); 5 | const { 6 | getCaptchaSign, 7 | generateDeviceId, 8 | genSign, 9 | getUserAgent, 10 | sleep, 11 | } = require("./tools"); 12 | 13 | const randomstring = require("randomstring"); 14 | 15 | class PikPak { 16 | constructor(email, password, deviceid, invite_code) { 17 | this.customAdapter = this.customAdapter.bind(this); 18 | 19 | // 初始化一个需要处理Cookie的axios处理验证程序 20 | const jar = new CookieJar(); 21 | this.jar = jar; 22 | this.client = wrapper(axios.create({ jar })); 23 | // 再初始化一个普通的axios处理普通的注册逻辑请求 24 | this.api = axios.create({ adapter: this.customAdapter }); 25 | 26 | // 一些 PikPak 的常量 27 | this.app_client_id = "YNxT9w7GMdWvEOKa"; 28 | this.web_client_id = "YUMx5nI8ZU8Ap8pm"; 29 | this.client_version = "1.42.8"; 30 | this.client_version_code = "10182"; 31 | this.client_secret = "dbw2OtmVEeuUvIptb1Coyg"; 32 | this.package_name = "com.pikcloud.pikpak"; 33 | 34 | // 初始化 35 | this.captcha_token = ""; 36 | this.deviceid = deviceid || generateDeviceId(); 37 | this.userAgent = getUserAgent( 38 | this.package_name, 39 | this.client_version, 40 | this.app_client_id, 41 | this.deviceid 42 | ); 43 | this.email = email; 44 | this.name = this.email.split("@")[0]; 45 | this.password = 46 | password || 47 | randomstring.generate({ 48 | length: 10, 49 | charset: "alphanumeric", 50 | }); 51 | this.invite_code = invite_code || "48834297"; 52 | 53 | this.access_token = ""; 54 | this.refresh_token = ""; 55 | this.user_id = ""; 56 | this.user_code = ""; 57 | this.verification_code = ""; 58 | this.verification_token = ""; 59 | this.verification_id = ""; 60 | } 61 | 62 | /** 63 | * 自定义适配器,尝试自动进行验证 64 | * @param config 65 | * @returns {Promise<*|AxiosResponse>} 66 | */ 67 | async customAdapter(config) { 68 | const validateAndRetry = async (config, retries = 1) => { 69 | try { 70 | return await axios(this.disposeConfig(config)); 71 | } catch (e) { 72 | // 检查响应码并处理 73 | if (e.response.data.error && retries <= 3) { 74 | // 图形验证码 75 | console.log(`发现captcha_token失效,第${retries}次尝试刷新`); 76 | await this.captchaInit( 77 | `${config.method.toUpperCase()}:${new URL(config.url).pathname}` 78 | ); 79 | return validateAndRetry(config, retries + 1); 80 | } else if (e.response.data.error) { 81 | throw new Error(`尝试验证失败,${JSON.stringify(e)}`); 82 | } 83 | } 84 | }; 85 | return validateAndRetry(config); 86 | } 87 | 88 | disposeConfig(config) { 89 | const { adapter, ...newConfig } = config; 90 | if (newConfig.data) { 91 | let data = JSON.parse(newConfig.data); 92 | if (data.captcha_token !== undefined) { 93 | data.captcha_token = this.captcha_token; 94 | } 95 | newConfig.data = JSON.stringify(data); 96 | } 97 | if ( 98 | newConfig.headers && 99 | newConfig.headers["x-captcha-token"] !== undefined 100 | ) { 101 | newConfig.headers["x-captcha-token"] = this.captcha_token; 102 | } 103 | return newConfig; 104 | } 105 | 106 | async captchaInit(action) { 107 | console.log("开始刷新captcha_token..."); 108 | const timestamp = Date.now(); 109 | const captchaSign = getCaptchaSign( 110 | this.package_name, 111 | this.app_client_id, 112 | this.client_version, 113 | this.deviceid, 114 | timestamp 115 | ); 116 | 117 | const url = `https://user.mypikpak.com/v1/shield/captcha/init`; 118 | const body = { 119 | action: action, 120 | captcha_token: this.captcha_token, 121 | client_id: this.app_client_id, 122 | device_id: this.deviceid, 123 | meta: { 124 | captcha_sign: captchaSign, 125 | user_id: "", 126 | package_name: this.package_name, 127 | client_version: this.client_version, 128 | email: this.email, 129 | timestamp: `${timestamp}`, 130 | }, 131 | redirect_uri: "xlaccsdk01://xbase.cloud/callback?state=harbor", 132 | }; 133 | const headers = { 134 | "user-agent": this.userAgent.appUserAgent, 135 | "x-device-id": this.deviceid, 136 | }; 137 | 138 | const { data } = await this.client.post(url, body, { 139 | params: { 140 | client_id: this.app_client_id, 141 | }, 142 | headers, 143 | }); 144 | this.captcha_token = data.captcha_token; 145 | if (data.url) { 146 | console.log("需要进行图形验证码验证..."); 147 | await this.pzzlGen(); 148 | } else { 149 | console.log(`获取到验证码Token:${data.captcha_token}`); 150 | this.captcha_token = data.captcha_token; 151 | } 152 | } 153 | 154 | /** 155 | * 获取图形验证码 156 | * @returns {Promise<{traceid: *, p: number, a: number, c: number, f: number, pid: *, deviceid: *, n: number}>} 157 | */ 158 | async pzzlGen() { 159 | console.log("开始获取验证码..."); 160 | console.log("补填Cookie..."); 161 | const cookies = [ 162 | new Cookie({ 163 | key: "PPA_CI", 164 | value: generateDeviceId(), 165 | domain: "user.mypikpak.com", 166 | path: "/", 167 | }), 168 | new Cookie({ 169 | key: "captcha_token", 170 | value: this.captcha_token, 171 | domain: "user.mypikpak.com", 172 | path: "/", 173 | }), 174 | new Cookie({ 175 | key: "mainHost", 176 | value: "user.mypikpak.com", 177 | domain: "user.mypikpak.com", 178 | path: "/", 179 | }), 180 | ]; 181 | cookies.forEach((cookie) => { 182 | this.jar.setCookie(cookie, "https://user.mypikpak.com", (err, cookie) => { 183 | if (err) { 184 | console.error(err); 185 | } else { 186 | console.log("Cookie 添加成功:", cookie); 187 | } 188 | }); 189 | }); 190 | 191 | const url = "https://user.mypikpak.com/pzzl/gen"; 192 | const params = { 193 | deviceid: this.deviceid, 194 | traceid: "", 195 | }; 196 | const headers = { 197 | "user-agent": this.userAgent.webUserAgent, 198 | "x-requested-with": this.package_name, 199 | }; 200 | 201 | const { data } = await this.client.get(url, { params, headers }); 202 | const body = genSign(data, this.deviceid); 203 | console.log(`获取到验证参数:${JSON.stringify(body)}`); 204 | await this.pzzlVerify(body); 205 | await this.creditReport({ 206 | deviceid: body.deviceid, 207 | captcha_token: this.captcha_token, 208 | type: "pzzlSlider", 209 | result: "0", 210 | data: body.pid, 211 | traceid: body.traceid, 212 | }); 213 | } 214 | 215 | /** 216 | * 图形验证码验证是否正确 217 | * @param params 218 | * @param webUserAgent 219 | * @returns {Promise<{result: string, traceid: (string|*), data: *, captcha_token: *, type: string, deviceid: *}>} 220 | */ 221 | async pzzlVerify(params) { 222 | console.log("开始验证码验证..."); 223 | const url = "https://user.mypikpak.com/pzzl/verify"; 224 | const headers = { 225 | "user-agent": this.userAgent.webUserAgent, 226 | "x-requested-with": this.package_name, 227 | }; 228 | 229 | const { data } = await this.client.get(url, { params, headers }); 230 | if ("accept" !== data.result) { 231 | throw new Error("验证失败,可能已经失效了~"); 232 | } 233 | console.log("验证成功"); 234 | } 235 | 236 | /** 237 | * 图形验证 238 | * @param params 239 | * @param webUserAgent 240 | * @returns {Promise} 241 | */ 242 | async creditReport(params) { 243 | console.log("开始汇报验证码,刷新captcha_token..."); 244 | const url = "https://user.mypikpak.com/credit/v1/report"; 245 | const headers = { 246 | "user-agent": this.userAgent.webUserAgent, 247 | "x-requested-with": this.package_name, 248 | }; 249 | 250 | const { data } = await this.client.get(url, { params, headers }); 251 | if (200 !== data.code) { 252 | throw new Error("验证失败,可能已经失效了~"); 253 | } 254 | console.log(`获取到新的captcha_token: ${data.captcha_token}`); 255 | this.captcha_token = data.captcha_token; 256 | } 257 | 258 | /** 259 | * 260 | * @param captcha_token 261 | * @param email 262 | * @param device_id 263 | * @param appUserAgent 264 | * @returns {Promise<*>} 265 | */ 266 | async authVerification() { 267 | console.log("开始获取身份验证ID..."); 268 | 269 | const url = `https://user.mypikpak.com/v1/auth/verification`; 270 | const body = { 271 | captcha_token: this.captcha_token, 272 | email: this.email, 273 | locale: "zh-CN", 274 | target: "ANY", 275 | client_id: this.app_client_id, 276 | }; 277 | const headers = { 278 | "x-device-id": this.deviceid, 279 | "user-agent": this.userAgent.appUserAgent, 280 | }; 281 | 282 | const { data } = await this.api.post(url, body, { 283 | params: { 284 | client_id: this.app_client_id, 285 | }, 286 | headers, 287 | }); 288 | console.log(`获取到身份验证ID:${data.verification_id}`); 289 | this.verification_id = data.verification_id; 290 | } 291 | 292 | async authVerificationVerify() { 293 | console.log("开始进行身份验证..."); 294 | 295 | const url = `https://user.mypikpak.com/v1/auth/verification/verify`; 296 | const body = { 297 | client_id: this.app_client_id, 298 | verification_id: this.verification_id, 299 | verification_code: this.verification_code, 300 | }; 301 | const headers = { 302 | "x-device-id": this.deviceid, 303 | "user-agent": this.userAgent.appUserAgent, 304 | }; 305 | 306 | const { data } = await this.api.post(url, body, { 307 | params: { 308 | client_id: this.app_client_id, 309 | }, 310 | headers, 311 | }); 312 | console.log(`获取到身份验证Token:${data.verification_token}`); 313 | this.verification_token = data.verification_token; 314 | } 315 | 316 | async authSignup() { 317 | console.log("开始注册..."); 318 | 319 | const url = `https://user.mypikpak.com/v1/auth/signup`; 320 | const body = { 321 | captcha_token: this.captcha_token, 322 | client_id: this.app_client_id, 323 | client_secret: this.client_secret, 324 | email: this.email, 325 | name: this.name, 326 | password: this.password, 327 | verification_token: this.verification_token, 328 | }; 329 | const headers = { 330 | "x-device-id": this.deviceid, 331 | "user-agent": this.userAgent.appUserAgent, 332 | }; 333 | 334 | const { data } = await this.api.post(url, body, { 335 | params: { 336 | client_id: this.app_client_id, 337 | }, 338 | headers, 339 | }); 340 | console.log(`注册成功`); 341 | this.access_token = data.access_token; 342 | this.refresh_token = data.refresh_token; 343 | this.user_id = data.sub; 344 | } 345 | 346 | async userMe() { 347 | console.log("尝试获取用户信息..."); 348 | 349 | const url = "https://user.mypikpak.com/v1/user/me"; 350 | const headers = { 351 | authorization: `Bearer ${this.access_token}`, 352 | "x-device-id": this.deviceid, 353 | "user-agent": this.userAgent.appUserAgent, 354 | }; 355 | 356 | const { data } = await this.api.get(url, { headers }); 357 | console.log(`获取到用户信息: ${JSON.stringify(data)}`); 358 | if (this.user_id !== data.sub) { 359 | throw new Error("获取到用户名好像不一致,是不是错了"); 360 | } 361 | } 362 | 363 | async activityInvite() { 364 | console.log("填写邀请码前一步..."); 365 | 366 | const url = "https://api-drive.mypikpak.com/vip/v1/activity/invite"; 367 | const body = { 368 | data: { 369 | sdk_int: "33", 370 | uuid: this.deviceid, 371 | userType: "1", 372 | userid: this.user_id, 373 | userSub: "", 374 | product_flavor_name: "cha", 375 | language_system: "zh-CN", 376 | language_app: "zh-CN", 377 | build_version_release: "13", 378 | phoneModel: this.userAgent.phoneModel.toUpperCase(), 379 | build_manufacturer: this.userAgent.build_manufacturer.toUpperCase(), 380 | build_sdk_int: "33", 381 | channel: "official", 382 | versionCode: this.client_version_code, 383 | versionName: this.client_version, 384 | installFrom: "other", 385 | country: "cn", 386 | }, 387 | apk_extra: { 388 | channel: "official", 389 | }, 390 | }; 391 | const headers = { 392 | authorization: `Bearer ${this.access_token}`, 393 | product_flavor_name: "cha", 394 | "x-client-version-code": this.client_version_code, 395 | "x-device-id": this.deviceid, 396 | "x-captcha-token": this.captcha_token, 397 | "user-agent": this.userAgent.appUserAgent, 398 | country: "CN", 399 | "x-peer-id": this.deviceid, 400 | "x-user-region": "2,3", 401 | "x-system-language": "zh-CN", 402 | "x-alt-capability": "3", 403 | }; 404 | 405 | await this.api.post(url, body, { headers }); 406 | } 407 | 408 | async activityInviteCode() { 409 | console.log("获取用户邀请码..."); 410 | 411 | const url = "https://api-drive.mypikpak.com/vip/v1/activity/inviteCode"; 412 | const headers = { 413 | "x-client-version-code": this.client_version_code, 414 | "x-device-id": this.deviceid, 415 | "user-agent": this.userAgent.appUserAgent, 416 | "x-system-language": "zh-CN", 417 | "x-alt-capability": "3", 418 | authorization: `Bearer ${this.access_token}`, 419 | "x-detection-time": 420 | "dl-a10b-0871:2612,dl-a10b-0867:2668,dl-a10b-0866:2734,dl-a10b-0883:2733,dl-a10b-0863:2754,dl-a10b-0865:2775,dl-a10b-0874:2774,dl-a10b-0870:2815,dl-a10b-0862:2832,dl-a10b-0873:2835,dl-a10b-0878:2839,dl-a10b-0869:2888,dl-a10b-0858:3059,dl-a10b-0879:3086,dl-a10b-0882:3198,dl-a10b-0872:3330,dl-a10b-0860:3460,dl-a10b-0884:3529,dl-a10b-0875:3583,dl-a10b-0880:3729,dl-a10b-0861:4388,dl-a10b-0859:4443,dl-a10b-0623:4508,dl-a10b-0621:4554,dl-a10b-0881:4560,dl-a10b-0877:4673,dl-a10b-0886:5086,dl-a10b-0625:5100,dl-a10b-0864:5569,dl-a10b-0876:5652,dl-a10b-0624:5658,dl-a10b-0887:6138,dl-a10b-0868:6177,dl-a10b-0885:6499,dl-a10b-0622:8542", 421 | product_flavor_name: "cha", 422 | "x-captcha-token": this.captcha_token, 423 | country: "CN", 424 | "x-peer-id": this.deviceid, 425 | "x-user-region": "2,3", 426 | }; 427 | 428 | const { data } = await this.api.get(url, { headers }); 429 | console.log(`获取到用户邀请码: ${JSON.stringify(data.code)}`); 430 | this.user_code = data.code; 431 | } 432 | 433 | async activationCode() { 434 | console.log(`开始填写邀请 ${this.invite_code}...`); 435 | 436 | const url = "https://api-drive.mypikpak.com/vip/v1/order/activation-code"; 437 | const body = { 438 | activation_code: this.invite_code, 439 | page: "invite", 440 | }; 441 | const headers = { 442 | "x-client-version-code": this.client_version_code, 443 | "x-device-id": this.deviceid, 444 | "user-agent": this.userAgent.appUserAgent, 445 | "x-system-language": "zh-CN", 446 | "x-alt-capability": "3", 447 | authorization: `Bearer ${this.access_token}`, 448 | "x-detection-time": 449 | "dl-a10b-0871:2612,dl-a10b-0867:2668,dl-a10b-0866:2734,dl-a10b-0883:2733,dl-a10b-0863:2754,dl-a10b-0865:2775,dl-a10b-0874:2774,dl-a10b-0870:2815,dl-a10b-0862:2832,dl-a10b-0873:2835,dl-a10b-0878:2839,dl-a10b-0869:2888,dl-a10b-0858:3059,dl-a10b-0879:3086,dl-a10b-0882:3198,dl-a10b-0872:3330,dl-a10b-0860:3460,dl-a10b-0884:3529,dl-a10b-0875:3583,dl-a10b-0880:3729,dl-a10b-0861:4388,dl-a10b-0859:4443,dl-a10b-0623:4508,dl-a10b-0621:4554,dl-a10b-0881:4560,dl-a10b-0877:4673,dl-a10b-0886:5086,dl-a10b-0625:5100,dl-a10b-0864:5569,dl-a10b-0876:5652,dl-a10b-0624:5658,dl-a10b-0887:6138,dl-a10b-0868:6177,dl-a10b-0885:6499,dl-a10b-0622:8542", 450 | product_flavor_name: "cha", 451 | "x-captcha-token": this.captcha_token, 452 | country: "CN", 453 | "x-peer-id": this.deviceid, 454 | "x-user-region": "2,3", 455 | }; 456 | 457 | const { data } = await this.api.post(url, body, { headers }); 458 | console.log(`结果: ${JSON.stringify(data)}`); 459 | } 460 | 461 | async getVerificationCode(mailjs) { 462 | console.log("开始获取验证码..."); 463 | for (let i = 0; i < 10; i++) { 464 | const { data } = await mailjs.getMessages(); 465 | console.log(`获取到邮件数量: ${data.length}`); 466 | if (data.length > 0) { 467 | let intro = data[0].intro; 468 | const regex = /\d+/g; 469 | const matches = intro.match(regex); 470 | 471 | if (matches && matches[0]) { 472 | console.log("提取到的验证码是:", matches[0]); 473 | this.verification_code = matches[0]; 474 | return; 475 | } else { 476 | console.log("暂时没有找到验证码~"); 477 | await sleep(3000); 478 | } 479 | } else { 480 | console.log("暂时没有找到验证码~"); 481 | await sleep(3000); 482 | } 483 | } 484 | throw new Error("未获取到验证码~"); 485 | } 486 | 487 | async signin() { 488 | console.log(`开始登录...`); 489 | 490 | const url = "https://user.mypikpak.com/v1/auth/signin"; 491 | const body = { 492 | captcha_token: "", 493 | client_id: this.app_client_id, 494 | client_secret: this.client_secret, 495 | password: this.password, 496 | username: this.email, 497 | }; 498 | const headers = { 499 | "x-device-id": this.deviceid, 500 | "user-agent": this.userAgent.appUserAgent, 501 | }; 502 | 503 | const { data } = await this.api.post(url, body, { 504 | params: { 505 | client_id: this.app_client_id, 506 | }, 507 | headers, 508 | }); 509 | 510 | if (data.access_token) { 511 | console.log("登录成功"); 512 | this.access_token = data.access_token; 513 | this.refresh_token = data.refresh_token; 514 | this.user_id = data.sub; 515 | } else { 516 | throw new Error("登录失败..."); 517 | } 518 | } 519 | 520 | printUserInfo() { 521 | console.log( 522 | `本次注册用户信息如下: 用户ID: ${this.user_id}, 用户昵称: ${this.name}, 用户邮箱: ${this.email}, 用户密码: ${this.password}, 用户设备ID: ${this.deviceid}, 用户邀请码: ${this.user_code}` 523 | ); 524 | } 525 | } 526 | 527 | module.exports = { 528 | PikPak, 529 | }; 530 | -------------------------------------------------------------------------------- /tools.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | const {v4: uuidv4} = require('uuid'); 3 | 4 | const device_lists = { 5 | timestamp: 1682864287202, 6 | products: [ 7 | { 8 | name: "华为/荣耀(旧)", 9 | value: "HUAWEI", 10 | models: [ 11 | {name: "HUAWEI Mate X3", value: "ALT-AL00"}, 12 | {name: "HUAWEI Mate X2 典藏版", value: "TET-AN50"}, 13 | {name: "HUAWEI Mate X2", value: "TET-AN00"}, 14 | {name: "HUAWEI Mate X", value: "TAH-AN00"}, 15 | {name: "HUAWEI Mate Xs 2 典藏版", value: "PAL-AL00-DC"}, 16 | {name: "HUAWEI Mate Xs 2", value: "PAL-AL00"}, 17 | {name: "HUAWEI Mate Xs", value: "TAH-AN00m"}, 18 | {name: "HUAWEI Mate 50 RS", value: "DCO-AL00-PD"}, 19 | {name: "HUAWEI Mate 50 Pro", value: "DCO-AL00"}, 20 | {name: "HUAWEI Mate 50", value: "CET-AL00"}, 21 | {name: "HUAWEI Mate 50E", value: "CET-AL60"}, 22 | {name: "HUAWEI Mate 40 RS", value: "NOP-AN00-PD"}, 23 | {name: "HUAWEI Mate 40 Pro+", value: "NOP-AN00"}, 24 | {name: "HUAWEI Mate 40 Pro", value: "NOH-AN00"}, 25 | {name: "HUAWEI Mate 40", value: "OCE-AN10"}, 26 | {name: "HUAWEI Mate 40E", value: "OCE-AN50"}, 27 | {name: "HUAWEI Mate 30 RS", value: "LIO-AN00P"}, 28 | {name: "HUAWEI Mate 30 Pro 5G", value: "LIO-AN00"}, 29 | {name: "HUAWEI Mate 30 5G", value: "TAS-AN00"}, 30 | {name: "HUAWEI Mate 30 Pro", value: "LIO-AL00"}, 31 | {name: "HUAWEI Mate 30", value: "TAS-AL00"}, 32 | {name: "HUAWEI Mate 30E Pro 5G", value: "LIO-AN00m"}, 33 | {name: "HUAWEI P60 Pro", value: "MNA-AL00"}, 34 | {name: "HUAWEI P60", value: "LNA-AL00"}, 35 | {name: "HUAWEI P50 Pocket", value: "BLA-AL80"}, 36 | {name: "HUAWEI P50 Pro", value: "JAD-AL80"}, 37 | {name: "HUAWEI P50", value: "ABR-AL80"}, 38 | {name: "HUAWEI P50E", value: "ABR-AL90"}, 39 | {name: "HUAWEI P40 Pro+", value: "ELS-AN10"}, 40 | {name: "HUAWEI P40 Pro", value: "ELS-AN00"}, 41 | {name: "HUAWEI P40", value: "ANA-AN00"}, 42 | {name: "HUAWEI P40 4G", value: "ANA-AL00"}, 43 | {name: "HUAWEI P30 Pro", value: "VOG-AL10"}, 44 | {name: "HUAWEI P30", value: "ELE-AL00"}, 45 | {name: "HUAWEI Pocket S", value: "BAL-AL60"}, 46 | {name: "HUAWEI nova 11 Ultra", value: "GOA-AL80U"}, 47 | {name: "HUAWEI nova 11 Pro", value: "GOA-AL80"}, 48 | {name: "HUAWEI nova 11", value: "FOA-AL00"}, 49 | {name: "HUAWEI nova 10 Pro", value: "GLA-AL00"}, 50 | {name: "HUAWEI nova 10", value: "NCO-AL00"}, 51 | {name: "HUAWEI nova 10 SE", value: "BNE-AL00"}, 52 | {name: "HUAWEI nova 10z", value: "CHA-AL80"}, 53 | {name: "HUAWEI nova 10青春版", value: "JLN-AL00"}, 54 | {name: "HUAWEI nova 9 Pro", value: "RTE-AL00"}, 55 | {name: "HUAWEI nova 9", value: "NAM-AL00"}, 56 | {name: "HUAWEI nova 9 SE", value: "JLN-AL00"}, 57 | {name: "荣耀30S", value: "CDY-AN90"}, 58 | {name: "荣耀30 Pro+", value: "EBG-AN10"}, 59 | {name: "荣耀30 Pro", value: "EBG-AN00"}, 60 | {name: "荣耀30", value: "BMH-AN10"}, 61 | {name: "荣耀30 青春版", value: "MXW-AN00"}, 62 | {name: "荣耀V30 Pro", value: "OXF-AN10"}, 63 | {name: "荣耀V30", value: "OXF-AN00"} 64 | ] 65 | }, 66 | { 67 | name: "荣耀", 68 | value: "HONOR", 69 | models: [ 70 | {name: "荣耀Magic Vs 至臻版", value: "FRI-AN10"}, 71 | {name: "荣耀Magic Vs", value: "FRI-AN00"}, 72 | {name: "荣耀Magic V", value: "MGI-AN00"}, 73 | {name: "荣耀Magic 5 至臻版", value: "PGT-AN20"}, 74 | {name: "荣耀Magic 5 Pro", value: "PGT-AN10"}, 75 | {name: "荣耀Magic 5", value: "PGT-AN00"}, 76 | {name: "荣耀Magic 4 至臻版", value: "LGE-AN20"}, 77 | {name: "荣耀Magic 4 Pro", value: "LGE-AN10"}, 78 | {name: "荣耀Magic 4", value: "LGE-AN00"}, 79 | {name: "荣耀80 GT", value: "AGT-AN00"}, 80 | {name: "荣耀80 Pro", value: "ANP-AN00"}, 81 | {name: "荣耀80 Pro 直屏版", value: "ANB-AN00"}, 82 | {name: "荣耀80", value: "ANN-AN00"}, 83 | {name: "荣耀80 SE", value: "GIA-AN80"}, 84 | {name: "荣耀70 Pro+", value: "HPB-AN00"}, 85 | {name: "荣耀70 Pro", value: "SDY-AN00"}, 86 | {name: "荣耀70", value: "FNE-AN00"}, 87 | {name: "荣耀60 Pro", value: "TNA-AN00"}, 88 | {name: "荣耀60", value: "LSA-AN00"}, 89 | {name: "荣耀X50i", value: "CRT-AN00"}, 90 | {name: "荣耀X40 GT", value: "ADT-AN00"}, 91 | {name: "荣耀40i", value: "DIO-AN00"}, 92 | {name: "荣耀X40", value: "RMO-AN00"} 93 | ] 94 | }, 95 | { 96 | name: "小米/Redmi", 97 | value: "Xiaomi", 98 | models: [ 99 | {name: "小米13 Ultra", value: "2304FPN6DC"}, 100 | {name: "小米13 Pro", value: "2210132C"}, 101 | {name: "小米13", value: "2211133C"}, 102 | {name: "小米12S Ultra", value: "2203121C"}, 103 | {name: "小米12S Pro", value: "2206122SC"}, 104 | {name: "小米12S", value: "2206123SC"}, 105 | {name: "小米12 Pro", value: "2201122C"}, 106 | {name: "小米12", value: "2201123C"}, 107 | {name: "小米12X", value: "2112123AC"}, 108 | {name: "小米12 Pro 天玑版", value: "2207122MC"}, 109 | {name: "小米11 Ultra", value: "M2102K1C"}, 110 | {name: "小米11 Pro", value: "M2102K1AC"}, 111 | {name: "小米11", value: "M2011K2C"}, 112 | {name: "小米11 青春版", value: "M2101K9C"}, 113 | {name: "小米11 青春活力版", value: "2107119DC"}, 114 | {name: "小米10 至尊纪念版", value: "M2007J1SC"}, 115 | {name: "小米10 青春版1", value: "M2022J9E"}, 116 | {name: "小米10 青春版2", value: "M2102J2SC"}, 117 | {name: "小米10 Pro", value: "Mi 10 Pro"}, 118 | {name: "小米10", value: "Mi 10"}, 119 | {name: "小米5", value: "MI 5"}, 120 | {name: "小米MIX Fold 2", value: "22061218C"}, 121 | {name: "小米MIX FOLD", value: "M2011J18C"}, 122 | {name: "小米MIX Alpha", value: "MIX Alpha"}, 123 | {name: "小米MIX 4", value: "2106118C"}, 124 | {name: "小米MIX 3 5G", value: "Mi MIX 3 5G"}, 125 | {name: "小米MIX 3 故宫特别版", value: "MIX 3 The Palace Museum Edition"}, 126 | {name: "小米MIX 3", value: "MIX 3"}, 127 | {name: "小米MIX 2S 翡翠艺术版", value: "MIX 2S Emerald Edition"}, 128 | {name: "小米MIX 2S", value: "MIX 2S"}, 129 | {name: "小米MIX 2 艺术特别版", value: "MIX 2 ART"}, 130 | {name: "小米MIX 2", value: "MIX 2"}, 131 | {name: "小米MIX", value: "MIX"}, 132 | {name: "小米Civi 3", value: "23046PNC9C"}, 133 | {name: "小米Civi 2", value: "2209129SC"}, 134 | {name: "小米Civi 1S", value: "2109119BC"}, 135 | {name: "小米Civi", value: "Xiaomi Civi"}, 136 | {name: "Redmi K60 Pro", value: "22127RK46C"}, 137 | {name: "Redmi K60", value: "23013RK75C"}, 138 | {name: "Redmi K60E", value: "22122RK93C"}, 139 | {name: "Redmi K50 电竞版", value: "21121210C"}, 140 | {name: "Redmi K50 至尊版", value: "22081212C"}, 141 | {name: "Redmi K50 Pro", value: "22011211C"}, 142 | {name: "Redmi K50", value: "22041211AC"}, 143 | {name: "Redmi K40S", value: "22021211RC"}, 144 | {name: "Redmi K40 游戏增强版", value: "M2012K10C"}, 145 | {name: "Redmi K40 Pro", value: "M2012K11C"}, 146 | {name: "Redmi K40", value: "M2012K11AC"}, 147 | {name: "Redmi Note 12 Turbo", value: "23049RAD8C"}, 148 | {name: "Redmi Note 12 Pro 极速版", value: "22101320C"}, 149 | {name: "Redmi Note 12 探索版", value: "22101316UC"}, 150 | {name: "Redmi Note 12 Pro+", value: "22101316UCP"}, 151 | {name: "Redmi Note 12 Pro", value: "22101316C"}, 152 | {name: "Redmi Note 12", value: "22101317C"}, 153 | {name: "Redmi Note 11T Pro+", value: "22041216UC"}, 154 | {name: "Redmi Note 11T Pro", value: "22041216C"}, 155 | {name: "Redmi Note 11 Pro+", value: "21091116UC"}, 156 | {name: "Redmi Note 11 Pro", value: "21091116C"}, 157 | {name: "Redmi Note 11 5G", value: "21091116AC"}, 158 | {name: "Redmi Note 11 4G", value: "21121119SC"}, 159 | {name: "Redmi Note 11R", value: "22095RA98C"}, 160 | {name: "Redmi Note 11E Pro", value: "2201116SC"} 161 | ] 162 | }, 163 | { 164 | name: "一加", 165 | value: "OnePlus", 166 | models: [ 167 | {name: "OnePlus 11", value: "PHB110"}, 168 | {name: "OnePlus 10 Pro", value: "NE2210"}, 169 | {name: "OnePlus 9R", value: "LE2100"}, 170 | {name: "OnePlus 9RT", value: "MT2110"}, 171 | {name: "OnePlus 9 Pro", value: "LE2120"}, 172 | {name: "OnePlus 9", value: "LE2110"}, 173 | {name: "OnePlus 8T", value: "KB2000"}, 174 | {name: "OnePlus 8 Pro", value: "IN2020"}, 175 | {name: "OnePlus 8", value: "IN2010"}, 176 | {name: "OnePlus 7T Pro", value: "HD1910"}, 177 | {name: "OnePlus 7T", value: "HD1900"}, 178 | {name: "OnePlus 7 Pro", value: "GM1910"}, 179 | {name: "OnePlus 7", value: "GM1900"}, 180 | {name: "OnePlus Ace 2V", value: "PHP110"}, 181 | {name: "OnePlus Ace 2", value: "PHK110"}, 182 | {name: "OnePlus Ace Pro", value: "PGP110"}, 183 | {name: "OnePlus Ace 竞速版", value: "PGZ110"}, 184 | {name: "OnePlus Ace", value: "PGKM10"} 185 | ] 186 | }, 187 | { 188 | name: "OPPO", 189 | value: "OPPO", 190 | models: [ 191 | {name: "OPPO Find N2", value: "PGU100"}, 192 | {name: "OPPO Find N2 Flip", value: "PGT100"}, 193 | {name: "OPPO Find N", value: "PEUM00"}, 194 | {name: "OPPO Find X6 Pro", value: "PGEM10"}, 195 | {name: "OPPO Find X6", value: "PGFM10"}, 196 | {name: "OPPO Find X5 Pro", value: "PFEM10"}, 197 | {name: "OPPO Find X5", value: "PFFM10"}, 198 | {name: "OPPO Find X3 Pro MARS", value: "PEEM00_MARS"}, 199 | {name: "OPPO Find X3 Pro", value: "PEEM00"}, 200 | {name: "OPPO Find X3", value: "PEDM00"}, 201 | {name: "OPPO Reno9 Pro+", value: "PGW110"}, 202 | {name: "OPPO Reno9 Pro", value: "PGX110"}, 203 | {name: "OPPO Reno9", value: "PHM110"}, 204 | {name: "OPPO Reno8 Pro+", value: "PFZM10"}, 205 | {name: "OPPO Reno8 Pro", value: "PGAM10"}, 206 | {name: "OPPO Reno8", value: "PGBM10"}, 207 | {name: "OPPO K10x", value: "PGGM10"}, 208 | {name: "OPPO K10 Pro", value: "PGIM10"}, 209 | {name: "OPPO K10", value: "PGJM10"}, 210 | {name: "OPPO K9s", value: "PERM10"}, 211 | {name: "OPPO K9 Pro", value: "PEYM00"}, 212 | {name: "OPPO K9", value: "PEXM00"}, 213 | {name: "OPPO A1 Pro", value: "PHQ110"}, 214 | {name: "OPPO A1", value: "PHS110"}, 215 | {name: "OPPO A97", value: "PFTM10"}, 216 | {name: "OPPO A96", value: "PFUM10"}, 217 | {name: "OPPO A58", value: "PHJ110"}, 218 | {name: "OPPO A57", value: "PFTM20"}, 219 | {name: "OPPO A55s", value: "PEMM00"}, 220 | {name: "OPPO A36", value: "PESM10"} 221 | ] 222 | }, 223 | { 224 | name: "真我", 225 | value: "realme", 226 | models: [ 227 | {name: "真我11 Pro+", value: "RMX3740"}, 228 | {name: "真我11 Pro", value: "RMX3770"}, 229 | {name: "真我11", value: "RMX3751"}, 230 | {name: "真我10s", value: "RMX3617"}, 231 | {name: "真我10 Pro+", value: "RMX3687"}, 232 | {name: "真我10 Pro", value: "RMX3663"}, 233 | {name: "真我10", value: "RMX3615"}, 234 | {name: "真我GT2大师探索版", value: "RMX3551"}, 235 | {name: "真我GT2 Pro", value: "RMX3300"}, 236 | {name: "真我GT2", value: "RMX3310"}, 237 | {name: "真我GT 大师版", value: "RMX3361"}, 238 | {name: "真我Q5 Pro", value: "RMX3572"}, 239 | {name: "真我Q5", value: "RMX3478"}, 240 | {name: "真我Q5i", value: "RMX3574"}, 241 | {name: "真我Q3s", value: "RMX3461"}, 242 | {name: "真我Q3t", value: "RMX3462"}, 243 | {name: "真我Q3 Pro 狂欢版", value: "RMX3142"}, 244 | {name: "真我Q3 Pro", value: "RMX2205"}, 245 | {name: "真我Q3", value: "RMX3161"}, 246 | {name: "真我Q3i", value: "RMX3042"}, 247 | {name: "真我GT Neo5", value: "RMX3708"}, 248 | {name: "真我GT Neo5 SE", value: "RMX3700"}, 249 | {name: "真我GT Neo3", value: "RMX3562"}, 250 | {name: "真我GT Neo 闪速版", value: "RMX3350"}, 251 | {name: "真我GT Neo2T", value: "RMX3357"}, 252 | {name: "真我GT Neo", value: "RMX3031"}, 253 | {name: "真我V30t", value: "RMX3618"}, 254 | {name: "真我X7 Pro 至尊版", value: "RMX3115"}, 255 | {name: "真我X7 Pro", value: "RMX2121"}, 256 | {name: "真我X7", value: "RMX2176"}, 257 | {name: "真我X50 Pro 玩家版", value: "RMX2072"}, 258 | {name: "真我X50 Pro", value: "RMX2071"}, 259 | {name: "真我X50m", value: "RMX2142"}, 260 | {name: "真我X50", value: "RMX2051"} 261 | ] 262 | }, 263 | { 264 | name: "vivo/iQOO", 265 | value: "vivo", 266 | models: [ 267 | {name: "vivo X Fold2", value: "V2266A"}, 268 | {name: "vivo X Flip", value: "V2256A"}, 269 | {name: "vivo X Fold+", value: "V2229A"}, 270 | {name: "vivo X Fold", value: "V2178A"}, 271 | {name: "vivo X Note", value: "V2170A"}, 272 | {name: "vivo X90 Pro+", value: "V2227A"}, 273 | {name: "vivo X90 Pro", value: "V2242A"}, 274 | {name: "vivo X90", value: "V2241A"}, 275 | {name: "vivo X80 Pro 天玑9000", value: "V2186A"}, 276 | {name: "vivo X80 Pro", value: "V2185A"}, 277 | {name: "vivo X80", value: "V2183A"}, 278 | {name: "vivo S16 Pro", value: "V2245A"}, 279 | {name: "vivo S16", value: "V2244A"}, 280 | {name: "vivo S16e", value: "V2239A"}, 281 | {name: "vivo S15 Pro", value: "V2207A"}, 282 | {name: "vivo S15", value: "V2203A"}, 283 | {name: "vivo S15e", value: "V2190A"}, 284 | {name: "vivo Y78+", value: "V2271A"}, 285 | {name: "vivo Y77", value: "V2219A"}, 286 | {name: "vivo Y73t", value: "V2164PA"}, 287 | {name: "vivo Y55s", value: "V2164A"}, 288 | {name: "vivo Y32", value: "V2158A"}, 289 | {name: "iQOO 11 Pro", value: "V2254A"}, 290 | {name: "iQOO 11", value: "V2243A"}, 291 | {name: "iQOO 10 Pro", value: "V2218A"}, 292 | {name: "iQOO 10", value: "V2217A"}, 293 | {name: "iQOO 9 Pro", value: "V2172A"}, 294 | {name: "iQOO 9", value: "V2171A"}, 295 | {name: "iQOO 8", value: "V2136A"}, 296 | {name: "iQOO 7", value: "V2049A"}, 297 | {name: "iQOO Neo7 SE", value: "V2038A"}, 298 | {name: "iQOO Neo7 竞速版", value: "V2232A"}, 299 | {name: "iQOO Neo7", value: "V2231A"}, 300 | {name: "iQOO Neo6 SE", value: "V2199A"}, 301 | {name: "iQOO Neo6", value: "V2196A"}, 302 | {name: "iQOO Z7x", value: "V2272A"}, 303 | {name: "iQOO Z7i", value: "V2230EA"}, 304 | {name: "iQOO Z7", value: "V2270A"}, 305 | {name: "iQOO Z6x", value: "V2164KA"}, 306 | {name: "iQOO Z6", value: "V2220A"}, 307 | {name: "iQOO U5x", value: "V2180GA"}, 308 | {name: "iQOO U5", value: "V2165A"}, 309 | {name: "iQOO U3", value: "V2061A"}, 310 | {name: "iQOO U1x", value: "V2065A"}, 311 | {name: "iQOO U1", value: "V2023A"} 312 | ] 313 | }, 314 | { 315 | name: "魅族", 316 | value: "meizu", 317 | models: [ 318 | {name: "魅族20 无界版", value: "MEIZU 20 Inf"}, 319 | {name: "魅族20 Pro", value: "MEIZU 20 Pro"}, 320 | {name: "魅族20", value: "MEIZU 20"}, 321 | {name: "魅族18s Pro", value: "MEIZU 18s Pro"}, 322 | {name: "魅族18s", value: "MEIZU 18s"}, 323 | {name: "魅族18X", value: "MEIZU 18X"}, 324 | {name: "魅族18 Pro", value: "MEIZU 18 Pro"}, 325 | {name: "魅族18", value: "MEIZU 18"}, 326 | {name: "魅族17 Pro", value: "meizu 17 Pro"}, 327 | {name: "魅族17", value: "meizu 17"} 328 | ] 329 | }, 330 | { 331 | name: "三星", 332 | value: "Samsung", 333 | models: [ 334 | {name: "Galaxy S23 Ultra", value: "SM-S9180"}, 335 | {name: "Galaxy S23+", value: "SM-S9160"}, 336 | {name: "Galaxy S23", value: "SM-S9110"}, 337 | {name: "Galaxy S22 Ultra", value: "SM-S9080"}, 338 | {name: "Galaxy S22+", value: "SM-S9060"}, 339 | {name: "Galaxy S22", value: "SM-S9010"}, 340 | {name: "Galaxy S21 Ultra", value: "SM-G9980"}, 341 | {name: "Galaxy S21+", value: "SM-G9960"}, 342 | {name: "Galaxy S21", value: "SM-G9910"}, 343 | {name: "Galaxy S21 FE", value: "SM-G9900"}, 344 | {name: "Galaxy Note20 Ultra", value: "SM-N9860"}, 345 | {name: "Galaxy Note20", value: "SM-N9810"}, 346 | {name: "Galaxy Note10+", value: "SM-N9760"}, 347 | {name: "Galaxy Note10", value: "SM-N9700"}, 348 | {name: "Galaxy Z Fold4", value: "SM-F9360"}, 349 | {name: "Galaxy Z Fold3", value: "SM-F9260"}, 350 | {name: "Galaxy Z Fold2", value: "SM-F9160"}, 351 | {name: "Galaxy Fold", value: "SM-F9000"}, 352 | {name: "Galaxy Z Flip4", value: "SM-F7210"}, 353 | {name: "Galaxy Z Flip3", value: "SM-F7110"}, 354 | {name: "Galaxy Z Flip 5G", value: "SM-F7070"}, 355 | {name: "Galaxy Z Flip", value: "SM-F7000"}, 356 | {name: "W23", value: "SM-W9023"}, 357 | {name: "W23 Flip", value: "SM-W7023"}, 358 | {name: "W22", value: "SM-W2022"}, 359 | {name: "W20", value: "SM-W2020"}, 360 | {name: "W21", value: "SM-W2021"} 361 | ] 362 | }, 363 | { 364 | name: "华硕/ROG", 365 | value: "asus", 366 | models: [ 367 | {name: "ROG 7 Pro", value: "ASUS_AI2205_B"}, 368 | {name: "ROG 7", value: "ASUS_AI2205_A"}, 369 | {name: "ROG 6 天玑至尊版", value: "ASUS_AI2203_B"}, 370 | {name: "ROG 6 天玑版", value: "ASUS_AI2203_A"}, 371 | {name: "ROG 6 Pro", value: "ASUS_AI2201_B"}, 372 | {name: "ROG 6", value: "ASUS_AI2201_A"}, 373 | {name: "ROG 5 幻影", value: "ASUS_I005DB"}, 374 | {name: "ROG 5", value: "ASUS_I005DA"}, 375 | {name: "ROG 3", value: "ASUS_I003DD"}, 376 | {name: "ROG 2", value: "ASUS_I001DA"}, 377 | {name: "ROG", value: "ASUS_Z01QD"}, 378 | {name: "Smartphone for Snapdragon Insiders", value: "ASUS_I007D"} 379 | ] 380 | }, 381 | { 382 | name: "索尼", 383 | value: "Sony", 384 | models: [ 385 | {name: "Xperia Pro-I", value: "XQ-BE72"}, 386 | {name: "Xperia 1", value: "J9110"}, 387 | {name: "Xperia 1 Ⅱ", value: "XQ-AT72"}, 388 | {name: "Xperia 1 Ⅲ", value: "XQ-BC72"}, 389 | {name: "Xperia 1 Ⅳ", value: "XQ-CT72"}, 390 | {name: "Xperia 5", value: "J9210"}, 391 | {name: "Xperia 5 Ⅱ", value: "XQ-AS72"}, 392 | {name: "Xperia 5 Ⅲ", value: "XQ-BQ72"}, 393 | {name: "Xperia 5 Ⅳ", value: "XQ-CQ72"}, 394 | {name: "Xperia 10 Plus", value: "I4293"} 395 | ] 396 | }, 397 | { 398 | name: "联想/拯救者", 399 | value: "Lenovo", 400 | models: [ 401 | {name: "拯救者Y90", value: "Lenovo L71061"}, 402 | {name: "拯救者Y70", value: "Lenovo L71091"}, 403 | {name: "拯救者2 Pro", value: "Lenovo L70081"}, 404 | {name: "拯救者Pro", value: "Lenovo L79031"}, 405 | {name: "Lenovo Z6 Pro 5G", value: "Lenovo L79041"}, 406 | {name: "Lenovo Z6 Pro", value: "Lenovo L78051"}, 407 | {name: "Lenovo Z6", value: "Lenovo L78121"}, 408 | {name: "Lenovo Z6 青春版", value: "Lenovo L38111"}, 409 | {name: "Lenovo Z5 Pro GT", value: "Lenovo L78032"}, 410 | {name: "Lenovo Z5 Pro", value: "Lenovo L78031"}, 411 | {name: "Lenovo Z5s", value: "Lenovo L78071"}, 412 | {name: "Lenovo Z5", value: "Lenovo L78011"} 413 | ] 414 | }, 415 | { 416 | name: "黑鲨", 417 | value: "blackshark", 418 | models: [ 419 | {name: "黑鲨5 Pro 中国航天版", value: "SHARK KTUS-A1"}, 420 | {name: "黑鲨5 中国航天版", value: "SHARK PAR-A1"}, 421 | {name: "黑鲨5 Pro", value: "SHARK KTUS-A0"}, 422 | {name: "黑鲨5", value: "SHARK PAR-A0"}, 423 | {name: "黑鲨5 RS", value: "SHARK KSR-A2"}, 424 | {name: "黑鲨4S 高达版", value: "SHARK PRS-A2"}, 425 | {name: "黑鲨4S", value: "SHARK PRS-A1"}, 426 | {name: "黑鲨4 Pro", value: "SHARK KSR-A0"}, 427 | {name: "黑鲨4", value: "SHARK PRS-A0"}, 428 | {name: "黑鲨3S", value: "SHARK KLE-A1"}, 429 | {name: "黑鲨3 Pro", value: "SHARK MBU-A0"}, 430 | {name: "黑鲨3", value: "SHARK KLE-A0"}, 431 | {name: "黑鲨2 Pro", value: "DLT-A0"}, 432 | {name: "黑鲨2", value: "SKW-A0"}, 433 | {name: "黑鲨Helo", value: "AWM-A0"}, 434 | {name: "黑鲨游戏手机", value: "SKR-A0"} 435 | ] 436 | }, 437 | { 438 | name: "努比亚/红魔", 439 | value: "nubia", 440 | models: [ 441 | {name: "红魔7S Pro 氘锋透明版", value: "NX709S-TMB"}, 442 | {name: "红魔7S Pro", value: "NX709S"}, 443 | {name: "红魔7S 氘锋透明版", value: "NX679S-TMB"}, 444 | {name: "红魔7S", value: "NX679S"}, 445 | {name: "红魔7 Pro 透明版", value: "NX709J-TMB"}, 446 | {name: "红魔7 Pro", value: "NX709J"}, 447 | {name: "红魔7 氘锋透明版", value: "NX679J-TMB"}, 448 | {name: "红魔7", value: "NX679J"}, 449 | {name: "红魔6S Pro", value: "NX669S"}, 450 | {name: "红魔6R", value: "NX669J-TMB"}, 451 | {name: "红魔6 Pro", value: "NX669J-P"}, 452 | {name: "红魔6", value: "NX679J"}, 453 | {name: "努比亚Z50 Ultra", value: "NX712J"}, 454 | {name: "努比亚Z50", value: "NX711J"}, 455 | {name: "努比亚Z40S Pro", value: "NX702J"}, 456 | {name: "努比亚Z40 Pro", value: "NX701J"}, 457 | {name: "努比亚Z30 Pro", value: "NX667J"}, 458 | {name: "红魔8 Pro+氘锋透明版", value: "NX729J_V1ATMB"}, 459 | {name: "红魔8 Pro+", value: "NX729J_V1A"}, 460 | {name: "红魔8 Pro氘锋透明版", value: "NX729J_V2ATMB"}, 461 | {name: "红魔8 Pro", value: "NX729J_V2A"}, 462 | {name: "红魔6R", value: "NX666J"}, 463 | {name: "红魔6 Pro氘锋透明版", value: "NX669J-TMB"} 464 | ] 465 | }, 466 | { 467 | name: "中兴", 468 | value: "ZTE", 469 | models: [ 470 | {name: "Axon 40 Ultra", value: "ZTE A2023P"}, 471 | {name: "Axon 40 Pro", value: "ZTE A2023"}, 472 | {name: "Axon 30 Ultra", value: "ZTE A2022P"}, 473 | {name: "Axon 30 Pro", value: "ZTE A2022"}, 474 | {name: "中兴S30", value: "ZTE 9030N"} 475 | ] 476 | }, 477 | { 478 | name: "摩托罗拉", 479 | value: "motorola", 480 | models: [ 481 | {name: "moto raza 2022", value: "XT2251-1"}, 482 | {name: "moto raza 5G", value: "XT2071-4"}, 483 | {name: "moto X40", value: "XT2301-5"}, 484 | {name: "moto X30 Pro", value: "XT2241-1"}, 485 | {name: "moto X30 屏下摄像版", value: "XT2201-6"}, 486 | {name: "moto edge X30", value: "XT2201-2"}, 487 | {name: "moto edge S30 Pro", value: "XT2243-2"}, 488 | {name: "moto edge S30", value: "XT2175-2"}, 489 | {name: "moto edge s pro", value: "XT2153-1"}, 490 | {name: "moto edge s", value: "XT2125-4"}, 491 | {name: "moto edge轻奢版", value: "XT2143-1"}, 492 | {name: "moto g53", value: "XT2335-3"}, 493 | {name: "moto g71s", value: "XT2225-2"} 494 | ] 495 | } 496 | ] 497 | } 498 | 499 | function checkFormat(matrix) { 500 | // 检查每一行,确保逗号后面的数字相同 501 | for (let i = 0; i < 3; i++) { 502 | if (!(matrix[i][0].split(',')[1] === matrix[i][1].split(',')[1] && 503 | matrix[i][1].split(',')[1] === matrix[i][2].split(',')[1])) { 504 | return false; 505 | } 506 | } 507 | 508 | // 检查每一列,确保逗号前面的数字相同 509 | for (let i = 0; i < 3; i++) { 510 | if (!(matrix[0][i].split(',')[0] === matrix[1][i].split(',')[0] && 511 | matrix[1][i].split(',')[0] === matrix[2][i].split(',')[0])) { 512 | return false; 513 | } 514 | } 515 | 516 | return true; // 如果所有条件都满足,则返回true 517 | } 518 | 519 | function findMatchingMatrix(matrix) { 520 | if (checkFormat(matrix)) { 521 | return matrix; 522 | } 523 | return null; 524 | } 525 | 526 | function tools(e, t, n) { 527 | return { 528 | ca: r(e, t), 529 | f: c(n, t) 530 | } 531 | } 532 | 533 | function r(e, t) { 534 | let n, r, u, c, f, l, d, p, h, g, y, m, v, w, b, x; 535 | n = t - 1, 536 | n < 0 && (n = 0), 537 | r = e[n], 538 | u = Math.floor(r.row / 2) + 1, 539 | c = Math.floor(r.column / 2) + 1, 540 | f = r.matrix[u][c], 541 | l = t + 1, 542 | l >= e.length && (l = t), 543 | d = e[l], 544 | p = l % d.row, 545 | h = l % d.column, 546 | g = d.matrix[p][h], 547 | y = e[t], 548 | m = 3 % y.row, 549 | v = 7 % y.column, 550 | w = y.matrix[m][v], 551 | b = i(f) + o(w), 552 | x = i(w) - o(f); 553 | return [s(a(i(f), o(f))), s(a(i(g), o(g))), s(a(i(w), o(w))), s(a(b, x))] 554 | } 555 | 556 | function i(e) { 557 | return +e.split(",")[0] 558 | } 559 | 560 | function o(e) { 561 | return +e.split(",")[1] 562 | } 563 | 564 | function a(e, t) { 565 | return e + "^⁣^" + t 566 | } 567 | 568 | function s(e) { 569 | let t = 0 570 | for (let r = 0; r < e.length; r++) { 571 | t = u(31 * t + e.charCodeAt(r)); 572 | } 573 | return t 574 | } 575 | 576 | function u(e) { 577 | const t = -2147483648 578 | , n = 2147483647; 579 | if (e > n) { 580 | return t + (e - n) % (n - t + 1) - 1 581 | } 582 | if (e < t) { 583 | return n - (t - e) % (n - t + 1) + 1 584 | } 585 | return e 586 | } 587 | 588 | function c(e, t) { 589 | return s(e + "⁣" + t) 590 | } 591 | 592 | function genSign(data, deviceid) { 593 | for (let j = 0; j < data.frames.length; j++) { 594 | const matrix = findMatchingMatrix(data.frames[j].matrix) 595 | if (matrix) { 596 | console.log(`找到目标步数:${j}`) 597 | const {ca, f} = tools(data.frames, j, data.pid); 598 | return { 599 | pid: data.pid, 600 | deviceid: deviceid, 601 | traceid: data.traceid, 602 | f: f, 603 | n: ca[0], 604 | p: ca[1], 605 | a: ca[2], 606 | c: ca[3] 607 | } 608 | } 609 | } 610 | throw new Error('未找到正确的位置') 611 | } 612 | 613 | function getCaptchaSign(package_name, client_id, client_version, deviceid, timestamp) { 614 | const e = [ 615 | {alg: "md5", salt: "Nw9cvH5q2DqkDTJG73"}, 616 | {alg: "md5", salt: "o+N/zglOE4td/6kmjQldcaT"}, 617 | {alg: "md5", salt: "SynqV"}, 618 | {alg: "md5", salt: "rObDr4xQLmbbk3K7YLn7nsNOlLmTS9h/zQNw+OjNNC"}, 619 | {alg: "md5", salt: "SD+x7W8CNeCIepTTUeENi0cPTRkQlYZuXeMHiu8KdMWs0R"}, 620 | {alg: "md5", salt: "d5bw"}, 621 | {alg: "md5", salt: "qS2pNvzAm3nkoIhK16fKVYp2yHLGwS4M"}, 622 | {alg: "md5", salt: "WKMmTWHMFLMhZxb2Nh"}, 623 | {alg: "md5", salt: "z7aRh"}, 624 | {alg: "md5", salt: "Y5qN0kxE3O"}, 625 | {alg: "md5", salt: "rpJq4"}, 626 | {alg: "md5", salt: "Lfdm3aGbd"}, 627 | {alg: "md5", salt: "X6dfcJrGemgMFLKN85ZcIl0arX3h"}, 628 | {alg: "md5", salt: "u2b"} 629 | ]; 630 | let hash = `${client_id}${client_version}${package_name}${deviceid}${timestamp}`; 631 | e.forEach(item => { 632 | hash += item.salt; 633 | hash = crypto.createHash('md5').update(hash).digest('hex'); 634 | }); 635 | 636 | return `1.${hash}`; 637 | } 638 | 639 | function getRandomNumber(n) { 640 | return Math.floor(Math.random() * n); 641 | } 642 | 643 | function capitalizeFirstLetter(str) { 644 | if (!str || typeof str !== 'string') { 645 | return "NONE"; 646 | } 647 | 648 | let result = ""; 649 | let isFirstLetter = true; 650 | 651 | for (const char of str) { 652 | if (isFirstLetter && /[a-zA-Z]/.test(char)) { 653 | result += char.toUpperCase(); 654 | isFirstLetter = false; 655 | } else { 656 | if (char === ' ') { 657 | isFirstLetter = true; 658 | } 659 | result += char.toLowerCase(); 660 | } 661 | } 662 | 663 | return result; 664 | } 665 | 666 | function processIdentifier(identifier) { 667 | const specialCharacter = " "; 668 | return identifier.replace(/ /g, specialCharacter); 669 | } 670 | 671 | function getUserAgent(package_name, client_version, client_id, deviceid) { 672 | const product_index = getRandomNumber(device_lists.products.length); 673 | const model_index = getRandomNumber(device_lists.products[product_index].models.length); 674 | 675 | const manufacturer = device_lists.products[product_index].value.toLowerCase(); 676 | const model = device_lists.products[product_index].models[model_index].value.toLowerCase(); 677 | 678 | let devicename = '' 679 | 680 | if (!model.toLowerCase().startsWith(manufacturer.toLowerCase())) { 681 | const manufacturerPart = capitalizeFirstLetter(manufacturer); 682 | if (manufacturerPart) { 683 | devicename = processIdentifier(manufacturerPart + "_" + capitalizeFirstLetter(model)); 684 | } 685 | } else { 686 | devicename = processIdentifier(capitalizeFirstLetter(model)); 687 | } 688 | 689 | const devicemodel = processIdentifier(model); 690 | const timestamp = Date.now(); 691 | 692 | return { 693 | phoneModel: model, 694 | build_manufacturer: manufacturer, 695 | appUserAgent: `ANDROID-${package_name}/${client_version} protocolversion/200 accesstype/ clientid/${client_id} clientversion/${client_version} action_type/ networktype/WIFI sessionid/ deviceid/${deviceid} providername/NONE devicesign/div101.${deviceid}430c9b9e393eb807dfc0c79466841630 refresh_token/ sdkversion/2.0.1.200201 datetime/${timestamp} usrno/ appname/android-${package_name} session_origin/ grant_type/ appid/ clientip/ devicename/${devicename} osversion/13 platformversion/10 accessmode/ devicemodel/${devicemodel}`, 696 | webUserAgent: `Mozilla/5.0 (Linux; Android 13; ${model} Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.119 Mobile Safari/537.36` 697 | } 698 | } 699 | 700 | function generateDeviceId() { 701 | return uuidv4().replace(/-/g, ''); 702 | } 703 | 704 | function sleep(ms) { 705 | return new Promise(resolve => setTimeout(resolve, ms)); 706 | } 707 | 708 | module.exports = { 709 | genSign, 710 | getCaptchaSign, 711 | getUserAgent, 712 | generateDeviceId, 713 | sleep 714 | } --------------------------------------------------------------------------------