|
|
/**
|
|
|
* Conservative subject-block strip: stop on body actions / Dear / 新增*
|
|
|
*/
|
|
|
import fs from "fs";
|
|
|
|
|
|
const STRIP_FN = `
|
|
|
function stripSubjectLines(text: string): string {
|
|
|
const lines = text.split(/\\n/);
|
|
|
const out: string[] = [];
|
|
|
let inSubject = false;
|
|
|
let cont = 0;
|
|
|
for (const line of lines) {
|
|
|
// "\\u4e3b\\u9898 Re:..." often has NO colon
|
|
|
if (/(?:\u4e3b\u9898|\u4e3b\u65e8|Subject)\\s*[\uFF1A:]?/i.test(line)) {
|
|
|
inSubject = true;
|
|
|
cont = 0;
|
|
|
continue;
|
|
|
}
|
|
|
if (inSubject) {
|
|
|
const t = line.trim();
|
|
|
if (!t) {
|
|
|
inSubject = false;
|
|
|
continue;
|
|
|
}
|
|
|
// real body starts
|
|
|
if (
|
|
|
BODY_ACTION_RE.test(line) ||
|
|
|
/Dear[,,]/.test(t) ||
|
|
|
/(?:\u65b0\u589e\u8f6c\u4ed3|\u65b0\u589e\u9884\u62a5|\u8bf7\u67e5\u6536|\u66f4\u65b0\u6d3e\u9001\u5355)/.test(
|
|
|
t,
|
|
|
) ||
|
|
|
/^\\d+[\\.\\u3001\\uff1a:]/.test(t)
|
|
|
) {
|
|
|
inSubject = false;
|
|
|
out.push(line);
|
|
|
continue;
|
|
|
}
|
|
|
if (
|
|
|
/^(?:\u5bc4\u4ef6\u4eba|\u53d1\u4ef6\u4eba|\u6536\u4ef6\u4eba|\u6284\u9001|\u65e5\u671f|\u53d1\u9001\u65f6\u95f4|From|To|Cc|Date|Sent|----)/i.test(
|
|
|
t,
|
|
|
) ||
|
|
|
/^date@/i.test(t) ||
|
|
|
t === "date"
|
|
|
) {
|
|
|
inSubject = false;
|
|
|
out.push(line);
|
|
|
continue;
|
|
|
}
|
|
|
// wrapped subject: ETA / container / voyage fragments only (max 4 lines)
|
|
|
if (
|
|
|
cont < 4 &&
|
|
|
/Fw:|\u8f6c\u53d1|ETA|ETD|\u8239\u540d|\u822a\u6b21|\u67dc\u53f7|[A-Z]{4}\\d{7}|40HQ|20GP|\u4ef6\\+|\\+\\s*$/i.test(
|
|
|
line,
|
|
|
)
|
|
|
) {
|
|
|
cont += 1;
|
|
|
continue;
|
|
|
}
|
|
|
inSubject = false;
|
|
|
out.push(line);
|
|
|
continue;
|
|
|
}
|
|
|
out.push(line);
|
|
|
}
|
|
|
return out.join("\\n");
|
|
|
}
|
|
|
`.trimStart();
|
|
|
|
|
|
function replaceStripInLexicon() {
|
|
|
const path = "src/services/parse/instruction-lexicon.ts";
|
|
|
let src = fs.readFileSync(path, "utf8");
|
|
|
const a = src.indexOf("function stripSubjectLines");
|
|
|
const b = src.indexOf("export function isForwardShellSegment");
|
|
|
if (a < 0 || b < 0) throw new Error("lexicon markers");
|
|
|
let start = src.lastIndexOf("/**", a);
|
|
|
if (start < 0 || a - start > 200) start = a;
|
|
|
src =
|
|
|
src.slice(0, start) +
|
|
|
"/** Drop subject block; stop early on real body actions */\n" +
|
|
|
STRIP_FN +
|
|
|
"\n" +
|
|
|
src.slice(b);
|
|
|
fs.writeFileSync(path, src);
|
|
|
console.log("lexicon ok");
|
|
|
}
|
|
|
|
|
|
function replaceBodyDetect() {
|
|
|
const path = "src/services/parse/split-instructions.ts";
|
|
|
let src = fs.readFileSync(path, "utf8");
|
|
|
// Import BODY_ACTION already exists from lexicon
|
|
|
const neu = `function bodyForKindDetect(segBody: string): string {
|
|
|
const lines = segBody.split(/\\n/);
|
|
|
const out: string[] = [];
|
|
|
let inSubject = false;
|
|
|
let cont = 0;
|
|
|
for (const line of lines) {
|
|
|
if (/(?:\u4e3b\u9898|\u4e3b\u65e8|Subject)\\s*[\uFF1A:]?/i.test(line)) {
|
|
|
inSubject = true;
|
|
|
cont = 0;
|
|
|
continue;
|
|
|
}
|
|
|
if (inSubject) {
|
|
|
const t = line.trim();
|
|
|
if (!t) {
|
|
|
inSubject = false;
|
|
|
continue;
|
|
|
}
|
|
|
if (
|
|
|
BODY_ACTION_RE.test(line) ||
|
|
|
/Dear[,,]/.test(t) ||
|
|
|
/(?:\u65b0\u589e\u8f6c\u4ed3|\u65b0\u589e\u9884\u62a5|\u8bf7\u67e5\u6536|\u66f4\u65b0\u6d3e\u9001\u5355)/.test(
|
|
|
t,
|
|
|
) ||
|
|
|
/^\\d+[\\.\\u3001\\uff1a:]/.test(t)
|
|
|
) {
|
|
|
inSubject = false;
|
|
|
out.push(line);
|
|
|
continue;
|
|
|
}
|
|
|
if (
|
|
|
/^(?:\u5bc4\u4ef6\u4eba|\u53d1\u4ef6\u4eba|\u6536\u4ef6\u4eba|\u6284\u9001|\u65e5\u671f|\u53d1\u9001\u65f6\u95f4|From|To|Cc|Date|Sent|----)/i.test(
|
|
|
t,
|
|
|
) ||
|
|
|
/^date@/i.test(t) ||
|
|
|
t === "date"
|
|
|
) {
|
|
|
inSubject = false;
|
|
|
out.push(line);
|
|
|
continue;
|
|
|
}
|
|
|
if (
|
|
|
cont < 4 &&
|
|
|
/Fw:|\u8f6c\u53d1|ETA|ETD|\u8239\u540d|\u822a\u6b21|\u67dc\u53f7|[A-Z]{4}\\d{7}|40HQ|20GP|\u4ef6\\+|\\+\\s*$/i.test(
|
|
|
line,
|
|
|
)
|
|
|
) {
|
|
|
cont += 1;
|
|
|
continue;
|
|
|
}
|
|
|
inSubject = false;
|
|
|
out.push(line);
|
|
|
continue;
|
|
|
}
|
|
|
out.push(line);
|
|
|
}
|
|
|
return out.join("\\n");
|
|
|
}
|
|
|
`;
|
|
|
const a = src.indexOf("function bodyForKindDetect");
|
|
|
const b = src.indexOf("export function detectKindsForSegment");
|
|
|
if (a < 0 || b < 0) throw new Error("split markers");
|
|
|
src = src.slice(0, a) + neu + "\n" + src.slice(b);
|
|
|
fs.writeFileSync(path, src);
|
|
|
console.log("split ok");
|
|
|
}
|
|
|
|
|
|
replaceStripInLexicon();
|
|
|
replaceBodyDetect();
|