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:
+37
-6
@@ -38,6 +38,30 @@ function normalizeSort(value) {
|
||||
return 'recommend';
|
||||
}
|
||||
|
||||
export function defaultPlazaCoverUrl(publicUrl) {
|
||||
const value = String(publicUrl ?? '').trim();
|
||||
if (!value) return '';
|
||||
const [pathname, suffix = ''] = value.split(/([?#].*)/, 2);
|
||||
if (!pathname) return '';
|
||||
const nextPath = pathname.endsWith('/') ? `${pathname}index.thumbnail.png` : `${pathname}.thumbnail.png`;
|
||||
return `${nextPath}${suffix}`;
|
||||
}
|
||||
|
||||
export function resolvePlazaCoverUrl(inputCoverUrl, publicUrl) {
|
||||
const value = String(inputCoverUrl ?? '').trim();
|
||||
if (!value) return defaultPlazaCoverUrl(publicUrl);
|
||||
if (/^https?:\/\//i.test(value)) return value;
|
||||
const base = String(publicUrl ?? '').trim();
|
||||
if (base && /^https?:\/\//i.test(base)) {
|
||||
try {
|
||||
return new URL(value, base).toString();
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function formatStats(row) {
|
||||
return {
|
||||
view_count: Number(row.view_count ?? 0),
|
||||
@@ -66,11 +90,12 @@ function promoteFreshPosts(items, now = Date.now()) {
|
||||
}
|
||||
|
||||
function formatPostRow(row, { category, viewerReacted = null, publicationUrl = null } = {}) {
|
||||
const resolvedPublicationUrl = publicationUrl ?? row.public_url ?? null;
|
||||
return {
|
||||
id: row.id,
|
||||
title: row.title,
|
||||
summary: row.summary ?? '',
|
||||
cover_url: row.cover_url ?? '',
|
||||
cover_url: resolvePlazaCoverUrl(row.cover_url, resolvedPublicationUrl),
|
||||
category: category ?? {
|
||||
id: row.category_id,
|
||||
name: row.category_name ?? '',
|
||||
@@ -87,7 +112,7 @@ function formatPostRow(row, { category, viewerReacted = null, publicationUrl = n
|
||||
stats: formatStats(row),
|
||||
viewer_reacted: viewerReacted,
|
||||
published_at: new Date(Number(row.published_at)).toISOString(),
|
||||
...(publicationUrl ? { publication_url: publicationUrl } : {}),
|
||||
...(resolvedPublicationUrl ? { publication_url: resolvedPublicationUrl } : {}),
|
||||
...(row.allow_comment != null ? { allow_comment: Boolean(row.allow_comment) } : {}),
|
||||
...(row.status ? { status: row.status } : {}),
|
||||
};
|
||||
@@ -97,6 +122,8 @@ export const plazaInternals = {
|
||||
normalizeTags,
|
||||
clampLimit,
|
||||
normalizeSort,
|
||||
defaultPlazaCoverUrl,
|
||||
resolvePlazaCoverUrl,
|
||||
};
|
||||
|
||||
export function createPlazaPostService(
|
||||
@@ -238,7 +265,7 @@ export function createPlazaPostService(
|
||||
const categoryId = await resolveCategoryId(input?.category_id, input?.category_slug);
|
||||
const userSnapshot = await loadUserSnapshot(userId);
|
||||
const tags = normalizeTags(input?.tags);
|
||||
const coverUrl = String(input?.cover_url ?? '').trim();
|
||||
const coverUrl = resolvePlazaCoverUrl(input?.cover_url, publication.public_url);
|
||||
const allowComment = input?.allow_comment == null ? true : Boolean(input.allow_comment);
|
||||
const now = Date.now();
|
||||
const postId = idFactory();
|
||||
@@ -298,7 +325,10 @@ export function createPlazaPostService(
|
||||
|
||||
const updatePost = async (userId, postId, input) => {
|
||||
const [rows] = await pool.query(
|
||||
`SELECT * FROM plaza_posts WHERE id = ? AND user_id = ? LIMIT 1`,
|
||||
`SELECT pp.*, pr.public_url
|
||||
FROM plaza_posts pp
|
||||
JOIN h5_publish_records pr ON pr.id = pp.publication_id
|
||||
WHERE pp.id = ? AND pp.user_id = ? LIMIT 1`,
|
||||
[postId, userId],
|
||||
);
|
||||
const post = rows[0];
|
||||
@@ -317,7 +347,7 @@ export function createPlazaPostService(
|
||||
}
|
||||
if (input?.cover_url != null) {
|
||||
updates.push('cover_url = ?');
|
||||
params.push(String(input.cover_url).trim());
|
||||
params.push(resolvePlazaCoverUrl(input.cover_url, post.public_url));
|
||||
}
|
||||
if (input?.allow_comment != null) {
|
||||
updates.push('allow_comment = ?');
|
||||
@@ -450,9 +480,10 @@ export function createPlazaPostService(
|
||||
: 'pp.hot_score DESC, pp.id DESC';
|
||||
|
||||
const [rows] = await pool.query(
|
||||
`SELECT pp.*, c.name AS category_name, c.slug AS category_slug, c.icon AS category_icon
|
||||
`SELECT pp.*, c.name AS category_name, c.slug AS category_slug, c.icon AS category_icon, pr.public_url
|
||||
FROM plaza_posts pp
|
||||
JOIN plaza_categories c ON c.id = pp.category_id
|
||||
JOIN h5_publish_records pr ON pr.id = pp.publication_id
|
||||
WHERE pp.status = ?
|
||||
${categoryFilter}
|
||||
${cursorClause}
|
||||
|
||||
Reference in New Issue
Block a user