Add smart ACK provider for WeChat MP replies
Replace fixed ackText with a rule-based AckProvider that picks response templates by message type and intent (translate, summary, rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync, zero I/O, auto-falls back to config.ackText on any error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { createDbPool } from '../db.mjs';
|
||||
import { defaultPlazaCoverUrl } from '../plaza-posts.mjs';
|
||||
|
||||
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const shouldWrite = process.argv.includes('--write');
|
||||
|
||||
function loadEnvFile(filePath) {
|
||||
if (!fs.existsSync(filePath)) return;
|
||||
for (const line of fs.readFileSync(filePath, 'utf8').split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||
const eq = trimmed.indexOf('=');
|
||||
if (eq < 0) continue;
|
||||
const key = trimmed.slice(0, eq).trim();
|
||||
const value = trimmed.slice(eq + 1).trim();
|
||||
if (!process.env[key]) process.env[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
function absolutize(url) {
|
||||
const value = String(url ?? '').trim();
|
||||
if (!value) return '';
|
||||
if (/^https?:\/\//i.test(value)) return value;
|
||||
return new URL(value, publicBaseUrl).toString();
|
||||
}
|
||||
|
||||
loadEnvFile(path.join(root, '../../.env.local'));
|
||||
loadEnvFile(path.join(root, '.env'));
|
||||
|
||||
const { resolvePublicBaseUrl } = await import('../user-publish.mjs');
|
||||
const publicBaseUrl = resolvePublicBaseUrl();
|
||||
|
||||
const pool = createDbPool();
|
||||
const [rows] = await pool.query(
|
||||
`SELECT pp.id, pp.publication_id, pp.title, pp.cover_url, pp.status, pr.public_url, pr.status AS publication_status
|
||||
FROM plaza_posts pp
|
||||
JOIN h5_publish_records pr ON pr.id = pp.publication_id
|
||||
WHERE pr.public_url IS NOT NULL
|
||||
ORDER BY pp.published_at DESC, pp.id DESC`,
|
||||
);
|
||||
|
||||
const updates = rows
|
||||
.map((row) => {
|
||||
const nextPublicUrl = absolutize(row.public_url);
|
||||
const nextCoverUrl = row.cover_url
|
||||
? absolutize(row.cover_url)
|
||||
: absolutize(defaultPlazaCoverUrl(nextPublicUrl));
|
||||
return {
|
||||
id: row.id,
|
||||
publicationId: row.publication_id,
|
||||
title: row.title,
|
||||
fromPublicUrl: String(row.public_url ?? ''),
|
||||
toPublicUrl: nextPublicUrl,
|
||||
fromCoverUrl: String(row.cover_url ?? ''),
|
||||
toCoverUrl: nextCoverUrl,
|
||||
status: row.status,
|
||||
publicationStatus: row.publication_status,
|
||||
};
|
||||
})
|
||||
.filter((row) => row.toPublicUrl && (row.fromPublicUrl !== row.toPublicUrl || row.fromCoverUrl !== row.toCoverUrl));
|
||||
|
||||
console.log(
|
||||
`${shouldWrite ? '写入模式' : 'Dry-run'}:共扫描 ${rows.length} 条帖子,命中 ${updates.length} 条待补 public_url/cover_url。`,
|
||||
);
|
||||
console.log(`Public base: ${publicBaseUrl}`);
|
||||
|
||||
for (const row of updates.slice(0, 20)) {
|
||||
console.log(`- ${row.id} | ${row.title}`);
|
||||
console.log(` public_url: ${row.fromPublicUrl || '(empty)'} -> ${row.toPublicUrl}`);
|
||||
console.log(` cover_url : ${row.fromCoverUrl || '(empty)'} -> ${row.toCoverUrl}`);
|
||||
}
|
||||
if (updates.length > 20) {
|
||||
console.log(`... 其余 ${updates.length - 20} 条省略`);
|
||||
}
|
||||
|
||||
if (shouldWrite && updates.length > 0) {
|
||||
const now = Date.now();
|
||||
for (const row of updates) {
|
||||
await pool.query(
|
||||
`UPDATE h5_publish_records pr
|
||||
JOIN plaza_posts pp ON pp.publication_id = pr.id
|
||||
SET pr.public_url = ?, pp.cover_url = ?, pr.updated_at = ?, pp.updated_at = ?
|
||||
WHERE pr.id = ?`,
|
||||
[row.toPublicUrl, row.toCoverUrl, now, now, row.publicationId],
|
||||
);
|
||||
}
|
||||
console.log(`已更新 ${updates.length} 条帖子公开链接与封面。`);
|
||||
} else if (!shouldWrite) {
|
||||
console.log('未写入数据库;如需正式回填,请执行: node scripts/backfill-plaza-public-urls.mjs --write');
|
||||
}
|
||||
|
||||
await pool.end();
|
||||
Reference in New Issue
Block a user