function toNumberRu(s) { if (!s) return null; const cleaned = String(s) .replace(/\s/g, "") .replace(",", ".") .replace(/[^\d.]/g, ""); const n = Number(cleaned); console.log("toNumberRu: " + Number.isFinite(n)); return Number.isFinite(n) ? n : null; } function paringSms(sms) { console.log(sms); const raw = sms.body.message ?? ""; console.log("raw: " + raw); const text = String(raw).replace(/\s+/g, " ").trim(); const lower = text.toLowerCase(); console.log("text: " + text); const sender = sms.body?.sender ?? null; console.log("sender: " + sender); // 1) Классификация let action = "unknown"; const rules = [ { action: "salary", re: /зарплат/i }, { action: "reversal", re: /(отмена|возврат)/i }, { action: "payment", re: /(оплата|покупк)/i }, { action: "transfer", re: /перевод/i }, { action: "writeoff", re: /списан/i }, { action: "income", re: /(поступлен|поступление|зачислен)/i }, ]; for (const r of rules) { if (r.re.test(lower)) { action = r.action; break; } } console.log("action: " + action); // 2) Баланс const balanceRegex = /(баланс)[:\s]*([0-9][0-9\s]*[.,]?\d{0,2})\s*(₽|руб\.?|rub|р)(?=\s|$)/i; const balanceMatch = text.match(balanceRegex); console.log("balanceMatch: " + balanceMatch); const balance = balanceMatch ? toNumberRu(balanceMatch[2]) : null; console.log("balance: " + balance); // 3) Сумма операции let amount = null; const amountNearActionRegex = /(отмена[:\s-]*оплата|отмена|списание|оплата|перевод|поступление|зарплат[аы]?)[\s:]*([0-9][0-9\s]*[.,]?\d{0,2})\s*(₽|руб\.?|rub|р)/i; const near = text.match(amountNearActionRegex); console.log("near: " + near); if (near) { amount = toNumberRu(near[2]); console.log(amount); } else { const textWithoutBalance = text.replace(balanceRegex, " "); console.log("textWithoutBalance: " + textWithoutBalance); const amountRegex = /([0-9][0-9\s]*[.,]?\d{0,2})\s*(₽|руб\.?|rub|р)/i; const m = textWithoutBalance.match(amountRegex); amount = m ? toNumberRu(m[1]) : null; console.log("m: " + m); } const currency = "RUB"; // 4) signedAmount let signedAmount = amount; if (amount != null) { if (["payment", "transfer", "writeoff"].includes(action)) signedAmount = -Math.abs(amount); if (["income", "salary", "reversal"].includes(action)) signedAmount = Math.abs(amount); } console.log({ raw_sms: raw, sms_text: text, sms_sender: sender, action, // income/payment/transfer/salary/reversal/writeoff amount, signed_amount: signedAmount, currency, balance, received_at: new Date().toISOString(), }); return [ { raw_sms: raw, sms_text: text, sms_sender: sender, action, // income/payment/transfer/salary/reversal/writeoff amount, signed_amount: signedAmount, currency, balance, received_at: new Date().toISOString(), }, ]; } const input_sms = { body: { message: 'Оплата 980р Карта*4215 "SKURATOV COFFE Баланс 207033.86р 19:52', sender: "VTB", formatted_message: '📩 *New SMS Received*\n👤 *From:* VTB\n\nОплата 980р Карта*4215 "SKURATOV COFFE Баланс 207033.86р 19:52', contact: "", }, }; const input_sms2 = { body: { formatted_message: "📩 *New SMS Received*\n👤 *From:* VTB\n\nОплата 6800р Карта*4215 IP SHARAFETDINO Баланс 199083.86р 09:56", contact: "", sender: "VTB", message: "Оплата 6800р Карта*4215 IP SHARAFETDINO Баланс 199083.86р 09:56", }, }; paringSms(input_sms); // paringSms(input_sms2);