oicq-icalingua-plus-plus 1.26.4 → 1.26.6

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.
@@ -80,7 +80,7 @@ const map = {
80
80
  106: "委屈",
81
81
  107: "快哭了",
82
82
  108: "阴险",
83
- 109: "亲亲",
83
+ 109: "左亲亲",
84
84
  110: "吓",
85
85
  111: "可怜",
86
86
  112: "菜刀",
@@ -94,8 +94,8 @@ const map = {
94
94
  120: "拳头",
95
95
  121: "差劲",
96
96
  122: "爱你",
97
- 123: "不",
98
- 124: "好",
97
+ 123: "NO",
98
+ 124: "OK",
99
99
  125: "转圈",
100
100
  126: "磕头",
101
101
  127: "回头",
@@ -127,6 +127,7 @@ const map = {
127
127
  176: "小纠结",
128
128
  177: "喷血",
129
129
  178: "斜眼笑",
130
+ 179: "doge",
130
131
  180: "惊喜",
131
132
  181: "戳一戳",
132
133
  182: "笑哭",
@@ -319,12 +320,10 @@ const map = {
319
320
  389: "/太赞了",
320
321
  390: "/太头秃",
321
322
  391: "/太沧桑",
322
-
323
323
  392: "/龙年快乐",
324
324
  393: "/新年中龙",
325
325
  394: "/新年大龙",
326
326
  395: "/略略略",
327
-
328
327
  396: "/狼狗",
329
328
  397: "/抛媚眼",
330
329
  398: "/超级ok",
@@ -343,12 +342,10 @@ const map = {
343
342
  411: "/一起嗨",
344
343
  412: "/开心",
345
344
  413: "/摇起来",
346
-
347
345
  415: "/划龙舟",
348
346
  416: "/中龙舟",
349
347
  417: "/大龙舟",
350
348
  418: "/填罐罐",
351
-
352
349
  419: "/火车",
353
350
  420: "/中火车",
354
351
  421: "/大火车",
@@ -362,8 +359,17 @@ const map = {
362
359
  429: "/蛇年快乐",
363
360
  430: "/蛇身",
364
361
  431: "/蛇尾",
365
- 432: "灵蛇献瑞",
366
-
362
+ 432: "/灵蛇献瑞",
363
+ 433: "/大鸽",
364
+ 435: "/关我鸟事",
365
+ 436: "/跟鸽走",
366
+ 437: "/鸽鸽生气",
367
+ 438: "/可靠",
368
+ 439: "/鸽瞅瞅",
369
+ 440: "/鸽喜欢",
370
+ 441: "/相信鸽",
371
+ 442: "/鸽王",
372
+ 449: "/+1",
367
373
  450: "/撇嘴",
368
374
  451: "/色",
369
375
  452: "/微笑",
@@ -385,6 +391,18 @@ const map = {
385
391
  468: "/失眠",
386
392
  469: "/坚毅",
387
393
  470: "/马到成功",
394
+ 472: "/心动",
395
+ 474: "/给你一拳",
396
+ 475: "/干饭",
397
+ 476: "/不是吧",
398
+ 477: "/你懂的",
399
+ 478: "/对的对的",
400
+ 479: "/不对不对",
401
+ 480: "/散味儿",
402
+ 481: "/学习",
403
+ 482: "/热化了",
404
+ 483: "/略",
405
+ 484: "/比爱心",
388
406
  };
389
407
 
390
408
  const FACE_OLD_BUF = Buffer.from([0x00, 0x01, 0x00, 0x04, 0x52, 0xCC, 0xF5, 0xD0]);
package/lib/service.js CHANGED
@@ -176,117 +176,138 @@ function highwayUploadStream(readable, obj, ip, port) {
176
176
  }
177
177
 
178
178
  const __ = Buffer.from([41])
179
- // TODO: 优化内存占用
180
179
  function highwayHttpUpload(readable, obj) {
181
- const agent = new http.Agent({ maxSockets: 10 })
180
+ const agent = new http.Agent({ maxSockets: 1 })
182
181
  const ip = this.storage.ip
183
182
  const port = this.storage.port
184
183
  if (!port) throw new Error("没有上传通道,如果你刚刚登录,请等待几秒")
185
184
 
186
185
  console.log(`highway(http) ip:${ip} port:${port}`)
187
186
  const url = "http://" + ip + ":" + port + "/cgi-bin/httpconn?htcmd=0x6FF0087&uin=" + this.uin
188
- let seq = 1
189
- let offset = 0, limit = 524288
187
+ const limit = 524288
190
188
  obj.ticket = this.storage.sig_session
191
189
 
192
- const bufs = new Set()
193
- const controller = new AbortController();
194
- require("events").setMaxListeners(233, controller.signal);
195
- let finished = 0
190
+ let seq = 1
191
+ let offset = 0
192
+ let totalChunks = 0
193
+ let readEnded = false
194
+
195
+ // 顺序队列:每读到一个完整分块就推入,drain 循环逐个串行上传
196
+ const queue = []
197
+ let notify = null // 用于队列非空时唤醒 drain
198
+ let errFlag = null // 记录首个错误,终止后续上传
199
+ let quickDone = false
196
200
 
201
+ const buildBuf = (chunk, chunkOffset) => {
202
+ const head = pb.encode({
203
+ 1: {
204
+ 1: 1,
205
+ 2: String(this.uin),
206
+ 3: "PicUp.DataUp",
207
+ 4: seq++,
208
+ 5: 0,
209
+ 6: this.apk.subid,
210
+ 8: obj.cmdid,
211
+ },
212
+ 2: {
213
+ 1: 0,
214
+ 2: obj.size,
215
+ 3: chunkOffset,
216
+ 4: chunk.length,
217
+ 6: obj.ticket,
218
+ 8: md5(chunk),
219
+ 9: obj.md5,
220
+ 10: 0,
221
+ 13: 0,
222
+ },
223
+ 3: obj.ext,
224
+ 4: Date.now()
225
+ })
226
+ const header = Buffer.allocUnsafe(9)
227
+ header.writeUInt8(40)
228
+ header.writeUInt32BE(head.length, 1)
229
+ header.writeUInt32BE(chunk.length, 5)
230
+ return Buffer.concat([header, head, chunk, __])
231
+ }
232
+
233
+ // 读取流 → 分块 → 入队
197
234
  readable.on("data", data => {
235
+ if (errFlag || quickDone) return
198
236
  let _offset = 0
199
237
  while (_offset < data.length) {
200
238
  const chunk = data.slice(_offset, limit + _offset)
201
- const head = pb.encode({
202
- 1: {
203
- 1: 1,
204
- 2: String(this.uin),
205
- 3: "PicUp.DataUp",
206
- 4: seq++,
207
- 5: 0,
208
- 6: this.apk.subid,
209
- 8: obj.cmdid,
210
- },
211
- 2: {
212
- 1: 0,
213
- 2: obj.size,
214
- 3: offset + _offset,
215
- 4: chunk.length,
216
- 6: obj.ticket,
217
- 8: md5(chunk),
218
- 9: obj.md5,
219
- 10: 0,
220
- 13: 0,
221
- },
222
- 3: obj.ext,
223
- 4: Date.now()
224
- })
225
239
  _offset += chunk.length
226
- const _ = Buffer.allocUnsafe(9)
227
- _.writeUInt8(40)
228
- _.writeUInt32BE(head.length, 1)
229
- _.writeUInt32BE(chunk.length, 5)
230
- const buf = Buffer.concat([_, head, chunk, __])
231
- bufs.add(buf)
240
+ ++totalChunks
241
+ const buf = buildBuf(chunk, offset + _offset - chunk.length)
242
+ queue.push(buf)
243
+ if (notify) { notify(); notify = null }
232
244
  }
233
245
  offset += data.length
234
246
  })
235
247
 
248
+ readable.on("err", err => { errFlag = err })
249
+
250
+ // 串行 drain 循环:逐个从队列取分块上传
251
+ const drain = async () => {
252
+ let finished = 0
253
+ while (true) {
254
+ while (queue.length === 0) {
255
+ if (errFlag) return
256
+ if (readEnded) {
257
+ // 流已结束且队列为空,检查是否全部完成
258
+ if (finished >= totalChunks) return
259
+ }
260
+ // 等待新分块入队
261
+ await new Promise(r => { notify = r })
262
+ }
263
+ const buf = queue.shift()
264
+ const r = await axios.post(url, buf, {
265
+ responseType: "arraybuffer",
266
+ httpAgent: agent,
267
+ headers: {
268
+ "Content-Length": String(buf.length),
269
+ "Content-Type": "application/octet-stream"
270
+ }
271
+ })
272
+ let rsp
273
+ try {
274
+ const respBuf = Buffer.from(r?.data)
275
+ const header = respBuf.slice(9, respBuf.length - 1)
276
+ rsp = pb.decode(header)
277
+ } catch (err) {
278
+ throw err
279
+ }
280
+ if (rsp?.[3] !== 0) {
281
+ throw new Error(`${rsp[3]}, unknown highway error`)
282
+ }
283
+ ++finished
284
+ const percentage = (finished / totalChunks * 100).toFixed(2)
285
+ this.logger.debug(`highway(http) chunk uploaded (${percentage}%)`)
286
+ if (typeof obj.callback === "function")
287
+ obj.callback(percentage)
288
+ // 快传:服务端已持有全部数据,跳过后续分块
289
+ if (rsp[7]?.toBuffer().length > 0) {
290
+ quickDone = true
291
+ this.logger.debug(`highway(http) can quick upload`)
292
+ this.logger.debug(`highway(http) chunk uploaded (100.00%)`)
293
+ if (typeof obj.callback === "function")
294
+ obj.callback("100.00")
295
+ return
296
+ }
297
+ }
298
+ }
299
+
236
300
  return new Promise((resolve, reject) => {
237
301
  readable.on("err", reject)
238
- .on("end", async() => {
239
- let flag = false
240
- for (const buf of bufs) {
241
- if (flag) break
242
- await axios.post(url, buf, {
243
- responseType: "arraybuffer",
244
- httpAgent: agent,
245
- signal: controller.signal,
246
- headers: {
247
- "Content-Length": String(buf.length),
248
- "Content-Type": "application/octet-stream"
249
- }
250
- }).then(r => {
251
- let percentage, rsp
252
- try {
253
- const buf = Buffer.from(r?.data)
254
- const header = buf.slice(9, buf.length - 1)
255
- rsp = pb.decode(header)
256
- } catch (err) {
257
- this.logger.error(err)
258
- reject(err)
259
- return
260
- }
261
- if (rsp?.[3] !== 0) {
262
- controller.abort()
263
- reject(new Error(`${rsp[3]}, unknown highway error"`))
264
- return
265
- }
266
- ++finished
267
- percentage = (finished / bufs.size * 100).toFixed(2)
268
- this.logger.debug(`highway(http) chunk uploaded (${percentage}%)`)
269
- if (typeof obj.callback === "function" && percentage)
270
- obj.callback(percentage)
271
- if (finished < bufs.size && rsp[7]?.toBuffer().length > 0) {
272
- controller.abort()
273
- flag = true
274
- this.logger.debug(`highway(http) can quick upload`)
275
- this.logger.debug(`highway(http) chunk uploaded (100.00%)`)
276
- if (typeof obj.callback === "function")
277
- obj.callback("100.00")
278
- }
279
- if (finished >= bufs.size && !rsp[7]?.toBuffer().length)
280
- reject("文件校验未通过,上传失败")
281
- }).catch(err => {
282
- if (err instanceof axios.Cancel === false) {
283
- reject(err)
284
- }
285
- flag = true
286
- })
287
- }
288
- resolve(undefined)
302
+ readable.on("end", () => {
303
+ readEnded = true
304
+ // 流结束时唤醒 drain(如果它正在等待)
305
+ if (notify) { notify(); notify = null }
289
306
  })
307
+ drain().then(() => {
308
+ if (errFlag) reject(errFlag)
309
+ else resolve(undefined)
310
+ }).catch(reject)
290
311
  })
291
312
  }
292
313
 
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.26.4",
5
- "app_version": "1.26.4",
6
- "upday": "2026/06/30",
4
+ "version": "1.26.6",
5
+ "app_version": "1.26.6",
6
+ "upday": "2026/07/18",
7
7
  "protocol_version": "v11",
8
8
  "description": "oicq(https://github.com/takayama-lily/oicq) v1 for Icalingua++",
9
9
  "main": "index.js",