@iflyrpa/actions 4.1.0-beta.5 → 4.1.0
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/dist/actions/searchAccountInfo/index.d.ts +1 -1
- package/dist/actions/shipinhaoPublishVideo/index.d.ts +45 -1
- package/dist/actions/shipinhaoPublishVideo/payload.d.ts +70 -0
- package/dist/actions/shipinhaoPublishVideo/uploader.d.ts +19 -0
- package/dist/actions/shipinhaoPublishVideo/videoMeta.d.ts +43 -5
- package/dist/actions/shipinhaoPublishVideo/videoValidator.d.ts +4 -2
- package/dist/bundle.js +886 -310
- package/dist/bundle.js.map +1 -1
- package/dist/index.js +884 -308
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +884 -308
- package/dist/index.mjs.map +1 -1
- package/dist/utils/feishuAlarm.d.ts +4 -1
- package/dist/utils/http.d.ts +16 -0
- package/dist/utils/shipinhao/utils.d.ts +10 -0
- package/package.json +2 -2
package/dist/bundle.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*! For license information please see bundle.js.LICENSE.txt */
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bf64112a-57bc-5eae-9ede-8d23fc55671f")}catch(e){}}();
|
|
4
4
|
var __webpack_modules__ = {
|
|
5
5
|
"../../node_modules/.pnpm/agent-base@7.1.4/node_modules/agent-base/dist/helpers.js": function(__unused_webpack_module, exports1, __webpack_require__) {
|
|
6
6
|
"use strict";
|
|
@@ -12491,9 +12491,11 @@ var __webpack_exports__ = {};
|
|
|
12491
12491
|
origin: ()=>utils_origin
|
|
12492
12492
|
});
|
|
12493
12493
|
var package_namespaceObject = {
|
|
12494
|
-
i8: "0.
|
|
12494
|
+
i8: "0.2.0"
|
|
12495
|
+
};
|
|
12496
|
+
var package_namespaceObject_0 = {
|
|
12497
|
+
i8: "4.1.0"
|
|
12495
12498
|
};
|
|
12496
|
-
var package_namespaceObject_0 = JSON.parse('{"i8":"4.1.0-beta.5"}');
|
|
12497
12499
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
12498
12500
|
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
12499
12501
|
const external_node_http_namespaceObject = require("node:http");
|
|
@@ -12584,7 +12586,7 @@ var __webpack_exports__ = {};
|
|
|
12584
12586
|
fileStream.on("error", (err)=>{
|
|
12585
12587
|
reject({
|
|
12586
12588
|
code: 500,
|
|
12587
|
-
message:
|
|
12589
|
+
message: "图片写入失败,请检查磁盘空间"
|
|
12588
12590
|
});
|
|
12589
12591
|
});
|
|
12590
12592
|
} else {
|
|
@@ -27073,6 +27075,11 @@ var __webpack_exports__ = {};
|
|
|
27073
27075
|
const RPA_ERROR_WEBHOOK_URL = "https://open.xfchat.iflytek.com/open-apis/bot/v2/hook/d202c0dc-5af5-40bc-83ed-abc677caa4a5";
|
|
27074
27076
|
const ALARM_THROTTLE_MS = 60000;
|
|
27075
27077
|
const lastSentAt = new Map();
|
|
27078
|
+
const THROTTLE_MAP_MAX_KEYS = 500;
|
|
27079
|
+
const pruneThrottleMap = (now)=>{
|
|
27080
|
+
if (lastSentAt.size < THROTTLE_MAP_MAX_KEYS) return;
|
|
27081
|
+
for (const [key, at] of lastSentAt)if (now - at >= ALARM_THROTTLE_MS) lastSentAt.delete(key);
|
|
27082
|
+
};
|
|
27076
27083
|
const postFeishuWebhook = (webhookUrl, payload)=>lib_axios.post(webhookUrl, payload, {
|
|
27077
27084
|
headers: {
|
|
27078
27085
|
"Content-Type": "application/json"
|
|
@@ -27150,10 +27157,11 @@ var __webpack_exports__ = {};
|
|
|
27150
27157
|
};
|
|
27151
27158
|
const reportFeishuAlarm = (report)=>{
|
|
27152
27159
|
try {
|
|
27153
|
-
const key = `${report.platform}|${report.source}|${report.errorType}|${report.code ?? ""}`;
|
|
27160
|
+
const key = `${report.platform}|${report.source}|${report.stage}|${report.errorType}|${report.code ?? ""}`;
|
|
27154
27161
|
const now = Date.now();
|
|
27155
27162
|
const last = lastSentAt.get(key);
|
|
27156
27163
|
if (last && now - last < ALARM_THROTTLE_MS) return;
|
|
27164
|
+
pruneThrottleMap(now);
|
|
27157
27165
|
lastSentAt.set(key, now);
|
|
27158
27166
|
postFeishuWebhook(RPA_ERROR_WEBHOOK_URL, buildFeishuPostMessage(report)).catch(()=>{});
|
|
27159
27167
|
} catch {}
|
|
@@ -27300,6 +27308,19 @@ var __webpack_exports__ = {};
|
|
|
27300
27308
|
461,
|
|
27301
27309
|
471
|
|
27302
27310
|
]);
|
|
27311
|
+
function isLocalAddress(url) {
|
|
27312
|
+
let hostname;
|
|
27313
|
+
try {
|
|
27314
|
+
hostname = new URL(url).hostname.toLowerCase();
|
|
27315
|
+
} catch {
|
|
27316
|
+
return false;
|
|
27317
|
+
}
|
|
27318
|
+
if ("localhost" === hostname || "::1" === hostname || "[::1]" === hostname) return true;
|
|
27319
|
+
if (hostname.endsWith(".localhost") || hostname.endsWith(".local")) return true;
|
|
27320
|
+
if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) return true;
|
|
27321
|
+
if ("0.0.0.0" === hostname) return true;
|
|
27322
|
+
return false;
|
|
27323
|
+
}
|
|
27303
27324
|
const HTTP_STATUS_MESSAGE = {
|
|
27304
27325
|
400: "请求参数错误,请检查参数格式是否正确!",
|
|
27305
27326
|
401: "登录状态已失效,请重新登录后重试!",
|
|
@@ -27336,7 +27357,14 @@ var __webpack_exports__ = {};
|
|
|
27336
27357
|
};
|
|
27337
27358
|
class Http {
|
|
27338
27359
|
static handleApiError(error) {
|
|
27339
|
-
if (error && "object" == typeof error && "code" in error && "message" in error)
|
|
27360
|
+
if (error && "object" == typeof error && "code" in error && "message" in error) {
|
|
27361
|
+
const resp = error;
|
|
27362
|
+
if ("string" != typeof resp.message || !resp.message.trim()) return {
|
|
27363
|
+
...resp,
|
|
27364
|
+
message: USER_MESSAGE.SYSTEM_ERROR
|
|
27365
|
+
};
|
|
27366
|
+
return resp;
|
|
27367
|
+
}
|
|
27340
27368
|
return {
|
|
27341
27369
|
code: 500,
|
|
27342
27370
|
message: USER_MESSAGE.SYSTEM_ERROR,
|
|
@@ -27474,25 +27502,47 @@ var __webpack_exports__ = {};
|
|
|
27474
27502
|
errorResponse.message = message;
|
|
27475
27503
|
}
|
|
27476
27504
|
if (error.message.includes("Proxy connection ended")) errorResponse.message = "所在区域代理连接超时,请更换区域或稍后重试!";
|
|
27477
|
-
|
|
27478
|
-
|
|
27479
|
-
|
|
27480
|
-
|
|
27481
|
-
|
|
27482
|
-
stage: `${(error.config?.method || "get").toUpperCase()} ${error.config?.url || "-"}`,
|
|
27483
|
-
errorType: status ? `HTTP_${status}` : error.code || "NETWORK_ERROR",
|
|
27484
|
-
code: errorResponse.code,
|
|
27485
|
-
msg: errorResponse.message,
|
|
27486
|
-
url: error.config?.url,
|
|
27487
|
-
title: "RPA接口异常"
|
|
27488
|
-
});
|
|
27505
|
+
errorResponse.extra = {
|
|
27506
|
+
...errorResponse.extra,
|
|
27507
|
+
alarmStatus: error.response?.status,
|
|
27508
|
+
alarmErrorCode: error.code
|
|
27509
|
+
};
|
|
27489
27510
|
throw errorResponse;
|
|
27490
27511
|
});
|
|
27491
27512
|
}
|
|
27513
|
+
reportRequestFailure(config, error, attempts) {
|
|
27514
|
+
const status = error.extra?.alarmStatus;
|
|
27515
|
+
const axiosCode = error.extra?.alarmErrorCode;
|
|
27516
|
+
const method = (config.method || "get").toUpperCase();
|
|
27517
|
+
const baseURL = config.baseURL || this.apiClient.defaults.baseURL || "";
|
|
27518
|
+
const fullUrl = config.url ? /^https?:\/\//.test(config.url) ? config.url : `${baseURL.replace(/\/$/, "")}${config.url}` : baseURL;
|
|
27519
|
+
if (!fullUrl) {
|
|
27520
|
+
this.logger?.debug(`[告警跳过] 请求失败但无 URL,不上报: ${error.message}`);
|
|
27521
|
+
return;
|
|
27522
|
+
}
|
|
27523
|
+
if (isLocalAddress(fullUrl)) {
|
|
27524
|
+
this.logger?.debug(`[告警跳过] 本机地址不上报: ${fullUrl}`);
|
|
27525
|
+
return;
|
|
27526
|
+
}
|
|
27527
|
+
const rawMsg = "string" == typeof error.message && error.message.trim() ? error.message : "";
|
|
27528
|
+
const baseMsg = rawMsg || `请求失败(无错误文案,code=${error.code ?? "unknown"})`;
|
|
27529
|
+
const retriedSuffix = attempts > 0 ? `(已重试${attempts}次仍失败)` : "";
|
|
27530
|
+
reportFeishuAlarm({
|
|
27531
|
+
level: status && ALARM_STATUS.has(status) ? "alarm" : "warning",
|
|
27532
|
+
platform: "@iflyrpa/playwright",
|
|
27533
|
+
source: "http",
|
|
27534
|
+
stage: `${method} ${fullUrl}`,
|
|
27535
|
+
errorType: status ? `HTTP_${status}` : axiosCode || "NETWORK_ERROR",
|
|
27536
|
+
code: error.code,
|
|
27537
|
+
msg: `${baseMsg}${retriedSuffix}`,
|
|
27538
|
+
url: fullUrl,
|
|
27539
|
+
title: "RPA接口异常"
|
|
27540
|
+
});
|
|
27541
|
+
}
|
|
27492
27542
|
async api(config, options) {
|
|
27493
27543
|
const retries = options?.retries ?? 0;
|
|
27494
27544
|
const retryDelay = options?.retryDelay ?? 500;
|
|
27495
|
-
const reqTimeout = options?.timeout ??
|
|
27545
|
+
const reqTimeout = options?.timeout ?? 60000;
|
|
27496
27546
|
const externalSignal = options?.signal;
|
|
27497
27547
|
let agent;
|
|
27498
27548
|
const sessionRt = async (Rtimes)=>{
|
|
@@ -27533,10 +27583,12 @@ var __webpack_exports__ = {};
|
|
|
27533
27583
|
].includes(handledError.code);
|
|
27534
27584
|
if (Rtimes < retries && isRetry) {
|
|
27535
27585
|
const url = config.url || "";
|
|
27536
|
-
|
|
27537
|
-
|
|
27586
|
+
const backoff = Math.min(retryDelay * 2 ** Rtimes, 5000);
|
|
27587
|
+
this.logger?.warn(`进入第${Rtimes + 1}次重试!错误码: ${handledError.code}, 等待: ${backoff}ms, 请求地址: ${url}`);
|
|
27588
|
+
await new Promise((resolve)=>setTimeout(resolve, backoff));
|
|
27538
27589
|
return sessionRt(Rtimes + 1);
|
|
27539
27590
|
}
|
|
27591
|
+
this.reportRequestFailure(config, handledError, Rtimes);
|
|
27540
27592
|
return Promise.reject(handledError);
|
|
27541
27593
|
}
|
|
27542
27594
|
};
|
|
@@ -32227,6 +32279,14 @@ var __webpack_exports__ = {};
|
|
|
32227
32279
|
};
|
|
32228
32280
|
return new schemas_ZodObject(def);
|
|
32229
32281
|
}
|
|
32282
|
+
function looseObject(shape, params) {
|
|
32283
|
+
return new schemas_ZodObject({
|
|
32284
|
+
type: "object",
|
|
32285
|
+
shape,
|
|
32286
|
+
catchall: schemas_unknown(),
|
|
32287
|
+
...util_normalizeParams(params)
|
|
32288
|
+
});
|
|
32289
|
+
}
|
|
32230
32290
|
const schemas_ZodUnion = /*@__PURE__*/ core_$constructor("ZodUnion", (inst, def)=>{
|
|
32231
32291
|
schemas_$ZodUnion.init(inst, def);
|
|
32232
32292
|
schemas_ZodType.init(inst, def);
|
|
@@ -32919,7 +32979,7 @@ var __webpack_exports__ = {};
|
|
|
32919
32979
|
".png"
|
|
32920
32980
|
].includes(ext)) throw {
|
|
32921
32981
|
code: 414,
|
|
32922
|
-
message:
|
|
32982
|
+
message: "图片格式不支持,百家号仅支持 jpg、png 格式,请转换后重试。",
|
|
32923
32983
|
data: ""
|
|
32924
32984
|
};
|
|
32925
32985
|
const image = await downloadImage(url, external_node_path_default().join(tmpCachePath, fileName));
|
|
@@ -33600,7 +33660,8 @@ var __webpack_exports__ = {};
|
|
|
33600
33660
|
},
|
|
33601
33661
|
_task.logger,
|
|
33602
33662
|
params.proxyLoc,
|
|
33603
|
-
params.accountId
|
|
33663
|
+
params.accountId,
|
|
33664
|
+
"xiaohongshu"
|
|
33604
33665
|
];
|
|
33605
33666
|
const http = new Http(...args);
|
|
33606
33667
|
const fans = {
|
|
@@ -33614,8 +33675,8 @@ var __webpack_exports__ = {};
|
|
|
33614
33675
|
url: "https://creator.xiaohongshu.com/api/galaxy/creator/home/personal_info"
|
|
33615
33676
|
}, {
|
|
33616
33677
|
retries: 3,
|
|
33617
|
-
retryDelay:
|
|
33618
|
-
timeout:
|
|
33678
|
+
retryDelay: 300,
|
|
33679
|
+
timeout: 30000
|
|
33619
33680
|
});
|
|
33620
33681
|
fans.fans_count = Number(res.data.fans_count);
|
|
33621
33682
|
fans.digg_count = Number(res.data.faved_count);
|
|
@@ -34752,7 +34813,8 @@ var __webpack_exports__ = {};
|
|
|
34752
34813
|
},
|
|
34753
34814
|
_task.logger,
|
|
34754
34815
|
params.proxyLoc,
|
|
34755
|
-
params.accountId
|
|
34816
|
+
params.accountId,
|
|
34817
|
+
"xiaohongshu"
|
|
34756
34818
|
];
|
|
34757
34819
|
const http = new Http(...args);
|
|
34758
34820
|
http.addResponseInterceptor((response)=>{
|
|
@@ -34800,8 +34862,8 @@ var __webpack_exports__ = {};
|
|
|
34800
34862
|
headers: loginBaseXsHeader
|
|
34801
34863
|
}, {
|
|
34802
34864
|
retries: 3,
|
|
34803
|
-
retryDelay:
|
|
34804
|
-
timeout:
|
|
34865
|
+
retryDelay: 300,
|
|
34866
|
+
timeout: 30000
|
|
34805
34867
|
}).catch((e)=>{
|
|
34806
34868
|
const clientTimestamp = Date.now();
|
|
34807
34869
|
const serverDate = e?.extra?.serverDate;
|
|
@@ -34833,8 +34895,8 @@ var __webpack_exports__ = {};
|
|
|
34833
34895
|
headers: webSessionXsHeader
|
|
34834
34896
|
}, {
|
|
34835
34897
|
retries: 3,
|
|
34836
|
-
retryDelay:
|
|
34837
|
-
timeout:
|
|
34898
|
+
retryDelay: 300,
|
|
34899
|
+
timeout: 30000
|
|
34838
34900
|
});
|
|
34839
34901
|
const [baseInfo, web_session] = await Promise.all([
|
|
34840
34902
|
_baseInfo,
|
|
@@ -34926,6 +34988,10 @@ var __webpack_exports__ = {};
|
|
|
34926
34988
|
};
|
|
34927
34989
|
return success(data, message);
|
|
34928
34990
|
};
|
|
34991
|
+
const extractEncFileKey = (downloadUrl)=>{
|
|
34992
|
+
if (!downloadUrl) return "";
|
|
34993
|
+
return downloadUrl.split("encfilekey=")[1]?.split("&")[0] || "";
|
|
34994
|
+
};
|
|
34929
34995
|
const rid = ()=>`${Math.floor(Date.now() / 1e3).toString(16)}-${[
|
|
34930
34996
|
...Array(8)
|
|
34931
34997
|
].map(()=>Math.floor(16 * Math.random()).toString(16)).join("")}`;
|
|
@@ -40571,7 +40637,8 @@ var __webpack_exports__ = {};
|
|
|
40571
40637
|
},
|
|
40572
40638
|
_task.logger,
|
|
40573
40639
|
params.proxyLoc,
|
|
40574
|
-
params.accountId
|
|
40640
|
+
params.accountId,
|
|
40641
|
+
"xiaohongshu"
|
|
40575
40642
|
];
|
|
40576
40643
|
const http = new Http(...args);
|
|
40577
40644
|
let unreadCount = {
|
|
@@ -40600,8 +40667,8 @@ var __webpack_exports__ = {};
|
|
|
40600
40667
|
headers: xsHeader
|
|
40601
40668
|
}, {
|
|
40602
40669
|
retries: 3,
|
|
40603
|
-
retryDelay:
|
|
40604
|
-
timeout:
|
|
40670
|
+
retryDelay: 300,
|
|
40671
|
+
timeout: 30000
|
|
40605
40672
|
});
|
|
40606
40673
|
const isSuccess = 0 === res.code;
|
|
40607
40674
|
if (isSuccess) unreadCount = res.data;
|
|
@@ -41014,7 +41081,8 @@ var __webpack_exports__ = {};
|
|
|
41014
41081
|
},
|
|
41015
41082
|
_task.logger,
|
|
41016
41083
|
params.proxyLoc,
|
|
41017
|
-
params.accountId
|
|
41084
|
+
params.accountId,
|
|
41085
|
+
"xiaohongshu"
|
|
41018
41086
|
];
|
|
41019
41087
|
const http = new Http(...args);
|
|
41020
41088
|
const xsEncrypt = new Xhshow();
|
|
@@ -41030,8 +41098,8 @@ var __webpack_exports__ = {};
|
|
|
41030
41098
|
url: "https://creator.xiaohongshu.com/api/galaxy/creator/home/personal_info"
|
|
41031
41099
|
}, {
|
|
41032
41100
|
retries: 3,
|
|
41033
|
-
retryDelay:
|
|
41034
|
-
timeout:
|
|
41101
|
+
retryDelay: 300,
|
|
41102
|
+
timeout: 30000
|
|
41035
41103
|
}),
|
|
41036
41104
|
http.api({
|
|
41037
41105
|
method: "get",
|
|
@@ -41040,8 +41108,8 @@ var __webpack_exports__ = {};
|
|
|
41040
41108
|
headers: sevenDataXsHeader
|
|
41041
41109
|
}, {
|
|
41042
41110
|
retries: 3,
|
|
41043
|
-
retryDelay:
|
|
41044
|
-
timeout:
|
|
41111
|
+
retryDelay: 300,
|
|
41112
|
+
timeout: 30000
|
|
41045
41113
|
})
|
|
41046
41114
|
]);
|
|
41047
41115
|
const xhsData = {
|
|
@@ -43903,7 +43971,7 @@ var __webpack_exports__ = {};
|
|
|
43903
43971
|
name: params.music.name,
|
|
43904
43972
|
artist: params.music.authorName,
|
|
43905
43973
|
mediaStreamingUrl: params.music.url,
|
|
43906
|
-
docType: params.music.raw.
|
|
43974
|
+
docType: 2 === params.music.raw.bgmSource ? 0 : 1
|
|
43907
43975
|
},
|
|
43908
43976
|
groupId: params.music.id,
|
|
43909
43977
|
hasBgm: 1,
|
|
@@ -44080,7 +44148,7 @@ var __webpack_exports__ = {};
|
|
|
44080
44148
|
const resultMsg = publishResult.data?.baseResp?.errmsg ?? publishResult.errMsg;
|
|
44081
44149
|
if (0 === resultCode) {
|
|
44082
44150
|
task.logger.info("[shipinhaoPublish] 发布成功");
|
|
44083
|
-
const publishId = uploadedImages[0]?.thumbUrl
|
|
44151
|
+
const publishId = extractEncFileKey(uploadedImages[0]?.thumbUrl);
|
|
44084
44152
|
await updateTaskState?.({
|
|
44085
44153
|
state: types_TaskState.SUCCESS,
|
|
44086
44154
|
result: {
|
|
@@ -44872,13 +44940,110 @@ var __webpack_exports__ = {};
|
|
|
44872
44940
|
pictureFileType
|
|
44873
44941
|
};
|
|
44874
44942
|
}
|
|
44943
|
+
const MENTION_TEXT_SUFFIX = "\u0020";
|
|
44944
|
+
const MENTION_XML_SUFFIX = "\u2005";
|
|
44945
|
+
function payload_buildDescription(params) {
|
|
44946
|
+
let description = params.description || "";
|
|
44947
|
+
for (const topic of params.topics || [])description += `#${topic}`;
|
|
44948
|
+
for (const user of params.mentionedUsers || [])description += `@${user.nickname}${MENTION_TEXT_SUFFIX}`;
|
|
44949
|
+
return description;
|
|
44950
|
+
}
|
|
44951
|
+
function buildMentionedUser(mentionedUsers) {
|
|
44952
|
+
return (mentionedUsers || []).map((user)=>({
|
|
44953
|
+
nickname: `${user.nickname}${MENTION_TEXT_SUFFIX}`
|
|
44954
|
+
}));
|
|
44955
|
+
}
|
|
44956
|
+
function payload_buildTopicXml(params) {
|
|
44957
|
+
const values = [];
|
|
44958
|
+
let atIndex = null;
|
|
44959
|
+
if (params.description) values.push(`<![CDATA[${params.description}]]>`);
|
|
44960
|
+
for (const topic of params.topics || [])values.push(`<topic><![CDATA[#${topic}#]]></topic>`);
|
|
44961
|
+
for (const user of params.mentionedUsers || []){
|
|
44962
|
+
if (null === atIndex) atIndex = values.length;
|
|
44963
|
+
values.push(`<![CDATA[@${user.nickname}${MENTION_XML_SUFFIX}]]>`);
|
|
44964
|
+
}
|
|
44965
|
+
let xml = "<finder>";
|
|
44966
|
+
xml += "<version>1</version>";
|
|
44967
|
+
xml += `<valuecount>${values.length}</valuecount>`;
|
|
44968
|
+
xml += `<style><at>${atIndex ?? ""}</at></style>`;
|
|
44969
|
+
values.forEach((value, index)=>{
|
|
44970
|
+
xml += `<value${index}>${value}</value${index}>`;
|
|
44971
|
+
});
|
|
44972
|
+
xml += "</finder>";
|
|
44973
|
+
return xml;
|
|
44974
|
+
}
|
|
44975
|
+
function payload_buildLocation(location) {
|
|
44976
|
+
if (!location) return {
|
|
44977
|
+
latitude: 0,
|
|
44978
|
+
longitude: 0,
|
|
44979
|
+
city: "",
|
|
44980
|
+
poiName: "",
|
|
44981
|
+
address: "",
|
|
44982
|
+
poiClassifyId: ""
|
|
44983
|
+
};
|
|
44984
|
+
return {
|
|
44985
|
+
latitude: location.latitude,
|
|
44986
|
+
longitude: location.longitude,
|
|
44987
|
+
city: location.city,
|
|
44988
|
+
poiName: location.poiName || "",
|
|
44989
|
+
address: location.address || "",
|
|
44990
|
+
poiClassifyId: location.poiClassifyId || ""
|
|
44991
|
+
};
|
|
44992
|
+
}
|
|
44993
|
+
function buildTopic(params) {
|
|
44994
|
+
const topic = {
|
|
44995
|
+
finderTopicInfo: payload_buildTopicXml(params)
|
|
44996
|
+
};
|
|
44997
|
+
if (params.collection) {
|
|
44998
|
+
topic.collectionId = params.collection.collectionId;
|
|
44999
|
+
topic.collectionName = params.collection.collectionName;
|
|
45000
|
+
}
|
|
45001
|
+
return topic;
|
|
45002
|
+
}
|
|
45003
|
+
function buildEvent(event) {
|
|
45004
|
+
if (!event) return {};
|
|
45005
|
+
return {
|
|
45006
|
+
eventTopicId: event.eventTopicId,
|
|
45007
|
+
eventName: event.eventName,
|
|
45008
|
+
eventCreatorNickname: event.eventCreatorNickname || ""
|
|
45009
|
+
};
|
|
45010
|
+
}
|
|
45011
|
+
function buildExtReading(link) {
|
|
45012
|
+
if (!link) return {
|
|
45013
|
+
link: "",
|
|
45014
|
+
title: "",
|
|
45015
|
+
urlType: 1
|
|
45016
|
+
};
|
|
45017
|
+
return {
|
|
45018
|
+
link: link.link.replace(/[\s\u200b]/g, ""),
|
|
45019
|
+
title: link.title,
|
|
45020
|
+
urlType: link.urlType ?? 1
|
|
45021
|
+
};
|
|
45022
|
+
}
|
|
45023
|
+
function buildTagInfo(tagInfo, tagKey) {
|
|
45024
|
+
return {
|
|
45025
|
+
...tagInfo,
|
|
45026
|
+
tagKey
|
|
45027
|
+
};
|
|
45028
|
+
}
|
|
44875
45029
|
const CHUNK_SIZE = 8388608;
|
|
45030
|
+
const UPLOAD_STAGE_TIMEOUT = 180000;
|
|
45031
|
+
const DEFAULT_TUNING = {
|
|
45032
|
+
metaTimeout: UPLOAD_STAGE_TIMEOUT,
|
|
45033
|
+
partTimeout: UPLOAD_STAGE_TIMEOUT,
|
|
45034
|
+
partRetries: 3,
|
|
45035
|
+
completeTimeout: UPLOAD_STAGE_TIMEOUT
|
|
45036
|
+
};
|
|
44876
45037
|
async function uploader_uploadFile(opts) {
|
|
44877
|
-
const { filePath, fileType, uin, authKey, http, logger } = opts;
|
|
45038
|
+
const { filePath, fileType, uin, authKey, http, logger, tuning } = opts;
|
|
44878
45039
|
const stat = external_node_fs_default().statSync(filePath);
|
|
44879
45040
|
const fileSize = stat.size;
|
|
44880
45041
|
const fileName = filePath.split(/[\\/]/).pop() || "file";
|
|
44881
|
-
|
|
45042
|
+
const metaTimeout = tuning?.metaTimeout ?? DEFAULT_TUNING.metaTimeout;
|
|
45043
|
+
const partTimeout = tuning?.partTimeout ?? DEFAULT_TUNING.partTimeout;
|
|
45044
|
+
const partRetries = tuning?.partRetries ?? DEFAULT_TUNING.partRetries;
|
|
45045
|
+
const completeTimeout = tuning?.completeTimeout ?? DEFAULT_TUNING.completeTimeout;
|
|
45046
|
+
logger?.info(`[shipinhaoPublishVideo] 开始上传: ${fileName} (${fileSize} B, filetype=${fileType})`);
|
|
44882
45047
|
const fileMd5 = await computeFileMd5(filePath);
|
|
44883
45048
|
const taskId = generateTaskId(fileName, fileSize, fileMd5);
|
|
44884
45049
|
const baseUrl = "https://finderassistancea.video.qq.com";
|
|
@@ -44889,7 +45054,7 @@ var __webpack_exports__ = {};
|
|
|
44889
45054
|
const chunkCount = Math.ceil(fileSize / CHUNK_SIZE);
|
|
44890
45055
|
const blockPartLength = [];
|
|
44891
45056
|
for(let i = 0; i < chunkCount; i++)blockPartLength.push(Math.min((i + 1) * CHUNK_SIZE, fileSize));
|
|
44892
|
-
logger?.info(
|
|
45057
|
+
logger?.info(`[shipinhaoPublishVideo] 视频分片: ${chunkCount} 片`);
|
|
44893
45058
|
const applyRes = await http.api({
|
|
44894
45059
|
method: "PUT",
|
|
44895
45060
|
url: `${baseUrl}/applyuploaddfs`,
|
|
@@ -44901,12 +45066,15 @@ var __webpack_exports__ = {};
|
|
|
44901
45066
|
BlockSum: chunkCount,
|
|
44902
45067
|
BlockPartLength: blockPartLength
|
|
44903
45068
|
}
|
|
45069
|
+
}, {
|
|
45070
|
+
timeout: metaTimeout,
|
|
45071
|
+
retries: 2,
|
|
45072
|
+
retryDelay: 2000
|
|
44904
45073
|
});
|
|
44905
45074
|
if (!applyRes.UploadID && !applyRes.ListPartsResult) throw new Error("申请 UploadID 失败: " + JSON.stringify(applyRes));
|
|
44906
45075
|
let uploadId = applyRes.UploadID;
|
|
44907
45076
|
const uploadedParts = new Set();
|
|
44908
45077
|
if (applyRes.ListPartsResult) {
|
|
44909
|
-
logger?.info("检测到已上传分片,执行续传");
|
|
44910
45078
|
const parts = Array.isArray(applyRes.ListPartsResult.Part) ? applyRes.ListPartsResult.Part : applyRes.ListPartsResult.Part ? [
|
|
44911
45079
|
applyRes.ListPartsResult.Part
|
|
44912
45080
|
] : [];
|
|
@@ -44922,6 +45090,10 @@ var __webpack_exports__ = {};
|
|
|
44922
45090
|
BlockSum: chunkCount,
|
|
44923
45091
|
BlockPartLength: blockPartLength
|
|
44924
45092
|
}
|
|
45093
|
+
}, {
|
|
45094
|
+
timeout: metaTimeout,
|
|
45095
|
+
retries: 2,
|
|
45096
|
+
retryDelay: 2000
|
|
44925
45097
|
});
|
|
44926
45098
|
uploadId = retryRes.UploadID;
|
|
44927
45099
|
if (!uploadId) throw new Error("续传获取 UploadID 失败");
|
|
@@ -44938,7 +45110,6 @@ var __webpack_exports__ = {};
|
|
|
44938
45110
|
PartNumber: partNumber,
|
|
44939
45111
|
ETag: existing.ETag
|
|
44940
45112
|
});
|
|
44941
|
-
logger?.info(`分片 ${partNumber}/${chunkCount} 已存在,跳过`);
|
|
44942
45113
|
continue;
|
|
44943
45114
|
}
|
|
44944
45115
|
}
|
|
@@ -44948,6 +45119,7 @@ var __webpack_exports__ = {};
|
|
|
44948
45119
|
const chunk = Buffer.alloc(chunkSize);
|
|
44949
45120
|
external_node_fs_default().readSync(fd, chunk, 0, chunkSize, start);
|
|
44950
45121
|
const chunkMd5 = external_node_crypto_default().createHash("md5").update(chunk).digest("hex");
|
|
45122
|
+
const partStart = Date.now();
|
|
44951
45123
|
await http.api({
|
|
44952
45124
|
method: "PUT",
|
|
44953
45125
|
url: `${baseUrl}/uploadpartdfs?PartNumber=${partNumber}&UploadID=${encodeURIComponent(uploadId)}`,
|
|
@@ -44957,17 +45129,20 @@ var __webpack_exports__ = {};
|
|
|
44957
45129
|
"Content-MD5": chunkMd5
|
|
44958
45130
|
},
|
|
44959
45131
|
data: chunk
|
|
45132
|
+
}, {
|
|
45133
|
+
timeout: partTimeout,
|
|
45134
|
+
retries: partRetries,
|
|
45135
|
+
retryDelay: 2000
|
|
44960
45136
|
});
|
|
45137
|
+
Date.now();
|
|
44961
45138
|
partInfo.push({
|
|
44962
45139
|
PartNumber: partNumber,
|
|
44963
45140
|
ETag: `"${chunkMd5}"`
|
|
44964
45141
|
});
|
|
44965
|
-
logger?.info(`分片 ${partNumber}/${chunkCount} 完成 (${chunkSize} B)`);
|
|
44966
45142
|
}
|
|
44967
45143
|
} finally{
|
|
44968
45144
|
external_node_fs_default().closeSync(fd);
|
|
44969
45145
|
}
|
|
44970
|
-
logger?.info("合并分片...");
|
|
44971
45146
|
const completeRes = await http.api({
|
|
44972
45147
|
method: "POST",
|
|
44973
45148
|
url: `${baseUrl}/completepartuploaddfs?UploadID=${encodeURIComponent(uploadId)}`,
|
|
@@ -44979,9 +45154,13 @@ var __webpack_exports__ = {};
|
|
|
44979
45154
|
TransFlag: "0_0",
|
|
44980
45155
|
PartInfo: partInfo
|
|
44981
45156
|
}
|
|
45157
|
+
}, {
|
|
45158
|
+
timeout: completeTimeout,
|
|
45159
|
+
retries: 1,
|
|
45160
|
+
retryDelay: 3000
|
|
44982
45161
|
});
|
|
44983
45162
|
if (!completeRes.DownloadURL) throw new Error("合并分片失败: " + JSON.stringify(completeRes));
|
|
44984
|
-
logger?.info(
|
|
45163
|
+
logger?.info(`[shipinhaoPublishVideo] ${fileName} 上传成功`);
|
|
44985
45164
|
return {
|
|
44986
45165
|
downloadUrl: completeRes.DownloadURL,
|
|
44987
45166
|
md5: fileMd5,
|
|
@@ -45001,85 +45180,233 @@ var __webpack_exports__ = {};
|
|
|
45001
45180
|
const input = `${fileName}-${fileSize}-${fileMd5}`;
|
|
45002
45181
|
return external_node_crypto_default().createHash("md5").update(input).digest("hex").slice(0, 32);
|
|
45003
45182
|
}
|
|
45183
|
+
const MAX_METADATA_BOX_SIZE = 268435456;
|
|
45184
|
+
function readBoxHeader(fd, offset, limit) {
|
|
45185
|
+
if (offset + 8 > limit) return null;
|
|
45186
|
+
const head = Buffer.alloc(16);
|
|
45187
|
+
const read = external_node_fs_default().readSync(fd, head, 0, 16, offset);
|
|
45188
|
+
if (read < 8) return null;
|
|
45189
|
+
let size = head.readUInt32BE(0);
|
|
45190
|
+
const type = head.toString("latin1", 4, 8);
|
|
45191
|
+
let headerSize = 8;
|
|
45192
|
+
if (1 === size) {
|
|
45193
|
+
if (read < 16) return null;
|
|
45194
|
+
size = head.readUInt32BE(8) * 2 ** 32 + head.readUInt32BE(12);
|
|
45195
|
+
headerSize = 16;
|
|
45196
|
+
} else if (0 === size) size = limit - offset;
|
|
45197
|
+
if (size < headerSize || offset + size > limit) return null;
|
|
45198
|
+
return {
|
|
45199
|
+
type,
|
|
45200
|
+
size,
|
|
45201
|
+
headerSize
|
|
45202
|
+
};
|
|
45203
|
+
}
|
|
45004
45204
|
function parseVideoMeta(filePath) {
|
|
45005
|
-
let
|
|
45205
|
+
let fd;
|
|
45206
|
+
let fileSize;
|
|
45207
|
+
try {
|
|
45208
|
+
fd = external_node_fs_default().openSync(filePath, "r");
|
|
45209
|
+
} catch {
|
|
45210
|
+
return null;
|
|
45211
|
+
}
|
|
45006
45212
|
try {
|
|
45007
|
-
|
|
45213
|
+
fileSize = external_node_fs_default().fstatSync(fd).size;
|
|
45214
|
+
const state = {
|
|
45215
|
+
movie: null,
|
|
45216
|
+
tracks: [],
|
|
45217
|
+
trexDefaults: new Map(),
|
|
45218
|
+
fragmentDurations: new Map(),
|
|
45219
|
+
trafTrackId: 0,
|
|
45220
|
+
trafDefaultSampleDuration: 0
|
|
45221
|
+
};
|
|
45222
|
+
let offset = 0;
|
|
45223
|
+
while(offset + 8 <= fileSize){
|
|
45224
|
+
const header = readBoxHeader(fd, offset, fileSize);
|
|
45225
|
+
if (!header) break;
|
|
45226
|
+
if ("moov" === header.type || "moof" === header.type) {
|
|
45227
|
+
const bodyLength = header.size - header.headerSize;
|
|
45228
|
+
if (bodyLength > 0 && bodyLength <= MAX_METADATA_BOX_SIZE) {
|
|
45229
|
+
const body = Buffer.alloc(bodyLength);
|
|
45230
|
+
const read = external_node_fs_default().readSync(fd, body, 0, bodyLength, offset + header.headerSize);
|
|
45231
|
+
state.trafTrackId = 0;
|
|
45232
|
+
state.trafDefaultSampleDuration = 0;
|
|
45233
|
+
walkBoxes(body.subarray(0, read), 0, read, state);
|
|
45234
|
+
}
|
|
45235
|
+
}
|
|
45236
|
+
offset += header.size;
|
|
45237
|
+
}
|
|
45238
|
+
const { movie, tracks } = state;
|
|
45239
|
+
const video = tracks.find((t)=>"vide" === t.handler) || tracks.find((t)=>t.width > 0 && t.height > 0);
|
|
45240
|
+
if (!video) return null;
|
|
45241
|
+
let { width, height } = video;
|
|
45242
|
+
if (90 === video.rotation || 270 === video.rotation) [width, height] = [
|
|
45243
|
+
height,
|
|
45244
|
+
width
|
|
45245
|
+
];
|
|
45246
|
+
return {
|
|
45247
|
+
width: Math.round(width),
|
|
45248
|
+
height: Math.round(height),
|
|
45249
|
+
duration: resolveDuration(movie, video, state.fragmentDurations),
|
|
45250
|
+
rotation: video.rotation,
|
|
45251
|
+
fileSize,
|
|
45252
|
+
codec: video.codec
|
|
45253
|
+
};
|
|
45008
45254
|
} catch {
|
|
45009
45255
|
return null;
|
|
45256
|
+
} finally{
|
|
45257
|
+
try {
|
|
45258
|
+
external_node_fs_default().closeSync(fd);
|
|
45259
|
+
} catch {}
|
|
45010
45260
|
}
|
|
45011
|
-
|
|
45012
|
-
|
|
45013
|
-
|
|
45014
|
-
|
|
45015
|
-
|
|
45016
|
-
|
|
45017
|
-
|
|
45018
|
-
|
|
45019
|
-
if (
|
|
45020
|
-
|
|
45021
|
-
|
|
45022
|
-
|
|
45023
|
-
|
|
45024
|
-
|
|
45025
|
-
|
|
45026
|
-
|
|
45027
|
-
|
|
45028
|
-
|
|
45029
|
-
|
|
45030
|
-
|
|
45031
|
-
|
|
45032
|
-
|
|
45033
|
-
|
|
45034
|
-
|
|
45035
|
-
|
|
45261
|
+
}
|
|
45262
|
+
function walkBoxes(buf, start, end, state) {
|
|
45263
|
+
let off = start;
|
|
45264
|
+
while(off + 8 <= end){
|
|
45265
|
+
let size = buf.readUInt32BE(off);
|
|
45266
|
+
const type = buf.toString("latin1", off + 4, off + 8);
|
|
45267
|
+
let headerSize = 8;
|
|
45268
|
+
if (1 === size) {
|
|
45269
|
+
if (off + 16 > end) break;
|
|
45270
|
+
const hi = buf.readUInt32BE(off + 8);
|
|
45271
|
+
const lo = buf.readUInt32BE(off + 12);
|
|
45272
|
+
size = hi * 2 ** 32 + lo;
|
|
45273
|
+
headerSize = 16;
|
|
45274
|
+
} else if (0 === size) size = end - off;
|
|
45275
|
+
if (size < headerSize || off + size > end) break;
|
|
45276
|
+
const bodyStart = off + headerSize;
|
|
45277
|
+
const bodyEnd = off + size;
|
|
45278
|
+
switch(type){
|
|
45279
|
+
case "trak":
|
|
45280
|
+
case "mdia":
|
|
45281
|
+
case "minf":
|
|
45282
|
+
case "stbl":
|
|
45283
|
+
case "mvex":
|
|
45284
|
+
case "traf":
|
|
45285
|
+
walkBoxes(buf, bodyStart, bodyEnd, state);
|
|
45286
|
+
break;
|
|
45287
|
+
case "mvhd":
|
|
45288
|
+
state.movie = parseMvhd(buf, bodyStart, bodyEnd);
|
|
45289
|
+
break;
|
|
45290
|
+
case "tkhd":
|
|
45291
|
+
state.tracks.push({
|
|
45292
|
+
...parseTkhd(buf, bodyStart, bodyEnd),
|
|
45293
|
+
handler: null,
|
|
45294
|
+
codec: null,
|
|
45295
|
+
timescale: 0,
|
|
45296
|
+
mdhdDuration: 0,
|
|
45297
|
+
sttsDuration: 0
|
|
45298
|
+
});
|
|
45299
|
+
break;
|
|
45300
|
+
case "mdhd":
|
|
45301
|
+
{
|
|
45302
|
+
const mdhd = parseMvhd(buf, bodyStart, bodyEnd);
|
|
45303
|
+
if (mdhd && state.tracks.length) {
|
|
45304
|
+
const track = state.tracks[state.tracks.length - 1];
|
|
45305
|
+
track.timescale = mdhd.timescale;
|
|
45306
|
+
track.mdhdDuration = mdhd.duration;
|
|
45307
|
+
}
|
|
45036
45308
|
break;
|
|
45037
|
-
|
|
45038
|
-
|
|
45309
|
+
}
|
|
45310
|
+
case "hdlr":
|
|
45311
|
+
if (bodyEnd - bodyStart >= 12 && state.tracks.length) state.tracks[state.tracks.length - 1].handler = buf.toString("latin1", bodyStart + 8, bodyStart + 12);
|
|
45312
|
+
break;
|
|
45313
|
+
case "stsd":
|
|
45314
|
+
{
|
|
45315
|
+
const codec = parseStsdCodec(buf, bodyStart, bodyEnd);
|
|
45316
|
+
if (codec && state.tracks.length) state.tracks[state.tracks.length - 1].codec = codec;
|
|
45039
45317
|
break;
|
|
45040
|
-
|
|
45041
|
-
|
|
45042
|
-
|
|
45043
|
-
|
|
45044
|
-
|
|
45045
|
-
|
|
45318
|
+
}
|
|
45319
|
+
case "stts":
|
|
45320
|
+
if (state.tracks.length) state.tracks[state.tracks.length - 1].sttsDuration = parseSttsDuration(buf, bodyStart, bodyEnd);
|
|
45321
|
+
break;
|
|
45322
|
+
case "trex":
|
|
45323
|
+
if (bodyStart + 20 > bodyEnd) break;
|
|
45324
|
+
state.trexDefaults.set(buf.readUInt32BE(bodyStart + 4), buf.readUInt32BE(bodyStart + 12));
|
|
45325
|
+
break;
|
|
45326
|
+
case "tfhd":
|
|
45327
|
+
{
|
|
45328
|
+
const tfhd = parseTfhd(buf, bodyStart, bodyEnd);
|
|
45329
|
+
state.trafTrackId = tfhd.trackId;
|
|
45330
|
+
state.trafDefaultSampleDuration = tfhd.defaultSampleDuration || state.trexDefaults.get(tfhd.trackId) || 0;
|
|
45046
45331
|
break;
|
|
45047
|
-
|
|
45048
|
-
|
|
45049
|
-
|
|
45050
|
-
|
|
45051
|
-
|
|
45332
|
+
}
|
|
45333
|
+
case "trun":
|
|
45334
|
+
{
|
|
45335
|
+
const duration = parseTrunDuration(buf, bodyStart, bodyEnd, state.trafDefaultSampleDuration);
|
|
45336
|
+
state.fragmentDurations.set(state.trafTrackId, (state.fragmentDurations.get(state.trafTrackId) || 0) + duration);
|
|
45052
45337
|
break;
|
|
45053
|
-
|
|
45054
|
-
{
|
|
45055
|
-
const codec = parseStsdCodec(buf, bodyStart, bodyEnd);
|
|
45056
|
-
if (codec && tracks.length) tracks[tracks.length - 1].codec = codec;
|
|
45057
|
-
break;
|
|
45058
|
-
}
|
|
45059
|
-
}
|
|
45060
|
-
off += size;
|
|
45338
|
+
}
|
|
45061
45339
|
}
|
|
45062
|
-
|
|
45063
|
-
|
|
45064
|
-
|
|
45065
|
-
|
|
45066
|
-
|
|
45067
|
-
|
|
45068
|
-
|
|
45069
|
-
|
|
45070
|
-
|
|
45071
|
-
|
|
45072
|
-
|
|
45073
|
-
|
|
45074
|
-
|
|
45075
|
-
|
|
45076
|
-
|
|
45077
|
-
|
|
45078
|
-
|
|
45340
|
+
off += size;
|
|
45341
|
+
}
|
|
45342
|
+
}
|
|
45343
|
+
const UNKNOWN_DURATION_32 = 0xffffffff;
|
|
45344
|
+
function isUsableDuration(duration) {
|
|
45345
|
+
return duration > 0 && duration !== UNKNOWN_DURATION_32;
|
|
45346
|
+
}
|
|
45347
|
+
function resolveDuration(movie, video, fragmentDurations) {
|
|
45348
|
+
if (movie && movie.timescale && isUsableDuration(movie.duration)) return movie.duration / movie.timescale;
|
|
45349
|
+
if (video.timescale) {
|
|
45350
|
+
if (isUsableDuration(video.mdhdDuration)) return video.mdhdDuration / video.timescale;
|
|
45351
|
+
if (video.sttsDuration > 0) return video.sttsDuration / video.timescale;
|
|
45352
|
+
const fragment = fragmentDurations.get(video.trackId) ?? (1 === fragmentDurations.size ? [
|
|
45353
|
+
...fragmentDurations.values()
|
|
45354
|
+
][0] : 0);
|
|
45355
|
+
if (fragment > 0) return fragment / video.timescale;
|
|
45356
|
+
}
|
|
45357
|
+
return 0;
|
|
45358
|
+
}
|
|
45359
|
+
function parseSttsDuration(buf, start, end) {
|
|
45360
|
+
if (start + 8 > end) return 0;
|
|
45361
|
+
const entryCount = buf.readUInt32BE(start + 4);
|
|
45362
|
+
let total = 0;
|
|
45363
|
+
for(let i = 0; i < entryCount; i++){
|
|
45364
|
+
const off = start + 8 + 8 * i;
|
|
45365
|
+
if (off + 8 > end) break;
|
|
45366
|
+
total += buf.readUInt32BE(off) * buf.readUInt32BE(off + 4);
|
|
45367
|
+
}
|
|
45368
|
+
return total;
|
|
45369
|
+
}
|
|
45370
|
+
function parseTfhd(buf, start, end) {
|
|
45371
|
+
if (start + 8 > end) return {
|
|
45372
|
+
trackId: 0,
|
|
45373
|
+
defaultSampleDuration: 0
|
|
45374
|
+
};
|
|
45375
|
+
const flags = buf.readUIntBE(start + 1, 3);
|
|
45376
|
+
const trackId = buf.readUInt32BE(start + 4);
|
|
45377
|
+
let off = start + 8;
|
|
45378
|
+
if (0x000001 & flags) off += 8;
|
|
45379
|
+
if (0x000002 & flags) off += 4;
|
|
45380
|
+
if (0x000008 & flags && off + 4 <= end) return {
|
|
45381
|
+
trackId,
|
|
45382
|
+
defaultSampleDuration: buf.readUInt32BE(off)
|
|
45079
45383
|
};
|
|
45384
|
+
return {
|
|
45385
|
+
trackId,
|
|
45386
|
+
defaultSampleDuration: 0
|
|
45387
|
+
};
|
|
45388
|
+
}
|
|
45389
|
+
function parseTrunDuration(buf, start, end, defaultSampleDuration) {
|
|
45390
|
+
if (start + 8 > end) return 0;
|
|
45391
|
+
const flags = buf.readUIntBE(start + 1, 3);
|
|
45392
|
+
const sampleCount = buf.readUInt32BE(start + 4);
|
|
45393
|
+
let off = start + 8;
|
|
45394
|
+
if (0x000001 & flags) off += 4;
|
|
45395
|
+
if (0x000004 & flags) off += 4;
|
|
45396
|
+
const hasDuration = (0x000100 & flags) !== 0;
|
|
45397
|
+
if (!hasDuration) return sampleCount * defaultSampleDuration;
|
|
45398
|
+
const entrySize = 4 + ((0x000200 & flags) !== 0 ? 4 : 0) + ((0x000400 & flags) !== 0 ? 4 : 0) + ((0x000800 & flags) !== 0 ? 4 : 0);
|
|
45399
|
+
let total = 0;
|
|
45400
|
+
for(let i = 0; i < sampleCount; i++){
|
|
45401
|
+
const entryOff = off + i * entrySize;
|
|
45402
|
+
if (entryOff + 4 > end) break;
|
|
45403
|
+
total += buf.readUInt32BE(entryOff);
|
|
45404
|
+
}
|
|
45405
|
+
return total;
|
|
45080
45406
|
}
|
|
45081
45407
|
function parseStsdCodec(buf, start, end) {
|
|
45082
45408
|
if (start + 16 > end) return null;
|
|
45409
|
+
if (0 === buf.readUInt32BE(start + 4)) return null;
|
|
45083
45410
|
return buf.toString("latin1", start + 12, start + 16).toLowerCase();
|
|
45084
45411
|
}
|
|
45085
45412
|
function parseMvhd(buf, start, end) {
|
|
@@ -45105,7 +45432,10 @@ var __webpack_exports__ = {};
|
|
|
45105
45432
|
const afterDuration = 1 === version ? 36 : 24;
|
|
45106
45433
|
const matrixOff = start + afterDuration + 16;
|
|
45107
45434
|
const whOff = matrixOff + 36;
|
|
45435
|
+
const trackIdOff = start + (1 === version ? 20 : 12);
|
|
45436
|
+
const trackId = trackIdOff + 4 <= end ? buf.readUInt32BE(trackIdOff) : 0;
|
|
45108
45437
|
if (whOff + 8 > end) return {
|
|
45438
|
+
trackId,
|
|
45109
45439
|
width: 0,
|
|
45110
45440
|
height: 0,
|
|
45111
45441
|
rotation: 0
|
|
@@ -45119,11 +45449,25 @@ var __webpack_exports__ = {};
|
|
|
45119
45449
|
else if (Math.abs(a + 1) < 0.01 && Math.abs(b) < 0.01) rotation = 180;
|
|
45120
45450
|
else if (Math.abs(a) < 0.01 && Math.abs(b + 1) < 0.01) rotation = 270;
|
|
45121
45451
|
return {
|
|
45452
|
+
trackId,
|
|
45122
45453
|
width,
|
|
45123
45454
|
height,
|
|
45124
45455
|
rotation
|
|
45125
45456
|
};
|
|
45126
45457
|
}
|
|
45458
|
+
function parseVideoCodec(filePath) {
|
|
45459
|
+
return parseVideoMeta(filePath)?.codec ?? null;
|
|
45460
|
+
}
|
|
45461
|
+
function buildVideoMetaFromParams(filePath, metadata) {
|
|
45462
|
+
return {
|
|
45463
|
+
width: Math.round(metadata.width),
|
|
45464
|
+
height: Math.round(metadata.height),
|
|
45465
|
+
duration: metadata.duration,
|
|
45466
|
+
rotation: 0,
|
|
45467
|
+
fileSize: metadata.fileSize,
|
|
45468
|
+
codec: parseVideoCodec(filePath)
|
|
45469
|
+
};
|
|
45470
|
+
}
|
|
45127
45471
|
const MAX_DURATION_SECONDS = 28800;
|
|
45128
45472
|
const MAX_FILE_SIZE = 21474836480;
|
|
45129
45473
|
const ALLOWED_EXTENSIONS = [
|
|
@@ -45134,6 +45478,7 @@ var __webpack_exports__ = {};
|
|
|
45134
45478
|
"avc3"
|
|
45135
45479
|
];
|
|
45136
45480
|
const MIN_TITLE_LENGTH = 6;
|
|
45481
|
+
const MAX_TITLE_LENGTH = 16;
|
|
45137
45482
|
function formatFileSize(bytes) {
|
|
45138
45483
|
if (bytes < 1048576) return `${(bytes / 1024).toFixed(2)} KB`;
|
|
45139
45484
|
if (bytes < 1073741824) return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
|
|
@@ -45160,26 +45505,62 @@ var __webpack_exports__ = {};
|
|
|
45160
45505
|
function validateShipinhaoTitle(title) {
|
|
45161
45506
|
if (void 0 === title) return null;
|
|
45162
45507
|
const trimmed = title.trim();
|
|
45508
|
+
if ("" === trimmed) return null;
|
|
45163
45509
|
const length = [
|
|
45164
45510
|
...trimmed
|
|
45165
45511
|
].length;
|
|
45166
|
-
if (length < MIN_TITLE_LENGTH) return
|
|
45512
|
+
if (length < MIN_TITLE_LENGTH || length > MAX_TITLE_LENGTH) return `视频号标题需要在 ${MIN_TITLE_LENGTH}-${MAX_TITLE_LENGTH} 个字符之间,当前 ${length} 个字符,请调整后重试。`;
|
|
45167
45513
|
return null;
|
|
45168
45514
|
}
|
|
45169
|
-
|
|
45170
|
-
|
|
45515
|
+
const POST_CREATE_PAGE_URL = "https://channels.weixin.qq.com/micro/content/post/create";
|
|
45516
|
+
const MICRO_CONTENT_BASE = "https://channels.weixin.qq.com/micro/content/cgi-bin/mmfinderassistant-bin";
|
|
45517
|
+
function resolveClientContext(params, fallbackUin) {
|
|
45518
|
+
const extra = params.extraParam || {};
|
|
45519
|
+
const deviceIdCookie = params.cookies.find((c)=>"device_id" === c.name || "finger_print_device_id" === c.name)?.value;
|
|
45520
|
+
return {
|
|
45521
|
+
aId: "string" == typeof extra.aId ? extra.aId : "",
|
|
45522
|
+
fingerPrintDeviceId: "string" == typeof extra.fingerPrintDeviceId ? extra.fingerPrintDeviceId : deviceIdCookie || "",
|
|
45523
|
+
uin: "string" == typeof extra.uin ? extra.uin : String(fallbackUin)
|
|
45524
|
+
};
|
|
45525
|
+
}
|
|
45526
|
+
function buildPublishHeaders(cookieString, client) {
|
|
45527
|
+
const headers = {
|
|
45528
|
+
cookie: cookieString,
|
|
45529
|
+
referer: POST_CREATE_PAGE_URL,
|
|
45530
|
+
origin: "https://channels.weixin.qq.com",
|
|
45531
|
+
"content-type": "application/json"
|
|
45532
|
+
};
|
|
45533
|
+
if (client.fingerPrintDeviceId) headers["finger-print-device-id"] = client.fingerPrintDeviceId;
|
|
45534
|
+
if (client.uin) headers["x-wechat-uin"] = client.uin;
|
|
45535
|
+
return headers;
|
|
45536
|
+
}
|
|
45537
|
+
function buildPublishQuery(client) {
|
|
45538
|
+
const query = {
|
|
45539
|
+
_rid: rid(),
|
|
45540
|
+
_pageUrl: POST_CREATE_PAGE_URL
|
|
45541
|
+
};
|
|
45542
|
+
if (client.aId) query._aid = client.aId;
|
|
45543
|
+
return query;
|
|
45544
|
+
}
|
|
45545
|
+
function buildCommonBody(finderUsername) {
|
|
45546
|
+
return {
|
|
45547
|
+
timestamp: String(Date.now()),
|
|
45548
|
+
_log_finder_uin: "",
|
|
45549
|
+
_log_finder_id: finderUsername,
|
|
45550
|
+
rawKeyBuff: "",
|
|
45551
|
+
pluginSessionId: null,
|
|
45552
|
+
scene: 7,
|
|
45553
|
+
reqScene: 7
|
|
45554
|
+
};
|
|
45555
|
+
}
|
|
45556
|
+
async function getTraceKey(auth, client, http, logger) {
|
|
45171
45557
|
const res = await http.api({
|
|
45172
45558
|
method: "POST",
|
|
45173
|
-
url:
|
|
45559
|
+
url: `${MICRO_CONTENT_BASE}/post/get-finder-post-trace-key`,
|
|
45560
|
+
params: buildPublishQuery(client),
|
|
45174
45561
|
data: {
|
|
45175
45562
|
objectId: "",
|
|
45176
|
-
|
|
45177
|
-
_log_finder_uin: "",
|
|
45178
|
-
_log_finder_id: auth.finderUsername,
|
|
45179
|
-
rawKeyBuff: "",
|
|
45180
|
-
pluginSessionId: null,
|
|
45181
|
-
scene: 7,
|
|
45182
|
-
reqScene: 7
|
|
45563
|
+
...buildCommonBody(auth.finderUsername)
|
|
45183
45564
|
},
|
|
45184
45565
|
defaultErrorMsg: "获取 traceKey 失败"
|
|
45185
45566
|
});
|
|
@@ -45187,18 +45568,38 @@ var __webpack_exports__ = {};
|
|
|
45187
45568
|
logger.error("[getTraceKey] 获取失败:", JSON.stringify(res));
|
|
45188
45569
|
throw new Error(`获取 traceKey 失败: ${JSON.stringify(res)}`);
|
|
45189
45570
|
}
|
|
45190
|
-
logger.info(`[getTraceKey] 获取成功: ${res.data.traceKey}`);
|
|
45191
45571
|
return res.data.traceKey;
|
|
45192
45572
|
}
|
|
45573
|
+
async function getObjectTagKey(auth, client, http, logger) {
|
|
45574
|
+
try {
|
|
45575
|
+
const res = await http.api({
|
|
45576
|
+
method: "POST",
|
|
45577
|
+
url: `${MICRO_CONTENT_BASE}/post/finder_get_object_tag_list`,
|
|
45578
|
+
params: buildPublishQuery(client),
|
|
45579
|
+
data: {
|
|
45580
|
+
source: 1,
|
|
45581
|
+
...buildCommonBody(auth.finderUsername)
|
|
45582
|
+
},
|
|
45583
|
+
defaultErrorMsg: "获取内容声明标注失败"
|
|
45584
|
+
});
|
|
45585
|
+
if (0 !== res.errCode || !res.data?.tagKey) {
|
|
45586
|
+
logger.warn(`[getObjectTagKey] 未取到 tagKey: ${JSON.stringify(res)}`);
|
|
45587
|
+
return null;
|
|
45588
|
+
}
|
|
45589
|
+
return res.data.tagKey;
|
|
45590
|
+
} catch (error) {
|
|
45591
|
+
logger.warn(`[getObjectTagKey] 获取 tagKey 异常: ${stringifyError(error)}`);
|
|
45592
|
+
return null;
|
|
45593
|
+
}
|
|
45594
|
+
}
|
|
45193
45595
|
async function submitAndPollTranscode(opts) {
|
|
45194
|
-
const { videoUrl, videoMeta, traceKey, uploadStartTime, uploadEndTime, finderUsername, http, logger } = opts;
|
|
45195
|
-
logger.info("[submitAndPollTranscode] 开始提交转码任务...");
|
|
45596
|
+
const { videoUrl, videoMeta, traceKey, uploadStartTime, uploadEndTime, finderUsername, client, http, logger } = opts;
|
|
45196
45597
|
const finderUrl = videoUrl.includes("wxapp.tc.qq.com") ? `https://finder.video.qq.com${videoUrl.split("qq.com")[1]}` : videoUrl;
|
|
45197
|
-
logger.info(`[submitAndPollTranscode] 视频URL: ${finderUrl}`);
|
|
45198
45598
|
logger.info(`[submitAndPollTranscode] 视频尺寸: ${videoMeta.width}x${videoMeta.height}, 时长: ${videoMeta.duration}s`);
|
|
45199
45599
|
const submitRes = await http.api({
|
|
45200
45600
|
method: "POST",
|
|
45201
|
-
url:
|
|
45601
|
+
url: `${MICRO_CONTENT_BASE}/post/post_clip_video`,
|
|
45602
|
+
params: buildPublishQuery(client),
|
|
45202
45603
|
data: {
|
|
45203
45604
|
url: finderUrl,
|
|
45204
45605
|
timeStart: 0,
|
|
@@ -45222,13 +45623,7 @@ var __webpack_exports__ = {};
|
|
|
45222
45623
|
targetHeight: videoMeta.height,
|
|
45223
45624
|
type: 4,
|
|
45224
45625
|
useAstraThumbCover: 1,
|
|
45225
|
-
|
|
45226
|
-
_log_finder_uin: "",
|
|
45227
|
-
_log_finder_id: finderUsername,
|
|
45228
|
-
rawKeyBuff: "",
|
|
45229
|
-
pluginSessionId: null,
|
|
45230
|
-
scene: 7,
|
|
45231
|
-
reqScene: 7
|
|
45626
|
+
...buildCommonBody(finderUsername)
|
|
45232
45627
|
},
|
|
45233
45628
|
defaultErrorMsg: "提交转码失败"
|
|
45234
45629
|
});
|
|
@@ -45237,43 +45632,39 @@ var __webpack_exports__ = {};
|
|
|
45237
45632
|
throw new Error(`提交转码失败: ${JSON.stringify(submitRes)}`);
|
|
45238
45633
|
}
|
|
45239
45634
|
const { clipKey, draftId } = submitRes.data;
|
|
45240
|
-
logger.info(`[submitAndPollTranscode] 转码任务已提交,clipKey: ${clipKey}, draftId: ${draftId}`);
|
|
45241
|
-
const maxPolls = 60;
|
|
45242
45635
|
const pollInterval = 5000;
|
|
45636
|
+
const pollBudget = Math.min(1800000, 300000 + 1000 * Math.ceil(1.5 * videoMeta.duration));
|
|
45637
|
+
const maxPolls = Math.ceil(pollBudget / pollInterval);
|
|
45243
45638
|
let pollCount = 0;
|
|
45244
|
-
logger.info(`[submitAndPollTranscode] 开始轮询转码结果,最多 ${maxPolls} 次,间隔 ${pollInterval / 1000}s`);
|
|
45245
45639
|
while(pollCount < maxPolls){
|
|
45246
45640
|
await mock_sleep(pollInterval);
|
|
45247
45641
|
pollCount++;
|
|
45248
45642
|
const pollRes = await http.api({
|
|
45249
45643
|
method: "POST",
|
|
45250
|
-
url:
|
|
45644
|
+
url: `${MICRO_CONTENT_BASE}/post/post_clip_video_result`,
|
|
45645
|
+
params: buildPublishQuery(client),
|
|
45251
45646
|
data: {
|
|
45252
45647
|
clipKey,
|
|
45253
45648
|
draftId,
|
|
45254
|
-
|
|
45255
|
-
_log_finder_uin: "",
|
|
45256
|
-
_log_finder_id: finderUsername,
|
|
45257
|
-
rawKeyBuff: "",
|
|
45258
|
-
pluginSessionId: null,
|
|
45259
|
-
scene: 7,
|
|
45260
|
-
reqScene: 7
|
|
45649
|
+
...buildCommonBody(finderUsername)
|
|
45261
45650
|
},
|
|
45262
45651
|
defaultErrorMsg: "转码轮询失败"
|
|
45652
|
+
}, {
|
|
45653
|
+
timeout: 60000,
|
|
45654
|
+
retries: 2,
|
|
45655
|
+
retryDelay: 3000
|
|
45263
45656
|
});
|
|
45264
45657
|
if (0 !== pollRes.errCode) {
|
|
45265
45658
|
logger.error(`[submitAndPollTranscode] 转码轮询失败 (poll ${pollCount}):`, JSON.stringify(pollRes));
|
|
45266
45659
|
throw new Error(`转码轮询失败 (poll ${pollCount}): ${JSON.stringify(pollRes)}`);
|
|
45267
45660
|
}
|
|
45268
45661
|
const { flag, url, width, height, duration, md5, fileSize } = pollRes.data || {};
|
|
45269
|
-
logger.info(`[submitAndPollTranscode] 轮询第 ${pollCount} 次,flag=${flag}`);
|
|
45270
45662
|
if (1 === flag) {
|
|
45271
45663
|
if (!url || !width || !height || !duration || !md5 || !fileSize) {
|
|
45272
45664
|
logger.error("[submitAndPollTranscode] 转码完成但返回数据不完整:", JSON.stringify(pollRes.data));
|
|
45273
45665
|
throw new Error(`转码完成但返回数据不完整: ${JSON.stringify(pollRes.data)}`);
|
|
45274
45666
|
}
|
|
45275
45667
|
logger.info(`[submitAndPollTranscode] 转码完成! 用时: ${pollCount * pollInterval / 1000}s`);
|
|
45276
|
-
logger.info(`[submitAndPollTranscode] 视频信息: ${width}x${height}, 时长: ${duration}s, 大小: ${fileSize}`);
|
|
45277
45668
|
return {
|
|
45278
45669
|
clipKey,
|
|
45279
45670
|
url,
|
|
@@ -45284,7 +45675,7 @@ var __webpack_exports__ = {};
|
|
|
45284
45675
|
fileSize
|
|
45285
45676
|
};
|
|
45286
45677
|
}
|
|
45287
|
-
if (2 === flag)
|
|
45678
|
+
if (2 === flag) ;
|
|
45288
45679
|
else {
|
|
45289
45680
|
logger.error(`[submitAndPollTranscode] 转码失败,未知 flag=${flag}:`, JSON.stringify(pollRes.data));
|
|
45290
45681
|
throw new Error(`转码失败,未知 flag=${flag}: ${JSON.stringify(pollRes.data)}`);
|
|
@@ -45294,162 +45685,151 @@ var __webpack_exports__ = {};
|
|
|
45294
45685
|
throw new Error(`转码超时 (${maxPolls * pollInterval / 1000}s)`);
|
|
45295
45686
|
}
|
|
45296
45687
|
async function publishVideo(opts) {
|
|
45297
|
-
const { params, auth, clipResult, videoUpload, coverUpload, traceKey, uploadStartTime, uploadEndTime, proxyHttp, logger } = opts;
|
|
45298
|
-
|
|
45299
|
-
const
|
|
45300
|
-
|
|
45688
|
+
const { params, auth, client, clipResult, videoUpload, coverUpload, verticalCoverUpload, videoMeta, traceKey, tagKey, uploadStartTime, uploadEndTime, proxyHttp, logger } = opts;
|
|
45689
|
+
const toFinderUrl = (url)=>url.includes("wxapp.tc.qq.com") ? `https://finder.video.qq.com${url.split("qq.com")[1]}` : url;
|
|
45690
|
+
const thumbFinderUrl = toFinderUrl(coverUpload.downloadUrl);
|
|
45691
|
+
const coverFinderUrl = toFinderUrl(verticalCoverUpload.downloadUrl);
|
|
45301
45692
|
const md5sumUuid = external_node_crypto_default().randomUUID();
|
|
45302
|
-
|
|
45303
|
-
|
|
45304
|
-
|
|
45305
|
-
|
|
45306
|
-
|
|
45307
|
-
|
|
45308
|
-
|
|
45309
|
-
|
|
45310
|
-
|
|
45311
|
-
|
|
45312
|
-
|
|
45313
|
-
|
|
45314
|
-
|
|
45315
|
-
|
|
45316
|
-
|
|
45317
|
-
|
|
45318
|
-
|
|
45319
|
-
|
|
45320
|
-
|
|
45321
|
-
|
|
45322
|
-
|
|
45323
|
-
|
|
45324
|
-
|
|
45325
|
-
|
|
45326
|
-
objectDesc: {
|
|
45327
|
-
mpTitle: "",
|
|
45328
|
-
description: params.description,
|
|
45329
|
-
shortTitle: params.title || "",
|
|
45330
|
-
extReading: {},
|
|
45693
|
+
const description = params.description;
|
|
45694
|
+
const objectDesc = {
|
|
45695
|
+
mpTitle: "",
|
|
45696
|
+
description,
|
|
45697
|
+
extReading: buildExtReading(params.link),
|
|
45698
|
+
mediaType: 4,
|
|
45699
|
+
location: payload_buildLocation(params.location),
|
|
45700
|
+
topic: buildTopic({
|
|
45701
|
+
description: params.description,
|
|
45702
|
+
topics: params.topics,
|
|
45703
|
+
mentionedUsers: params.mentionedUsers,
|
|
45704
|
+
collection: params.collection
|
|
45705
|
+
}),
|
|
45706
|
+
event: buildEvent(params.event),
|
|
45707
|
+
mentionedUser: buildMentionedUser(params.mentionedUsers),
|
|
45708
|
+
media: [
|
|
45709
|
+
{
|
|
45710
|
+
url: clipResult.url,
|
|
45711
|
+
fileSize: clipResult.fileSize,
|
|
45712
|
+
thumbUrl: thumbFinderUrl,
|
|
45713
|
+
fullThumbUrl: thumbFinderUrl,
|
|
45714
|
+
coverUrl: coverFinderUrl,
|
|
45715
|
+
fullCoverUrl: coverFinderUrl,
|
|
45716
|
+
shareCoverUrl: coverFinderUrl,
|
|
45331
45717
|
mediaType: 4,
|
|
45332
|
-
|
|
45333
|
-
latitude: params.location.latitude,
|
|
45334
|
-
longitude: params.location.longitude,
|
|
45335
|
-
city: params.location.city,
|
|
45336
|
-
poiClassifyId: params.location.poiClassifyId || ""
|
|
45337
|
-
} : {
|
|
45338
|
-
latitude: 0,
|
|
45339
|
-
longitude: 0,
|
|
45340
|
-
city: "",
|
|
45341
|
-
poiClassifyId: ""
|
|
45342
|
-
},
|
|
45343
|
-
topic: {
|
|
45344
|
-
finderTopicInfo: `<finder><version>1</version><valuecount>1</valuecount><style><at></at></style><value0><![CDATA[${params.description}]]></value0></finder>`
|
|
45345
|
-
},
|
|
45346
|
-
event: {},
|
|
45347
|
-
mentionedUser: [],
|
|
45348
|
-
media: [
|
|
45349
|
-
{
|
|
45350
|
-
url: clipResult.url,
|
|
45351
|
-
fileSize: clipResult.fileSize,
|
|
45352
|
-
thumbUrl: coverFinderUrl,
|
|
45353
|
-
fullThumbUrl: coverFinderUrl,
|
|
45354
|
-
coverUrl: coverFinderUrl,
|
|
45355
|
-
fullCoverUrl: coverFinderUrl,
|
|
45356
|
-
shareCoverUrl: coverFinderUrl,
|
|
45357
|
-
mediaType: 4,
|
|
45358
|
-
videoPlayLen: Math.round(clipResult.duration),
|
|
45359
|
-
width: clipResult.width,
|
|
45360
|
-
height: clipResult.height,
|
|
45361
|
-
md5sum: md5sumUuid,
|
|
45362
|
-
cardShowStyle: 2,
|
|
45363
|
-
urlCdnTaskId: clipResult.clipKey
|
|
45364
|
-
}
|
|
45365
|
-
],
|
|
45366
|
-
member: {}
|
|
45367
|
-
},
|
|
45368
|
-
effectiveTime: params.scheduleTime || 0,
|
|
45369
|
-
report: {
|
|
45370
|
-
clipKey: clipResult.clipKey,
|
|
45371
|
-
draftId: clipResult.clipKey,
|
|
45372
|
-
timestamp: String(Date.now()),
|
|
45373
|
-
_log_finder_uin: "",
|
|
45374
|
-
_log_finder_id: auth.finderUsername,
|
|
45375
|
-
rawKeyBuff: "",
|
|
45376
|
-
pluginSessionId: null,
|
|
45377
|
-
scene: 7,
|
|
45378
|
-
reqScene: 7,
|
|
45379
|
-
height: clipResult.height,
|
|
45718
|
+
videoPlayLen: Math.round(clipResult.duration),
|
|
45380
45719
|
width: clipResult.width,
|
|
45381
|
-
|
|
45382
|
-
|
|
45383
|
-
|
|
45384
|
-
|
|
45385
|
-
|
|
45386
|
-
|
|
45387
|
-
|
|
45388
|
-
|
|
45389
|
-
|
|
45390
|
-
|
|
45391
|
-
|
|
45392
|
-
|
|
45393
|
-
|
|
45394
|
-
|
|
45720
|
+
height: clipResult.height,
|
|
45721
|
+
md5sum: md5sumUuid,
|
|
45722
|
+
cardShowStyle: 2,
|
|
45723
|
+
urlCdnTaskId: clipResult.clipKey
|
|
45724
|
+
}
|
|
45725
|
+
],
|
|
45726
|
+
shortTitle: params.title ? [
|
|
45727
|
+
{
|
|
45728
|
+
shortTitle: params.title
|
|
45729
|
+
}
|
|
45730
|
+
] : [],
|
|
45731
|
+
member: {}
|
|
45732
|
+
};
|
|
45733
|
+
const publishData = {
|
|
45734
|
+
objectType: 0,
|
|
45735
|
+
longitude: 0,
|
|
45736
|
+
latitude: 0,
|
|
45737
|
+
feedLongitude: 0,
|
|
45738
|
+
feedLatitude: 0,
|
|
45739
|
+
originalFlag: params.originalFlag ?? 0,
|
|
45740
|
+
topics: params.topics || [],
|
|
45741
|
+
isFullPost: 1,
|
|
45742
|
+
handleFlag: 2,
|
|
45743
|
+
videoClipTaskId: clipResult.clipKey,
|
|
45744
|
+
traceInfo: {
|
|
45745
|
+
traceKey,
|
|
45746
|
+
uploadCdnStart: uploadStartTime,
|
|
45747
|
+
uploadCdnEnd: uploadEndTime
|
|
45395
45748
|
},
|
|
45749
|
+
objectDesc,
|
|
45750
|
+
report: {
|
|
45751
|
+
clipKey: clipResult.clipKey,
|
|
45752
|
+
draftId: clipResult.clipKey,
|
|
45753
|
+
...buildCommonBody(auth.finderUsername),
|
|
45754
|
+
height: videoMeta.height,
|
|
45755
|
+
width: videoMeta.width,
|
|
45756
|
+
duration: videoMeta.duration,
|
|
45757
|
+
fileSize: videoUpload.fileSize,
|
|
45758
|
+
uploadCost: (uploadEndTime - uploadStartTime) * 1000
|
|
45759
|
+
},
|
|
45760
|
+
postFlag: 0,
|
|
45761
|
+
mode: 1,
|
|
45762
|
+
clientid: external_node_crypto_default().randomUUID(),
|
|
45763
|
+
...buildCommonBody(auth.finderUsername)
|
|
45764
|
+
};
|
|
45765
|
+
if (params.scheduledTime) publishData.effectiveTime = params.scheduledTime;
|
|
45766
|
+
if (params.tagInfo && tagKey) publishData.tagInfo = buildTagInfo(params.tagInfo, tagKey);
|
|
45767
|
+
const publishRes = await proxyHttp.api({
|
|
45768
|
+
method: "POST",
|
|
45769
|
+
url: `${MICRO_CONTENT_BASE}/post/post_create`,
|
|
45770
|
+
params: buildPublishQuery(client),
|
|
45771
|
+
data: publishData,
|
|
45396
45772
|
defaultErrorMsg: "发布视频失败"
|
|
45397
45773
|
});
|
|
45398
|
-
logger.info(`[publishVideo]
|
|
45774
|
+
logger.info(`[publishVideo] 发布结果: errCode=${publishRes.errCode}, baseResp.errcode=${publishRes.data?.baseResp?.errcode}`);
|
|
45399
45775
|
return publishRes;
|
|
45400
45776
|
}
|
|
45401
45777
|
function mock_sleep(ms) {
|
|
45402
45778
|
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
45403
45779
|
}
|
|
45780
|
+
async function resolveLocalCoverPath(coverPath, label, tmpCachePath, logger) {
|
|
45781
|
+
if (!/^https?:\/\//i.test(coverPath)) return coverPath;
|
|
45782
|
+
const fileName = getFilenameFromUrl(coverPath);
|
|
45783
|
+
const savePath = external_node_path_default().join(tmpCachePath, `${Date.now()}-${label}-${fileName}`);
|
|
45784
|
+
await downloadImage(coverPath, savePath);
|
|
45785
|
+
return savePath;
|
|
45786
|
+
}
|
|
45404
45787
|
const shipinhaoPublishVideo_mock_mockAction = async (task, params)=>{
|
|
45405
|
-
task.logger.info("[shipinhaoPublishVideo] 开始执行视频号视频发布 - Mock API 方式");
|
|
45406
45788
|
const updateTaskState = task.taskStageStore?.update?.bind(task.taskStageStore, task.taskId || "");
|
|
45407
45789
|
let currentStep = "初始化";
|
|
45408
45790
|
try {
|
|
45409
45791
|
currentStep = "解析认证信息";
|
|
45410
45792
|
const cookieString = params.cookies.map((c)=>`${c.name}=${c.value}`).join("; ");
|
|
45411
|
-
const
|
|
45412
|
-
|
|
45413
|
-
|
|
45793
|
+
const http = new Http({
|
|
45794
|
+
headers: {
|
|
45795
|
+
cookie: cookieString
|
|
45796
|
+
}
|
|
45797
|
+
});
|
|
45798
|
+
currentStep = "验证发布参数";
|
|
45799
|
+
if (!params.videoPath) return utils_response(414, "视频文件路径不能为空", "");
|
|
45800
|
+
if (!params.coverPath) return utils_response(414, "横屏封面图片路径不能为空", "");
|
|
45801
|
+
currentStep = "获取上传认证";
|
|
45802
|
+
const auth = await getShipinhaoUploadAuth(cookieString, http);
|
|
45803
|
+
const client = resolveClientContext(params, auth.uin);
|
|
45804
|
+
const publishHeaders = buildPublishHeaders(cookieString, client);
|
|
45805
|
+
const microHttp = new Http({
|
|
45806
|
+
headers: publishHeaders
|
|
45807
|
+
});
|
|
45414
45808
|
const args = [
|
|
45415
45809
|
{
|
|
45416
|
-
headers
|
|
45810
|
+
headers: publishHeaders
|
|
45417
45811
|
},
|
|
45418
45812
|
task.logger,
|
|
45419
45813
|
params.proxyLoc,
|
|
45420
45814
|
params.accountId,
|
|
45421
45815
|
"shipinhao"
|
|
45422
45816
|
];
|
|
45423
|
-
const http = new Http({
|
|
45424
|
-
headers
|
|
45425
|
-
});
|
|
45426
45817
|
const proxyHttp = new Http(...args);
|
|
45427
|
-
currentStep = "
|
|
45428
|
-
|
|
45429
|
-
if (!params.coverPath) return utils_response(414, "封面图片路径不能为空", "");
|
|
45430
|
-
currentStep = "获取上传认证";
|
|
45431
|
-
task.logger.info("[shipinhaoPublishVideo] 获取上传认证...");
|
|
45432
|
-
const auth = await getShipinhaoUploadAuth(cookieString, http);
|
|
45433
|
-
currentStep = "解析视频元数据";
|
|
45434
|
-
task.logger.info("[shipinhaoPublishVideo] 解析视频元数据...");
|
|
45435
|
-
const videoMeta = parseVideoMeta(params.videoPath);
|
|
45436
|
-
if (!videoMeta) return utils_response(414, "视频文件解析失败,请检查文件格式(仅支持 MP4)", "");
|
|
45818
|
+
currentStep = "组装视频元数据";
|
|
45819
|
+
const videoMeta = buildVideoMetaFromParams(params.videoPath, params.videoMetadata);
|
|
45437
45820
|
task.logger.info(`[shipinhaoPublishVideo] 视频: ${videoMeta.width}×${videoMeta.height}, ${videoMeta.duration.toFixed(2)}s, ${(videoMeta.fileSize / 1024 / 1024).toFixed(2)}MB, codec=${videoMeta.codec || "unknown"}`);
|
|
45438
45821
|
currentStep = "校验视频限制";
|
|
45439
45822
|
const validationError = validateShipinhaoVideo(params.videoPath, videoMeta);
|
|
45440
45823
|
if (validationError) {
|
|
45441
|
-
task.logger.error(`[shipinhaoPublishVideo] 视频校验未通过: ${validationError}`);
|
|
45442
45824
|
await updateTaskState?.({
|
|
45443
45825
|
state: types_TaskState.FAILED,
|
|
45444
45826
|
error: validationError
|
|
45445
45827
|
});
|
|
45446
45828
|
return utils_response(414, validationError, "");
|
|
45447
45829
|
}
|
|
45448
|
-
task.logger.info("[shipinhaoPublishVideo] 视频校验通过");
|
|
45449
45830
|
currentStep = "校验标题";
|
|
45450
45831
|
const titleError = validateShipinhaoTitle(params.title);
|
|
45451
45832
|
if (titleError) {
|
|
45452
|
-
task.logger.error(`[shipinhaoPublishVideo] 标题校验未通过: ${titleError}`);
|
|
45453
45833
|
await updateTaskState?.({
|
|
45454
45834
|
state: types_TaskState.FAILED,
|
|
45455
45835
|
error: titleError
|
|
@@ -45457,14 +45837,14 @@ var __webpack_exports__ = {};
|
|
|
45457
45837
|
return utils_response(414, titleError, "");
|
|
45458
45838
|
}
|
|
45459
45839
|
currentStep = "获取 traceKey";
|
|
45460
|
-
task.logger
|
|
45461
|
-
|
|
45840
|
+
const traceKey = await getTraceKey(auth, client, microHttp, task.logger);
|
|
45841
|
+
let tagKey = null;
|
|
45842
|
+
if (params.tagInfo) {
|
|
45843
|
+
currentStep = "获取内容声明 tagKey";
|
|
45844
|
+
tagKey = await getObjectTagKey(auth, client, microHttp, task.logger);
|
|
45845
|
+
}
|
|
45462
45846
|
const uploadStartTime = Math.floor(Date.now() / 1000);
|
|
45463
|
-
task.logger.info(`[shipinhaoPublishVideo] 上传开始时间: ${uploadStartTime}`);
|
|
45464
45847
|
currentStep = "上传视频";
|
|
45465
|
-
task.logger.info("[shipinhaoPublishVideo] 上传视频...");
|
|
45466
|
-
task.logger.info(`[shipinhaoPublishVideo] 视频路径: ${params.videoPath}`);
|
|
45467
|
-
task.logger.info(`[shipinhaoPublishVideo] 视频文件类型: ${auth.videoFileType}`);
|
|
45468
45848
|
const videoUpload = await uploader_uploadFile({
|
|
45469
45849
|
filePath: params.videoPath,
|
|
45470
45850
|
fileType: auth.videoFileType,
|
|
@@ -45473,24 +45853,32 @@ var __webpack_exports__ = {};
|
|
|
45473
45853
|
http,
|
|
45474
45854
|
logger: task.logger
|
|
45475
45855
|
});
|
|
45476
|
-
task.logger.info(`[shipinhaoPublishVideo] 视频上传完成,URL: ${videoUpload.downloadUrl}`);
|
|
45477
45856
|
const uploadEndTime = Math.floor(Date.now() / 1000);
|
|
45478
|
-
task.logger.info(`[shipinhaoPublishVideo]
|
|
45479
|
-
currentStep = "
|
|
45480
|
-
task.
|
|
45481
|
-
task.logger.info(`[shipinhaoPublishVideo] 封面路径: ${params.coverPath}`);
|
|
45482
|
-
task.logger.info(`[shipinhaoPublishVideo] 封面文件类型: ${auth.pictureFileType}`);
|
|
45857
|
+
task.logger.info(`[shipinhaoPublishVideo] 耗时: ${uploadEndTime - uploadStartTime}s`);
|
|
45858
|
+
currentStep = "上传横屏封面";
|
|
45859
|
+
const localCoverPath = await resolveLocalCoverPath(params.coverPath, "横屏封面", task.getTmpPath(), task.logger);
|
|
45483
45860
|
const coverUpload = await uploader_uploadFile({
|
|
45484
|
-
filePath:
|
|
45861
|
+
filePath: localCoverPath,
|
|
45485
45862
|
fileType: auth.pictureFileType,
|
|
45486
45863
|
uin: auth.uin,
|
|
45487
45864
|
authKey: auth.authKey,
|
|
45488
45865
|
http,
|
|
45489
45866
|
logger: task.logger
|
|
45490
45867
|
});
|
|
45491
|
-
|
|
45868
|
+
let verticalCoverUpload = coverUpload;
|
|
45869
|
+
if (params.verticalCoverPath) {
|
|
45870
|
+
currentStep = "上传竖屏封面";
|
|
45871
|
+
const localVerticalPath = await resolveLocalCoverPath(params.verticalCoverPath, "竖屏封面", task.getTmpPath(), task.logger);
|
|
45872
|
+
verticalCoverUpload = await uploader_uploadFile({
|
|
45873
|
+
filePath: localVerticalPath,
|
|
45874
|
+
fileType: auth.pictureFileType,
|
|
45875
|
+
uin: auth.uin,
|
|
45876
|
+
authKey: auth.authKey,
|
|
45877
|
+
http,
|
|
45878
|
+
logger: task.logger
|
|
45879
|
+
});
|
|
45880
|
+
}
|
|
45492
45881
|
currentStep = "提交转码";
|
|
45493
|
-
task.logger.info("[shipinhaoPublishVideo] 提交转码...");
|
|
45494
45882
|
const clipResult = await submitAndPollTranscode({
|
|
45495
45883
|
videoUrl: videoUpload.downloadUrl,
|
|
45496
45884
|
videoMeta,
|
|
@@ -45498,21 +45886,24 @@ var __webpack_exports__ = {};
|
|
|
45498
45886
|
uploadStartTime,
|
|
45499
45887
|
uploadEndTime,
|
|
45500
45888
|
finderUsername: auth.finderUsername,
|
|
45501
|
-
|
|
45889
|
+
client,
|
|
45890
|
+
http: microHttp,
|
|
45502
45891
|
logger: task.logger
|
|
45503
45892
|
});
|
|
45504
45893
|
currentStep = "发布视频";
|
|
45505
|
-
task.logger.info("[shipinhaoPublishVideo] 发布视频...");
|
|
45506
|
-
task.logger.info(`[shipinhaoPublishVideo] clipKey: ${clipResult.clipKey}`);
|
|
45507
45894
|
let publishResult;
|
|
45508
45895
|
try {
|
|
45509
45896
|
publishResult = await publishVideo({
|
|
45510
45897
|
params,
|
|
45511
45898
|
auth,
|
|
45899
|
+
client,
|
|
45512
45900
|
clipResult,
|
|
45513
45901
|
videoUpload,
|
|
45514
45902
|
coverUpload,
|
|
45903
|
+
verticalCoverUpload,
|
|
45904
|
+
videoMeta,
|
|
45515
45905
|
traceKey,
|
|
45906
|
+
tagKey,
|
|
45516
45907
|
uploadStartTime,
|
|
45517
45908
|
uploadEndTime,
|
|
45518
45909
|
proxyHttp,
|
|
@@ -45524,7 +45915,6 @@ var __webpack_exports__ = {};
|
|
|
45524
45915
|
const classified = classifyPublishError(handledError);
|
|
45525
45916
|
if (classified) {
|
|
45526
45917
|
const message = `${classified.userMessage}${task.debug ? ` ${http.proxyInfo}` : ""}`;
|
|
45527
|
-
task.logger.error(`[shipinhaoPublishVideo] ${classified.category},直接返回: ${handledError.message} (code=${handledError.code})`, stringifyError(handledError));
|
|
45528
45918
|
await updateTaskState?.({
|
|
45529
45919
|
state: types_TaskState.FAILED,
|
|
45530
45920
|
error: message
|
|
@@ -45539,12 +45929,10 @@ var __webpack_exports__ = {};
|
|
|
45539
45929
|
}
|
|
45540
45930
|
task.logger.info(`[shipinhaoPublishVideo] publishResult: ${JSON.stringify(publishResult)}`);
|
|
45541
45931
|
const resultCode = publishResult.data?.baseResp?.errcode ?? publishResult.errCode;
|
|
45542
|
-
const resultMsg = publishResult.data?.baseResp?.errmsg ?? "发布成功";
|
|
45932
|
+
const resultMsg = publishResult.data?.baseResp?.errmsg ?? (0 === resultCode ? "发布成功" : `发布失败(errCode=${resultCode})`);
|
|
45543
45933
|
if (0 === resultCode) {
|
|
45544
|
-
|
|
45545
|
-
task.logger.
|
|
45546
|
-
task.logger.info(`[shipinhaoPublishVideo] 视频URL: ${clipResult.url}`);
|
|
45547
|
-
task.logger.info(`[shipinhaoPublishVideo] 封面URL: ${coverUpload.downloadUrl}`);
|
|
45934
|
+
const publishId = extractEncFileKey(verticalCoverUpload.downloadUrl);
|
|
45935
|
+
if (!publishId) task.logger.error(`[shipinhaoPublishVideo] 封面 DownloadURL 中未解析到 encfilekey,关联 id 为空: ${verticalCoverUpload.downloadUrl}`);
|
|
45548
45936
|
await updateTaskState?.({
|
|
45549
45937
|
state: types_TaskState.SUCCESS,
|
|
45550
45938
|
result: {
|
|
@@ -45560,41 +45948,49 @@ var __webpack_exports__ = {};
|
|
|
45560
45948
|
uid: params.uid,
|
|
45561
45949
|
publishParams: {
|
|
45562
45950
|
videoPath: params.videoPath,
|
|
45563
|
-
coverPath: params.coverPath
|
|
45951
|
+
coverPath: params.coverPath,
|
|
45952
|
+
verticalCoverPath: params.verticalCoverPath,
|
|
45953
|
+
title: params.title,
|
|
45954
|
+
topics: params.topics,
|
|
45955
|
+
mentionedUsers: params.mentionedUsers,
|
|
45956
|
+
collection: params.collection,
|
|
45957
|
+
event: params.event,
|
|
45958
|
+
link: params.link,
|
|
45959
|
+
tagInfo: params.tagInfo,
|
|
45960
|
+
originalFlag: params.originalFlag,
|
|
45961
|
+
scheduledTime: params.scheduledTime
|
|
45564
45962
|
},
|
|
45565
45963
|
platform: "shipinhao"
|
|
45566
45964
|
});
|
|
45567
|
-
|
|
45568
|
-
return utils_response(0, "发布成功", clipResult.clipKey);
|
|
45965
|
+
return utils_response(0, "发布成功", publishId);
|
|
45569
45966
|
}
|
|
45570
45967
|
let errorMessage = resultMsg;
|
|
45571
45968
|
if (-11224 === resultCode) errorMessage = "视频号管理员完成实名且绑定手机号后才可以发表";
|
|
45572
45969
|
else if (300333 === resultCode || 300334 === resultCode) errorMessage = "登录失效";
|
|
45573
45970
|
else if (300330 === resultCode) errorMessage = "未登录";
|
|
45971
|
+
else if (300002 === resultCode) errorMessage = "官方平台在校验音乐/位置/定时信息时失败了,请重新编辑后发布";
|
|
45574
45972
|
task.logger.error(`[shipinhaoPublishVideo] 发布失败: ${errorMessage} (errCode=${resultCode})`);
|
|
45575
45973
|
await updateTaskState?.({
|
|
45576
45974
|
state: types_TaskState.FAILED,
|
|
45577
45975
|
error: errorMessage
|
|
45578
45976
|
});
|
|
45579
|
-
return utils_response(
|
|
45977
|
+
return utils_response(414, errorMessage, "");
|
|
45580
45978
|
} catch (error) {
|
|
45581
45979
|
const handledError = Http.handleApiError(error);
|
|
45582
45980
|
const errorMsg = handledError.message || "发布失败,请稍后重试";
|
|
45583
|
-
const errorCode = handledError.code || 414;
|
|
45584
45981
|
task.logger.error(`[shipinhaoPublishVideo] 发布流程异常 [${currentStep}]: ${errorMsg}`, stringifyError(error), handledError.extra);
|
|
45585
|
-
task.logger.error(`[shipinhaoPublishVideo] 错误码: ${errorCode}, 当前步骤: ${currentStep}`);
|
|
45586
45982
|
await updateTaskState?.({
|
|
45587
45983
|
state: types_TaskState.FAILED,
|
|
45588
45984
|
error: errorMsg
|
|
45589
45985
|
});
|
|
45590
|
-
return utils_response(
|
|
45986
|
+
return utils_response(414, errorMsg, "");
|
|
45591
45987
|
}
|
|
45592
45988
|
};
|
|
45593
45989
|
const shipinhaoPublishVideo_rpa_rpaAction = async (task, params)=>{
|
|
45594
45990
|
task.logger.info("开始微信视频号视频发布(RPA 模式)");
|
|
45595
|
-
const videoMeta =
|
|
45596
|
-
if (!videoMeta) return utils_response(414, "视频文件解析失败,请检查文件格式(仅支持 MP4)", "");
|
|
45991
|
+
const videoMeta = buildVideoMetaFromParams(params.videoPath, params.videoMetadata);
|
|
45597
45992
|
task.logger.info(`视频: ${videoMeta.width}×${videoMeta.height}, ${videoMeta.duration.toFixed(2)}s, ${(videoMeta.fileSize / 1024 / 1024).toFixed(2)}MB, codec=${videoMeta.codec || "unknown"}`);
|
|
45993
|
+
if (!videoMeta.codec) task.logger.warn("未能读取视频编码格式,跳过 H.264 预检,交由服务端判断");
|
|
45598
45994
|
const validationError = validateShipinhaoVideo(params.videoPath, videoMeta);
|
|
45599
45995
|
if (validationError) {
|
|
45600
45996
|
task.logger.error(`视频校验未通过: ${validationError}`);
|
|
@@ -45606,6 +46002,17 @@ var __webpack_exports__ = {};
|
|
|
45606
46002
|
task.logger.error(`标题校验未通过: ${titleError}`);
|
|
45607
46003
|
return utils_response(414, titleError, "");
|
|
45608
46004
|
}
|
|
46005
|
+
const unsupported = [
|
|
46006
|
+
params.verticalCoverPath && "verticalCoverPath",
|
|
46007
|
+
params.collection && "collection",
|
|
46008
|
+
params.originalFlag && "originalFlag",
|
|
46009
|
+
params.postWithMemberZoneLink && "postWithMemberZoneLink"
|
|
46010
|
+
].filter(Boolean);
|
|
46011
|
+
if (unsupported.length) task.logger.warn(`RPA 模式不支持以下参数,将被忽略: ${unsupported.join("、")};如需生效请使用 mockApi 模式`);
|
|
46012
|
+
if (params.tagInfo && 5 === params.tagInfo.tagType) {
|
|
46013
|
+
const shootInfo = params.tagInfo.shootInfo;
|
|
46014
|
+
if (shootInfo && (shootInfo.provinceCode || shootInfo.cityCode)) task.logger.warn("tagInfo.tagType=5 在 RPA 模式下仅支持拍摄时间和国家选择,省市选择需要使用 mockApi 模式");
|
|
46015
|
+
}
|
|
45609
46016
|
const tmpCachePath = task.getTmpPath();
|
|
45610
46017
|
const page = await task.createPage({
|
|
45611
46018
|
url: "https://channels.weixin.qq.com/platform/post/create",
|
|
@@ -45716,7 +46123,12 @@ var __webpack_exports__ = {};
|
|
|
45716
46123
|
}
|
|
45717
46124
|
});
|
|
45718
46125
|
}
|
|
45719
|
-
|
|
46126
|
+
const descriptionText = payload_buildDescription({
|
|
46127
|
+
description: params.description,
|
|
46128
|
+
topics: params.topics,
|
|
46129
|
+
mentionedUsers: params.mentionedUsers
|
|
46130
|
+
});
|
|
46131
|
+
if (descriptionText) {
|
|
45720
46132
|
task.logger.info("填写视频描述");
|
|
45721
46133
|
await retryAction(async ()=>{
|
|
45722
46134
|
const descEditor = await waitForElement(".input-editor", 10000);
|
|
@@ -45728,7 +46140,7 @@ var __webpack_exports__ = {};
|
|
|
45728
46140
|
});
|
|
45729
46141
|
await page.waitForTimeout(300);
|
|
45730
46142
|
task.logger.info("已清空编辑器内容");
|
|
45731
|
-
await descEditor.pressSequentially(
|
|
46143
|
+
await descEditor.pressSequentially(descriptionText, {
|
|
45732
46144
|
delay: 10
|
|
45733
46145
|
});
|
|
45734
46146
|
await page.waitForTimeout(500);
|
|
@@ -45763,7 +46175,59 @@ var __webpack_exports__ = {};
|
|
|
45763
46175
|
await poperInstance.nth(1).click();
|
|
45764
46176
|
task.logger.info("地点选择完成");
|
|
45765
46177
|
}
|
|
45766
|
-
if (params.
|
|
46178
|
+
if (params.collection) {
|
|
46179
|
+
task.logger.info(`选择合集: ${params.collection.collectionName}`);
|
|
46180
|
+
const instanceCollection = page.locator(".post-album-display-wrap");
|
|
46181
|
+
await instanceCollection.click();
|
|
46182
|
+
await page.waitForTimeout(1000);
|
|
46183
|
+
page.locator(".post-album-wrap .option-item").filter({
|
|
46184
|
+
hasText: params.collection.collectionName
|
|
46185
|
+
}).first().click({
|
|
46186
|
+
force: true
|
|
46187
|
+
});
|
|
46188
|
+
}
|
|
46189
|
+
if (params.link) {
|
|
46190
|
+
task.logger.info(`设置扩展阅读链接: ${params.link.title}`);
|
|
46191
|
+
await page.locator(".post-link-wrap .link-display-wrap").click();
|
|
46192
|
+
await page.waitForTimeout(300);
|
|
46193
|
+
const linkTypeText = 2 === params.link.urlType ? "红包封面" : "公众号文章";
|
|
46194
|
+
await page.locator(".link-option-item .title-wrap span").filter({
|
|
46195
|
+
hasText: linkTypeText
|
|
46196
|
+
}).click();
|
|
46197
|
+
await page.waitForTimeout(300);
|
|
46198
|
+
const placeholder = 2 === params.link.urlType ? "粘贴红包封面链接" : "粘贴公众号文章链接";
|
|
46199
|
+
await page.locator(`.link-input-wrap input[placeholder="${placeholder}"]`).fill(params.link.link);
|
|
46200
|
+
await page.waitForTimeout(500);
|
|
46201
|
+
task.logger.info(`已设置${linkTypeText}: ${params.link.link}`);
|
|
46202
|
+
}
|
|
46203
|
+
if (params.event) {
|
|
46204
|
+
task.logger.info(`选择活动: ${params.event.eventName}`);
|
|
46205
|
+
await page.locator(".post-activity-wrap .activity-display").click();
|
|
46206
|
+
await page.waitForTimeout(500);
|
|
46207
|
+
await page.locator(".activity-filter-wrap .weui-desktop-form__input[placeholder='搜索活动']").fill(params.event.eventName);
|
|
46208
|
+
await page.waitForTimeout(500);
|
|
46209
|
+
const searchLoading = page.locator(".search-loading");
|
|
46210
|
+
await searchLoading.waitFor({
|
|
46211
|
+
state: "hidden",
|
|
46212
|
+
timeout: 5000
|
|
46213
|
+
}).catch(()=>{
|
|
46214
|
+
task.logger.warn("活动搜索加载超时,继续尝试选择");
|
|
46215
|
+
});
|
|
46216
|
+
const activityItem = page.locator(".option-item .activity-item .activity-item-info .name").filter({
|
|
46217
|
+
hasText: params.event.eventName
|
|
46218
|
+
});
|
|
46219
|
+
const count = await activityItem.count();
|
|
46220
|
+
if (count > 0) {
|
|
46221
|
+
await activityItem.first().click();
|
|
46222
|
+
await page.waitForTimeout(300);
|
|
46223
|
+
task.logger.info(`已选择活动: ${params.event.eventName}`);
|
|
46224
|
+
} else {
|
|
46225
|
+
task.logger.warn(`未找到活动: ${params.event.eventName},将不参与活动`);
|
|
46226
|
+
await page.locator(".post-activity-wrap .activity-display").click();
|
|
46227
|
+
await page.waitForTimeout(300);
|
|
46228
|
+
}
|
|
46229
|
+
}
|
|
46230
|
+
if (params.scheduledTime) {
|
|
45767
46231
|
task.logger.info("设置定时发布");
|
|
45768
46232
|
const timingRadio = page.locator(".weui-desktop-form__check-label").filter({
|
|
45769
46233
|
hasNotText: "不定时"
|
|
@@ -45772,10 +46236,10 @@ var __webpack_exports__ = {};
|
|
|
45772
46236
|
await page.waitForTimeout(500);
|
|
45773
46237
|
const instance = page.locator(".weui-desktop-picker__date");
|
|
45774
46238
|
await instance.click();
|
|
45775
|
-
const dateD = utils_TimeFormatter.format(1000 * params.
|
|
46239
|
+
const dateD = utils_TimeFormatter.format(1000 * params.scheduledTime, "d");
|
|
45776
46240
|
const nowMonth = utils_TimeFormatter.format(Date.now(), "MM月");
|
|
45777
46241
|
const nowMonthText = utils_TimeFormatter.format(Date.now(), "M月");
|
|
45778
|
-
const month = utils_TimeFormatter.format(1000 * params.
|
|
46242
|
+
const month = utils_TimeFormatter.format(1000 * params.scheduledTime, "MM月");
|
|
45779
46243
|
const monthLocator = await page.locator("weui-desktop-picker__panel__label").filter({
|
|
45780
46244
|
hasText: month
|
|
45781
46245
|
}).first();
|
|
@@ -45792,14 +46256,85 @@ var __webpack_exports__ = {};
|
|
|
45792
46256
|
await page.locator(".weui-desktop-picker__table-row td a").filter({
|
|
45793
46257
|
hasText: dateD
|
|
45794
46258
|
}).first().click();
|
|
45795
|
-
await page.locator(".weui-desktop-form__input-wrp input[placeholder*='请选择时间']").fill(utils_TimeFormatter.format(1000 * params.
|
|
46259
|
+
await page.locator(".weui-desktop-form__input-wrp input[placeholder*='请选择时间']").fill(utils_TimeFormatter.format(1000 * params.scheduledTime, "hh:mm"));
|
|
45796
46260
|
await page.locator("i.weui-desktop-icon__time").click();
|
|
45797
46261
|
await page.locator(".post-time-wrap .form-item .label").filter({
|
|
45798
46262
|
hasText: "发表时间"
|
|
45799
46263
|
}).click();
|
|
45800
46264
|
}
|
|
46265
|
+
if (params.tagInfo) {
|
|
46266
|
+
task.logger.info(`设置视频标注: tagType=${params.tagInfo.tagType}`);
|
|
46267
|
+
await page.locator(".mark-tag-select").click();
|
|
46268
|
+
await page.waitForTimeout(300);
|
|
46269
|
+
const tagTypeTextMap = {
|
|
46270
|
+
0: "无需标注",
|
|
46271
|
+
1: "含AI生成内容",
|
|
46272
|
+
2: "内容包含营销广告",
|
|
46273
|
+
3: "内容为虚构剧情,仅供娱乐",
|
|
46274
|
+
5: "内容为自行拍摄",
|
|
46275
|
+
7: "内容为转载",
|
|
46276
|
+
8: "个人观点,仅供参考"
|
|
46277
|
+
};
|
|
46278
|
+
const tagText = tagTypeTextMap[params.tagInfo.tagType];
|
|
46279
|
+
if (tagText) {
|
|
46280
|
+
await page.locator(".mark-tag-option .option-main").filter({
|
|
46281
|
+
hasText: tagText
|
|
46282
|
+
}).click();
|
|
46283
|
+
await page.waitForTimeout(300);
|
|
46284
|
+
if (5 === params.tagInfo.tagType) {
|
|
46285
|
+
const shootInfo = params.tagInfo.shootInfo;
|
|
46286
|
+
if (shootInfo) {
|
|
46287
|
+
task.logger.info("填写拍摄时间和地点...");
|
|
46288
|
+
await page.waitForTimeout(500);
|
|
46289
|
+
if (shootInfo.postTimestamp) {
|
|
46290
|
+
task.logger.info(`设置拍摄时间: ${shootInfo.postTimestamp}`);
|
|
46291
|
+
const timestamp = 1000 * parseInt(shootInfo.postTimestamp, 10);
|
|
46292
|
+
const date = new Date(timestamp);
|
|
46293
|
+
await page.locator(".original-dialog-content .weui-desktop-picker__date input[placeholder*='请选择拍摄时间']").click();
|
|
46294
|
+
await page.waitForTimeout(300);
|
|
46295
|
+
const dayNum = date.getDate();
|
|
46296
|
+
await page.locator(".weui-desktop-picker__table a").filter({
|
|
46297
|
+
hasText: new RegExp(`^\\s*${dayNum}\\s*$`)
|
|
46298
|
+
}).first().click();
|
|
46299
|
+
await page.waitForTimeout(300);
|
|
46300
|
+
}
|
|
46301
|
+
if (shootInfo.countryCode || shootInfo.provinceCode || shootInfo.cityCode) {
|
|
46302
|
+
task.logger.info("设置拍摄地点...");
|
|
46303
|
+
await page.locator(".original-dialog-content .weui-desktop-form__dropdowncascade .weui-desktop-form__dropdowncascade__dt").click();
|
|
46304
|
+
await page.waitForTimeout(300);
|
|
46305
|
+
if (1156 === shootInfo.countryCode) {
|
|
46306
|
+
await page.locator(".weui-desktop-dropdown__list-ele .weui-desktop-dropdown__list-ele__text").filter({
|
|
46307
|
+
hasText: "中国"
|
|
46308
|
+
}).click();
|
|
46309
|
+
await page.waitForTimeout(300);
|
|
46310
|
+
task.logger.warn("RPA 模式下暂不支持选择具体省份和城市,仅选择了国家");
|
|
46311
|
+
} else task.logger.warn(`不支持的国家代码: ${shootInfo.countryCode},跳过地点设置`);
|
|
46312
|
+
}
|
|
46313
|
+
const confirmBtn = await waitForElement(".weui-desktop-dialog .weui-desktop-btn_primary");
|
|
46314
|
+
if (confirmBtn) {
|
|
46315
|
+
await confirmBtn.click();
|
|
46316
|
+
await page.waitForTimeout(300);
|
|
46317
|
+
}
|
|
46318
|
+
} else task.logger.warn("tagType=5 需要提供 shootInfo 字段(拍摄时间和地点)");
|
|
46319
|
+
}
|
|
46320
|
+
if (7 === params.tagInfo.tagType) {
|
|
46321
|
+
const repostSource = params.tagInfo.repostSource;
|
|
46322
|
+
if (repostSource) {
|
|
46323
|
+
task.logger.info(`填写转载来源: ${repostSource}`);
|
|
46324
|
+
await page.waitForTimeout(500);
|
|
46325
|
+
await page.locator(".repost-dialog-content .repost-textarea").fill(repostSource);
|
|
46326
|
+
await page.waitForTimeout(300);
|
|
46327
|
+
const confirmBtn = await waitForElement(".weui-desktop-dialog .weui-desktop-btn_primary");
|
|
46328
|
+
if (confirmBtn) {
|
|
46329
|
+
await confirmBtn.click();
|
|
46330
|
+
await page.waitForTimeout(300);
|
|
46331
|
+
}
|
|
46332
|
+
} else task.logger.warn("tagType=7 需要提供 repostSource 字段(转载来源)");
|
|
46333
|
+
}
|
|
46334
|
+
} else task.logger.warn(`未知的 tagType: ${params.tagInfo.tagType},跳过标注设置`);
|
|
46335
|
+
}
|
|
45801
46336
|
task.logger.info("准备发布...");
|
|
45802
|
-
await page.waitForTimeout(
|
|
46337
|
+
await page.waitForTimeout(500);
|
|
45803
46338
|
let videoId = "";
|
|
45804
46339
|
const handleResponse = async (response)=>{
|
|
45805
46340
|
const url = response.url();
|
|
@@ -45865,19 +46400,60 @@ var __webpack_exports__ = {};
|
|
|
45865
46400
|
};
|
|
45866
46401
|
const ShipinhaoPublishVideoParamsSchema = ActionCommonParamsSchema.extend({
|
|
45867
46402
|
videoPath: classic_schemas_string().min(1),
|
|
46403
|
+
videoMetadata: classic_schemas_object({
|
|
46404
|
+
duration: classic_schemas_number().positive(),
|
|
46405
|
+
width: classic_schemas_number().int().positive(),
|
|
46406
|
+
height: classic_schemas_number().int().positive(),
|
|
46407
|
+
fileSize: classic_schemas_number().int().positive(),
|
|
46408
|
+
path: classic_schemas_string().min(1).optional(),
|
|
46409
|
+
fileName: classic_schemas_string().min(1)
|
|
46410
|
+
}),
|
|
45868
46411
|
coverPath: classic_schemas_string().min(1),
|
|
46412
|
+
verticalCoverPath: classic_schemas_string().min(1).optional(),
|
|
45869
46413
|
description: classic_schemas_string(),
|
|
45870
46414
|
title: classic_schemas_string().optional(),
|
|
45871
|
-
|
|
46415
|
+
scheduledTime: classic_schemas_number().int().positive().optional(),
|
|
46416
|
+
isImmediatelyPublish: classic_schemas_boolean().optional(),
|
|
46417
|
+
topics: classic_schemas_array(classic_schemas_string()).optional(),
|
|
46418
|
+
mentionedUsers: classic_schemas_array(classic_schemas_object({
|
|
46419
|
+
nickname: classic_schemas_string()
|
|
46420
|
+
})).optional(),
|
|
46421
|
+
collection: classic_schemas_object({
|
|
46422
|
+
collectionId: classic_schemas_string(),
|
|
46423
|
+
collectionName: classic_schemas_string()
|
|
46424
|
+
}).optional(),
|
|
46425
|
+
event: classic_schemas_object({
|
|
46426
|
+
eventTopicId: classic_schemas_string(),
|
|
46427
|
+
eventName: classic_schemas_string(),
|
|
46428
|
+
eventCreatorNickname: classic_schemas_string().optional()
|
|
46429
|
+
}).optional(),
|
|
46430
|
+
link: classic_schemas_object({
|
|
46431
|
+
link: classic_schemas_string(),
|
|
46432
|
+
title: classic_schemas_string(),
|
|
46433
|
+
urlType: classic_schemas_number().int().default(1)
|
|
46434
|
+
}).optional(),
|
|
46435
|
+
tagInfo: looseObject({
|
|
46436
|
+
tagType: classic_schemas_number().int()
|
|
46437
|
+
}).optional(),
|
|
46438
|
+
originalFlag: schemas_union([
|
|
46439
|
+
literal(0),
|
|
46440
|
+
literal(1)
|
|
46441
|
+
]).optional(),
|
|
46442
|
+
postWithMemberZoneLink: schemas_union([
|
|
46443
|
+
literal(0),
|
|
46444
|
+
literal(1)
|
|
46445
|
+
]).optional(),
|
|
45872
46446
|
location: classic_schemas_object({
|
|
45873
46447
|
latitude: classic_schemas_number(),
|
|
45874
46448
|
longitude: classic_schemas_number(),
|
|
45875
46449
|
city: classic_schemas_string(),
|
|
46450
|
+
poiName: classic_schemas_string().optional(),
|
|
46451
|
+
address: classic_schemas_string().optional(),
|
|
45876
46452
|
poiClassifyId: classic_schemas_string().optional()
|
|
45877
46453
|
}).optional()
|
|
45878
46454
|
});
|
|
45879
46455
|
const shipinhaoPublishVideo = async (task, params)=>{
|
|
45880
|
-
task.logger.info(`shipinhaoPublishVideo actionType: ${params.actionType}`);
|
|
46456
|
+
task.logger.info(`[shipinhaoPublishVideo] actionType: ${params.actionType}`);
|
|
45881
46457
|
if ("rpa" === params.actionType) return shipinhaoPublishVideo_rpa_rpaAction(task, params);
|
|
45882
46458
|
if ("mockApi" === params.actionType) return shipinhaoPublishVideo_mock_mockAction(task, params);
|
|
45883
46459
|
return executeAction(shipinhaoPublishVideo_mock_mockAction, shipinhaoPublishVideo_rpa_rpaAction)(task, params);
|
|
@@ -51979,4 +52555,4 @@ if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_targe
|
|
|
51979
52555
|
});
|
|
51980
52556
|
|
|
51981
52557
|
//# sourceMappingURL=bundle.js.map
|
|
51982
|
-
//# debugId=
|
|
52558
|
+
//# debugId=bf64112a-57bc-5eae-9ede-8d23fc55671f
|