oicq-icalingua-plus-plus 1.23.71 → 1.23.73

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/index.d.ts CHANGED
@@ -219,7 +219,8 @@ export interface FaceElem {
219
219
  data: {
220
220
  id: number,
221
221
  text?: string,
222
- qlottie?: string
222
+ qlottie?: string,
223
+ extra?: string
223
224
  }
224
225
  }
225
226
 
package/lib/client-ext.js CHANGED
@@ -372,7 +372,7 @@ Client.prototype.registerQSign = async function(retry = 0) {
372
372
  const { data } = await axios.get(url,
373
373
  {
374
374
  params,
375
- timeout: 15000,
375
+ timeout: 45000,
376
376
  headers: {
377
377
  'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.199 Safari/537.36 OICQ/1.23 ILPP/2",
378
378
  'Content-Type': "application/x-www-form-urlencoded"
@@ -438,7 +438,7 @@ Client.prototype.submitSsoCallback = async function(cmd, callbackId, body, retry
438
438
  const { data } = await axios.get(url,
439
439
  {
440
440
  params,
441
- timeout: 15000,
441
+ timeout: 45000,
442
442
  headers: {
443
443
  'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.199 Safari/537.36 OICQ/1.23 ILPP/2",
444
444
  'Content-Type': "application/x-www-form-urlencoded"
@@ -478,7 +478,7 @@ Client.prototype.refreshQSignToken = async function(retry = 0) {
478
478
  const { data } = await axios.get(url,
479
479
  {
480
480
  params,
481
- timeout: 15000,
481
+ timeout: 45000,
482
482
  headers: {
483
483
  'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.199 Safari/537.36 OICQ/1.23 ILPP/2",
484
484
  'Content-Type': "application/x-www-form-urlencoded"
@@ -563,7 +563,7 @@ Client.prototype.getSign = async function(cmd, body, retry = 0) {
563
563
  key: this.config.sign_api_key
564
564
  },
565
565
  {
566
- timeout: 15000,
566
+ timeout: 45000,
567
567
  headers: {
568
568
  'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.199 Safari/537.36 OICQ/1.23 ILPP/2",
569
569
  'Content-Type': "application/x-www-form-urlencoded"
@@ -628,7 +628,7 @@ Client.prototype.getT544 = async function(cmd, retry = 0) {
628
628
  const { data } = await axios.get(url,
629
629
  {
630
630
  params,
631
- timeout: 15000,
631
+ timeout: 45000,
632
632
  headers: {
633
633
  'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.199 Safari/537.36 OICQ/1.23 ILPP/2",
634
634
  'Content-Type': "application/x-www-form-urlencoded"
@@ -250,29 +250,46 @@ class Builder {
250
250
  text = "/" + id;
251
251
  if (!text.startsWith("/"))
252
252
  text = "/" + text;
253
+ let lottieElem = {
254
+ packId: "1",
255
+ lottieId: cq.qlottie,
256
+ faceId: id,
257
+ sourceType: 1,
258
+ lottieType: 1,
259
+ resultId: "",
260
+ text: text,
261
+ surpriseId: "",
262
+ ramdomType: 1,
263
+ };
264
+ if (cq.extra) {
265
+ try {
266
+ const extra = JSON.parse(cq.extra);
267
+ Object.assign(lottieElem, extra);
268
+ }
269
+ }
253
270
  this.elems2.push([
254
271
  {
255
272
  53: {
256
273
  1: 37,
257
274
  2: {
258
- 1: "1",
259
- 2: cq.qlottie,
260
- 3: id,
261
- 4: 1,
262
- 5: 1,
263
- 6: "",
264
- 7: text,
265
- 8: "",
266
- 9: 1
275
+ 1: lottieElem.packId,
276
+ 2: lottieElem.lottieId,
277
+ 3: lottieElem.faceId,
278
+ 4: lottieElem.sourceType,
279
+ 5: lottieElem.lottieType,
280
+ 6: lottieElem.resultId,
281
+ 7: lottieElem.text,
282
+ 8: lottieElem.surpriseId,
283
+ 9: lottieElem.ramdomType,
267
284
  },
268
285
  3: 1
269
286
  }
270
287
  },
271
288
  {
272
289
  1: {
273
- 1: text,
290
+ 1: lottieElem.text,
274
291
  12: {
275
- 1: "[" + text.replace("/", "") + "]请使用最新版手机QQ体验新功能"
292
+ 1: "[" + lottieElem.text.replace("/", "") + "]请使用最新版手机QQ体验新功能"
276
293
  }
277
294
  }
278
295
  }
@@ -276,6 +276,8 @@ const map = {
276
276
  346: "/你真棒棒",
277
277
  347: "/大展宏兔",
278
278
  348: "/福萝卜",
279
+ 358: "/骰子",
280
+ 359: "/包剪锤",
279
281
  };
280
282
 
281
283
  const FACE_OLD_BUF = Buffer.from([0x00, 0x01, 0x00, 0x04, 0x52, 0xCC, 0xF5, 0xD0]);
@@ -532,6 +532,69 @@ async function uploadImages(target, imgs, c2c = false) {
532
532
  }
533
533
  }
534
534
 
535
+ /**
536
+ * 下载QQNT群图
537
+ * @this {import("../ref").Client}
538
+ * @param {number} group_id
539
+ * @param {import("../ref").Proto} elem
540
+ */
541
+ async function groupNTPicDown(group_id, elem) {
542
+ const req = {
543
+ 1: group_id,
544
+ 2: this.uin,
545
+ 3: elem[7], //fileid
546
+ 4: elem[13], //fileMd5
547
+ 5: 4, //urlFlag
548
+ 6: 32, //urlType
549
+ 7: 5, //reqTerm
550
+ 8: 9, //reqPlatformType
551
+ 10: 212, //buType
552
+ 12: 0, //fileId
553
+ 19: common.timestamp(),
554
+ 20: 2, //reqTransferType
555
+ };
556
+ const body = pb.encode({
557
+ 1: 3,
558
+ 2: 2,
559
+ 4: req,
560
+ });
561
+ const blob = await this.sendUni("ImgStore.GroupPicDown", body);
562
+ const rsp = pb.decode(blob)[4];
563
+ return "https://" + String(rsp[11]) + String(rsp[13]);
564
+ }
565
+
566
+ /**
567
+ * 下载QQNT私聊图
568
+ * @this {import("../ref").Client}
569
+ * @param {number} user_id
570
+ * @param {import("../ref").Proto} elem
571
+ */
572
+ async function offNTPicDown(user_id, elem) {
573
+ const req = {
574
+ 1: user_id,
575
+ 2: this.uin,
576
+ 3: elem[2], //fileResId
577
+ 4: 4, //urlFlag
578
+ 6: 32, //urlType
579
+ 7: 5, //reqTerm
580
+ 8: 9, //reqPlatformType
581
+ 9: 1, //srcFileType
582
+ 11: 0, //addressBook
583
+ 12: 8, //buType
584
+ 14: common.timestamp(),
585
+ 15: 2, //reqTransferType
586
+ };
587
+ const body = pb.encode({
588
+ 1: 2,
589
+ 3: req,
590
+ 10: 3
591
+ });
592
+ const blob = await this.sendUni("LongConn.OffPicDown", body);
593
+ const rsp = pb.decode(blob)[3];
594
+ return "https://gchat.qpic.cn" + String(rsp[11]);
595
+ }
596
+
535
597
  module.exports = {
536
- ImageBuilder, uploadImages, buildImageFileParam
598
+ ImageBuilder, uploadImages, buildImageFileParam,
599
+ groupNTPicDown, offNTPicDown,
537
600
  };
@@ -10,7 +10,7 @@ const pb = require("../algo/pb");
10
10
  const face = require("./face");
11
11
  const { getGroupMsgs } = require("./history");
12
12
  const { int32ip2str } = require("../service");
13
- const { buildImageFileParam } = require("./image");
13
+ const { buildImageFileParam, groupNTPicDown, offNTPicDown } = require("./image");
14
14
  const { Gfs, getC2CFileUrl } = require("./file");
15
15
  const { getVideoUrl, getPttUrl } = require("./ptt");
16
16
  const { genC2CMessageId, genGroupMessageId, timestamp, parseFunString, code2uin, genRandom, unzip } = require("../common");
@@ -202,20 +202,15 @@ class Parser {
202
202
  break;
203
203
  case 3: //flash
204
204
  msg.type = "flash";
205
- msg.data = this.parseImgElem(elem);
205
+ msg.data = await this.parseImgElem(elem);
206
206
  brief = "[闪照]";
207
207
  break;
208
208
  case 0: //ptt
209
209
  msg.type = "record";
210
210
  msg.data.file = "protobuf://" + elem.toBase64();
211
- if (elem[20]) {
212
- const url = String(elem[20]);
213
- msg.data.url = url.startsWith("http") ? url : "https://grouptalk.c2c.qq.com" + url;
214
- } else {
215
- try {
216
- msg.data.url = await getPttUrl.call(this.c, elem, this.gid);
217
- } catch { }
218
- }
211
+ try {
212
+ msg.data.url = await getPttUrl.call(this.c, elem, this.gid);
213
+ } catch { }
219
214
  brief = "[语音]";
220
215
  break;
221
216
  case 19: //video
@@ -256,6 +251,17 @@ class Parser {
256
251
  msg.type = "face";
257
252
  msg.data.id = elem[2][3];
258
253
  if (elem[2][2]) msg.data.qlottie = String(elem[2][2]);
254
+ if (elem[2][2]) msg.data.extra = JSON.stringify({
255
+ packId: elem[2][1], //string
256
+ lottieId: elem[2][2], //string
257
+ faceId: elem[2][3], //number
258
+ sourceType: elem[2][4], //number
259
+ lottieType: elem[2][5], //number
260
+ resultId: elem[2][6], //string
261
+ text: elem[2][7], //string
262
+ surpriseId: elem[2][8], //string
263
+ ramdomType: elem[2][9], //number
264
+ });
259
265
  msg.data.text = face.map[msg.data.id];
260
266
  if (!msg.data.text)
261
267
  msg.data.text = elem[2][7] ? String(elem[2][7]) : ("/" + msg.data.id);
@@ -279,7 +285,7 @@ class Parser {
279
285
  * @param {number} type
280
286
  * @param {import("../ref").Proto} elem
281
287
  */
282
- parsePartialElem(type, elem) {
288
+ async parsePartialElem(type, elem) {
283
289
  /**
284
290
  * @type {import("../ref").MessageElem}
285
291
  */
@@ -336,7 +342,7 @@ class Parser {
336
342
  case 4:
337
343
  case 8:
338
344
  msg.type = "image";
339
- msg.data = this.parseImgElem(elem);
345
+ msg.data = await this.parseImgElem(elem);
340
346
  brief = "[图片]";
341
347
  break;
342
348
  case 34: //sface
@@ -422,7 +428,7 @@ class Parser {
422
428
  case 8: //customFace
423
429
  case 31: //mirai
424
430
  case 34: //sface
425
- this.parsePartialElem(type, elem);
431
+ await this.parsePartialElem(type, elem);
426
432
  break;
427
433
  case 5: //transElem
428
434
  case 12: //xml
@@ -435,7 +441,7 @@ class Parser {
435
441
  if (elem[1] === 3) { //flash
436
442
  await this.parseExclusiveElem(3, elem[2][1] ? elem[2][1] : elem[2][2]);
437
443
  } else if (elem[1] === 33) { //face(id>255)
438
- this.parsePartialElem(33, elem[2]);
444
+ await this.parsePartialElem(33, elem[2]);
439
445
  } else if (elem[1] === 2) { //poke
440
446
  await this.parseExclusiveElem(126, elem);
441
447
  } else if (elem[1] === 37) { //qlottie
@@ -459,9 +465,12 @@ class Parser {
459
465
  * @private
460
466
  * @param {import("../ref").Proto} elem
461
467
  */
462
- parseImgElem(elem) {
468
+ async parseImgElem(elem) {
463
469
  const data = { };
464
- if (elem[7].toHex) { //私图
470
+ if (!elem[7]) { //QQNT私图
471
+ data.file = buildImageFileParam(elem[13].toHex(), elem[25], elem[22], elem[23], elem[20]);
472
+ data.url = await offNTPicDown.call(this.c, this.uid, elem);
473
+ } else if (elem[7].toHex) { //私图
465
474
  data.file = buildImageFileParam(elem[7].toHex(), elem[2], elem[9], elem[8], elem[5]);
466
475
  if (elem[29] && elem[29][30])
467
476
  data.url = "https://gchat.qpic.cn" + elem[29][30] + "&spec=0&rf=naio";
@@ -469,12 +478,16 @@ class Parser {
469
478
  data.url = "https://c2cpicdw.qpic.cn" + elem[15];
470
479
  else if (elem[10])
471
480
  data.url = `https://c2cpicdw.qpic.cn/offpic_new/${this.uid}/${elem[10]}/0?term=2`;
481
+ if (!data.url || !data.url.includes("offpic_new"))
482
+ data.url = await offNTPicDown.call(this.c, this.uid, elem);
472
483
  } else { //群图
473
484
  data.file = buildImageFileParam(elem[13].toHex(), elem[25], elem[22], elem[23], elem[20]);
474
485
  if (elem[16])
475
486
  data.url = "https://gchat.qpic.cn" + elem[16];
476
487
  else
477
488
  data.url = `https://gchat.qpic.cn/gchatpic_new/${this.uid}/${code2uin(this.gid)||0}-${elem[7]>>>0}-${elem[13].toHex().toUpperCase()}/0?term=2`;
489
+ if (!data.url.includes("gchatpic_new"))
490
+ data.url = await groupNTPicDown.call(this.c, this.gid, elem);
478
491
  }
479
492
  return data;
480
493
  }
@@ -293,7 +293,7 @@ async function getVideoUrl(elem) {
293
293
  });
294
294
  const blob = await this.sendUni("PttStore.GroupPttDown", body);
295
295
  const rsp = pb.decode(blob)[6];
296
- return `https://grouptalk.c2c.qq.com${rsp[9].toString()}`;
296
+ return `https://${rsp[8].toString()}${rsp[9].toString()}`;
297
297
  } else {
298
298
  const body = pb.encode({
299
299
  1: 1200,
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.23.71",
5
- "app_version": "1.23.71",
6
- "upday": "2023/09/10",
4
+ "version": "1.23.73",
5
+ "app_version": "1.23.73",
6
+ "upday": "2023/09/21",
7
7
  "protocol_version": "v11",
8
8
  "description": "oicq(https://github.com/takayama-lily/oicq) v1 for Icalingua++",
9
9
  "main": "index.js",