You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mail-yubao/scripts/patch-skip-instruction-rows.ts

95 lines
3.5 KiB

import fs from "fs";
{
const path = "src/services/parse/packing-list.ts";
let src = fs.readFileSync(path, "utf8");
if (!src.includes("function isInstructionNoiseRow")) {
const insertAt = src.indexOf("export async function parsePackingListBuffer");
if (insertAt < 0) throw new Error("fn missing");
const helper = `/** Template footer instruction row <20>?not a shipment */
export function isInstructionNoiseRow(raw: Record<string, unknown>): boolean {
const parts = Object.values(raw).map((v) => String(v ?? "").trim());
const blob = parts.join(" ");
if (!blob) return false;
if (/^\u6ce8\u610f\\s*[\\uFF1A:]/.test(blob)) return true;
if (parts.some((p) => /^\u6ce8\u610f\\s*[\\uFF1A:]/.test(p))) return true;
const channel = String(raw.F_Transporter ?? "").trim();
const fba = String(raw.F_FBACode ?? "").trim();
const addr = String(raw.F_Address ?? "").trim();
if (
(channel.length > 40 || fba.length > 40 || addr.length > 80) &&
/\u6ce8\u610f|\u586b\u5199|\u5355\u5143\u683c|\u5fc5\u987b\u586b\u5199/.test(blob)
) {
return true;
}
return false;
}
`;
src = src.slice(0, insertAt) + helper + src.slice(insertAt);
}
if (!src.includes("isInstructionNoiseRow(raw)")) {
src = src.replace(
/\/\/ \u8df3\u8fc7\u7a7a\u884c\r?\n\s*const hasAny = Object\.values\(raw\)\.some\(\r?\n\s*\(v\) => v != null && String\(v\)\.trim\(\) !== "",\r?\n\s*\);\r?\n\s*if \(!hasAny\) continue;/,
`// skip empty / instruction footer rows\n const hasAny = Object.values(raw).some(\n (v) => v != null && String(v).trim() !== "",\n );\n if (!hasAny) continue;\n if (isInstructionNoiseRow(raw)) continue;`,
);
}
if (!src.includes("isInstructionNoiseRow(raw)")) {
throw new Error("failed to insert skip call");
}
fs.writeFileSync(path, src);
console.log("packing-list patched");
}
{
const path = "src/services/parse/channel-map.ts";
let src = fs.readFileSync(path, "utf8");
if (src.includes("text.length > 40")) {
console.log("channel-map already ok");
} else {
src = src.replace(
/export function mapChannel\(raw: string\): \{[\s\S]*?return \{ transporter: text\.slice\(0, 30\), unmapped: true \};\n\}/,
`export function mapChannel(raw: string): {
transporter: string;
unmapped: boolean;
} {
const text = (raw || "").trim();
if (!text) return { transporter: "", unmapped: true };
// Long instruction text must not map (e.g. note mentioning Truck)
if (text.length > 40 || /^\\u6ce8\\u610f\\s*[\\uFF1A:]/.test(text)) {
return { transporter: "", unmapped: true };
}
const upper = text.toUpperCase();
for (const rule of CHANNEL_MAP) {
if (
rule.keys.some((k) => {
const key = k.toUpperCase();
if (/^[A-Z0-9]+$/i.test(k)) {
return new RegExp(\`(?:^|[^A-Z0-9])\${key}(?:[^A-Z0-9]|$)\`).test(upper);
}
return upper.includes(key);
})
) {
return { transporter: rule.value, unmapped: false };
}
}
return { transporter: text.slice(0, 30), unmapped: true };
}`,
);
// Fix the broken unicode escape in the written file - use real chars
src = src.replace(
"if (text.length > 40 || /^\\\\u6ce8\\\\u610f\\\\s*[\\\\uFF1A:]/.test(text))",
"if (text.length > 40 || /^\u6ce8\u610f\\s*[\uFF1A:]/.test(text))",
);
// Also if the replace used the regex with single backslash unicode incorrectly
if (!src.includes("text.length > 40")) {
throw new Error("channel map replace failed");
}
fs.writeFileSync(path, src);
console.log("channel-map patched");
}
}