feat(wechat): channel split with stub-safe page delivery
Introduce wechat/ channel package; never send stub HTML links to service-account users.
This commit was merged in pull request #2.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import fs from 'node:fs';
|
||||
|
||||
const STUB_MARKERS = ['临时补出', '服务号兜底', '服务号自动补出简版页面'];
|
||||
|
||||
export function isStubPublicHtmlContent(content) {
|
||||
const value = String(content ?? '');
|
||||
return STUB_MARKERS.some((marker) => value.includes(marker));
|
||||
}
|
||||
|
||||
export function artifactFileExists(artifact) {
|
||||
const localPath = String(artifact?.localPath ?? '').trim();
|
||||
if (!localPath) return false;
|
||||
try {
|
||||
return fs.existsSync(localPath) && fs.statSync(localPath).isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isStubPublicHtmlArtifact(artifact) {
|
||||
const localPath = String(artifact?.localPath ?? '').trim();
|
||||
if (!localPath) return false;
|
||||
try {
|
||||
return isStubPublicHtmlContent(fs.readFileSync(localPath, 'utf8'));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Real HTML artifacts only — never fall back to stub placeholders. */
|
||||
export function filterSendableHtmlArtifacts(artifacts = []) {
|
||||
return artifacts.filter((artifact) => artifactFileExists(artifact) && !isStubPublicHtmlArtifact(artifact));
|
||||
}
|
||||
|
||||
export function selectSendableHtmlArtifacts({ verifiedArtifacts = [], confirmedArtifacts = [] } = {}) {
|
||||
const candidates = verifiedArtifacts.length > 0 ? verifiedArtifacts : confirmedArtifacts;
|
||||
return filterSendableHtmlArtifacts(candidates);
|
||||
}
|
||||
|
||||
export function verifyPageArtifactContent(artifact, { minBytes = 512 } = {}) {
|
||||
if (!artifactFileExists(artifact)) {
|
||||
return { ok: false, reason: 'missing_file' };
|
||||
}
|
||||
if (isStubPublicHtmlArtifact(artifact)) {
|
||||
return { ok: false, reason: 'stub_placeholder' };
|
||||
}
|
||||
const size = fs.statSync(artifact.localPath).size;
|
||||
if (size < minBytes) {
|
||||
return { ok: false, reason: 'too_small' };
|
||||
}
|
||||
const content = fs.readFileSync(artifact.localPath, 'utf8');
|
||||
if (!/<(?:html|body|main|article)\b/i.test(content)) {
|
||||
return { ok: false, reason: 'not_html_document' };
|
||||
}
|
||||
return { ok: true, reason: null };
|
||||
}
|
||||
Reference in New Issue
Block a user