Initial commit: KOC LOOP platform

This commit is contained in:
巫凤萍
2026-07-30 12:06:41 +08:00
commit d2cde2c9b2
98 changed files with 44076 additions and 0 deletions

16
tests/date-utils.test.mjs Normal file
View File

@@ -0,0 +1,16 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
formatShanghaiDate,
parseStoredDate,
} from "../lib/date-utils.ts";
test("treats D1 CURRENT_TIMESTAMP values as UTC and displays Beijing time", () => {
const stored = "2026-07-29 05:36:00";
assert.equal(parseStoredDate(stored).toISOString(), "2026-07-29T05:36:00.000Z");
assert.match(formatShanghaiDate(stored, true), /07\/29.*13:36/);
});
test("keeps date-only deadlines on the intended Shanghai calendar date", () => {
assert.match(formatShanghaiDate("2026-08-12"), /08\/12/);
});

View File

@@ -0,0 +1,177 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
clearFeishuAccessTokenCacheForTests,
readFeishuSource,
} from "../lib/feishu-client.ts";
const bindings = {
FEISHU_APP_ID: "cli_test",
FEISHU_APP_SECRET: "secret_test",
};
function apiResponse(data) {
return Response.json({ code: 0, msg: "success", data });
}
function fakeFeishu(options = {}) {
const calls = [];
const fetchImpl = async (input, init = {}) => {
const url = new URL(String(input));
calls.push({ url, init });
if (url.pathname.endsWith("/tenant_access_token/internal")) {
return Response.json({
code: 0,
msg: "success",
tenant_access_token: "tenant-test",
expire: 7200,
});
}
if (url.pathname.endsWith("/wiki/v2/spaces/get_node")) {
return apiResponse({
node: {
obj_type: "sheet",
obj_token: "spreadsheet-test",
},
});
}
if (url.pathname.endsWith("/sheets/query")) {
return apiResponse({
sheets:
options.sheets ??
[
{
sheet_id: "sheet-one",
title: "内容池",
resource_type: "sheet",
hidden: false,
grid_properties: { row_count: 20, column_count: 10 },
},
],
});
}
if (url.pathname.endsWith("/values_batch_get")) {
return apiResponse({
valueRanges: [
{
values: [
["作品ID", "标题", "标签", "正文", null, null],
[
7,
"一篇测试笔记",
"#测试 #KOC",
"测试正文",
{
type: "embed-image",
fileToken: "file-token-one",
width: 1080,
height: 1440,
},
[
{
type: "embed-image",
fileToken: "file-token-two",
width: 1080,
height: 1440,
},
],
],
[8, "", "", "空标题不会导入"],
],
},
],
});
}
throw new Error(`Unexpected request: ${url.pathname}`);
};
return { calls, fetchImpl };
}
test("resolves a wiki sheet and imports title, body, tags, and all images", async () => {
clearFeishuAccessTokenCacheForTests();
const { calls, fetchImpl } = fakeFeishu();
const source = await readFeishuSource(
"https://tenant.feishu.cn/wiki/wiki-test",
bindings,
fetchImpl,
);
assert.equal(source.spreadsheetToken, "spreadsheet-test");
assert.equal(source.sheetId, "sheet-one");
assert.equal(source.sheetName, "内容池");
assert.equal(source.rows.length, 1);
assert.equal(source.rows[0].sourceRow, 7);
assert.equal(source.rows[0].body, "测试正文\n\n#测试 #KOC");
assert.deepEqual(
source.rows[0].images.map((image) => image.fileToken),
["file-token-one", "file-token-two"],
);
assert.deepEqual(source.columns, [
"作品ID",
"标题",
"标签",
"正文",
"图片1",
"图片2",
]);
const valuesCall = calls.find((call) =>
call.url.pathname.endsWith("/values_batch_get"),
);
assert.equal(valuesCall.url.searchParams.get("ranges"), "sheet-one!A1:J20");
});
test("requires an exact sheet link when a workbook has multiple visible sheets", async () => {
clearFeishuAccessTokenCacheForTests();
const { fetchImpl } = fakeFeishu({
sheets: [
{
sheet_id: "one",
title: "内容A",
resource_type: "sheet",
hidden: false,
},
{
sheet_id: "two",
title: "内容B",
resource_type: "sheet",
hidden: false,
},
],
});
await assert.rejects(
readFeishuSource(
"https://tenant.feishu.cn/wiki/wiki-test",
bindings,
fetchImpl,
),
/包含多个工作表/,
);
});
test("rejects a wiki node that is not a spreadsheet", async () => {
clearFeishuAccessTokenCacheForTests();
const fetchImpl = async (input) => {
const url = new URL(String(input));
if (url.pathname.endsWith("/tenant_access_token/internal")) {
return Response.json({
code: 0,
msg: "success",
tenant_access_token: "tenant-test",
expire: 7200,
});
}
return apiResponse({
node: { obj_type: "docx", obj_token: "document-test" },
});
};
await assert.rejects(
readFeishuSource(
"https://tenant.feishu.cn/wiki/wiki-test",
bindings,
fetchImpl,
),
/不是电子表格/,
);
});

View File

@@ -0,0 +1,510 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
collectXhsMetricsFromMcp,
resolveCollectionMcpConfig,
resolveXhsPublicAccountDetails,
resolveXhsPublicAccountId,
resolveXhsAccountProfileFromMcp,
resolveXhsProfileDetailsFromMcp,
xhsNoteIdFromUrl,
} from "../lib/mcp-collection-client.ts";
function sse(payload, options = {}) {
return new Response(
`event: message\ndata: ${JSON.stringify(payload)}\n\n`,
{
status: 200,
...options,
headers: {
"content-type": "text/event-stream",
...(options.headers ?? {}),
},
},
);
}
function toolEnvelope(payload, isError = false) {
return {
jsonrpc: "2.0",
id: "tool-call",
result: {
isError,
content: [
{
type: "text",
text: JSON.stringify(payload),
},
],
},
};
}
function createFakeMcp(toolResults) {
let toolIndex = 0;
const calls = [];
const fetchImpl = async (url, init) => {
const body = JSON.parse(init.body);
calls.push({ url: String(url), body, headers: new Headers(init.headers) });
if (body.method === "initialize") {
return sse(
{
jsonrpc: "2.0",
id: body.id,
result: {
protocolVersion: "2025-03-26",
capabilities: { tools: { listChanged: false } },
serverInfo: { name: "ai-tool-center", version: "test" },
},
},
{ headers: { "mcp-session-id": "session-test" } },
);
}
if (body.method === "notifications/initialized") {
return new Response("", { status: 202 });
}
if (body.method === "tools/call") {
const result = toolResults[toolIndex];
toolIndex += 1;
return sse(result);
}
throw new Error(`Unexpected MCP method: ${body.method}`);
};
return { calls, fetchImpl };
}
test("collects likes, comments and favorites from the verified MCP shape", async () => {
const { calls, fetchImpl } = createFakeMcp([
toolEnvelope({
http_status: 200,
response: {
code: 200,
success: true,
msg: "获取内容详情成功",
data: {
likes: "483",
comments: "41",
collects: "519",
},
},
}),
]);
const result = await collectXhsMetricsFromMcp(
"https://www.xiaohongshu.com/discovery/item/test?xsec_token=valid",
{
endpoint: "https://collector.example/mcp",
key: "test-key",
},
fetchImpl,
);
assert.deepEqual(result, {
likes: 483,
comments: 41,
collects: 519,
});
assert.equal(calls.length, 3);
assert.equal(calls[2].body.params.name, "fetch_content_detail");
assert.equal(calls[2].body.params.arguments.include_comments, false);
assert.equal(calls[2].headers.get("mcp-session-id"), "session-test");
assert.equal(new URL(calls[0].url).searchParams.get("key"), "test-key");
});
test("resolves the real XHS account profile from a submitted note link", async () => {
const { calls, fetchImpl } = createFakeMcp([
toolEnvelope({
response: {
code: 200,
success: true,
data: {
note_detail: {
products: [
{
content_tags: [
{
notes: [
{
ip_location: "重庆",
note_id: "6a671108000000000f004bef",
user: {
nickname: "N我的麻辣烫好了吗",
profile_url:
"https://www.xiaohongshu.com/user/profile/6905cbca0000000037009f49",
red_id: "94329495984",
user_id: "6905cbca0000000037009f49",
},
},
],
},
],
},
],
},
},
},
}),
toolEnvelope({
response: {
code: 200,
success: true,
data: {
fans_count: "734",
},
},
}),
]);
const profile = await resolveXhsAccountProfileFromMcp(
"https://www.xiaohongshu.com/discovery/item/6a671108000000000f004bef",
"回填昵称",
{
endpoint: "https://collector.example/mcp",
key: "test-key",
},
fetchImpl,
);
assert.deepEqual(profile, {
platformUid: "6905cbca0000000037009f49",
nickname: "N我的麻辣烫好了吗",
profileUrl:
"https://www.xiaohongshu.com/user/profile/6905cbca0000000037009f49",
redId: "94329495984",
ipLocation: "重庆",
followers: 734,
});
assert.equal(calls.length, 4);
assert.equal(
calls[2].body.params.name,
"collect_xhs_wen_note_detail",
);
assert.equal(
calls[2].body.params.arguments.note_id,
"6a671108000000000f004bef",
);
assert.equal(calls[3].body.params.name, "parse_xhs_user_summary");
assert.equal(
calls[3].body.params.arguments.url,
"https://www.xiaohongshu.com/user/profile/6905cbca0000000037009f49",
);
assert.equal(
xhsNoteIdFromUrl(
"https://www.xiaohongshu.com/explore/6a671108000000000f004bef",
),
"6a671108000000000f004bef",
);
});
test("resolves followers directly from the supported XHS user summary tool", async () => {
const { calls, fetchImpl } = createFakeMcp([
toolEnvelope({
response: {
code: 200,
success: true,
msg: "用户摘要解析成功",
data: {
user: {
fansCount: 6,
ipLocation: "福建",
nickname: "555 五",
userId: "1020668113",
},
},
},
}),
]);
const details = await resolveXhsProfileDetailsFromMcp(
"https://www.xiaohongshu.com/user/profile/5fb21d32000000000101c23e",
{
endpoint: "https://collector.example/mcp",
key: "test-key",
},
fetchImpl,
);
assert.deepEqual(details, {
followers: 6,
redId: "1020668113",
ipLocation: "福建",
});
assert.equal(calls[2].body.params.name, "parse_xhs_user_summary");
});
test("resolves an xhslink short URL before requesting the author profile", async () => {
const fakeMcp = createFakeMcp([
toolEnvelope({
response: {
code: 200,
success: true,
data: {
note_detail: {
note_id: "6a572da40000000021018bd2",
ip_location: "上海",
user: {
nickname: "短链作者",
user_id: "6905cbca0000000037009f49",
},
},
},
},
}),
toolEnvelope({
response: {
code: 200,
success: true,
data: {
red_id: "1020668113",
followers: "1.2万",
},
},
}),
]);
const fetchImpl = async (url, init) => {
if (String(url) === "http://xhslink.cn/o/AJFyP5dnj7O") {
return new Response(null, {
status: 302,
headers: {
location:
"https://www.xiaohongshu.com/discovery/item/6a572da40000000021018bd2?xsec_token=valid",
},
});
}
return fakeMcp.fetchImpl(url, init);
};
const profile = await resolveXhsAccountProfileFromMcp(
"http://xhslink.cn/o/AJFyP5dnj7O",
"回填昵称",
{
endpoint: "https://collector.example/mcp",
key: "test-key",
},
fetchImpl,
);
assert.equal(profile.nickname, "短链作者");
assert.equal(profile.platformUid, "6905cbca0000000037009f49");
assert.equal(profile.redId, "1020668113");
assert.equal(profile.followers, 12_000);
assert.equal(
profile.profileUrl,
"https://www.xiaohongshu.com/user/profile/6905cbca0000000037009f49",
);
assert.equal(
fakeMcp.calls[2].body.params.arguments.note_id,
"6a572da40000000021018bd2",
);
});
test("uses the public note author when MCP profile lookup fails", async () => {
const fakeMcp = createFakeMcp([
toolEnvelope(
{
response: {
code: 500,
success: false,
msg: "作者详情暂时不可用",
},
},
true,
),
]);
const fetchImpl = async (url, init) => {
if (String(url) === "http://xhslink.cn/o/AJFyP5dnj7O") {
return new Response(
'<script>window.__STATE__={&quot;noteData&quot;:{&quot;desc&quot;:&quot;测试&quot;,&quot;user&quot;:{&quot;userId&quot;:&quot;5fb21d32000000000101c23e&quot;,&quot;nickName&quot;:&quot;555 五&quot;}}}</script>',
{
status: 200,
headers: {
"content-type": "text/html; charset=utf-8",
location:
"https://www.xiaohongshu.com/discovery/item/6a572da40000000021018bd2?xsec_token=valid",
},
},
);
}
if (
String(url) ===
"https://www.xiaohongshu.com/user/profile/5fb21d32000000000101c23e"
) {
return new Response(
'<script>{"redId":"1020668113","interactions":[{"name":"粉丝","count":"6","i18nCount":"6"}]}</script>',
{ status: 200 },
);
}
return fakeMcp.fetchImpl(url, init);
};
const profile = await resolveXhsAccountProfileFromMcp(
"http://xhslink.cn/o/AJFyP5dnj7O",
"回填昵称",
{
endpoint: "https://collector.example/mcp",
key: "test-key",
},
fetchImpl,
);
assert.deepEqual(profile, {
platformUid: "5fb21d32000000000101c23e",
nickname: "555 五",
profileUrl:
"https://www.xiaohongshu.com/user/profile/5fb21d32000000000101c23e",
redId: "1020668113",
ipLocation: "待识别",
followers: 6,
});
assert.equal(
fakeMcp.calls[2].body.params.name,
"collect_xhs_wen_note_detail",
);
});
test("reads the user-visible Xiaohongshu number from a public profile", async () => {
const fetchImpl = async () =>
new Response(
'<div class="redId">小红书号1020668113</div><script>{"redId":"1020668113","interactions":[{"name":"粉丝","count":"10+","i18nCount":"10+"}]}</script>',
{ status: 200 },
);
const accountId = await resolveXhsPublicAccountId(
"https://www.xiaohongshu.com/user/profile/5fb21d32000000000101c23e",
fetchImpl,
);
const details = await resolveXhsPublicAccountDetails(
"https://www.xiaohongshu.com/user/profile/5fb21d32000000000101c23e",
fetchImpl,
);
assert.equal(accountId, "1020668113");
assert.deepEqual(details, {
redId: "1020668113",
followers: 10,
ipLocation: "",
});
});
test("falls back to parse_xhs_note when the primary tool fails", async () => {
const { calls, fetchImpl } = createFakeMcp([
toolEnvelope(
{
response: {
code: 400,
success: false,
msg: "获取内容详情失败",
data: null,
},
},
true,
),
toolEnvelope({
response: {
code: 200,
success: true,
data: {
likes: "1.2万",
comments: 32,
collects: "2,345",
},
},
}),
]);
const result = await collectXhsMetricsFromMcp(
"https://www.xiaohongshu.com/explore/test",
{
endpoint: "https://collector.example/mcp?key=test-key",
},
fetchImpl,
);
assert.deepEqual(result, {
likes: 12_000,
comments: 32,
collects: 2_345,
});
assert.equal(calls[3].body.params.name, "parse_xhs_note");
});
test("requires the MCP key without sending a network request", async () => {
let requested = false;
await assert.rejects(
collectXhsMetricsFromMcp(
"https://www.xiaohongshu.com/explore/test",
resolveCollectionMcpConfig({}),
async () => {
requested = true;
return new Response();
},
),
/MCP采集密钥未配置/,
);
assert.equal(requested, false);
});
test("rebuilds the MCP session after a gateway session miss", async () => {
let initializeCount = 0;
const fetchImpl = async (_url, init) => {
const body = JSON.parse(init.body);
if (body.method === "initialize") {
initializeCount += 1;
return sse(
{
jsonrpc: "2.0",
id: body.id,
result: {
protocolVersion: "2025-03-26",
capabilities: { tools: { listChanged: false } },
serverInfo: { name: "ai-tool-center", version: "test" },
},
},
{
headers: {
"mcp-session-id": `session-${initializeCount}`,
},
},
);
}
if (
body.method === "notifications/initialized" &&
initializeCount === 1
) {
return Response.json(
{
jsonrpc: "2.0",
id: "server-error",
error: { code: -32600, message: "Session not found" },
},
{ status: 404 },
);
}
if (body.method === "notifications/initialized") {
return new Response("", { status: 202 });
}
if (body.method === "tools/call") {
return sse(
toolEnvelope({
response: {
code: 200,
success: true,
data: { likes: 8, comments: 2, collects: 5 },
},
}),
);
}
throw new Error(`Unexpected MCP method: ${body.method}`);
};
const result = await collectXhsMetricsFromMcp(
"https://www.xiaohongshu.com/explore/test",
{
endpoint: "https://collector.example/mcp",
key: "test-key",
},
fetchImpl,
);
assert.deepEqual(result, { likes: 8, comments: 2, collects: 5 });
assert.equal(initializeCount, 2);
});

View File

@@ -0,0 +1,30 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
extractXhsPublishUrl,
} from "../lib/publish-url.ts";
const longShareText =
"81 【汕头街头的夏天,有点可爱 - pyeong | 小红书 - 你的生活兴趣社区】 😆 qpF2vquW4v6E0uq 😆 https://www.xiaohongshu.com/discovery/item/6a5a407d000000000e0363c7?source=webshare&xhsshare=pc_web&xsec_token=ABQTS76SGS2MKA1rYfSay-1cyULvb_8k7kNIw4mKVrcDA=&xsec_source=pc_share";
const shortShareText =
"汕头街头的夏天,有点可爱 今天的关键词: 浅蓝色、草... http://xhslink.cn/o/6UDG4oUB8kR 保留这段,去【小红书】逛逛吧~";
test("extracts Xiaohongshu long and short URLs from full share text", () => {
const longUrl = extractXhsPublishUrl(longShareText);
const shortUrl = extractXhsPublishUrl(shortShareText);
assert.equal(
new URL(longUrl).pathname,
"/discovery/item/6a5a407d000000000e0363c7",
);
assert.equal(new URL(longUrl).searchParams.get("source"), "webshare");
assert.equal(shortUrl, "http://xhslink.cn/o/6UDG4oUB8kR");
});
test("rejects text that does not contain a Xiaohongshu URL", () => {
assert.equal(extractXhsPublishUrl("只有文案,没有链接"), "");
assert.equal(
extractXhsPublishUrl("https://example.com/not-xhs"),
"",
);
});

View File

@@ -0,0 +1,261 @@
import assert from "node:assert/strict";
import { access, readFile } from "node:fs/promises";
import test from "node:test";
test("builds the KOC LOOP product shell", async () => {
const [page, adminApp, layout] = await Promise.all([
readFile(new URL("../app/page.tsx", import.meta.url), "utf8"),
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
readFile(new URL("../app/layout.tsx", import.meta.url), "utf8"),
]);
assert.match(page, /requireChatGPTUser/);
assert.match(page, /isAdminEmail/);
assert.match(adminApp, /KOC LOOP/);
assert.match(adminApp, /内容分发闭环/);
assert.match(adminApp, /分发工作台/);
assert.match(adminApp, /获取KOC领取链接/);
assert.match(layout, /KOC LOOP内容分发闭环/);
assert.doesNotMatch(adminApp, /codex-preview|Your site is taking shape/);
await access(new URL("../dist/server/index.js", import.meta.url));
await access(new URL("../dist/client/assets", import.meta.url));
});
test("ships persistence, uploads, metadata, and no starter preview", async () => {
const [adminApp, layout, packageJson, hosting] = await Promise.all([
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
readFile(new URL("../app/layout.tsx", import.meta.url), "utf8"),
readFile(new URL("../package.json", import.meta.url), "utf8"),
readFile(new URL("../.openai/hosting.json", import.meta.url), "utf8"),
]);
assert.doesNotMatch(adminApp, /批量回填发布链接/);
assert.match(adminApp, /复制领取链接/);
assert.match(adminApp, /compressScreenshot/);
assert.match(layout, /KOC LOOP内容分发闭环/);
assert.match(layout, /\/og\.png/);
assert.doesNotMatch(packageJson, /react-loading-skeleton/);
assert.match(hosting, /"d1": "DB"/);
assert.match(hosting, /"r2": "UPLOADS"/);
await access(new URL("../public/og.png", import.meta.url));
});
test("organizes distribution and recovery by task and imports the verified Feishu source", async () => {
const [adminApp, snapshotText, migration, imageMigration] = await Promise.all([
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
readFile(new URL("../lib/feishu-source-snapshot.json", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0001_sloppy_blue_blade.sql", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0003_needy_doctor_strange.sql", import.meta.url), "utf8"),
]);
const snapshot = JSON.parse(snapshotText);
assert.match(adminApp, /选择一个分发任务/);
assert.match(adminApp, /选择一个数据回收任务/);
assert.match(adminApp, /读取表格/);
assert.match(adminApp, /当前仅展示/);
assert.equal(snapshot.sheetId, "954953");
assert.equal(snapshot.rows.length, 61);
assert.equal(
snapshot.rows.reduce((total, row) => total + row.images.length, 0),
64,
);
assert.ok(snapshot.rows.every((row) => row.images.length > 0));
assert.match(migration, /source_sheet_id/);
assert.match(migration, /source_row/);
assert.match(imageMigration, /image_assets/);
assert.match(imageMigration, /claims_task_partner_created_idx/);
});
test("issues external task links and supports one-to-one note submissions", async () => {
const [
adminApp,
actionRoute,
partnerRoute,
uploadRoute,
imageRoute,
imageUploadRoute,
cors,
migration,
accountEnrichment,
partnerUtils,
publishUrlUtils,
creatorScreenshotRoute,
] = await Promise.all([
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
readFile(new URL("../app/api/action/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/partner/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/partner-upload/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/partner-image/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/content-image-upload/route.ts", import.meta.url), "utf8"),
readFile(new URL("../lib/partner-cors.ts", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0002_wealthy_maelstrom.sql", import.meta.url), "utf8"),
readFile(new URL("../lib/account-enrichment-service.ts", import.meta.url), "utf8"),
readFile(new URL("../lib/partner-utils.ts", import.meta.url), "utf8"),
readFile(new URL("../lib/publish-url.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/creator-screenshot/route.ts", import.meta.url), "utf8"),
]);
assert.match(adminApp, /复制领取链接/);
assert.match(adminApp, /小红书号/);
assert.match(adminApp, /public_account_id/);
assert.doesNotMatch(adminApp, /title=\{account\.platform_uid\}/);
assert.doesNotMatch(adminApp, /平均阅读/);
assert.doesNotMatch(adminApp, /批量回填发布链接/);
assert.doesNotMatch(actionRoute, /submit_links/);
assert.match(partnerRoute, /publish_screenshot_key/);
assert.match(partnerRoute, /creator_screenshot_key/);
assert.match(partnerRoute, /submit_creator_metrics/);
assert.match(partnerRoute, /ocr_status = 'manual'/);
assert.match(partnerRoute, /请填写正确的曝光量和阅读量/);
assert.match(partnerRoute, /笔记与领取凭证不匹配/);
assert.match(partnerRoute, /action === "recover"/);
assert.match(partnerRoute, /extractXhsPublishUrl/);
assert.match(partnerRoute, /小红书长链或短链/);
assert.match(partnerRoute, /没有找到领取记录/);
assert.match(partnerRoute, /publicImageAssets/);
assert.match(partnerRoute, /withPartnerCors/);
assert.match(partnerRoute, /enrichDistributionAccount/);
assert.match(partnerRoute, /getRequestExecutionContext/);
assert.match(partnerRoute, /executionContext\.waitUntil\(enrichment\)/);
assert.match(accountEnrichment, /profile_url = excluded\.profile_url/);
assert.match(accountEnrichment, /resolveXhsAccountProfileFromMcp/);
assert.match(accountEnrichment, /resolveXhsProfileDetailsFromMcp/);
assert.match(accountEnrichment, /isVerifiedXhsProfileUrl/);
assert.match(accountEnrichment, /endsWith\("\.xiaohongshu\.com"\)/);
assert.match(accountEnrichment, /DELETE FROM accounts/);
assert.match(accountEnrichment, /a\.followers/);
assert.match(accountEnrichment, /followers = CASE/);
assert.match(accountEnrichment, /Number\(row\.followers \?\? 0\) === 0/);
assert.match(partnerUtils, /pending-\$\{hashText/);
assert.match(partnerUtils, /profileUrl:\s*""/);
assert.match(publishUrlUtils, /xhslink\.cn/);
assert.doesNotMatch(partnerUtils, /user\/profile\/\$\{platformUid\}/);
assert.match(uploadRoute, /publish-evidence/);
assert.match(uploadRoute, /creator-center/);
assert.match(uploadRoute, /ELSE 'uploaded'/);
assert.doesNotMatch(uploadRoute, /ocrMetric/);
assert.match(uploadRoute, /x-koc-upload-kind/);
assert.match(uploadRoute, /x-koc-distribution/);
assert.match(uploadRoute, /request\.arrayBuffer/);
assert.match(imageRoute, /content-assets\//);
assert.match(imageRoute, /cl\.claim_token/);
assert.match(imageUploadRoute, /isAdminRequest/);
assert.match(cors, /KOC_PORTAL_URL/);
assert.match(cors, /X-KOC-Distribution/);
assert.match(cors, /X-KOC-Upload-Kind/);
assert.match(cors, /Access-Control-Allow-Origin/);
assert.match(adminApp, /hasCreatorMetrics/);
assert.match(adminApp, /待KOC填写数据/);
assert.match(creatorScreenshotRoute, /getUploadBucket/);
assert.match(creatorScreenshotRoute, /Content-Disposition/);
assert.match(creatorScreenshotRoute, /isAdminRequest/);
assert.match(migration, /share_token/);
assert.match(migration, /claim_token/);
});
test("supports task collection schedules and latest public metrics", async () => {
const [
adminApp,
actionRoute,
bootstrapRoute,
collectionService,
worker,
viteConfig,
migration,
accountMigration,
deployConfig,
] = await Promise.all([
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
readFile(new URL("../app/api/action/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/bootstrap/route.ts", import.meta.url), "utf8"),
readFile(new URL("../lib/collection-service.ts", import.meta.url), "utf8"),
readFile(new URL("../worker/index.ts", import.meta.url), "utf8"),
readFile(new URL("../vite.config.ts", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0004_sharp_the_liberteens.sql", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0005_foamy_sage.sql", import.meta.url), "utf8"),
readFile(new URL("../dist/server/wrangler.json", import.meta.url), "utf8"),
]);
for (const label of [
"点赞",
"收藏",
"评论",
"总互动",
"数据更新时间",
"采集状态",
"发布时间",
]) {
assert.match(adminApp, new RegExp(label));
}
assert.match(adminApp, /选择开始日期与采集日/);
assert.match(adminApp, /第1天到第7天/);
assert.match(adminApp, /内容 \/ 发布账号/);
assert.match(adminApp, /recovery-title-link/);
assert.match(adminApp, /打开小红书笔记/);
assert.match(adminApp, /noopener noreferrer/);
assert.match(actionRoute, /save_collection_schedule/);
assert.match(actionRoute, /collect_now/);
assert.match(actionRoute, /backfill_account_profiles/);
assert.match(actionRoute, /set_public_account_ids/);
assert.match(actionRoute, /run_due_collections/);
assert.match(actionRoute, /retry_failed_collections/);
assert.match(actionRoute, /createCollectionRunTasks/);
assert.match(bootstrapRoute, /runDueScheduledCollections/);
assert.match(collectionService, /INSERT OR IGNORE INTO collection_runs/);
assert.match(collectionService, /collectXhsMetricsFromMcp/);
assert.doesNotMatch(collectionService, /hashText/);
assert.match(collectionService, /runScheduledCollections/);
assert.match(collectionService, /runDueScheduledCollections/);
assert.match(collectionService, /retryFailedCollections/);
assert.match(collectionService, /exposure IS NOT NULL AND views IS NOT NULL/);
assert.match(collectionService, /等待第\$\{scheduleDay\}天 10:00自动采集/);
assert.doesNotMatch(collectionService, /latestDueSchedule/);
assert.match(collectionService, /自动追采/);
assert.match(worker, /async scheduled/);
assert.match(worker, /backfillAccountProfiles/);
assert.match(bootstrapRoute, /backfillAccountProfiles/);
assert.match(viteConfig, /"0 2 \* \* \*"/);
assert.match(migration, /latest_likes/);
assert.match(migration, /collection_runs_distribution_date_idx/);
assert.match(accountMigration, /public_account_id/);
assert.match(deployConfig, /"crons":\["0 2 \* \* \*"\]/);
});
test("supports anonymous partner delegation without creating a second data flow", async () => {
const [
adminApp,
partnerRoute,
uploadRoute,
imageRoute,
cors,
schema,
runtimeSchema,
migration,
] = await Promise.all([
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
readFile(new URL("../app/api/partner/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/partner-upload/route.ts", import.meta.url), "utf8"),
readFile(new URL("../app/api/partner-image/route.ts", import.meta.url), "utf8"),
readFile(new URL("../lib/partner-cors.ts", import.meta.url), "utf8"),
readFile(new URL("../db/schema.ts", import.meta.url), "utf8"),
readFile(new URL("../lib/mvp-db.ts", import.meta.url), "utf8"),
readFile(new URL("../drizzle/0006_moaning_dark_phoenix.sql", import.meta.url), "utf8"),
]);
assert.match(schema, /delegationBundles/);
assert.match(schema, /delegationBundleId/);
assert.match(runtimeSchema, /CREATE TABLE IF NOT EXISTS delegation_bundles/);
assert.match(migration, /delegation_bundles/);
assert.match(migration, /delegation_bundle_id/);
assert.match(partnerRoute, /action === "create_delegation"/);
assert.match(partnerRoute, /action === "revoke_delegation"/);
assert.match(partnerRoute, /findAccessibleAssignment/);
assert.match(partnerRoute, /b\.status = 'active'/);
assert.match(partnerRoute, /部分笔记刚刚已被转派/);
assert.match(partnerRoute, /分享链接只能用于查看和回填包内笔记/);
assert.match(partnerRoute, /private, no-store/);
assert.match(uploadRoute, /x-koc-delegation/);
assert.match(uploadRoute, /delegation_bundles/);
assert.match(imageRoute, /delegation_bundles/);
assert.match(cors, /X-KOC-Delegation/);
assert.match(adminApp, /合作社资源 · 不可直联/);
});