From 7c931e1bad421c1eff8a1b5641d0514bb5b78c2a Mon Sep 17 00:00:00 2001 From: cristianchiriac <80774326+cristianchiriac@users.noreply.github.com> Date: Sat, 17 Oct 2026 10:33:09 +0300 Subject: [PATCH] Treat RichText strings as JSON only when they parse to an object Plain text that happens to parse as JSON, like a "[56]" superscript footnote mark, was turned into a list and then crashed with 'pop expected at most 1 argument, got 2'. Fixes #2634 --- telebot/types.py | 19 ++++++++++--------- tests/test_types.py | 11 +++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 4ce780b2c..1b3388c01 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -14688,16 +14688,17 @@ def de_json(cls, json_string): if json_string is None: return None if isinstance(json_string, str): # "...can be either a String for plain text..." - if (json_string.startswith('{') and json_string.endswith('}')) or (json_string.startswith('[') and json_string.endswith(']')): - try: - # Check if string is valid json. If so, assume it's json, not plain string - json.loads(json_string) - # If it's valid json, continue to json processing below - except (ValueError, TypeError, json.JSONDecodeError): - # If it's not valid json, return the string as is - return json_string - else: + # Only a JSON object is a serialized RichText. Plain text can look + # like JSON too, e.g. a "[56]" footnote mark, and stays text. + if not (json_string.startswith('{') and json_string.endswith('}')): + return json_string + try: + parsed = json.loads(json_string) + except (ValueError, TypeError): + return json_string + if not isinstance(parsed, dict): return json_string + json_string = parsed elif isinstance(json_string, list): # "...an Array of :class:`RichText`..." return [RichText.de_json(item) for item in json_string] diff --git a/tests/test_types.py b/tests/test_types.py index 73578e17b..cf18632eb 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -547,6 +547,17 @@ def test_json_richtextbold(): assert result.text == 'Test' +def test_json_richtext_plain_text_that_looks_like_json(): + # issue #2634: a "[56]" footnote mark is plain text, not a JSON array + json_str = r'{"type": "url", "text": {"type": "superscript", "text": "[56]"}, "url": "https://example.com/#cite_note-56"}' + result = types.RichText.de_json(json_str) + assert isinstance(result, types.RichTextUrl) + assert isinstance(result.text, types.RichTextSuperscript) + assert result.text.text == '[56]' + for text in ['[56]', '[]', '{}x', '123', 'null', '["a", "b"]']: + assert types.RichText.de_json(text) == text + + def test_json_richtextitalic(): json_str = r'{"type": "italic", "text": "Test"}' result = types.RichText.de_json(json_str)