import type { DatabaseClient } from "./database"; import { getRuntimeEnv, isEnabled } from "./runtime-env"; import { sendWecomRobotMessage, type WecomConfig } from "./wecom-client"; type FetchLike = typeof fetch; export function isWecomFeedbackEnabled() { return isEnabled(getRuntimeEnv().WECOM_FEEDBACK_ENABLED, false); } type SubmittedRow = { claimant_name: string | null; partner_name: string | null; task_name: string; content_title: string | null; publish_url: string | null; }; function truncate(value: string, max: number) { return value.length > max ? `${value.slice(0, max)}…` : value; } export function buildPublishSubmittedMessage( row: SubmittedRow, kind: "publish" | "screenshot", ): string { const partner = row.partner_name || row.claimant_name || "未知合作方"; if (kind === "screenshot") { return [ "【KOC 已提交截图】", `合作方:${partner}`, `任务:${truncate(row.task_name, 24)}`, `内容:${truncate(row.content_title ?? "", 24)}`, "请到后台「数据回收」页查看与审核。", ].join("\n"); } return [ "【KOC 已提交发布】", `合作方:${partner}`, `任务:${truncate(row.task_name, 24)}`, `内容:${truncate(row.content_title ?? "", 24)}`, `链接:${row.publish_url ?? ""}`, "链接已入库,采集计划将按日自动执行。", ].join("\n"); } export async function notifyPartnerSubmitted( db: DatabaseClient, params: { distributionId: string; kind: "publish" | "screenshot" }, config: WecomConfig, fetchImpl: FetchLike = fetch, ): Promise { if (!config.robotWebhook) return false; const distributionId = String(params.distributionId ?? "").trim(); if (!distributionId) return false; const row = await db .prepare( `SELECT d.claimant_name, d.publish_url, t.name AS task_name, c.title AS content_title, p.name AS partner_name FROM distributions d JOIN tasks t ON t.id = d.task_id LEFT JOIN contents c ON c.id = d.content_id LEFT JOIN partners p ON p.id = d.partner_id WHERE d.id = ?`, ) .bind(distributionId) .first(); if (!row) return false; const message = buildPublishSubmittedMessage(row, params.kind); await sendWecomRobotMessage(message, config, fetchImpl); return true; } export function buildCollectionFinishedMessage(summary: { currentDate: string; dueTasks: number; attempted: number; succeeded: number; failed: number; }): string { const lines = [ `【数据采集日报】${summary.currentDate}`, `应采集任务 ${summary.dueTasks} 个,执行 ${summary.attempted} 条:成功 ${summary.succeeded}、失败 ${summary.failed}。`, ]; if (summary.failed > 0) { lines.push("有采集失败,请到后台「数据回收」页查看并重试。"); } return lines.join("\n"); } export async function notifyCollectionFinished( summary: { currentDate: string; dueTasks: number; attempted: number; succeeded: number; failed: number; }, config: WecomConfig, fetchImpl: FetchLike = fetch, ): Promise { if (!config.robotWebhook) return false; if (summary.attempted <= 0 && summary.failed <= 0) return false; const message = buildCollectionFinishedMessage(summary); await sendWecomRobotMessage(message, config, fetchImpl); return true; }