From 6326d5c6f6e5f574d6e788939716506610a7b832 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Sat, 27 Jun 2026 03:31:29 +0530 Subject: [PATCH] fix: remove duplicated table renderer from Telegram adapter The PR's original refactor commit only replaced the primitives (regex, is_table_row, split_markdown_table_row) with shared imports but left the verbatim-copied renderer (_render_table_block_for_telegram) and driver (_wrap_markdown_tables) in place. Both are logic-identical to the shared convert_table_to_bullets in gateway/platforms/helpers.py. Replace both with a direct import alias. _TABLE_SEPARATOR_RE is still imported separately because it's used by the rich-message routing logic (lines 1024, 1044) to detect whether content contains tables. Found by 3-agent parallel code-reuse review. --- plugins/platforms/telegram/adapter.py | 113 +------------------------- 1 file changed, 3 insertions(+), 110 deletions(-) diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index 6f89b9aed00ec..02c10918440be 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -217,122 +217,15 @@ def _separate_chunk_indicator_from_fence(text: str) -> str: # --------------------------------------------------------------------------- # Telegram's MarkdownV2 has no table syntax — '|' is just an escaped literal, # so pipe tables render as noisy backslash-pipe text with no alignment. -# Reformating each row into a bold heading plus bullet list keeps the content -# readable on mobile clients while preserving the source data. +# The shared convert_table_to_bullets() in gateway.platforms.helpers handles +# the full conversion (detection + rendering); Telegram just calls it. -# Table detection primitives are shared with Discord via gateway.platforms.helpers. from gateway.platforms.helpers import ( TABLE_SEPARATOR_RE as _TABLE_SEPARATOR_RE, - is_table_row as _is_table_row, - split_markdown_table_row as _split_markdown_table_row, + convert_table_to_bullets as _wrap_markdown_tables, ) -def _render_table_block_for_telegram(table_block: list[str]) -> str: - """Render a detected GFM table as Telegram-friendly row groups.""" - if len(table_block) < 3: - return "\n".join(table_block) - - headers = _split_markdown_table_row(table_block[0]) - if len(headers) < 2: - return "\n".join(table_block) - - # Detect row-label column: present when data rows have one more cell - # than the header row (the row-label column carries no header). - first_data_row = _split_markdown_table_row(table_block[2]) if len(table_block) > 2 else [] - has_row_label_col = len(first_data_row) == len(headers) + 1 - - rendered_groups: list[str] = [] - for index, row in enumerate(table_block[2:], start=1): - cells = _split_markdown_table_row(row) - if has_row_label_col: - # First cell is the row-label (heading); remaining cells align with headers. - heading = cells[0] if cells and cells[0] else f"Row {index}" - data_cells = cells[1:] - else: - # No row-label column: use first non-empty cell as heading. - heading = next((cell for cell in cells if cell), f"Row {index}") - data_cells = cells - - # Pad or trim data_cells to match headers length. - if len(data_cells) < len(headers): - data_cells.extend([""] * (len(headers) - len(data_cells))) - elif len(data_cells) > len(headers): - data_cells = data_cells[: len(headers)] - - # Build the bulleted lines for this row. Skip any bullet whose value - # duplicates the heading text -- when has_row_label_col is False the - # heading IS the first data cell, and emitting it twice (once as the - # bold heading, once as the first bullet) is visual noise. - bullets: list[str] = [] - for header, value in zip(headers, data_cells): - if not has_row_label_col and value == heading: - continue - bullets.append(f"• {header}: {value}") - - # Within a row-group: single newline between heading and its bullets, - # and between successive bullets. This keeps the row visually tight - # on Telegram instead of stretching each bullet into its own paragraph. - group_lines = [f"**{heading}**", *bullets] - rendered_groups.append("\n".join(group_lines)) - - # Between row-groups: blank line so each group reads as a distinct block. - return "\n\n".join(rendered_groups) - - -def _wrap_markdown_tables(text: str) -> str: - """Rewrite GFM-style pipe tables into Telegram-friendly bullet groups. - - Detected by a row containing '|' immediately followed by a delimiter - row matching :data:`_TABLE_SEPARATOR_RE`. Subsequent pipe-containing - non-blank lines are consumed as the table body and rewritten as - per-row bullet groups. Tables inside existing fenced code blocks are left - alone. - """ - if '|' not in text or '-' not in text: - return text - - lines = text.split('\n') - out: list[str] = [] - in_fence = False - i = 0 - while i < len(lines): - line = lines[i] - stripped = line.lstrip() - - # Track existing fenced code blocks — never touch content inside. - if stripped.startswith('```'): - in_fence = not in_fence - out.append(line) - i += 1 - continue - if in_fence: - out.append(line) - i += 1 - continue - - # Look for a header row (contains '|') immediately followed by a - # delimiter row. - if ( - '|' in line - and i + 1 < len(lines) - and _TABLE_SEPARATOR_RE.match(lines[i + 1]) - ): - table_block = [line, lines[i + 1]] - j = i + 2 - while j < len(lines) and _is_table_row(lines[j]): - table_block.append(lines[j]) - j += 1 - out.append(_render_table_block_for_telegram(table_block)) - i = j - continue - - out.append(line) - i += 1 - - return '\n'.join(out) - - # --------------------------------------------------------------------------- # Rich-message newline normalization # ---------------------------------------------------------------------------