Files
memind/mindspace-config.mjs
T
john 9b4a25799f 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>
2026-06-26 15:19:03 +08:00

97 lines
3.0 KiB
JavaScript

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,
};