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 @@
|
||||
const PUBLIC_PAGE_LIMIT_KEY = 'public_page_limit';
|
||||
|
||||
function asPositiveInteger(value, fallback) {
|
||||
const parsed = Number(value);
|
||||
if (!Number.isFinite(parsed) || parsed < 1) return fallback;
|
||||
return Math.floor(parsed);
|
||||
}
|
||||
|
||||
async function ensureConfigTable(pool) {
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS mindspace_config (
|
||||
\`key\` VARCHAR(64) PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
description VARCHAR(255) NULL,
|
||||
updated_at BIGINT NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
`);
|
||||
}
|
||||
|
||||
export function defaultMindSpaceConfig(env = process.env) {
|
||||
return {
|
||||
publicPageLimit: asPositiveInteger(env.MINDSPACE_FREE_PUBLIC_PAGE_LIMIT ?? 5, 5),
|
||||
};
|
||||
}
|
||||
|
||||
async function readConfigRows(pool) {
|
||||
const [rows] = await pool.query(
|
||||
'SELECT `key`, value FROM mindspace_config',
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
export async function ensureMindSpaceConfig(pool, { env = process.env, seedDefault = true } = {}) {
|
||||
await ensureConfigTable(pool);
|
||||
if (!seedDefault) return;
|
||||
const [rows] = await pool.query('SELECT COUNT(*) AS count FROM mindspace_config');
|
||||
if (Number(rows[0]?.count ?? 0) > 0) return;
|
||||
|
||||
const now = Date.now();
|
||||
const defaults = defaultMindSpaceConfig(env);
|
||||
await pool.query(
|
||||
`INSERT INTO mindspace_config (\`key\`, value, description, updated_at)
|
||||
VALUES (?, ?, ?, ?)`,
|
||||
[PUBLIC_PAGE_LIMIT_KEY, String(defaults.publicPageLimit), '公开页面数量上限', now],
|
||||
);
|
||||
}
|
||||
|
||||
export async function loadMindSpaceConfig(pool, { env = process.env } = {}) {
|
||||
const config = defaultMindSpaceConfig(env);
|
||||
try {
|
||||
const rows = await readConfigRows(pool);
|
||||
for (const row of rows) {
|
||||
if (row.key === PUBLIC_PAGE_LIMIT_KEY) {
|
||||
config.publicPageLimit = asPositiveInteger(row.value, config.publicPageLimit);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (error?.code === 'ER_NO_SUCH_TABLE') return config;
|
||||
throw error;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
export async function updateMindSpaceConfig(pool, patch, { env = process.env } = {}) {
|
||||
await ensureConfigTable(pool);
|
||||
const updates = [];
|
||||
if (patch?.publicPageLimit !== undefined) {
|
||||
const publicPageLimit = asPositiveInteger(patch.publicPageLimit, null);
|
||||
if (!publicPageLimit) {
|
||||
throw Object.assign(new Error('公开页面数量上限必须是大于 0 的整数'), {
|
||||
code: 'invalid_mindspace_config',
|
||||
});
|
||||
}
|
||||
updates.push([PUBLIC_PAGE_LIMIT_KEY, String(publicPageLimit), '公开页面数量上限']);
|
||||
}
|
||||
|
||||
if (updates.length === 0) return loadMindSpaceConfig(pool, { env });
|
||||
|
||||
const now = Date.now();
|
||||
for (const [key, value, description] of updates) {
|
||||
await pool.query(
|
||||
`INSERT INTO mindspace_config (\`key\`, value, description, updated_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
value = VALUES(value),
|
||||
description = VALUES(description),
|
||||
updated_at = VALUES(updated_at)`,
|
||||
[key, value, description, now],
|
||||
);
|
||||
}
|
||||
return loadMindSpaceConfig(pool, { env });
|
||||
}
|
||||
|
||||
export const mindspaceConfigInternals = {
|
||||
PUBLIC_PAGE_LIMIT_KEY,
|
||||
};
|
||||
Reference in New Issue
Block a user