karin-plugin-kkk 2.20.2 → 2.20.3
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/CHANGELOG.md +25 -0
- package/config/default_config/app.yaml +1 -7
- package/lib/apps/admin.js +3 -3
- package/lib/apps/help.js +3 -3
- package/lib/apps/push.js +3 -3
- package/lib/apps/qrlogin.js +3 -3
- package/lib/apps/tools.js +3 -3
- package/lib/apps/update.js +3 -3
- package/lib/build-metadata.json +5 -5
- package/lib/core_chunk/{main-Du8yBcGG.js → main-CXz1QLHw.js} +332 -112
- package/lib/core_chunk/{template-CQ-u6h09.js → template-Bo8XmVaD.js} +370 -168
- package/lib/core_chunk/template.d.mts +8 -1
- package/lib/core_chunk/template.js +2 -2
- package/lib/core_chunk/{vendor-B3KhGHI_.js → vendor-DrIRnh5C.js} +191 -104
- package/lib/index.js +3 -3
- package/lib/karin-plugin-kkk.css +36 -0
- package/lib/root.js +1 -1
- package/lib/web.config.js +3 -3
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __esmMin, o as __toESM, r as __export } from "./rolldown-runtime-BMXAG3ag.js";
|
|
2
|
-
import { E as zhCN, T as init_locale, _n as zod_default, a as init_lib, cn as require_protobufjs, dn as AxiosError$1, et as init_date_fns, fn as init_axios, gn as init_zod, hn as
|
|
3
|
-
import { n as init_client, r as reactServerRender } from "./template-
|
|
2
|
+
import { E as zhCN, T as init_locale, _n as zod_default, a as init_lib, cn as require_protobufjs, dn as AxiosError$1, et as init_date_fns, fn as init_axios, gn as init_zod, hn as init_dist, i as require_qr_code_styling, it as differenceInSeconds, ln as Chalk, mn as Xhshow, n as require_dist, nt as formatDistanceToNow, o as Window, on as require_jsQR, pn as axios_default, r as require_lib, rt as format, sn as require_express, t as require_heic_convert, tt as fromUnixTime, un as init_source } from "./vendor-DrIRnh5C.js";
|
|
3
|
+
import { n as init_client, r as reactServerRender } from "./template-Bo8XmVaD.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import karin$1, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, checkPort, common, components, config, copyConfigSync, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, ffmpeg, ffprobe, filesByExt, getBot, hooks, karin, karinPathHtml, karinPathTemp, logger, logs, mkdirSync, range, render, requireFileSync, restart, segment, updatePkg, watch } from "node-karin";
|
|
6
6
|
import fs from "node:fs";
|
|
@@ -15,8 +15,8 @@ import YAML from "node-karin/yaml";
|
|
|
15
15
|
import util from "node:util";
|
|
16
16
|
import { Transformer } from "@napi-rs/image";
|
|
17
17
|
import axios, { AxiosError } from "node-karin/axios";
|
|
18
|
-
import { pipeline } from "node:stream/promises";
|
|
19
18
|
import { Transform } from "node:stream";
|
|
19
|
+
import { pipeline } from "node:stream/promises";
|
|
20
20
|
import express from "node-karin/express";
|
|
21
21
|
import template from "node-karin/template";
|
|
22
22
|
import _ from "node-karin/lodash";
|
|
@@ -905,7 +905,7 @@ var init_kuaishou$2 = __esmMin(() => {
|
|
|
905
905
|
});
|
|
906
906
|
var xiaohongshuSign;
|
|
907
907
|
var init_sign$1 = __esmMin(() => {
|
|
908
|
-
|
|
908
|
+
init_dist();
|
|
909
909
|
xiaohongshuSign = class {
|
|
910
910
|
static client = new Xhshow();
|
|
911
911
|
static generateXSGet(path$1, a1Cookie, clientType = "xhs-pc-web", params = {}) {
|
|
@@ -2207,8 +2207,8 @@ var init_sign = __esmMin(() => {
|
|
|
2207
2207
|
douyinSign = class {
|
|
2208
2208
|
static Mstoken(length) {
|
|
2209
2209
|
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
2210
|
-
const randomBytes = crypto.randomBytes(length ?? 116);
|
|
2211
|
-
return Array.from(randomBytes, (byte) => characters[byte % 62]).join("");
|
|
2210
|
+
const randomBytes$1 = crypto.randomBytes(length ?? 116);
|
|
2211
|
+
return Array.from(randomBytes$1, (byte) => characters[byte % 62]).join("");
|
|
2212
2212
|
}
|
|
2213
2213
|
static AB(url, userAgent) {
|
|
2214
2214
|
return a_bogus_default(url, userAgent ?? defaultUserAgent);
|
|
@@ -5768,7 +5768,7 @@ var init_src = __esmMin(() => {
|
|
|
5768
5768
|
init_server();
|
|
5769
5769
|
init_types$1();
|
|
5770
5770
|
init_api_spec();
|
|
5771
|
-
getVersion = () => "6.0.0-beta.
|
|
5771
|
+
getVersion = () => "6.0.0-beta.3";
|
|
5772
5772
|
VERSION = getVersion();
|
|
5773
5773
|
Object.defineProperty(CreateAmagiApp, "version", {
|
|
5774
5774
|
value: VERSION,
|
|
@@ -6488,94 +6488,109 @@ var init_QRCodeScanner = __esmMin(() => {
|
|
|
6488
6488
|
const { width, height } = imageData;
|
|
6489
6489
|
const dataSizeMB = (width * height * 4 / 1024 / 1024).toFixed(2);
|
|
6490
6490
|
logger.debug(`图片数据: ${width}x${height}, 内存占用: ${dataSizeMB}MB`);
|
|
6491
|
-
if (width <=
|
|
6492
|
-
logger.debug("
|
|
6491
|
+
if (width <= 1024 && height <= 1024) {
|
|
6492
|
+
logger.debug("图片尺寸较小,使用全图识别策略");
|
|
6493
6493
|
const result = this.tryRecognizeInRegion(imageData, "全图");
|
|
6494
6494
|
if (result) return result;
|
|
6495
6495
|
}
|
|
6496
|
-
logger.debug(
|
|
6496
|
+
logger.debug(`使用分块扫描策略 (${width}x${height})`);
|
|
6497
6497
|
const scanRegions = [];
|
|
6498
|
-
const blockSize =
|
|
6498
|
+
const blockSize = Math.min(800, Math.floor(Math.max(width, height) * .6));
|
|
6499
|
+
const blockW = Math.min(blockSize, width);
|
|
6500
|
+
const blockH = Math.min(blockSize, height);
|
|
6499
6501
|
logger.debug("添加四角扫描区域");
|
|
6500
6502
|
scanRegions.push({
|
|
6501
6503
|
name: "左上角",
|
|
6502
6504
|
x: 0,
|
|
6503
6505
|
y: 0,
|
|
6504
|
-
w:
|
|
6505
|
-
h:
|
|
6506
|
+
w: blockW,
|
|
6507
|
+
h: blockH
|
|
6506
6508
|
});
|
|
6507
|
-
|
|
6509
|
+
scanRegions.push({
|
|
6508
6510
|
name: "右上角",
|
|
6509
|
-
x:
|
|
6511
|
+
x: Math.max(0, width - blockW),
|
|
6510
6512
|
y: 0,
|
|
6511
|
-
w:
|
|
6512
|
-
h:
|
|
6513
|
+
w: blockW,
|
|
6514
|
+
h: blockH
|
|
6513
6515
|
});
|
|
6514
|
-
|
|
6516
|
+
scanRegions.push({
|
|
6515
6517
|
name: "左下角",
|
|
6516
6518
|
x: 0,
|
|
6517
|
-
y:
|
|
6518
|
-
w:
|
|
6519
|
-
h:
|
|
6519
|
+
y: Math.max(0, height - blockH),
|
|
6520
|
+
w: blockW,
|
|
6521
|
+
h: blockH
|
|
6520
6522
|
});
|
|
6521
|
-
|
|
6523
|
+
scanRegions.push({
|
|
6522
6524
|
name: "右下角",
|
|
6523
|
-
x:
|
|
6524
|
-
y:
|
|
6525
|
-
w:
|
|
6526
|
-
h:
|
|
6525
|
+
x: Math.max(0, width - blockW),
|
|
6526
|
+
y: Math.max(0, height - blockH),
|
|
6527
|
+
w: blockW,
|
|
6528
|
+
h: blockH
|
|
6527
6529
|
});
|
|
6528
|
-
if (width >
|
|
6530
|
+
if (width > blockW * 1.5) {
|
|
6529
6531
|
logger.debug("添加顶部/底部中间扫描区域");
|
|
6530
6532
|
scanRegions.push({
|
|
6531
6533
|
name: "顶部中",
|
|
6532
|
-
x: Math.floor((width -
|
|
6534
|
+
x: Math.floor((width - blockW) / 2),
|
|
6533
6535
|
y: 0,
|
|
6534
|
-
w:
|
|
6535
|
-
h:
|
|
6536
|
+
w: blockW,
|
|
6537
|
+
h: blockH
|
|
6536
6538
|
});
|
|
6537
|
-
if (height >
|
|
6539
|
+
if (height > blockH * 1.5) scanRegions.push({
|
|
6538
6540
|
name: "底部中",
|
|
6539
|
-
x: Math.floor((width -
|
|
6540
|
-
y: height -
|
|
6541
|
-
w:
|
|
6542
|
-
h:
|
|
6541
|
+
x: Math.floor((width - blockW) / 2),
|
|
6542
|
+
y: Math.max(0, height - blockH),
|
|
6543
|
+
w: blockW,
|
|
6544
|
+
h: blockH
|
|
6543
6545
|
});
|
|
6544
6546
|
}
|
|
6545
|
-
if (height >
|
|
6547
|
+
if (height > blockH * 1.5) {
|
|
6546
6548
|
logger.debug("添加左右中间扫描区域");
|
|
6547
|
-
const middleY = Math.floor((height -
|
|
6549
|
+
const middleY = Math.floor((height - blockH) / 2);
|
|
6548
6550
|
scanRegions.push({
|
|
6549
6551
|
name: "左中",
|
|
6550
6552
|
x: 0,
|
|
6551
6553
|
y: middleY,
|
|
6552
|
-
w:
|
|
6553
|
-
h:
|
|
6554
|
+
w: blockW,
|
|
6555
|
+
h: blockH
|
|
6554
6556
|
});
|
|
6555
|
-
if (width >
|
|
6557
|
+
if (width > blockW * 1.5) scanRegions.push({
|
|
6556
6558
|
name: "右中",
|
|
6557
|
-
x: width -
|
|
6559
|
+
x: Math.max(0, width - blockW),
|
|
6558
6560
|
y: middleY,
|
|
6559
|
-
w:
|
|
6560
|
-
h:
|
|
6561
|
+
w: blockW,
|
|
6562
|
+
h: blockH
|
|
6561
6563
|
});
|
|
6562
6564
|
}
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
let slidingWindowCount = 0;
|
|
6566
|
-
for (let y = 0; y < height - blockSize; y += step) {
|
|
6565
|
+
if (width > blockW && height > blockH) {
|
|
6566
|
+
logger.debug("添加中心区域");
|
|
6567
6567
|
scanRegions.push({
|
|
6568
|
-
name:
|
|
6569
|
-
x:
|
|
6570
|
-
y,
|
|
6571
|
-
w:
|
|
6572
|
-
h:
|
|
6568
|
+
name: "中心",
|
|
6569
|
+
x: Math.floor((width - blockW) / 2),
|
|
6570
|
+
y: Math.floor((height - blockH) / 2),
|
|
6571
|
+
w: blockW,
|
|
6572
|
+
h: blockH
|
|
6573
6573
|
});
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6574
|
+
}
|
|
6575
|
+
logger.debug("添加滑动窗口扫描区域");
|
|
6576
|
+
const step = Math.floor(blockSize * .6);
|
|
6577
|
+
let slidingWindowCount = 0;
|
|
6578
|
+
for (let y = 0; y <= height - blockH; y += step) {
|
|
6579
|
+
for (let x = 0; x <= width - blockW; x += step) {
|
|
6580
|
+
scanRegions.push({
|
|
6581
|
+
name: `滑动-${slidingWindowCount}`,
|
|
6582
|
+
x,
|
|
6583
|
+
y,
|
|
6584
|
+
w: blockW,
|
|
6585
|
+
h: blockH
|
|
6586
|
+
});
|
|
6587
|
+
slidingWindowCount++;
|
|
6588
|
+
if (scanRegions.length > 40) {
|
|
6589
|
+
logger.debug(`滑动窗口数量达到上限,停止添加 (已添加 ${slidingWindowCount} 个)`);
|
|
6590
|
+
break;
|
|
6591
|
+
}
|
|
6578
6592
|
}
|
|
6593
|
+
if (scanRegions.length > 40) break;
|
|
6579
6594
|
}
|
|
6580
6595
|
logger.debug(`共生成 ${scanRegions.length} 个扫描区域,开始逐个扫描`);
|
|
6581
6596
|
for (let i = 0; i < scanRegions.length; i++) {
|
|
@@ -6766,8 +6781,122 @@ var init_Common = __esmMin(async () => {
|
|
|
6766
6781
|
};
|
|
6767
6782
|
Common = new Tools();
|
|
6768
6783
|
});
|
|
6784
|
+
function getEmojiId(e, type) {
|
|
6785
|
+
return (PLATFORM_EMOJI_IDS[e.bot?.adapter?.platform || "other"] || PLATFORM_EMOJI_IDS.other)[type];
|
|
6786
|
+
}
|
|
6787
|
+
async function setEmojiReaction(e, emojiId, isSet = true) {
|
|
6788
|
+
if (!Config.app.EmojiReply) return false;
|
|
6789
|
+
if (e.isPrivate) return false;
|
|
6790
|
+
try {
|
|
6791
|
+
await e.bot.setMsgReaction(e.contact, e.messageId, emojiId, isSet);
|
|
6792
|
+
return true;
|
|
6793
|
+
} catch (err) {
|
|
6794
|
+
logger.debug("[EmojiReaction] 设置表情回复失败(已忽略):", err);
|
|
6795
|
+
return false;
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
var PLATFORM_EMOJI_IDS, EmojiReactionManager;
|
|
6769
6799
|
var init_EmojiReaction = __esmMin(() => {
|
|
6770
6800
|
init_Config();
|
|
6801
|
+
PLATFORM_EMOJI_IDS = {
|
|
6802
|
+
qq: {
|
|
6803
|
+
EYES: 128064,
|
|
6804
|
+
PROCESSING: 366,
|
|
6805
|
+
SUCCESS: 389,
|
|
6806
|
+
ERROR: 379
|
|
6807
|
+
},
|
|
6808
|
+
wechat: {
|
|
6809
|
+
EYES: "WECHAT_EYES_PLACEHOLDER",
|
|
6810
|
+
PROCESSING: "WECHAT_PROCESSING_PLACEHOLDER",
|
|
6811
|
+
SUCCESS: "WECHAT_SUCCESS_PLACEHOLDER",
|
|
6812
|
+
ERROR: "WECHAT_ERROR_PLACEHOLDER"
|
|
6813
|
+
},
|
|
6814
|
+
telegram: {
|
|
6815
|
+
EYES: "TELEGRAM_EYES_PLACEHOLDER",
|
|
6816
|
+
PROCESSING: "TELEGRAM_PROCESSING_PLACEHOLDER",
|
|
6817
|
+
SUCCESS: "TELEGRAM_SUCCESS_PLACEHOLDER",
|
|
6818
|
+
ERROR: "TELEGRAM_ERROR_PLACEHOLDER"
|
|
6819
|
+
},
|
|
6820
|
+
discord: {
|
|
6821
|
+
EYES: "👀",
|
|
6822
|
+
PROCESSING: "⏳",
|
|
6823
|
+
SUCCESS: "✅",
|
|
6824
|
+
ERROR: "❌"
|
|
6825
|
+
},
|
|
6826
|
+
koko: {
|
|
6827
|
+
EYES: "KOKO_EYES_PLACEHOLDER",
|
|
6828
|
+
PROCESSING: "KOKO_PROCESSING_PLACEHOLDER",
|
|
6829
|
+
SUCCESS: "KOKO_SUCCESS_PLACEHOLDER",
|
|
6830
|
+
ERROR: "KOKO_ERROR_PLACEHOLDER"
|
|
6831
|
+
},
|
|
6832
|
+
other: {
|
|
6833
|
+
EYES: "OTHER_EYES_PLACEHOLDER",
|
|
6834
|
+
PROCESSING: "OTHER_PROCESSING_PLACEHOLDER",
|
|
6835
|
+
SUCCESS: "OTHER_SUCCESS_PLACEHOLDER",
|
|
6836
|
+
ERROR: "OTHER_ERROR_PLACEHOLDER"
|
|
6837
|
+
}
|
|
6838
|
+
};
|
|
6839
|
+
PLATFORM_EMOJI_IDS.qq;
|
|
6840
|
+
EmojiReactionManager = class {
|
|
6841
|
+
e;
|
|
6842
|
+
emojiIds = /* @__PURE__ */ new Set();
|
|
6843
|
+
constructor(e) {
|
|
6844
|
+
this.e = e;
|
|
6845
|
+
}
|
|
6846
|
+
getPlatformEmojiId(type) {
|
|
6847
|
+
return getEmojiId(this.e, type);
|
|
6848
|
+
}
|
|
6849
|
+
normalizeEmojiId(emojiId) {
|
|
6850
|
+
return typeof emojiId === "string" && [
|
|
6851
|
+
"EYES",
|
|
6852
|
+
"PROCESSING",
|
|
6853
|
+
"SUCCESS",
|
|
6854
|
+
"ERROR"
|
|
6855
|
+
].includes(emojiId) ? this.getPlatformEmojiId(emojiId) : emojiId;
|
|
6856
|
+
}
|
|
6857
|
+
async add(emojiId) {
|
|
6858
|
+
const actualEmojiId = this.normalizeEmojiId(emojiId);
|
|
6859
|
+
const success = await setEmojiReaction(this.e, actualEmojiId, true);
|
|
6860
|
+
if (success) this.emojiIds.add(actualEmojiId);
|
|
6861
|
+
return success;
|
|
6862
|
+
}
|
|
6863
|
+
async remove(emojiId) {
|
|
6864
|
+
const actualEmojiId = this.normalizeEmojiId(emojiId);
|
|
6865
|
+
const success = await setEmojiReaction(this.e, actualEmojiId, false);
|
|
6866
|
+
if (success) this.emojiIds.delete(actualEmojiId);
|
|
6867
|
+
return success;
|
|
6868
|
+
}
|
|
6869
|
+
async replace(oldEmojiId, newEmojiId, delayMs = 2e3) {
|
|
6870
|
+
const addSuccess = await this.add(newEmojiId);
|
|
6871
|
+
await new Promise((resolve$1) => setTimeout(resolve$1, delayMs));
|
|
6872
|
+
await this.remove(oldEmojiId);
|
|
6873
|
+
return addSuccess;
|
|
6874
|
+
}
|
|
6875
|
+
async clearAll() {
|
|
6876
|
+
let count = 0;
|
|
6877
|
+
for (const emojiId of this.emojiIds) if (await setEmojiReaction(this.e, emojiId, false)) count++;
|
|
6878
|
+
this.emojiIds.clear();
|
|
6879
|
+
return count;
|
|
6880
|
+
}
|
|
6881
|
+
async keepOnly(keepEmojiIds) {
|
|
6882
|
+
const keepSet = new Set(keepEmojiIds);
|
|
6883
|
+
let removedCount = 0;
|
|
6884
|
+
for (const emojiId of this.emojiIds) if (!keepSet.has(emojiId)) {
|
|
6885
|
+
if (await this.remove(emojiId)) removedCount++;
|
|
6886
|
+
}
|
|
6887
|
+
for (const emojiId of keepEmojiIds) if (!this.emojiIds.has(emojiId)) await this.add(emojiId);
|
|
6888
|
+
return removedCount;
|
|
6889
|
+
}
|
|
6890
|
+
getCurrentEmojiIds() {
|
|
6891
|
+
return Array.from(this.emojiIds);
|
|
6892
|
+
}
|
|
6893
|
+
has(emojiId) {
|
|
6894
|
+
return this.emojiIds.has(emojiId);
|
|
6895
|
+
}
|
|
6896
|
+
count() {
|
|
6897
|
+
return this.emojiIds.size;
|
|
6898
|
+
}
|
|
6899
|
+
};
|
|
6771
6900
|
});
|
|
6772
6901
|
async function detectEncoder$1(codec) {
|
|
6773
6902
|
if (cachedEncoders$1[codec]) return cachedEncoders$1[codec];
|
|
@@ -7468,6 +7597,12 @@ var init_danmaku = __esmMin(async () => {
|
|
|
7468
7597
|
};
|
|
7469
7598
|
MAX_OUTPUT_WIDTH = 2160;
|
|
7470
7599
|
});
|
|
7600
|
+
async function fixM4sFile(inputPath, outputPath) {
|
|
7601
|
+
const result = await ffmpeg(`-y -i "${inputPath}" -c copy -movflags +faststart "${outputPath}"`);
|
|
7602
|
+
if (result.status) logger.debug(`m4s 文件修复成功: ${outputPath}`);
|
|
7603
|
+
else logger.error("m4s 文件修复失败", result);
|
|
7604
|
+
return result.status;
|
|
7605
|
+
}
|
|
7471
7606
|
async function getMediaDuration(path$1) {
|
|
7472
7607
|
const { stdout } = await ffprobe(`-v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${path$1}"`);
|
|
7473
7608
|
return parseFloat(parseFloat(stdout.trim()).toFixed(2));
|
|
@@ -7775,6 +7910,37 @@ var init_Downloader = __esmMin(() => {
|
|
|
7775
7910
|
});
|
|
7776
7911
|
const response = await this.axiosInstance(requestConfig);
|
|
7777
7912
|
clearTimeout(timeoutId);
|
|
7913
|
+
if (response.status === 416) {
|
|
7914
|
+
logger.warn("服务器返回 416,文件可能已下载完成,验证文件大小...");
|
|
7915
|
+
if (fs.existsSync(this.filepath)) {
|
|
7916
|
+
const stats = fs.statSync(this.filepath);
|
|
7917
|
+
logger.debug(`当前文件大小: ${formatBytes(stats.size)}`);
|
|
7918
|
+
if (stats.size > 1024) {
|
|
7919
|
+
logger.debug("文件大小合理,认为下载已完成");
|
|
7920
|
+
return {
|
|
7921
|
+
filepath: this.filepath,
|
|
7922
|
+
totalBytes: stats.size
|
|
7923
|
+
};
|
|
7924
|
+
} else {
|
|
7925
|
+
logger.warn("文件太小,删除并重新下载");
|
|
7926
|
+
fs.unlinkSync(this.filepath);
|
|
7927
|
+
return this.download(progressCallback, retryCount + 1);
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
}
|
|
7931
|
+
if (response.status !== 200 && response.status !== 206) {
|
|
7932
|
+
logger.error(`下载失败: HTTP ${response.status}, URL: ${this.url}`);
|
|
7933
|
+
logger.error(`响应头: ${JSON.stringify(response.headers)}`);
|
|
7934
|
+
if (response.headers["content-length"] && parseInt(response.headers["content-length"]) < 10240) {
|
|
7935
|
+
let errorBody = "";
|
|
7936
|
+
response.data.on("data", (chunk) => {
|
|
7937
|
+
errorBody += chunk.toString();
|
|
7938
|
+
});
|
|
7939
|
+
await new Promise((resolve$1) => setTimeout(resolve$1, 100));
|
|
7940
|
+
logger.error(`响应内容: ${errorBody}`);
|
|
7941
|
+
}
|
|
7942
|
+
throw new Error(`HTTP ${response.status}: ${this.url}`);
|
|
7943
|
+
}
|
|
7778
7944
|
const supportsRange = response.status === 206;
|
|
7779
7945
|
if (startByte > 0 && !supportsRange) {
|
|
7780
7946
|
logger.warn("服务器不支持断点续传,将重新下载整个文件");
|
|
@@ -7802,18 +7968,36 @@ var init_Downloader = __esmMin(() => {
|
|
|
7802
7968
|
};
|
|
7803
7969
|
const interval = totalBytes > 0 && totalBytes < 10 * 1024 * 1024 ? 1e3 : 500;
|
|
7804
7970
|
intervalId = setInterval(printProgress, interval);
|
|
7805
|
-
const
|
|
7806
|
-
downloadedBytes +=
|
|
7807
|
-
|
|
7808
|
-
|
|
7971
|
+
const counterStream = new Transform({ transform(chunk, encoding, callback) {
|
|
7972
|
+
downloadedBytes += chunk.length;
|
|
7973
|
+
callback(null, chunk);
|
|
7974
|
+
} });
|
|
7809
7975
|
if (this.throttleConfig.enabled) {
|
|
7810
7976
|
throttleStream = new ThrottleStream(this.currentSpeed);
|
|
7811
7977
|
logger.debug(`启用限速下载: ${formatBytes(this.currentSpeed)}/s`);
|
|
7812
|
-
await pipeline(response.data, throttleStream, writer);
|
|
7813
|
-
} else await pipeline(response.data, writer);
|
|
7978
|
+
await pipeline(response.data, throttleStream, counterStream, writer);
|
|
7979
|
+
} else await pipeline(response.data, counterStream, writer);
|
|
7814
7980
|
if (intervalId) clearInterval(intervalId);
|
|
7815
|
-
|
|
7816
|
-
|
|
7981
|
+
logger.debug("文件下载并写入完成");
|
|
7982
|
+
if (fs.existsSync(this.filepath)) {
|
|
7983
|
+
const actualSize = fs.statSync(this.filepath).size;
|
|
7984
|
+
const expectedSize = totalBytes > 0 ? totalBytes : downloadedBytes;
|
|
7985
|
+
if (actualSize < 1024 && expectedSize < 1024) {
|
|
7986
|
+
logger.error(`下载的文件异常小 (${formatBytes(actualSize)}),可能是错误响应`);
|
|
7987
|
+
try {
|
|
7988
|
+
const content = fs.readFileSync(this.filepath, "utf-8");
|
|
7989
|
+
logger.error(`文件内容: ${content}`);
|
|
7990
|
+
} catch {
|
|
7991
|
+
logger.error("无法读取文件内容(可能是二进制文件)");
|
|
7992
|
+
}
|
|
7993
|
+
throw new Error(`下载的文件异常小: ${formatBytes(actualSize)},可能是错误响应或链接失效`);
|
|
7994
|
+
}
|
|
7995
|
+
if (actualSize < expectedSize) {
|
|
7996
|
+
logger.warn(`文件大小不匹配: 实际 ${formatBytes(actualSize)}, 预期 ${formatBytes(expectedSize)}`);
|
|
7997
|
+
logger.warn(`差异: ${formatBytes(expectedSize - actualSize)} (${((expectedSize - actualSize) / expectedSize * 100).toFixed(2)}%)`);
|
|
7998
|
+
if ((expectedSize - actualSize) / expectedSize > .01) throw new Error(`文件下载不完整: 实际 ${formatBytes(actualSize)}, 预期 ${formatBytes(expectedSize)}`);
|
|
7999
|
+
} else logger.debug(`文件大小验证通过: ${formatBytes(actualSize)}`);
|
|
8000
|
+
}
|
|
7817
8001
|
this.consecutiveResets = 0;
|
|
7818
8002
|
return {
|
|
7819
8003
|
filepath: this.filepath,
|
|
@@ -12743,6 +12927,7 @@ var init_sender = __esmMin(() => {
|
|
|
12743
12927
|
var handleBusinessError, wrapWithErrorHandler;
|
|
12744
12928
|
var init_handler = __esmMin(async () => {
|
|
12745
12929
|
await init_module();
|
|
12930
|
+
await init_EmojiReaction();
|
|
12746
12931
|
await init_render();
|
|
12747
12932
|
await init_sender();
|
|
12748
12933
|
await init_strategy();
|
|
@@ -12783,10 +12968,23 @@ var init_handler = __esmMin(async () => {
|
|
|
12783
12968
|
}
|
|
12784
12969
|
};
|
|
12785
12970
|
wrapWithErrorHandler = (fn, options) => async (e, next) => {
|
|
12971
|
+
const emojiManager = e ? new EmojiReactionManager(e) : void 0;
|
|
12972
|
+
if (emojiManager) {
|
|
12973
|
+
await emojiManager.add("EYES");
|
|
12974
|
+
setTimeout(() => {
|
|
12975
|
+
emojiManager.add("PROCESSING").catch(() => {});
|
|
12976
|
+
}, 1500);
|
|
12977
|
+
}
|
|
12786
12978
|
const ctx = logger.runContext(async () => fn(e, next));
|
|
12787
12979
|
try {
|
|
12788
|
-
|
|
12980
|
+
const result = await ctx.run();
|
|
12981
|
+
if (emojiManager) await emojiManager.replace("PROCESSING", "SUCCESS");
|
|
12982
|
+
return result;
|
|
12789
12983
|
} catch (error) {
|
|
12984
|
+
if (emojiManager) {
|
|
12985
|
+
await emojiManager.clearAll();
|
|
12986
|
+
await emojiManager.add("ERROR");
|
|
12987
|
+
}
|
|
12790
12988
|
await new Promise((resolve$1) => setTimeout(resolve$1, 100));
|
|
12791
12989
|
if (await handleBusinessError(error, options, parseLogsToStructured(ctx.logs()), e) === "handled") return void 0;
|
|
12792
12990
|
throw error;
|
|
@@ -14212,22 +14410,6 @@ const webConfig = defineConfig({
|
|
|
14212
14410
|
description: "在解析任务开始时添加表情回应,若适配器不支持需要关闭",
|
|
14213
14411
|
defaultSelected: all.app.EmojiReply
|
|
14214
14412
|
}),
|
|
14215
|
-
components.input.number("EmojiReplyID", {
|
|
14216
|
-
label: "表情 ID",
|
|
14217
|
-
isDisabled: !all.app.EmojiReply,
|
|
14218
|
-
description: "详情查看:https://koishi.js.org/QFace/#/qqnt 中调试信息的 emojiId 字段,Emoji则是 qcid ",
|
|
14219
|
-
defaultValue: all.app.EmojiReplyID.toString(),
|
|
14220
|
-
rules: [{
|
|
14221
|
-
min: 0,
|
|
14222
|
-
max: 1145141919810
|
|
14223
|
-
}]
|
|
14224
|
-
}),
|
|
14225
|
-
components.switch.create("EmojiReplyIgnoreError", {
|
|
14226
|
-
label: "忽略表情回应失败",
|
|
14227
|
-
description: "开启后表情回应失败时不会抛出错误,程序会继续执行",
|
|
14228
|
-
defaultSelected: all.app.EmojiReplyIgnoreError,
|
|
14229
|
-
isDisabled: !all.app.EmojiReply
|
|
14230
|
-
}),
|
|
14231
14413
|
components.checkbox.group("errorLogSendTo", {
|
|
14232
14414
|
label: "错误日志",
|
|
14233
14415
|
description: "遇到错误时谁会收到错误日志。注:推送任务只可发送给主人。「第一个主人」与「所有主人」互斥。",
|
|
@@ -14878,11 +15060,6 @@ var Bilibili = class extends Base {
|
|
|
14878
15060
|
this.headers.Cookie = Config.cookies.bilibili;
|
|
14879
15061
|
}
|
|
14880
15062
|
async BilibiliHandler(iddata) {
|
|
14881
|
-
if (Config.app.EmojiReply) try {
|
|
14882
|
-
await this.e.bot.setMsgReaction(this.e.contact, this.e.messageId, Config.app.EmojiReplyID, true);
|
|
14883
|
-
} catch (err) {
|
|
14884
|
-
if (!Config.app.EmojiReplyIgnoreError) throw err;
|
|
14885
|
-
}
|
|
14886
15063
|
Config.bilibili.tip && await this.e.reply("检测到B站链接,开始解析");
|
|
14887
15064
|
switch (this.Type) {
|
|
14888
15065
|
case "one_video": {
|
|
@@ -15306,6 +15483,22 @@ var Bilibili = class extends Base {
|
|
|
15306
15483
|
shareurl: "动态分享链接",
|
|
15307
15484
|
Resolution: null
|
|
15308
15485
|
}));
|
|
15486
|
+
let staff = void 0;
|
|
15487
|
+
if (INFODATA.data.data.staff && Array.isArray(INFODATA.data.data.staff)) {
|
|
15488
|
+
const currentMid = dynamicInfo.data.data.item.modules.module_author.mid;
|
|
15489
|
+
staff = INFODATA.data.data.staff.map((member) => ({
|
|
15490
|
+
mid: member.mid,
|
|
15491
|
+
title: member.title,
|
|
15492
|
+
name: member.name,
|
|
15493
|
+
face: member.face,
|
|
15494
|
+
follower: member.follower
|
|
15495
|
+
}));
|
|
15496
|
+
const currentUserIndex = staff.findIndex((member) => member.mid === currentMid);
|
|
15497
|
+
if (currentUserIndex > 0) {
|
|
15498
|
+
const currentUser = staff.splice(currentUserIndex, 1)[0];
|
|
15499
|
+
staff.unshift(currentUser);
|
|
15500
|
+
}
|
|
15501
|
+
}
|
|
15309
15502
|
img$1 = await Render("bilibili/dynamic/DYNAMIC_TYPE_AV", {
|
|
15310
15503
|
image_url: INFODATA.data.data.pic,
|
|
15311
15504
|
text: br$3(INFODATA.data.data.title),
|
|
@@ -15317,7 +15510,7 @@ var Bilibili = class extends Base {
|
|
|
15317
15510
|
coin: Count(dycrad.stat.coin),
|
|
15318
15511
|
duration_text: dynamicInfo.data.data.item.modules.module_dynamic.major.archive.duration_text,
|
|
15319
15512
|
create_time: TimeFormatter.toDateTime(INFODATA.data.data.ctime),
|
|
15320
|
-
avatar_url:
|
|
15513
|
+
avatar_url: userProfileData.data.data.card.face,
|
|
15321
15514
|
frame: dynamicInfo.data.data.item.modules.module_author.pendant.image,
|
|
15322
15515
|
share_url: "https://www.bilibili.com/video/" + bvid,
|
|
15323
15516
|
username: checkvip$2(userProfileData.data.data.card),
|
|
@@ -15327,7 +15520,8 @@ var Bilibili = class extends Base {
|
|
|
15327
15520
|
following_count: Count(userProfileData.data.data.card.attention),
|
|
15328
15521
|
render_time: TimeFormatter.now(),
|
|
15329
15522
|
dynamicTYPE: "视频动态",
|
|
15330
|
-
dynamic_id: dynamicInfo.data.data.item.id_str
|
|
15523
|
+
dynamic_id: dynamicInfo.data.data.item.id_str,
|
|
15524
|
+
staff
|
|
15331
15525
|
});
|
|
15332
15526
|
this.e.reply(img$1);
|
|
15333
15527
|
}
|
|
@@ -15450,15 +15644,39 @@ var Bilibili = class extends Base {
|
|
|
15450
15644
|
switch (this.islogin) {
|
|
15451
15645
|
case true: {
|
|
15452
15646
|
logger.debug("视频 URL:", this.Type === "one_video" ? playUrlData.data?.dash?.video[0].base_url : playUrlData.result.dash.video[0].base_url);
|
|
15453
|
-
const
|
|
15454
|
-
|
|
15455
|
-
|
|
15647
|
+
const downloadHeaders = {
|
|
15648
|
+
...this.headers,
|
|
15649
|
+
Referer: "https://www.bilibili.com"
|
|
15650
|
+
};
|
|
15651
|
+
const bmp4Raw = await downloadFile(this.Type === "one_video" ? playUrlData.data?.dash?.video[0].base_url : playUrlData.result.dash.video[0].base_url, {
|
|
15652
|
+
title: `Bil_V_${this.Type === "one_video" ? infoData && infoData.data.bvid : infoData && infoData.result.season_id}.m4s`,
|
|
15653
|
+
headers: downloadHeaders
|
|
15456
15654
|
});
|
|
15655
|
+
const videoPath = Common.tempDri.video + `Bil_V_${this.Type === "one_video" ? infoData && infoData.data.bvid : infoData && infoData.result.season_id}.mp4`;
|
|
15656
|
+
if (!await fixM4sFile(bmp4Raw.filepath, videoPath)) {
|
|
15657
|
+
logger.error("视频文件修复失败");
|
|
15658
|
+
return false;
|
|
15659
|
+
}
|
|
15660
|
+
await Common.removeFile(bmp4Raw.filepath, true);
|
|
15457
15661
|
logger.debug("音频 URL:", this.Type === "one_video" ? playUrlData.data?.dash?.audio[0].base_url : playUrlData.result.dash.audio[0].base_url);
|
|
15458
|
-
const
|
|
15459
|
-
title: `Bil_A_${this.Type === "one_video" ? infoData && infoData.data.bvid : infoData && infoData.result.season_id}.
|
|
15460
|
-
headers:
|
|
15662
|
+
const bmp3Raw = await downloadFile(this.Type === "one_video" ? playUrlData.data?.dash?.audio[0].base_url : playUrlData.result.dash.audio[0].base_url, {
|
|
15663
|
+
title: `Bil_A_${this.Type === "one_video" ? infoData && infoData.data.bvid : infoData && infoData.result.season_id}.m4s`,
|
|
15664
|
+
headers: downloadHeaders
|
|
15461
15665
|
});
|
|
15666
|
+
const audioPath = Common.tempDri.video + `Bil_A_${this.Type === "one_video" ? infoData && infoData.data.bvid : infoData && infoData.result.season_id}.m4a`;
|
|
15667
|
+
if (!await fixM4sFile(bmp3Raw.filepath, audioPath)) {
|
|
15668
|
+
logger.error("音频文件修复失败");
|
|
15669
|
+
return false;
|
|
15670
|
+
}
|
|
15671
|
+
await Common.removeFile(bmp3Raw.filepath, true);
|
|
15672
|
+
const bmp4 = {
|
|
15673
|
+
filepath: videoPath,
|
|
15674
|
+
totalBytes: bmp4Raw.totalBytes
|
|
15675
|
+
};
|
|
15676
|
+
const bmp3 = {
|
|
15677
|
+
filepath: audioPath,
|
|
15678
|
+
totalBytes: bmp3Raw.totalBytes
|
|
15679
|
+
};
|
|
15462
15680
|
if (bmp4.filepath && bmp3.filepath) {
|
|
15463
15681
|
const hasDanmaku = (this.forceBurnDanmaku || Config.bilibili.burnDanmaku) && danmakuList.length > 0;
|
|
15464
15682
|
const resultPath = Common.tempDri.video + `Bil_Result_${this.Type === "one_video" ? infoData && infoData.data.bvid : infoData && infoData.result.season_id}.mp4`;
|
|
@@ -16300,7 +16518,7 @@ await init_amagiClient();
|
|
|
16300
16518
|
await init_Config();
|
|
16301
16519
|
var bilibiliBaseHeaders = {
|
|
16302
16520
|
...BASE_HEADERS,
|
|
16303
|
-
Referer: "https://
|
|
16521
|
+
Referer: "https://www.bilibili.com",
|
|
16304
16522
|
Cookie: Config.cookies.bilibili
|
|
16305
16523
|
};
|
|
16306
16524
|
var Bilibilipush = class extends Base {
|
|
@@ -16447,6 +16665,22 @@ var Bilibilipush = class extends Base {
|
|
|
16447
16665
|
send_video = false;
|
|
16448
16666
|
logger.debug(`UP主:${INFODATA.data.data.owner.name} 的该动态类型为${logger.yellow("番剧或影视")},默认跳过不下载,直达:${logger.green(INFODATA.data.data.redirect_url)}`);
|
|
16449
16667
|
}
|
|
16668
|
+
let staff = void 0;
|
|
16669
|
+
if (INFODATA.data.data.staff && Array.isArray(INFODATA.data.data.staff)) {
|
|
16670
|
+
const currentMid = data$1[dynamicId].host_mid;
|
|
16671
|
+
staff = INFODATA.data.data.staff.map((member) => ({
|
|
16672
|
+
mid: member.mid,
|
|
16673
|
+
title: member.title,
|
|
16674
|
+
name: member.name,
|
|
16675
|
+
face: member.face,
|
|
16676
|
+
follower: member.follower
|
|
16677
|
+
}));
|
|
16678
|
+
const currentUserIndex = staff.findIndex((member) => member.mid === currentMid);
|
|
16679
|
+
if (currentUserIndex > 0) {
|
|
16680
|
+
const currentUser = staff.splice(currentUserIndex, 1)[0];
|
|
16681
|
+
staff.unshift(currentUser);
|
|
16682
|
+
}
|
|
16683
|
+
}
|
|
16450
16684
|
img$2 = await Render("bilibili/dynamic/DYNAMIC_TYPE_AV", {
|
|
16451
16685
|
image_url: INFODATA.data.data.pic,
|
|
16452
16686
|
text: br$1(INFODATA.data.data.title),
|
|
@@ -16458,7 +16692,7 @@ var Bilibilipush = class extends Base {
|
|
|
16458
16692
|
coin: Count(dycrad.stat.coin),
|
|
16459
16693
|
duration_text: data$1[dynamicId].Dynamic_Data.modules.module_dynamic.major?.archive?.duration_text ?? "0:00",
|
|
16460
16694
|
create_time: TimeFormatter.toDateTime(data$1[dynamicId].Dynamic_Data.modules.module_author.pub_ts),
|
|
16461
|
-
avatar_url:
|
|
16695
|
+
avatar_url: userINFO.data.data.card.face,
|
|
16462
16696
|
frame: data$1[dynamicId].Dynamic_Data.modules.module_author.pendant.image,
|
|
16463
16697
|
share_url: "https://www.bilibili.com/video/" + bvid,
|
|
16464
16698
|
username: checkvip(userINFO.data.data.card),
|
|
@@ -16468,7 +16702,8 @@ var Bilibilipush = class extends Base {
|
|
|
16468
16702
|
following_count: Count(userINFO.data.data.card.attention),
|
|
16469
16703
|
render_time: TimeFormatter.now(),
|
|
16470
16704
|
dynamicTYPE: "视频动态推送",
|
|
16471
|
-
dynamic_id: dynamicId
|
|
16705
|
+
dynamic_id: dynamicId,
|
|
16706
|
+
staff
|
|
16472
16707
|
});
|
|
16473
16708
|
}
|
|
16474
16709
|
break;
|
|
@@ -17158,11 +17393,6 @@ var DouYin = class extends Base {
|
|
|
17158
17393
|
this.hasProcessedLiveImage = false;
|
|
17159
17394
|
}
|
|
17160
17395
|
async DouyinHandler(data$1) {
|
|
17161
|
-
if (Config.app.EmojiReply && !this.e.isPrivate) try {
|
|
17162
|
-
await this.e.bot.setMsgReaction(this.e.contact, this.e.messageId, Config.app.EmojiReplyID, true);
|
|
17163
|
-
} catch (err) {
|
|
17164
|
-
if (!Config.app.EmojiReplyIgnoreError) throw err;
|
|
17165
|
-
}
|
|
17166
17396
|
if (Config.douyin.tip) this.e.reply("检测到抖音链接,开始解析");
|
|
17167
17397
|
switch (this.type) {
|
|
17168
17398
|
case "one_work": {
|
|
@@ -18881,11 +19111,6 @@ var Kuaishou = class extends Base {
|
|
|
18881
19111
|
this.type = iddata?.type;
|
|
18882
19112
|
}
|
|
18883
19113
|
async KuaishouHandler(data$1) {
|
|
18884
|
-
if (Config.app.EmojiReply) try {
|
|
18885
|
-
await this.e.bot.setMsgReaction(this.e.contact, this.e.messageId, Config.app.EmojiReplyID, true);
|
|
18886
|
-
} catch (err) {
|
|
18887
|
-
if (!Config.app.EmojiReplyIgnoreError) throw err;
|
|
18888
|
-
}
|
|
18889
19114
|
if (data$1.VideoData.data.data.visionVideoDetail.status !== 1) {
|
|
18890
19115
|
await this.e.reply("不支持解析的视频");
|
|
18891
19116
|
return true;
|
|
@@ -19962,11 +20187,6 @@ var Xiaohongshu = class extends Base {
|
|
|
19962
20187
|
this.type = iddata?.type;
|
|
19963
20188
|
}
|
|
19964
20189
|
async XiaohongshuHandler(data$1) {
|
|
19965
|
-
if (Config.app.EmojiReply && !this.e.isPrivate) try {
|
|
19966
|
-
await this.e.bot.setMsgReaction(this.e.contact, this.e.messageId, Config.app.EmojiReplyID, true);
|
|
19967
|
-
} catch (err) {
|
|
19968
|
-
if (!Config.app.EmojiReplyIgnoreError) throw err;
|
|
19969
|
-
}
|
|
19970
20190
|
Config.xiaohongshu.tip && await this.e.reply("检测到小红书链接,开始解析");
|
|
19971
20191
|
const NoteData = await this.amagi.xiaohongshu.fetcher.fetchNoteDetail({
|
|
19972
20192
|
typeMode: "strict",
|