feat: 完善视频任务与 KOC 资源库
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
type CollectionMcpBindings,
|
||||
} from "./mcp-collection-client";
|
||||
import { ensureSchema, getRawDb } from "./mvp-db";
|
||||
import { extractXhsPublishUrl } from "./publish-url";
|
||||
import { extractAnyPublishUrl } from "./publish-url";
|
||||
import { buildClaimUrl } from "./task-service";
|
||||
|
||||
export type McpOperationBindings = CollectionMcpBindings & {
|
||||
@@ -123,9 +123,9 @@ export async function taskGet(taskId: string, portalUrl: string) {
|
||||
const [notes, claims, runs] = await Promise.all([
|
||||
db
|
||||
.prepare(
|
||||
`SELECT c.id AS content_id, c.source_row, c.title, c.body, c.image_assets, c.status AS content_status,
|
||||
`SELECT c.id AS content_id, c.source_row, c.title, c.body, c.image_assets, c.video_assets, c.status AS content_status,
|
||||
d.id AS distribution_id, d.status AS distribution_status, d.publish_url, d.publish_time,
|
||||
d.exposure, d.views, d.latest_likes, d.latest_comments, d.latest_collects,
|
||||
d.exposure, d.views, d.latest_likes, d.latest_comments, d.latest_collects, d.latest_shares,
|
||||
d.collection_status, d.collection_status_description, d.collection_updated_at,
|
||||
a.id AS account_id, a.nickname AS account_nickname, a.profile_url, a.followers,
|
||||
p.name AS cooperation_source, cl.claimant_name
|
||||
@@ -172,12 +172,14 @@ export async function taskGet(taskId: string, portalUrl: string) {
|
||||
notes: notes.results.map((row) => ({
|
||||
...row,
|
||||
image_assets: parseJsonArray(row.image_assets),
|
||||
video_assets: parseJsonArray(row.video_assets),
|
||||
total_interactions:
|
||||
row.latest_likes == null
|
||||
? null
|
||||
: Number(row.latest_likes) +
|
||||
Number(row.latest_comments ?? 0) +
|
||||
Number(row.latest_collects ?? 0),
|
||||
Number(row.latest_collects ?? 0) +
|
||||
Number(row.latest_shares ?? 0),
|
||||
})),
|
||||
claims: claims.results,
|
||||
collection_runs: runs.results,
|
||||
@@ -220,7 +222,8 @@ export async function recoveryList(
|
||||
const [rows, count] = await Promise.all([
|
||||
db
|
||||
.prepare(
|
||||
`SELECT d.*, t.name AS task_name, c.source_row, c.title,
|
||||
`SELECT d.*, t.name AS task_name, t.platform AS task_platform,
|
||||
t.content_format, c.source_row, c.title,
|
||||
a.nickname AS account_nickname, a.profile_url, p.name AS cooperation_source,
|
||||
cl.claimant_name ${base}
|
||||
ORDER BY COALESCE(d.publish_time, d.claimed_at) DESC LIMIT ${limit} OFFSET ${offset}`,
|
||||
@@ -241,7 +244,7 @@ export async function recoveryList(
|
||||
total_interactions:
|
||||
row.latest_likes == null
|
||||
? null
|
||||
: Number(row.latest_likes) + Number(row.latest_comments ?? 0) + Number(row.latest_collects ?? 0),
|
||||
: Number(row.latest_likes) + Number(row.latest_comments ?? 0) + Number(row.latest_collects ?? 0) + Number(row.latest_shares ?? 0),
|
||||
})),
|
||||
};
|
||||
}
|
||||
@@ -358,9 +361,11 @@ function resourceWhere(input: ResourceFilters) {
|
||||
const conditions: string[] = [];
|
||||
const bindings: unknown[] = [];
|
||||
if (input.query?.trim()) {
|
||||
conditions.push("(a.nickname LIKE ? ESCAPE '\\' OR a.public_account_id LIKE ? ESCAPE '\\')");
|
||||
conditions.push(
|
||||
"(a.nickname LIKE ? ESCAPE '\\' OR a.public_account_id LIKE ? ESCAPE '\\' OR a.current_contact LIKE ? ESCAPE '\\' OR a.tags LIKE ? ESCAPE '\\' OR a.bio LIKE ? ESCAPE '\\')",
|
||||
);
|
||||
const pattern = like(input.query.trim());
|
||||
bindings.push(pattern, pattern);
|
||||
bindings.push(pattern, pattern, pattern, pattern, pattern);
|
||||
}
|
||||
if (input.ipLocation?.trim()) {
|
||||
conditions.push("a.ip_location LIKE ? ESCAPE '\\'");
|
||||
@@ -369,8 +374,12 @@ function resourceWhere(input: ResourceFilters) {
|
||||
if (input.cooperationSource?.trim()) {
|
||||
conditions.push(
|
||||
`(a.cooperation_source LIKE ? ESCAPE '\\' OR
|
||||
EXISTS (SELECT 1 FROM distributions dx JOIN partners px ON px.id = dx.partner_id
|
||||
WHERE dx.account_id = a.id AND px.name LIKE ? ESCAPE '\\'))`,
|
||||
EXISTS (SELECT 1 FROM distributions dx
|
||||
JOIN partners px ON px.id = dx.partner_id
|
||||
LEFT JOIN claims cx ON cx.id = dx.claim_id
|
||||
WHERE dx.account_id = a.id
|
||||
AND (cx.claimant_name IS NULL OR px.name != cx.claimant_name)
|
||||
AND px.name LIKE ? ESCAPE '\\'))`,
|
||||
);
|
||||
const pattern = like(input.cooperationSource.trim());
|
||||
bindings.push(pattern, pattern);
|
||||
@@ -389,7 +398,12 @@ export async function resourceSearch(input: ResourceFilters) {
|
||||
const db = getRawDb();
|
||||
const select = `SELECT a.*,
|
||||
(SELECT COUNT(*) FROM distributions d WHERE d.account_id = a.id) AS cooperation_count,
|
||||
(SELECT GROUP_CONCAT(DISTINCT p.name) FROM distributions d JOIN partners p ON p.id = d.partner_id WHERE d.account_id = a.id) AS cooperation_sources`;
|
||||
(SELECT GROUP_CONCAT(DISTINCT p.name)
|
||||
FROM distributions d
|
||||
JOIN partners p ON p.id = d.partner_id
|
||||
LEFT JOIN claims c ON c.id = d.claim_id
|
||||
WHERE d.account_id = a.id
|
||||
AND (c.claimant_name IS NULL OR p.name != c.claimant_name)) AS cooperation_sources`;
|
||||
const [rows, count] = await Promise.all([
|
||||
db.prepare(`${select} FROM accounts a ${where} ORDER BY a.last_seen_at DESC LIMIT ${limit} OFFSET ${offset}`)
|
||||
.bind(...bindings).all<Record<string, unknown>>(),
|
||||
@@ -422,7 +436,7 @@ export async function resourceGet(accountId: string) {
|
||||
if (!account) throw new Error("账号不存在");
|
||||
const history = await db.prepare(
|
||||
`SELECT d.id AS distribution_id, d.task_id, t.name AS task_name, c.title,
|
||||
d.publish_url, d.publish_time, d.latest_likes, d.latest_comments, d.latest_collects,
|
||||
d.publish_url, d.publish_time, d.latest_likes, d.latest_comments, d.latest_collects, d.latest_shares,
|
||||
d.exposure, d.views, p.name AS cooperation_source, cl.claimant_name
|
||||
FROM distributions d JOIN tasks t ON t.id = d.task_id
|
||||
JOIN contents c ON c.id = d.content_id JOIN partners p ON p.id = d.partner_id
|
||||
@@ -438,7 +452,7 @@ export async function backfillResourceProfile(
|
||||
) {
|
||||
await ensureSchema();
|
||||
const db = getRawDb();
|
||||
const publishUrl = input.publishUrl ? extractXhsPublishUrl(input.publishUrl) : "";
|
||||
const publishUrl = input.publishUrl ? extractAnyPublishUrl(input.publishUrl) : "";
|
||||
const row = input.distributionId
|
||||
? await db.prepare(
|
||||
`SELECT d.id, d.publish_url, COALESCE(a.nickname, '') AS nickname
|
||||
|
||||
Reference in New Issue
Block a user