beervid-app-cli 0.2.0 → 0.2.2
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/README.md +26 -7
- package/SKILL.md +16 -8
- package/agents/openai.yaml +7 -0
- package/dist/cli.mjs +210 -217
- package/package.json +3 -1
- package/references/api-reference.md +605 -0
package/dist/cli.mjs
CHANGED
|
@@ -371,12 +371,11 @@ function register4(cli2) {
|
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
// src/commands/poll-status.ts
|
|
374
|
-
var TERMINAL_STATUSES = ["PUBLISH_COMPLETE", "FAILED"];
|
|
375
374
|
function sleep(ms) {
|
|
376
375
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
377
376
|
}
|
|
378
377
|
function register5(cli2) {
|
|
379
|
-
cli2.command("poll-status", "\u8F6E\u8BE2\u666E\u901A\u89C6\u9891\u53D1\u5E03\u72B6\u6001").option("--business-id <id>", "TT \u8D26\u53F7 businessId\uFF08\u5FC5\u586B\uFF09").option("--share-id <id>", "\u53D1\u5E03\u65F6\u8FD4\u56DE\u7684 shareId\uFF08\u5FC5\u586B\uFF09").option("--interval <sec>", "\u8F6E\u8BE2\u95F4\u9694\u79D2\u6570\uFF08\u9ED8\u8BA4
|
|
378
|
+
cli2.command("poll-status", "\u8F6E\u8BE2\u666E\u901A\u89C6\u9891\u53D1\u5E03\u72B6\u6001").option("--business-id <id>", "TT \u8D26\u53F7 businessId\uFF08\u5FC5\u586B\uFF09").option("--share-id <id>", "\u53D1\u5E03\u65F6\u8FD4\u56DE\u7684 shareId\uFF08\u5FC5\u586B\uFF09").option("--interval <sec>", "\u8F6E\u8BE2\u95F4\u9694\u79D2\u6570\uFF08\u9ED8\u8BA4 5\uFF09").option("--max-polls <n>", "\u6700\u5927\u8F6E\u8BE2\u6B21\u6570\uFF08\u9ED8\u8BA4 60\uFF09").action(
|
|
380
379
|
async (options) => {
|
|
381
380
|
if (!options.businessId || !options.shareId) {
|
|
382
381
|
const missing = [
|
|
@@ -388,7 +387,7 @@ function register5(cli2) {
|
|
|
388
387
|
console.error("\u7528\u6CD5: beervid poll-status --business-id <id> --share-id <id>");
|
|
389
388
|
process.exit(1);
|
|
390
389
|
}
|
|
391
|
-
const intervalSec = parseInt(options.interval ?? "
|
|
390
|
+
const intervalSec = parseInt(options.interval ?? "5", 10);
|
|
392
391
|
const maxPolls = parseInt(options.maxPolls ?? "60", 10);
|
|
393
392
|
if (Number.isNaN(intervalSec) || intervalSec <= 0) {
|
|
394
393
|
console.error("\u9519\u8BEF: --interval \u5FC5\u987B\u4E3A\u5927\u4E8E 0 \u7684\u6574\u6570");
|
|
@@ -403,35 +402,43 @@ function register5(cli2) {
|
|
|
403
402
|
console.log(`businessId: ${options.businessId}`);
|
|
404
403
|
console.log(`shareId: ${options.shareId}
|
|
405
404
|
`);
|
|
405
|
+
let lastStatus = "UNKNOWN";
|
|
406
406
|
for (let i = 1; i <= maxPolls; i++) {
|
|
407
407
|
const data = await openApiPost("/api/v1/open/tiktok/video/status", {
|
|
408
408
|
businessId: options.businessId,
|
|
409
409
|
shareId: options.shareId
|
|
410
410
|
});
|
|
411
411
|
const status = data.status ?? data.Status ?? "UNKNOWN";
|
|
412
|
+
const postIds = data.post_ids ?? [];
|
|
413
|
+
lastStatus = status;
|
|
412
414
|
console.log(`[${i}/${maxPolls}] \u72B6\u6001: ${status}`);
|
|
413
|
-
if (
|
|
415
|
+
if (status === "FAILED") {
|
|
414
416
|
console.log("");
|
|
415
|
-
|
|
416
|
-
console.log("\u53D1\u5E03\u6210\u529F!");
|
|
417
|
-
if (data.post_ids && data.post_ids.length > 0) {
|
|
418
|
-
console.log(`\u89C6\u9891 ID: ${data.post_ids[0]}`);
|
|
419
|
-
console.log(
|
|
420
|
-
`\u63D0\u793A: \u4F7F\u7528 beervid query-video --business-id ${options.businessId} --item-ids ${data.post_ids[0]} \u67E5\u8BE2\u6570\u636E`
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
} else {
|
|
424
|
-
console.log(`\u53D1\u5E03\u5931\u8D25: ${data.reason ?? "\u672A\u77E5\u539F\u56E0"}`);
|
|
425
|
-
}
|
|
417
|
+
console.log(`\u53D1\u5E03\u5931\u8D25: ${data.reason ?? "\u672A\u77E5\u539F\u56E0"}`);
|
|
426
418
|
printResult(data);
|
|
427
|
-
process.exit(
|
|
419
|
+
process.exit(1);
|
|
420
|
+
}
|
|
421
|
+
if (status === "PUBLISH_COMPLETE" && postIds.length > 0) {
|
|
422
|
+
console.log("");
|
|
423
|
+
console.log("\u53D1\u5E03\u6210\u529F!");
|
|
424
|
+
console.log(`\u89C6\u9891 ID: ${postIds[0]}`);
|
|
425
|
+
console.log(
|
|
426
|
+
`\u63D0\u793A: \u4F7F\u7528 beervid query-video --business-id ${options.businessId} --item-ids ${postIds[0]} \u67E5\u8BE2\u6570\u636E`
|
|
427
|
+
);
|
|
428
|
+
printResult(data);
|
|
429
|
+
process.exit(0);
|
|
428
430
|
}
|
|
429
431
|
if (i < maxPolls) {
|
|
430
432
|
await sleep(intervalSec * 1e3);
|
|
431
433
|
}
|
|
432
434
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
+
if (lastStatus === "PUBLISH_COMPLETE") {
|
|
436
|
+
console.error(`
|
|
437
|
+
\u8D85\u8FC7\u6700\u5927\u8F6E\u8BE2\u6B21\u6570 (${maxPolls})\uFF0C\u72B6\u6001\u4E3A PUBLISH_COMPLETE \u4F46 post_ids \u4ECD\u4E3A\u7A7A`);
|
|
438
|
+
} else {
|
|
439
|
+
console.error(`
|
|
440
|
+
\u8D85\u8FC7\u6700\u5927\u8F6E\u8BE2\u6B21\u6570 (${maxPolls})\uFF0C\u4ECD\u672A\u62FF\u5230 post_ids`);
|
|
441
|
+
}
|
|
435
442
|
process.exit(2);
|
|
436
443
|
} catch (err) {
|
|
437
444
|
rethrowIfProcessExit(err);
|
|
@@ -504,139 +511,10 @@ function register6(cli2) {
|
|
|
504
511
|
);
|
|
505
512
|
}
|
|
506
513
|
|
|
507
|
-
// src/commands/query-products.ts
|
|
508
|
-
var VALID_PRODUCT_TYPES = ["shop", "showcase", "all"];
|
|
509
|
-
function extractImageUrl(imageStr) {
|
|
510
|
-
const match = imageStr.match(/url=([^,}]+)/);
|
|
511
|
-
return match?.[1]?.trim() ?? imageStr;
|
|
512
|
-
}
|
|
513
|
-
async function queryProducts(creatorId, type, pageSize, pageToken) {
|
|
514
|
-
return openApiPost("/api/v1/open/tts/products/query", {
|
|
515
|
-
creatorUserOpenId: creatorId,
|
|
516
|
-
productType: type,
|
|
517
|
-
pageSize,
|
|
518
|
-
pageToken
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
function register7(cli2) {
|
|
522
|
-
cli2.command("query-products", "\u67E5\u8BE2 TTS \u5546\u54C1\u5217\u8868").option("--creator-id <id>", "TTS \u8D26\u53F7 creatorUserOpenId\uFF08\u5FC5\u586B\uFF09").option("--product-type <type>", "\u5546\u54C1\u6765\u6E90: shop / showcase / all\uFF08\u9ED8\u8BA4 all\uFF09").option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09").option("--cursor <cursor>", "\u5206\u9875\u6E38\u6807\uFF08\u9996\u9875\u4E0D\u4F20\uFF09").action(
|
|
523
|
-
async (options) => {
|
|
524
|
-
if (!options.creatorId) {
|
|
525
|
-
console.error("\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570: --creator-id\n");
|
|
526
|
-
console.error("\u7528\u6CD5: beervid query-products --creator-id <id>");
|
|
527
|
-
process.exit(1);
|
|
528
|
-
}
|
|
529
|
-
const creatorId = options.creatorId;
|
|
530
|
-
const productType = (options.productType ?? "all").toLowerCase();
|
|
531
|
-
const pageSize = parseInt(options.pageSize ?? "20", 10);
|
|
532
|
-
const cursor = options.cursor ?? "";
|
|
533
|
-
if (!VALID_PRODUCT_TYPES.includes(productType)) {
|
|
534
|
-
console.error("\u9519\u8BEF: --product-type \u5FC5\u987B\u4E3A shop\u3001showcase \u6216 all");
|
|
535
|
-
process.exit(1);
|
|
536
|
-
}
|
|
537
|
-
if (Number.isNaN(pageSize) || pageSize <= 0) {
|
|
538
|
-
console.error("\u9519\u8BEF: --page-size \u5FC5\u987B\u4E3A\u5927\u4E8E 0 \u7684\u6574\u6570");
|
|
539
|
-
process.exit(1);
|
|
540
|
-
}
|
|
541
|
-
try {
|
|
542
|
-
let shopToken = "";
|
|
543
|
-
let showcaseToken = "";
|
|
544
|
-
if (cursor) {
|
|
545
|
-
try {
|
|
546
|
-
const decoded = JSON.parse(
|
|
547
|
-
Buffer.from(cursor, "base64").toString()
|
|
548
|
-
);
|
|
549
|
-
shopToken = decoded.shopToken ?? "";
|
|
550
|
-
showcaseToken = decoded.showcaseToken ?? "";
|
|
551
|
-
} catch {
|
|
552
|
-
console.error("\u9519\u8BEF: \u65E0\u6548\u7684 cursor \u683C\u5F0F");
|
|
553
|
-
process.exit(1);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
const typesToQuery = productType === "all" ? ["shop", "showcase"] : [productType];
|
|
557
|
-
const allProducts = /* @__PURE__ */ new Map();
|
|
558
|
-
let nextShopToken = null;
|
|
559
|
-
let nextShowcaseToken = null;
|
|
560
|
-
let successCount = 0;
|
|
561
|
-
const results = await Promise.allSettled(
|
|
562
|
-
typesToQuery.map(async (type) => {
|
|
563
|
-
const token = type === "shop" ? shopToken : showcaseToken;
|
|
564
|
-
const data = await queryProducts(creatorId, type, pageSize, token);
|
|
565
|
-
return { type, data };
|
|
566
|
-
})
|
|
567
|
-
);
|
|
568
|
-
for (const result of results) {
|
|
569
|
-
if (result.status === "rejected") {
|
|
570
|
-
console.error("\u67E5\u8BE2\u5931\u8D25:", result.reason?.message);
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
const { type, data } = result.value;
|
|
574
|
-
successCount += 1;
|
|
575
|
-
const items = Array.isArray(data) ? data : [data];
|
|
576
|
-
for (const group of items) {
|
|
577
|
-
if (type === "shop") nextShopToken = group.nextPageToken ?? null;
|
|
578
|
-
if (type === "showcase") nextShowcaseToken = group.nextPageToken ?? null;
|
|
579
|
-
for (const product of group.products ?? []) {
|
|
580
|
-
if (!allProducts.has(product.id)) {
|
|
581
|
-
allProducts.set(product.id, {
|
|
582
|
-
id: product.id,
|
|
583
|
-
title: product.title,
|
|
584
|
-
price: product.price,
|
|
585
|
-
images: (product.images ?? []).map(extractImageUrl),
|
|
586
|
-
salesCount: product.salesCount ?? 0,
|
|
587
|
-
brandName: product.brandName ?? "",
|
|
588
|
-
shopName: product.shopName ?? "",
|
|
589
|
-
source: product.source ?? type,
|
|
590
|
-
reviewStatus: product.reviewStatus,
|
|
591
|
-
inventoryStatus: product.inventoryStatus
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
if (successCount === 0) {
|
|
598
|
-
console.error("\u67E5\u8BE2\u5546\u54C1\u5931\u8D25: \u6240\u6709\u5546\u54C1\u6E90\u90FD\u8BF7\u6C42\u5931\u8D25");
|
|
599
|
-
process.exit(1);
|
|
600
|
-
}
|
|
601
|
-
const productList = Array.from(allProducts.values());
|
|
602
|
-
let nextCursor = null;
|
|
603
|
-
if (nextShopToken || nextShowcaseToken) {
|
|
604
|
-
nextCursor = Buffer.from(
|
|
605
|
-
JSON.stringify({
|
|
606
|
-
shopToken: nextShopToken ?? "",
|
|
607
|
-
showcaseToken: nextShowcaseToken ?? ""
|
|
608
|
-
})
|
|
609
|
-
).toString("base64");
|
|
610
|
-
}
|
|
611
|
-
console.log(`\u67E5\u8BE2\u5230 ${productList.length} \u4E2A\u5546\u54C1:
|
|
612
|
-
`);
|
|
613
|
-
for (const p of productList) {
|
|
614
|
-
console.log(` [${p.source}] ${p.title}`);
|
|
615
|
-
console.log(` ID: ${p.id} \u9500\u91CF: ${p.salesCount} \u54C1\u724C: ${p.brandName}`);
|
|
616
|
-
if (p.images.length > 0) console.log(` \u56FE\u7247: ${p.images[0]}`);
|
|
617
|
-
console.log("");
|
|
618
|
-
}
|
|
619
|
-
if (nextCursor) {
|
|
620
|
-
console.log(`\u4E0B\u4E00\u9875\u6E38\u6807: ${nextCursor}`);
|
|
621
|
-
console.log(`\u4F7F\u7528: beervid query-products --creator-id ${creatorId} --cursor ${nextCursor}`);
|
|
622
|
-
} else {
|
|
623
|
-
console.log("\u5DF2\u5230\u6700\u540E\u4E00\u9875");
|
|
624
|
-
}
|
|
625
|
-
printResult({ products: productList, nextCursor });
|
|
626
|
-
} catch (err) {
|
|
627
|
-
rethrowIfProcessExit(err);
|
|
628
|
-
console.error("\u67E5\u8BE2\u5546\u54C1\u5931\u8D25:", err.message);
|
|
629
|
-
process.exit(1);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
514
|
// src/workflows/index.ts
|
|
636
515
|
import { createInterface } from "readline/promises";
|
|
637
516
|
import { stdin as input, stdout as output } from "process";
|
|
638
517
|
var MAX_PRODUCT_TITLE_LENGTH2 = 29;
|
|
639
|
-
var TERMINAL_STATUSES2 = ["PUBLISH_COMPLETE", "FAILED"];
|
|
640
518
|
function sleep2(ms) {
|
|
641
519
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
642
520
|
}
|
|
@@ -662,18 +540,32 @@ async function publishTtsVideo(creatorId, fileId, productId, productTitle, capti
|
|
|
662
540
|
return { publish, productTitle: normalizedTitle };
|
|
663
541
|
}
|
|
664
542
|
async function pollNormalVideoStatus(businessId, shareId, intervalSec, maxPolls) {
|
|
543
|
+
let lastData = null;
|
|
544
|
+
let lastStatus = "UNKNOWN";
|
|
665
545
|
for (let i = 1; i <= maxPolls; i++) {
|
|
666
546
|
const data = await openApiPost("/api/v1/open/tiktok/video/status", {
|
|
667
547
|
businessId,
|
|
668
548
|
shareId
|
|
669
549
|
});
|
|
550
|
+
lastData = data;
|
|
670
551
|
const status = data.status ?? data.Status ?? "UNKNOWN";
|
|
671
|
-
|
|
552
|
+
const postIds = data.post_ids ?? [];
|
|
553
|
+
lastStatus = status;
|
|
554
|
+
if (status === "FAILED") {
|
|
672
555
|
return {
|
|
673
556
|
pollCount: i,
|
|
674
557
|
finalStatus: status,
|
|
675
558
|
reason: data.reason ?? null,
|
|
676
|
-
postIds
|
|
559
|
+
postIds,
|
|
560
|
+
raw: data
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
if (status === "PUBLISH_COMPLETE" && postIds.length > 0) {
|
|
564
|
+
return {
|
|
565
|
+
pollCount: i,
|
|
566
|
+
finalStatus: status,
|
|
567
|
+
reason: data.reason ?? null,
|
|
568
|
+
postIds,
|
|
677
569
|
raw: data
|
|
678
570
|
};
|
|
679
571
|
}
|
|
@@ -684,9 +576,9 @@ async function pollNormalVideoStatus(businessId, shareId, intervalSec, maxPolls)
|
|
|
684
576
|
return {
|
|
685
577
|
pollCount: maxPolls,
|
|
686
578
|
finalStatus: "TIMEOUT",
|
|
687
|
-
reason: `\u8D85\u8FC7\u6700\u5927\u8F6E\u8BE2\u6B21\u6570 (${maxPolls})\uFF0C\u72B6\u6001\u4ECD\u672A\
|
|
579
|
+
reason: lastStatus === "PUBLISH_COMPLETE" ? `\u8D85\u8FC7\u6700\u5927\u8F6E\u8BE2\u6B21\u6570 (${maxPolls})\uFF0C\u72B6\u6001\u4E3A PUBLISH_COMPLETE \u4F46 post_ids \u4ECD\u4E3A\u7A7A` : `\u8D85\u8FC7\u6700\u5927\u8F6E\u8BE2\u6B21\u6570 (${maxPolls})\uFF0C\u4ECD\u672A\u62FF\u5230 post_ids`,
|
|
688
580
|
postIds: [],
|
|
689
|
-
raw:
|
|
581
|
+
raw: lastData
|
|
690
582
|
};
|
|
691
583
|
}
|
|
692
584
|
function normalizeVideoQuery(data) {
|
|
@@ -728,25 +620,30 @@ async function queryVideoWithRetry(businessId, itemId, intervalSec, maxAttempts)
|
|
|
728
620
|
});
|
|
729
621
|
return { query: null, warnings };
|
|
730
622
|
}
|
|
731
|
-
function
|
|
623
|
+
function extractImageUrl(imageStr) {
|
|
732
624
|
const match = imageStr.match(/url=([^,}]+)/);
|
|
733
625
|
return match?.[1]?.trim() ?? imageStr;
|
|
734
626
|
}
|
|
735
627
|
function decodeCursor(cursor) {
|
|
736
628
|
const decoded = JSON.parse(Buffer.from(cursor, "base64").toString());
|
|
737
629
|
return {
|
|
738
|
-
shopToken: decoded.shopToken
|
|
739
|
-
showcaseToken: decoded.showcaseToken
|
|
630
|
+
shopToken: decoded.shopToken === void 0 ? "" : decoded.shopToken,
|
|
631
|
+
showcaseToken: decoded.showcaseToken === void 0 ? "" : decoded.showcaseToken
|
|
740
632
|
};
|
|
741
633
|
}
|
|
742
634
|
function encodeCursor(cursor) {
|
|
635
|
+
if (cursor.shopToken === null && cursor.showcaseToken === null) return null;
|
|
743
636
|
return Buffer.from(JSON.stringify(cursor)).toString("base64");
|
|
744
637
|
}
|
|
745
638
|
async function queryProductsPage(creatorId, productType, pageSize, cursor) {
|
|
746
|
-
const
|
|
639
|
+
const allTypesToQuery = productType === "all" ? ["shop", "showcase"] : [productType];
|
|
640
|
+
const typesToQuery = allTypesToQuery.filter((type) => {
|
|
641
|
+
const token = type === "shop" ? cursor.shopToken : cursor.showcaseToken;
|
|
642
|
+
return token !== null;
|
|
643
|
+
});
|
|
747
644
|
const allProducts = /* @__PURE__ */ new Map();
|
|
748
|
-
let nextShopToken =
|
|
749
|
-
let nextShowcaseToken =
|
|
645
|
+
let nextShopToken = cursor.shopToken;
|
|
646
|
+
let nextShowcaseToken = cursor.showcaseToken;
|
|
750
647
|
let successCount = 0;
|
|
751
648
|
const failedSources = [];
|
|
752
649
|
const results = await Promise.allSettled(
|
|
@@ -756,7 +653,7 @@ async function queryProductsPage(creatorId, productType, pageSize, cursor) {
|
|
|
756
653
|
creatorUserOpenId: creatorId,
|
|
757
654
|
productType: type,
|
|
758
655
|
pageSize,
|
|
759
|
-
pageToken
|
|
656
|
+
pageToken: pageToken ?? ""
|
|
760
657
|
});
|
|
761
658
|
return { type, data };
|
|
762
659
|
})
|
|
@@ -773,15 +670,16 @@ async function queryProductsPage(creatorId, productType, pageSize, cursor) {
|
|
|
773
670
|
const { data } = result.value;
|
|
774
671
|
const groups = Array.isArray(data) ? data : [data];
|
|
775
672
|
for (const group of groups) {
|
|
776
|
-
|
|
777
|
-
if (type === "
|
|
673
|
+
const token = group.nextPageToken === void 0 ? null : group.nextPageToken;
|
|
674
|
+
if (type === "shop") nextShopToken = token;
|
|
675
|
+
if (type === "showcase") nextShowcaseToken = token;
|
|
778
676
|
for (const product of group.products ?? []) {
|
|
779
677
|
if (!allProducts.has(product.id)) {
|
|
780
678
|
allProducts.set(product.id, {
|
|
781
679
|
id: product.id,
|
|
782
680
|
title: product.title,
|
|
783
681
|
price: product.price,
|
|
784
|
-
images: (product.images ?? []).map(
|
|
682
|
+
images: (product.images ?? []).map(extractImageUrl),
|
|
785
683
|
salesCount: product.salesCount ?? 0,
|
|
786
684
|
brandName: product.brandName ?? "",
|
|
787
685
|
shopName: product.shopName ?? "",
|
|
@@ -793,7 +691,7 @@ async function queryProductsPage(creatorId, productType, pageSize, cursor) {
|
|
|
793
691
|
}
|
|
794
692
|
}
|
|
795
693
|
}
|
|
796
|
-
const nextCursor =
|
|
694
|
+
const nextCursor = encodeCursor({ shopToken: nextShopToken, showcaseToken: nextShowcaseToken });
|
|
797
695
|
return {
|
|
798
696
|
products: Array.from(allProducts.values()),
|
|
799
697
|
nextCursor,
|
|
@@ -840,8 +738,24 @@ async function fetchProductPool(creatorId, productType, pageSize, maxPages) {
|
|
|
840
738
|
}
|
|
841
739
|
};
|
|
842
740
|
}
|
|
741
|
+
function buildSkippedProductQuerySummary(productType, pageSize) {
|
|
742
|
+
return {
|
|
743
|
+
productType,
|
|
744
|
+
pageSize,
|
|
745
|
+
pagesScanned: 0,
|
|
746
|
+
productCount: 0,
|
|
747
|
+
nextCursor: null,
|
|
748
|
+
reachedPageLimit: false,
|
|
749
|
+
failedSources: []
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function isProductPublishable(product) {
|
|
753
|
+
if (product.reviewStatus && product.reviewStatus.toUpperCase() !== "APPROVED") return false;
|
|
754
|
+
if (product.inventoryStatus && product.inventoryStatus.toUpperCase() !== "IN_STOCK") return false;
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
843
757
|
function sortProductsForSelection(products) {
|
|
844
|
-
return
|
|
758
|
+
return products.filter(isProductPublishable).sort((a, b) => b.salesCount - a.salesCount);
|
|
845
759
|
}
|
|
846
760
|
function buildSelectedProductSummary(product, selectionMode) {
|
|
847
761
|
return {
|
|
@@ -859,8 +773,11 @@ async function promptForProductSelection(products) {
|
|
|
859
773
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
860
774
|
throw new Error("\u4EA4\u4E92\u6A21\u5F0F\u9700\u8981\u5728 TTY \u7EC8\u7AEF\u4E2D\u8FD0\u884C");
|
|
861
775
|
}
|
|
862
|
-
const candidates =
|
|
863
|
-
|
|
776
|
+
const candidates = products.filter(isProductPublishable).sort((a, b) => b.salesCount - a.salesCount).slice(0, 20);
|
|
777
|
+
if (candidates.length === 0) {
|
|
778
|
+
throw new Error("\u5F53\u524D\u5546\u54C1\u6C60\u4E2D\u6CA1\u6709\u53EF\u53D1\u5E03\u5546\u54C1\uFF08\u5BA1\u6838\u672A\u901A\u8FC7\u6216\u65E0\u5E93\u5B58\uFF09\uFF0C\u5982\u9700\u5F3A\u5236\u6307\u5B9A\u8BF7\u4F7F\u7528 --product-id/--product-title");
|
|
779
|
+
}
|
|
780
|
+
console.log(`\u53EF\u9009\u5546\u54C1\uFF08\u5C55\u793A\u524D ${candidates.length} \u4E2A\uFF0C\u6309\u9500\u91CF\u964D\u5E8F\uFF0C\u5DF2\u8FC7\u6EE4\u4E0D\u53EF\u53D1\u5E03\u5546\u54C1\uFF09\uFF1A`);
|
|
864
781
|
for (const [index, product] of candidates.entries()) {
|
|
865
782
|
console.log(
|
|
866
783
|
`${index + 1}. [${product.source}] ${product.title} | ID: ${product.id} | \u9500\u91CF: ${product.salesCount}`
|
|
@@ -884,6 +801,73 @@ async function promptForProductSelection(products) {
|
|
|
884
801
|
}
|
|
885
802
|
}
|
|
886
803
|
|
|
804
|
+
// src/commands/query-products.ts
|
|
805
|
+
var VALID_PRODUCT_TYPES = ["shop", "showcase", "all"];
|
|
806
|
+
function register7(cli2) {
|
|
807
|
+
cli2.command("query-products", "\u67E5\u8BE2 TTS \u5546\u54C1\u5217\u8868").option("--creator-id <id>", "TTS \u8D26\u53F7 creatorUserOpenId\uFF08\u5FC5\u586B\uFF09").option("--product-type <type>", "\u5546\u54C1\u6765\u6E90: shop / showcase / all\uFF08\u9ED8\u8BA4 all\uFF09").option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09").option("--cursor <cursor>", "\u5206\u9875\u6E38\u6807\uFF08\u9996\u9875\u4E0D\u4F20\uFF09").action(
|
|
808
|
+
async (options) => {
|
|
809
|
+
if (!options.creatorId) {
|
|
810
|
+
console.error("\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570: --creator-id\n");
|
|
811
|
+
console.error("\u7528\u6CD5: beervid query-products --creator-id <id>");
|
|
812
|
+
process.exit(1);
|
|
813
|
+
}
|
|
814
|
+
const creatorId = options.creatorId;
|
|
815
|
+
const productType = (options.productType ?? "all").toLowerCase();
|
|
816
|
+
const pageSize = parseInt(options.pageSize ?? "20", 10);
|
|
817
|
+
const cursor = options.cursor ?? "";
|
|
818
|
+
if (!VALID_PRODUCT_TYPES.includes(productType)) {
|
|
819
|
+
console.error("\u9519\u8BEF: --product-type \u5FC5\u987B\u4E3A shop\u3001showcase \u6216 all");
|
|
820
|
+
process.exit(1);
|
|
821
|
+
}
|
|
822
|
+
if (Number.isNaN(pageSize) || pageSize <= 0) {
|
|
823
|
+
console.error("\u9519\u8BEF: --page-size \u5FC5\u987B\u4E3A\u5927\u4E8E 0 \u7684\u6574\u6570");
|
|
824
|
+
process.exit(1);
|
|
825
|
+
}
|
|
826
|
+
try {
|
|
827
|
+
let inputCursor = { shopToken: "", showcaseToken: "" };
|
|
828
|
+
if (cursor) {
|
|
829
|
+
try {
|
|
830
|
+
inputCursor = decodeCursor(cursor);
|
|
831
|
+
} catch {
|
|
832
|
+
console.error("\u9519\u8BEF: \u65E0\u6548\u7684 cursor \u683C\u5F0F");
|
|
833
|
+
process.exit(1);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
const pageResult = await queryProductsPage(
|
|
837
|
+
creatorId,
|
|
838
|
+
productType,
|
|
839
|
+
pageSize,
|
|
840
|
+
inputCursor
|
|
841
|
+
);
|
|
842
|
+
if (pageResult.successCount === 0 && pageResult.failedSources.length > 0) {
|
|
843
|
+
console.error("\u67E5\u8BE2\u5546\u54C1\u5931\u8D25: \u6240\u6709\u5546\u54C1\u6E90\u90FD\u8BF7\u6C42\u5931\u8D25");
|
|
844
|
+
process.exit(1);
|
|
845
|
+
}
|
|
846
|
+
const productList = pageResult.products;
|
|
847
|
+
console.log(`\u67E5\u8BE2\u5230 ${productList.length} \u4E2A\u5546\u54C1:
|
|
848
|
+
`);
|
|
849
|
+
for (const p of productList) {
|
|
850
|
+
console.log(` [${p.source}] ${p.title}`);
|
|
851
|
+
console.log(` ID: ${p.id} \u9500\u91CF: ${p.salesCount} \u54C1\u724C: ${p.brandName}`);
|
|
852
|
+
if (p.images.length > 0) console.log(` \u56FE\u7247: ${p.images[0]}`);
|
|
853
|
+
console.log("");
|
|
854
|
+
}
|
|
855
|
+
if (pageResult.nextCursor) {
|
|
856
|
+
console.log(`\u4E0B\u4E00\u9875\u6E38\u6807: ${pageResult.nextCursor}`);
|
|
857
|
+
console.log(`\u4F7F\u7528: beervid query-products --creator-id ${creatorId} --cursor ${pageResult.nextCursor}`);
|
|
858
|
+
} else {
|
|
859
|
+
console.log("\u5DF2\u5230\u6700\u540E\u4E00\u9875");
|
|
860
|
+
}
|
|
861
|
+
printResult({ products: productList, nextCursor: pageResult.nextCursor });
|
|
862
|
+
} catch (err) {
|
|
863
|
+
rethrowIfProcessExit(err);
|
|
864
|
+
console.error("\u67E5\u8BE2\u5546\u54C1\u5931\u8D25:", err.message);
|
|
865
|
+
process.exit(1);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
|
|
887
871
|
// src/commands/publish-tt-flow.ts
|
|
888
872
|
function parsePositiveInt(value, optionName, defaultValue) {
|
|
889
873
|
const parsed = parseInt(value ?? `${defaultValue}`, 10);
|
|
@@ -894,7 +878,7 @@ function parsePositiveInt(value, optionName, defaultValue) {
|
|
|
894
878
|
return parsed;
|
|
895
879
|
}
|
|
896
880
|
function register8(cli2) {
|
|
897
|
-
cli2.command("publish-tt-flow", "\u6267\u884C TT \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B\uFF1A\u4E0A\u4F20\u3001\u53D1\u5E03\u3001\u8F6E\u8BE2\u3001\u67E5\u8BE2\u6570\u636E").option("--business-id <id>", "TT \u8D26\u53F7 businessId\uFF08\u5FC5\u586B\uFF09").option("--file <path>", "\u89C6\u9891\u6587\u4EF6\u8DEF\u5F84\u6216 URL\uFF08\u5FC5\u586B\uFF09").option("--caption <text>", "\u89C6\u9891\u63CF\u8FF0/\u6587\u6848\uFF08\u53EF\u9009\uFF09").option("--token <token>", "\u5DF2\u6709\u4E0A\u4F20\u51ED\u8BC1\uFF08\u53EF\u9009\uFF09").option("--interval <sec>", "\u8F6E\u8BE2\u95F4\u9694\u79D2\u6570\uFF08\u9ED8\u8BA4
|
|
881
|
+
cli2.command("publish-tt-flow", "\u6267\u884C TT \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B\uFF1A\u4E0A\u4F20\u3001\u53D1\u5E03\u3001\u8F6E\u8BE2\u3001\u67E5\u8BE2\u6570\u636E").option("--business-id <id>", "TT \u8D26\u53F7 businessId\uFF08\u5FC5\u586B\uFF09").option("--file <path>", "\u89C6\u9891\u6587\u4EF6\u8DEF\u5F84\u6216 URL\uFF08\u5FC5\u586B\uFF09").option("--caption <text>", "\u89C6\u9891\u63CF\u8FF0/\u6587\u6848\uFF08\u53EF\u9009\uFF09").option("--token <token>", "\u5DF2\u6709\u4E0A\u4F20\u51ED\u8BC1\uFF08\u53EF\u9009\uFF09").option("--interval <sec>", "\u8F6E\u8BE2\u95F4\u9694\u79D2\u6570\uFF08\u9ED8\u8BA4 5\uFF09").option("--max-polls <n>", "\u6700\u5927\u8F6E\u8BE2\u6B21\u6570\uFF08\u9ED8\u8BA4 60\uFF09").option("--query-interval <sec>", "\u89C6\u9891\u6570\u636E\u67E5\u8BE2\u91CD\u8BD5\u95F4\u9694\u79D2\u6570\uFF08\u9ED8\u8BA4 5\uFF09").option("--query-max-attempts <n>", "\u89C6\u9891\u6570\u636E\u67E5\u8BE2\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF08\u9ED8\u8BA4 3\uFF09").action(
|
|
898
882
|
async (options) => {
|
|
899
883
|
if (!options.businessId || !options.file) {
|
|
900
884
|
const missing = [
|
|
@@ -908,7 +892,7 @@ function register8(cli2) {
|
|
|
908
892
|
);
|
|
909
893
|
process.exit(1);
|
|
910
894
|
}
|
|
911
|
-
const intervalSec = parsePositiveInt(options.interval, "--interval",
|
|
895
|
+
const intervalSec = parsePositiveInt(options.interval, "--interval", 5);
|
|
912
896
|
const maxPolls = parsePositiveInt(options.maxPolls, "--max-polls", 60);
|
|
913
897
|
const queryIntervalSec = parsePositiveInt(options.queryInterval, "--query-interval", 5);
|
|
914
898
|
const queryMaxAttempts = parsePositiveInt(
|
|
@@ -946,11 +930,6 @@ function register8(cli2) {
|
|
|
946
930
|
);
|
|
947
931
|
query = queryResult.query;
|
|
948
932
|
warnings.push(...queryResult.warnings);
|
|
949
|
-
} else if (status.finalStatus === "PUBLISH_COMPLETE") {
|
|
950
|
-
warnings.push({
|
|
951
|
-
code: "VIDEO_ID_MISSING",
|
|
952
|
-
message: "\u53D1\u5E03\u6210\u529F\uFF0C\u4F46\u72B6\u6001\u7ED3\u679C\u4E2D\u672A\u8FD4\u56DE videoId\uFF0C\u5DF2\u8DF3\u8FC7\u89C6\u9891\u6570\u636E\u67E5\u8BE2"
|
|
953
|
-
});
|
|
954
933
|
}
|
|
955
934
|
const result = {
|
|
956
935
|
flowType: "tt",
|
|
@@ -1044,58 +1023,71 @@ function register9(cli2) {
|
|
|
1044
1023
|
);
|
|
1045
1024
|
try {
|
|
1046
1025
|
console.log("\u5F00\u59CB\u6267\u884C TTS \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B...");
|
|
1047
|
-
console.log("1/4 \u6B63\u5728\u67E5\u8BE2\u5546\u54C1\u5217\u8868...");
|
|
1048
|
-
const productPool = await fetchProductPool(
|
|
1049
|
-
options.creatorId,
|
|
1050
|
-
productType,
|
|
1051
|
-
pageSize,
|
|
1052
|
-
maxProductPages
|
|
1053
|
-
);
|
|
1054
1026
|
const warnings = [];
|
|
1055
|
-
if (productPool.summary.reachedPageLimit && productPool.summary.nextCursor) {
|
|
1056
|
-
warnings.push({
|
|
1057
|
-
code: "PRODUCT_SCAN_LIMIT_REACHED",
|
|
1058
|
-
message: `\u5546\u54C1\u626B\u63CF\u5DF2\u8FBE\u5230\u9875\u6570\u4E0A\u9650 ${maxProductPages}\uFF0C\u4ECD\u5B58\u5728\u672A\u62C9\u53D6\u5206\u9875`
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
|
-
if (productPool.summary.failedSources.length > 0) {
|
|
1062
|
-
warnings.push({
|
|
1063
|
-
code: "PRODUCT_SOURCE_PARTIAL_FAILURE",
|
|
1064
|
-
message: `\u4EE5\u4E0B\u5546\u54C1\u6E90\u8BF7\u6C42\u5931\u8D25: ${productPool.summary.failedSources.join(", ")}\uFF0C\u5546\u54C1\u6C60\u53EF\u80FD\u4E0D\u5B8C\u6574`
|
|
1065
|
-
});
|
|
1066
|
-
}
|
|
1067
|
-
if (productPool.products.length === 0) {
|
|
1068
|
-
console.error("TTS \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B\u5931\u8D25: \u5F53\u524D\u5546\u54C1\u6C60\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u9009\u62E9\u5546\u54C1");
|
|
1069
|
-
process.exit(1);
|
|
1070
|
-
}
|
|
1071
1027
|
let selectionMode = "automatic";
|
|
1072
1028
|
let selectedProduct;
|
|
1073
|
-
|
|
1029
|
+
let productPoolSummary;
|
|
1030
|
+
if (options.productId && options.productTitle) {
|
|
1074
1031
|
selectionMode = "manual";
|
|
1075
|
-
|
|
1076
|
-
|
|
1032
|
+
console.log("1/4 \u5DF2\u624B\u52A8\u6307\u5B9A\u5546\u54C1\uFF0C\u8DF3\u8FC7\u5546\u54C1\u67E5\u8BE2...");
|
|
1033
|
+
selectedProduct = buildManualProduct(options.productId, options.productTitle);
|
|
1034
|
+
} else {
|
|
1035
|
+
console.log("1/4 \u6B63\u5728\u67E5\u8BE2\u5546\u54C1\u5217\u8868...");
|
|
1036
|
+
const productPool = await fetchProductPool(
|
|
1037
|
+
options.creatorId,
|
|
1038
|
+
productType,
|
|
1039
|
+
pageSize,
|
|
1040
|
+
maxProductPages
|
|
1077
1041
|
);
|
|
1078
|
-
|
|
1079
|
-
if (
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1042
|
+
productPoolSummary = productPool.summary;
|
|
1043
|
+
if (productPool.summary.reachedPageLimit && productPool.summary.nextCursor) {
|
|
1044
|
+
warnings.push({
|
|
1045
|
+
code: "PRODUCT_SCAN_LIMIT_REACHED",
|
|
1046
|
+
message: `\u5546\u54C1\u626B\u63CF\u5DF2\u8FBE\u5230\u9875\u6570\u4E0A\u9650 ${maxProductPages}\uFF0C\u4ECD\u5B58\u5728\u672A\u62C9\u53D6\u5206\u9875`
|
|
1047
|
+
});
|
|
1084
1048
|
}
|
|
1085
|
-
|
|
1086
|
-
if (!matchedProduct) {
|
|
1049
|
+
if (productPool.summary.failedSources.length > 0) {
|
|
1087
1050
|
warnings.push({
|
|
1088
|
-
code: "
|
|
1089
|
-
message:
|
|
1051
|
+
code: "PRODUCT_SOURCE_PARTIAL_FAILURE",
|
|
1052
|
+
message: `\u4EE5\u4E0B\u5546\u54C1\u6E90\u8BF7\u6C42\u5931\u8D25: ${productPool.summary.failedSources.join(", ")}\uFF0C\u5546\u54C1\u6C60\u53EF\u80FD\u4E0D\u5B8C\u6574`
|
|
1090
1053
|
});
|
|
1091
1054
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1055
|
+
if (options.productId) {
|
|
1056
|
+
selectionMode = "manual";
|
|
1057
|
+
const matchedProduct = productPool.products.find(
|
|
1058
|
+
(product) => product.id === options.productId
|
|
1059
|
+
);
|
|
1060
|
+
const resolvedTitle = matchedProduct?.title;
|
|
1061
|
+
if (!resolvedTitle) {
|
|
1062
|
+
console.error(
|
|
1063
|
+
"\u9519\u8BEF: \u624B\u52A8\u6307\u5B9A --product-id \u65F6\uFF0C\u5982\u65E0\u6CD5\u4ECE\u5DF2\u626B\u63CF\u5546\u54C1\u6C60\u8865\u9F50\u6807\u9898\uFF0C\u5219\u5FC5\u987B\u663E\u5F0F\u4F20\u5165 --product-title"
|
|
1064
|
+
);
|
|
1065
|
+
process.exit(1);
|
|
1066
|
+
}
|
|
1067
|
+
selectedProduct = buildManualProduct(options.productId, resolvedTitle, matchedProduct);
|
|
1068
|
+
} else if (options.interactive) {
|
|
1069
|
+
if (productPool.products.length === 0) {
|
|
1070
|
+
console.error("TTS \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B\u5931\u8D25: \u5F53\u524D\u5546\u54C1\u6C60\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u9009\u62E9\u5546\u54C1");
|
|
1071
|
+
process.exit(1);
|
|
1072
|
+
}
|
|
1073
|
+
selectionMode = "interactive";
|
|
1074
|
+
console.log("2/4 \u8BF7\u9009\u62E9\u8981\u6302\u8F66\u7684\u5546\u54C1...");
|
|
1075
|
+
selectedProduct = await promptForProductSelection(productPool.products);
|
|
1076
|
+
} else {
|
|
1077
|
+
if (productPool.products.length === 0) {
|
|
1078
|
+
console.error("TTS \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B\u5931\u8D25: \u5F53\u524D\u5546\u54C1\u6C60\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u9009\u62E9\u5546\u54C1");
|
|
1079
|
+
process.exit(1);
|
|
1080
|
+
}
|
|
1081
|
+
console.log("2/4 \u6B63\u5728\u81EA\u52A8\u9009\u62E9\u5546\u54C1\uFF08\u6309\u9500\u91CF\u6700\u9AD8\u4F18\u5148\uFF09...");
|
|
1082
|
+
const publishable = sortProductsForSelection(productPool.products);
|
|
1083
|
+
if (publishable.length === 0) {
|
|
1084
|
+
console.error(
|
|
1085
|
+
"TTS \u5B8C\u6574\u53D1\u5E03\u6D41\u7A0B\u5931\u8D25: \u5546\u54C1\u6C60\u4E2D\u6CA1\u6709\u53EF\u53D1\u5E03\u5546\u54C1\uFF08\u5BA1\u6838\u672A\u901A\u8FC7\u6216\u65E0\u5E93\u5B58\uFF09\uFF0C\u5982\u9700\u5F3A\u5236\u6307\u5B9A\u8BF7\u4F7F\u7528 --product-id/--product-title"
|
|
1086
|
+
);
|
|
1087
|
+
process.exit(1);
|
|
1088
|
+
}
|
|
1089
|
+
selectedProduct = publishable[0];
|
|
1090
|
+
}
|
|
1099
1091
|
}
|
|
1100
1092
|
console.log("3/4 \u6B63\u5728\u4E0A\u4F20\u6302\u8F66\u89C6\u9891...");
|
|
1101
1093
|
const upload = await uploadTtsVideo(options.file, options.creatorId, options.token);
|
|
@@ -1115,7 +1107,7 @@ function register9(cli2) {
|
|
|
1115
1107
|
}
|
|
1116
1108
|
const result = {
|
|
1117
1109
|
flowType: "tts",
|
|
1118
|
-
productQuery:
|
|
1110
|
+
productQuery: productPoolSummary ?? buildSkippedProductQuerySummary(productType, pageSize),
|
|
1119
1111
|
selectedProduct: buildSelectedProductSummary(selectedProduct, selectionMode),
|
|
1120
1112
|
upload,
|
|
1121
1113
|
publish: publishResult.publish,
|
|
@@ -1172,6 +1164,7 @@ function register10(cli2) {
|
|
|
1172
1164
|
|
|
1173
1165
|
// src/cli.ts
|
|
1174
1166
|
var cli = cac("beervid");
|
|
1167
|
+
var cliVersion = true ? "0.2.2" : pkg.version;
|
|
1175
1168
|
register10(cli);
|
|
1176
1169
|
register(cli);
|
|
1177
1170
|
register2(cli);
|
|
@@ -1183,7 +1176,7 @@ register7(cli);
|
|
|
1183
1176
|
register8(cli);
|
|
1184
1177
|
register9(cli);
|
|
1185
1178
|
cli.help();
|
|
1186
|
-
cli.version(
|
|
1179
|
+
cli.version(cliVersion);
|
|
1187
1180
|
if (process.argv.slice(2).length === 0) {
|
|
1188
1181
|
cli.outputHelp();
|
|
1189
1182
|
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beervid-app-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "BEERVID App CLI — TikTok video publish, account auth, and data query",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist/",
|
|
14
|
+
"agents/",
|
|
15
|
+
"references/",
|
|
14
16
|
"SKILL.md",
|
|
15
17
|
"README.md"
|
|
16
18
|
],
|