extract Descriotion too. below is the handlerl.ts
type MsgCtx = {
from?: string;
body?: string;
timestamp?: number;
channelId?: string;
messageId?: string;
mediaPath?: string;
mediaType?: string;
};
function cleanSenderPhone(value: string | undefined): string {
if (!value) return "";
return value.replace(/^whatsapp:/, "").trim();
}
function isPlaceholderBody(body: string | undefined): boolean {
const text = (body ?? "").trim();
return !text || text.startsWith("<media:") || text === "[Image]";
}
function normalizeCaption(body: string | undefined): string {
const text = (body ?? "").trim();
if (!text) return "";
return text.replace(/^[WhatsApp[^]]]\s/i, "").trim();
}
function parseNumber(value: string | undefined): number | undefined {
if (!value) return undefined;
const normalized = value.replace(/[,\s₹]/g, "");
const num = Number(normalized);
return Number.isFinite(num) ? num : undefined;
}
function extractCaptionFields(body: string | undefined): {
name: string;
sellingPrice?: number;
purchasePrice?: number;
quantity?: number;
} {
const raw = normalizeCaption(body);
if (isPlaceholderBody(raw)) {
return { name: "Untitled product" };
}
const purchaseRegex =
/\b(?:pp|purchase(?:\sprice)?)\b\s[:=-]?\s*(?:rs.?|₹)?\s*([0-9][0-9,]*)\b/i;
const qtyRegex =
/\b(?:qty|quantity)\b\s*[:=-]?\s*([0-9][0-9,]*)\b/i;
const purchaseMatch = raw.match(purchaseRegex);
const purchasePrice = parseNumber(purchaseMatch?.[1]);
// Remove purchase fragment first so generic "price" does not capture it.
const withoutPurchase = raw.replace(
/\b(?:pp|purchase(?:\sprice)?)\b\s[:=-]?\s*(?:rs.?|₹)?\s*[0-9][0-9,]*\b/gi,
" ",
);
const sellingRegex =
/\b(?:sp|selling(?:\sprice)?|sale(?:\sprice)?|price)\b\s*[:=-]?\s*(?:rs.?|₹)?\s*([0-9][0-9,]*)\b/i;
const sellingMatch = withoutPurchase.match(sellingRegex);
const sellingPrice = parseNumber(sellingMatch?.[1]);
const qtyMatch = raw.match(qtyRegex);
const quantity = parseNumber(qtyMatch?.[1]);