Files
koc-loop/lib/wecom-feedback-service.ts

108 lines
3.3 KiB
TypeScript
Raw Permalink Normal View History

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<boolean> {
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<SubmittedRow>();
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<boolean> {
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;
}