oicq-icalingua-plus-plus 1.24.39 → 1.24.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/oicq.js CHANGED
@@ -14,7 +14,7 @@ const { timestamp, BUF0, BUF16, unzip, log } = require("./common");
14
14
  const push = require("./onlinepush");
15
15
  const sysmsg = require("./core/sysmsg");
16
16
  const { initFL, initGL } = require("./core/friendlist");
17
- const { int32ip2str, getUploadChannel } = require("./service");
17
+ const { int32ip2str, getUploadChannel, checkIPConnectivity } = require("./service");
18
18
 
19
19
  /**
20
20
  * @this {Client}
@@ -102,6 +102,11 @@ function pushReqListener(blob, seq) {
102
102
  if (v[1] === 10) {
103
103
  this.storage.port = v[2][0][3];
104
104
  this.storage.ip = int32ip2str(v[2][0][2]);
105
+ checkIPConnectivity(this.storage.ip, this.storage.port).then((res) => {
106
+ if (res) return;
107
+ this.logger.warn("上传通道IP不可用,将使用通用域名");
108
+ this.storage.ip = "v6.htdata.qq.com";
109
+ });
105
110
  }
106
111
  }
107
112
  this.saveStorageConfig();
@@ -170,7 +175,6 @@ function msfOfflineListener(blob) {
170
175
  * @this {Client}
171
176
  */
172
177
  function kickoffListener(data) {
173
- this._wt.deleteToken();
174
178
  this.status = STATUS_PENDING;
175
179
  this._stopHeartbeat();
176
180
  this.logger.warn(data.info);
@@ -191,6 +195,7 @@ function kickoffListener(data) {
191
195
  this.logger.mark("3秒后重新连接..");
192
196
  setTimeout(this.login.bind(this), 3000);
193
197
  }
198
+ if (sub_type !== "kickoff") this._wt.deleteToken();
194
199
  this.em("system.offline." + sub_type, { message: data.info });
195
200
  }
196
201
 
@@ -209,6 +214,7 @@ Client.prototype._register = async function () {
209
214
  };
210
215
 
211
216
  Client.prototype._var4 = 0;
217
+ Client.prototype._nt_hb_var = 0;
212
218
  Client.prototype._runCircleTask = async function () {
213
219
  if (this._var4++ > 10) {
214
220
  await this._wt.refreshD2();
@@ -235,13 +241,22 @@ Client.prototype._startHeartbeat = function () {
235
241
  }
236
242
  this._wt.syncTimeDiff();
237
243
  this._wt.heartbeat();
238
- if (this.config.useNT) this._wt.ssoHeartbeat();
244
+ if (this.config.useNT) {
245
+ if (this._nt_hb_var++ >= 5) {
246
+ this._nt_hb_var = 0;
247
+ this._wt.ssoHeartbeat();
248
+ }
249
+ }
239
250
  if (timestamp() - this.sig.qsign_token_time >= (60 * 60)) {
240
251
  this.sig.qsign_token_time = timestamp();
241
252
  this.refreshQSignToken();
242
253
  }
243
254
  if (!this.storage.port) {
244
- await getUploadChannel.call(this);
255
+ try {
256
+ await getUploadChannel.call(this);
257
+ } catch {
258
+ this.logger.warn("getUploadChannel failed");
259
+ }
245
260
  }
246
261
  }, 30000);
247
262
  };
package/lib/qimei.js CHANGED
@@ -17,6 +17,22 @@ LQ+FLkpncClKVIrBwv6PHyUvuCb0rIarmgDnzkfQAqVufEtR64iazGDKatvJ9y6B
17
17
  9NMbHddGSAUmRTCrHQIDAQAB
18
18
  -----END PUBLIC KEY-----`;
19
19
 
20
+ class SeededRandom {
21
+ constructor(seed) {
22
+ this.seed = seed;
23
+ this.state = md5(seed.toString()).toString("hex");
24
+ }
25
+
26
+ next() {
27
+ this.state = md5(this.state + secret).toString("hex");
28
+ return parseInt(this.state.substring(0, 8), 16) / 0xffffffff;
29
+ }
30
+
31
+ nextInt(min, max) {
32
+ return Math.floor(this.next() * (max - min + 1)) + min;
33
+ }
34
+ }
35
+
20
36
  function dateFormat(fmt = "YYYY-mm-dd HH:MM:SS", date = new Date()) {
21
37
  let ret;
22
38
  const opt = {
@@ -43,10 +59,9 @@ function dateFormat(fmt = "YYYY-mm-dd HH:MM:SS", date = new Date()) {
43
59
  * @returns
44
60
  */
45
61
  function genRandomPayloadByDevice(info, apk, platform) {
62
+ const seededRandom = new SeededRandom(info.android_id);
46
63
  const rangeRand = (max = 1, min = 0) => {
47
- if (max < min) [max, min] = [min, max]
48
- const diff = max - min
49
- return Math.floor(Math.random() * diff) + min
64
+ return seededRandom.nextInt(min, max);
50
65
  };
51
66
  const reserved = {
52
67
  "harmony": "0",
@@ -67,10 +82,10 @@ function genRandomPayloadByDevice(info, apk, platform) {
67
82
  "kernel": info.proc_version
68
83
  };
69
84
  let beaconId = "";
70
- const timestamp = Date.now();
71
- const mtime1 = new Date(info.mtime);
85
+ const timestamp = info.mtime || apk.buildtime * 1000 + rangeRand(10 * 24 * 60 * 60 * 1000, 0);
86
+ const mtime1 = new Date(timestamp);
72
87
  const mtimeStr1 = dateFormat("YYYY-mm-ddHHMMSS", mtime1) + "." + info.imei.slice(2, 11);
73
- const mtime2 = new Date(info.mtime - parseInt(info.imei.slice(2, 4)));
88
+ const mtime2 = new Date(timestamp - parseInt(info.imei.slice(2, 4)));
74
89
  const mtimeStr2 = dateFormat("YYYY-mm-ddHHMMSS", mtime2) + "." + info.imei.slice(5, 14);
75
90
  for (let i = 1; i <= 40; i++) {
76
91
  if ([1, 13, 14, 17, 18, 21, 33, 34, 37, 38].includes(i)) {
package/lib/service.js CHANGED
@@ -354,10 +354,47 @@ async function getUploadChannel() {
354
354
  const rsp = pb.decode(blob)[1281];
355
355
  this.storage.sig_session = rsp[1].toBuffer();
356
356
  this.storage.session_key = rsp[2].toBuffer();
357
- this.storage.ip = int32ip2str(rsp[3][2][0][2]);
358
- this.storage.port = rsp[3][2][0][3];
357
+ const server = Array.isArray(rsp[3][2]) ? rsp[3][2][0] : rsp[3][2];
358
+ this.storage.ip = int32ip2str(server[2]);
359
+ this.storage.port = server[3];
360
+ if (!(await checkIPConnectivity(this.storage.ip, this.storage.port))) {
361
+ this.logger.warn("上传通道IP不可用,将使用通用域名");
362
+ this.storage.ip = "v6.htdata.qq.com";
363
+ }
364
+ }
365
+
366
+ /**
367
+ * 检查IP地址是否连通
368
+ * @param {string} ip - 要检查的IP地址
369
+ * @param {number} port - 要检查的端口号
370
+ * @param {number} timeout - 超时时间,单位毫秒
371
+ * @returns {Promise<boolean>}
372
+ */
373
+ function checkIPConnectivity(ip, port, timeout = 5000) {
374
+ return new Promise((resolve) => {
375
+ const socket = new net.Socket();
376
+
377
+ socket.setTimeout(timeout);
378
+
379
+ socket.on('connect', () => {
380
+ socket.destroy();
381
+ resolve(true);
382
+ });
383
+
384
+ socket.on('timeout', () => {
385
+ socket.destroy();
386
+ resolve(false);
387
+ });
388
+
389
+ socket.on('error', () => {
390
+ socket.destroy();
391
+ resolve(false);
392
+ });
393
+
394
+ socket.connect(port, ip);
395
+ });
359
396
  }
360
397
 
361
398
  module.exports = {
362
- downloadFromWeb, highwayUploadStream, int32ip2str, highwayHttpUpload, MAX_UPLOAD_SIZE, getUploadChannel,
399
+ downloadFromWeb, highwayUploadStream, int32ip2str, highwayHttpUpload, MAX_UPLOAD_SIZE, getUploadChannel, checkIPConnectivity
363
400
  };
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "oicq-icalingua-plus-plus",
3
3
  "app_name": "oicq-icalingua-plus-plus",
4
- "version": "1.24.39",
5
- "app_version": "1.24.39",
6
- "upday": "2024/08/07",
4
+ "version": "1.24.40",
5
+ "app_version": "1.24.40",
6
+ "upday": "2024/08/08",
7
7
  "protocol_version": "v11",
8
8
  "description": "oicq(https://github.com/takayama-lily/oicq) v1 for Icalingua++",
9
9
  "main": "index.js",