From 5dc3cddf1a04808d3da5c97e6e37ecc2c1e72d13 Mon Sep 17 00:00:00 2001 From: bohd4nx Date: Thu, 5 Mar 2026 04:16:49 +0200 Subject: [PATCH] refactor: replace manual base64 decoder with pytoniq_core Cell parser - clean_decode now uses Cell.one_from_boc + load_snake_string - no more regex/string hacks, native BOC parsing - added full transaction_data debug log in process_transaction --- app/utils/decoder.py | 38 +++++++++++++++++++++++++------------- app/utils/transaction.py | 2 ++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/app/utils/decoder.py b/app/utils/decoder.py index 1a0656a..eb57a04 100644 --- a/app/utils/decoder.py +++ b/app/utils/decoder.py @@ -1,26 +1,38 @@ import base64 import logging -import re -import string + +from pytoniq_core import Cell logger = logging.getLogger(__name__) +# OLD decoder (manual base64 + regex, kept for reference): +# +# import re, string +# def clean_decode(payload: str) -> str: +# s = re.sub(r'[^A-Za-z0-9+/=]', '', payload.strip()) +# s += '=' * (-len(s) % 4) +# text = base64.b64decode(s).decode('utf-8', errors='ignore') +# text = ''.join(c for c in text if c in string.printable or c.isspace()) +# match = re.search(r'([0-9]*\s*Telegram .*?Ref#[A-Za-z0-9]+)', text, re.S) +# return match.group(1).strip() if match else text.strip() + + def clean_decode(payload: str) -> str: logger.debug("Original payload: %s", payload) - # Strip non-Base64 chars and decode - s = re.sub(r'[^A-Za-z0-9+/=]', '', payload.strip()) - s += '=' * (-len(s) % 4) - text = base64.b64decode(s).decode('utf-8', errors='ignore') + # Pad and decode base64 → BOC bytes + s = payload.strip() + if not s: + return "" + s += "=" * (-len(s) % 4) + boc = base64.b64decode(s) - # Keep only printable characters - text = ''.join(c for c in text if c in string.printable or c.isspace()) - - # Extract "Telegram … Ref#XXXX" block - match = re.search(r'([0-9]*\s*Telegram .*?Ref#[A-Za-z0-9]+)', text, re.S) - result = match.group(1).strip() if match else text.strip() + # Parse BOC cell and read snake-encoded text (skipping 32-bit op prefix) + cell = Cell.one_from_boc(boc) + sl = cell.begin_parse() + sl.load_uint(32) # op code — always 0 for text comment + result = sl.load_snake_string().strip() logger.debug("Decoded result: %s", result) return result - diff --git a/app/utils/transaction.py b/app/utils/transaction.py index 4df802c..ffa255f 100644 --- a/app/utils/transaction.py +++ b/app/utils/transaction.py @@ -11,6 +11,8 @@ logger = logging.getLogger(__name__) async def process_transaction(transaction_data: dict) -> str: + logger.debug("transaction_data: %s", transaction_data) + if "transaction" not in transaction_data or "messages" not in transaction_data["transaction"]: raise TransactionError( "Fragment returned an invalid transaction payload. "