|
|
/**
|
|
|
* Fix: ignore subject/主旨 lines when detecting forward shells & kinds pollution
|
|
|
*/
|
|
|
import fs from "fs";
|
|
|
|
|
|
{
|
|
|
const path = "src/services/parse/instruction-lexicon.ts";
|
|
|
let src = fs.readFileSync(path, "utf8");
|
|
|
|
|
|
if (!src.includes("function stripSubjectLines")) {
|
|
|
const insertAt = src.indexOf("export function isForwardShellSegment");
|
|
|
if (insertAt < 0) throw new Error("isForwardShellSegment missing");
|
|
|
const helper = `/** Drop subject/\\u4e3b\\u65e8 lines so thread titles do not count as body actions */\nfunction stripSubjectLines(text: string): string {\n return text\n .split(/\\n/)\n .filter((line) => !/(?:\\u4e3b\\u9898|\\u4e3b\\u65e8|Subject)\\s*[\\uff1a:]/i.test(line))\n .join("\\n");\n}\n\n`;
|
|
|
// Use real Chinese in helper via unicode escapes already - wait use actual:
|
|
|
const helper2 = `/** Drop subject lines so thread titles do not count as body actions */\nfunction stripSubjectLines(text: string): string {\n return text\n .split(/\\n/)\n .filter((line) => !/(?:\u4e3b\u9898|\u4e3b\u65e8|Subject)\\s*[\uFF1A:]/i.test(line))\n .join("\\n");\n}\n\n`;
|
|
|
src = src.slice(0, insertAt) + helper2 + src.slice(insertAt);
|
|
|
}
|
|
|
|
|
|
// Rewrite isForwardShellSegment body
|
|
|
const start = src.indexOf("export function isForwardShellSegment");
|
|
|
const end = src.indexOf("export function isNonInstructionSegment");
|
|
|
if (start < 0 || end < 0) throw new Error("shell funcs missing");
|
|
|
|
|
|
const replacement = `export function isForwardShellSegment(text: string): boolean {
|
|
|
const compact = text.replace(/\\s+/g, " ").trim();
|
|
|
if (/\u53d1\u81ea\u6211\u7684iPhone/.test(compact)) return true;
|
|
|
|
|
|
const bodyOnly = stripSubjectLines(text);
|
|
|
const bodyCompact = bodyOnly.replace(/\\s+/g, " ").trim();
|
|
|
|
|
|
// date / QQ pure forward wrapper (keywords only in \u4e3b\u65e8)
|
|
|
if (
|
|
|
/date@usasinogroup\\.com/i.test(compact) &&
|
|
|
!/Dear[,,]/.test(bodyOnly) &&
|
|
|
!BODY_ACTION_RE.test(bodyOnly)
|
|
|
) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
/\u53d1\u81ea\u6211\u7684iPhone|\u5927\u5c0f\\s*\\d/.test(compact) &&
|
|
|
!BODY_ACTION_RE.test(bodyOnly) &&
|
|
|
!/\u65b0\u589e\u9884\u62a5|\u8bf7\u67e5\u6536\u65b0\u589e\u9884\u62a5|\u65b0\u589e\u8f6c\u4ed3|DO\u8bf7\u67e5\u6536/.test(
|
|
|
bodyOnly,
|
|
|
)
|
|
|
) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// short date forward: only headers + signature
|
|
|
if (
|
|
|
/\u5bc4\u4ef6\u4eba/.test(compact) &&
|
|
|
/date@usasinogroup\\.com/i.test(compact) &&
|
|
|
bodyCompact.length < 120 &&
|
|
|
!/Dear[,,]/.test(bodyOnly)
|
|
|
) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
`;
|
|
|
|
|
|
src = src.slice(0, start) + replacement + src.slice(end);
|
|
|
|
|
|
// Also update isNonInstructionSegment QQ shell to use stripSubjectLines
|
|
|
src = src.replace(
|
|
|
` // QQ \u5916\u58f3\uff1a\u4ec5\u8f6c\u53d1\u5143\u6570\u636e\u3001\u65e0\u4e1a\u52a1\u52a8\u4f5c
|
|
|
if (
|
|
|
/\u53d1\u81ea\u6211\u7684iPhone|\u5927\u5c0f\\s*\\d/.test(compact) &&
|
|
|
!BODY_ACTION_RE.test(compact) &&
|
|
|
!/\u65b0\u589e\u9884\u62a5|\u8bf7\u67e5\u6536\u65b0\u589e\u9884\u62a5|\u65b0\u589e\u8f6c\u4ed3|DO\u8bf7\u67e5\u6536/.test(compact)
|
|
|
) {
|
|
|
return true;
|
|
|
}`,
|
|
|
` // QQ shell without body actions (ignore subject title noise)
|
|
|
{
|
|
|
const bodyOnly = stripSubjectLines(text);
|
|
|
if (
|
|
|
/\u53d1\u81ea\u6211\u7684iPhone|\u5927\u5c0f\\s*\\d/.test(compact) &&
|
|
|
!BODY_ACTION_RE.test(bodyOnly) &&
|
|
|
!/\u65b0\u589e\u9884\u62a5|\u8bf7\u67e5\u6536\u65b0\u589e\u9884\u62a5|\u65b0\u589e\u8f6c\u4ed3|DO\u8bf7\u67e5\u6536/.test(
|
|
|
bodyOnly,
|
|
|
)
|
|
|
) {
|
|
|
return true;
|
|
|
}
|
|
|
}`,
|
|
|
);
|
|
|
|
|
|
fs.writeFileSync(path, src);
|
|
|
console.log("lexicon shell ok");
|
|
|
}
|
|
|
|
|
|
{
|
|
|
const path = "src/services/parse/split-instructions.ts";
|
|
|
let src = fs.readFileSync(path, "utf8");
|
|
|
// Strengthen bodyForKindDetect: strip ALL subject lines + Re:新增预报 pollution lines
|
|
|
const old = `function bodyForKindDetect(segBody: string): string {
|
|
|
if (!BODY_ACTION_RE.test(segBody)) return segBody;
|
|
|
return segBody
|
|
|
.split(/\\n/)
|
|
|
.filter(
|
|
|
(line) =>
|
|
|
!/(?:\u4e3b\u9898|\u4e3b\u65e8|Subject)\\s*[\uFF1A:].*(?:\u65b0\u589e\u9884\u62a5|Fw:|\u8f6c\u53d1)/i.test(line),
|
|
|
)
|
|
|
.join("\\n");
|
|
|
}`;
|
|
|
|
|
|
const neu = `function bodyForKindDetect(segBody: string): string {
|
|
|
// Always strip subject/Re title lines; they carry historical \u65b0\u589e\u9884\u62a5
|
|
|
const stripped = segBody
|
|
|
.split(/\\n/)
|
|
|
.filter((line) => {
|
|
|
if (/(?:\u4e3b\u9898|\u4e3b\u65e8|Subject)\\s*[\uFF1A:]/i.test(line)) return false;
|
|
|
if (/^Re:\\s*Re:/i.test(line.trim()) && /\u65b0\u589e\u9884\u62a5/.test(line))
|
|
|
return false;
|
|
|
return true;
|
|
|
})
|
|
|
.join("\\n");
|
|
|
return stripped;
|
|
|
}`;
|
|
|
|
|
|
if (!src.includes("function bodyForKindDetect")) throw new Error("no bodyForKindDetect");
|
|
|
// replace by function bounds
|
|
|
const a = src.indexOf("function bodyForKindDetect");
|
|
|
const b = src.indexOf("export function detectKindsForSegment");
|
|
|
if (a < 0 || b < 0) throw new Error("bounds");
|
|
|
src = src.slice(0, a) + neu + "\n\n" + src.slice(b);
|
|
|
|
|
|
// useSubject: only when body (stripped) has no action words
|
|
|
src = src.replace(
|
|
|
` const useSubject =
|
|
|
!BODY_ACTION_RE.test(segBody) ||
|
|
|
/\\u8bf7\\u67e5\\u6536\\u65b0\\u589e\\u9884\\u62a5/.test(bodyText);`,
|
|
|
` const useSubject =
|
|
|
!BODY_ACTION_RE.test(bodyText) ||
|
|
|
/\u8bf7\u67e5\u6536\u65b0\u589e\u9884\u62a5/.test(bodyText);`,
|
|
|
);
|
|
|
|
|
|
// Also fix the actual Chinese version if unicode escape didn't match
|
|
|
src = src.replace(
|
|
|
/const useSubject =\s*!BODY_ACTION_RE\.test\(segBody\) \|\|\s*\/请查收新增预报\/\.test\(bodyText\);/,
|
|
|
`const useSubject =
|
|
|
!BODY_ACTION_RE.test(bodyText) ||
|
|
|
/\u8bf7\u67e5\u6536\u65b0\u589e\u9884\u62a5/.test(bodyText);`,
|
|
|
);
|
|
|
|
|
|
fs.writeFileSync(path, src);
|
|
|
console.log("split bodyForKindDetect ok");
|
|
|
}
|