Как отправить таблицы с помощью Telegram Bot API?

Мне нужно отправить данные фондового рынка, и форматирование - отстой. Нужно отправить что-то подобное

| Symbol | Price | Change | 
|--------|-------|--------|
| ABC | 20.85 | 1.626 | 
| DEF | 78.95 | 0.099 | 
| GHI | 23.45 | 0.192 | 
| JKL | 98.85 | 0.292 |

Это то, что я пытался.

| Символ | Цена | Изменить |
| -------- | ------- | -------- |
| ABC | 20,85 | 1.626 |
| DEF | 78,95 | 0.099 |
| GHI | 23,45 | 0,192 |
JKL | 98,85 | 0,292 |

10 ответов

Установите для параметра Telegram parse_mode значение HTML и оберните текст в<pre></pre>

<pre> | Tables | Are | Cool | |----------|:-------------:|------:| | col 1 is | left-aligned | $1600 | | col 2 is | centered | $12 | | col 3 is | right-aligned | $1 | </pre>

Результат в мессенджере Telegram:

Обновлено. Будет проблема с маленькими экранами смартфонов. Так что это плохой метод. Единственный вариант - преобразовать таблицы на картинке и так отправить.:(

Попробуй это

```| Symbol | Price | Change |
|--------|-------|--------|
| ABC    | 20.85 |  1.626 |
| DEF    | 78.95 |  0.099 |
| GHI    | 23.45 |  0.192 |
| JKL    | 98.85 |  0.292 |```

Импортируйте библиотеку "prettytable" в Python для форматирования таблицы:

      import prettytable as pt
from telegram import ParseMode
from telegram.ext import CallbackContext, Updater


def send_table(update: Updater, context: CallbackContext):
    table = pt.PrettyTable(['Symbol', 'Price', 'Change'])
    table.align['Symbol'] = 'l'
    table.align['Price'] = 'r'
    table.align['Change'] = 'r'

    data = [
        ('ABC', 20.85, 1.626),
        ('DEF', 78.95, 0.099),
        ('GHI', 23.45, 0.192),
        ('JKL', 98.85, 0.292),
    ]
    for symbol, price, change in data:
        table.add_row([symbol, f'{price:.2f}', f'{change:.3f}'])

    update.message.reply_text(f'<pre>{table}</pre>', parse_mode=ParseMode.HTML)
    # or use markdown
    update.message.reply_text(f'```{table}```', parse_mode=ParseMode.MARKDOWN_V2)

Вы получите сообщение вроде:

      +--------+-------+--------+
| Symbol | Price | Change |
+--------+-------+--------+
| ABC    | 20.85 |  1.626 |
| DEF    | 78.95 |  0.099 |
| GHI    | 23.45 |  0.192 |
| JKL    | 98.85 |  0.292 |
+--------+-------+--------+

Вы можете использовать разметку HTML или Markdown, чтобы отправить что-то вроде <pre> в HTML. Так же, как этот пример.

Самый простой и профессиональный метод – использоватьTelegram Web App Bot, который был добавлен в недавнем обновлении.

шаг 1: создайте html-файл и напишите свою таблицу.

Шаг 2 : добавьте этот скрипт в свой html-файл.<script src="https://telegram.org/js/telegram-web-app.js"></script>

шаг 3 : перенаправить пользователя на страницу с помощью этого метода API

      {
    "text": "Test web_app",
    "web_app": {
        "url": "https://yourDomain/yourFile.html"
    }
}

примечание: страница будет отображаться на странице бота, а не в браузере

для получения дополнительной информации прочитайте официальный документ: https://core.telegram.org/bots/webapps#initializing-web-apps

Вот мое решение, использующее puppeteer для снимка экрана элемента таблицы.

Прежде всего, вам нужно сгенерировать HTML-код таблицы, вот код для генерации этого кода.

      async function generateHtml(rows) {
    return `<!DOCTYPE html>
    <html>
    <head>
    <style>
    thead,
tfoot {
    background-color: #3f87a6;
    color: #fff;
}

tbody {
    background-color: #e4f0f5;
}

caption {
    padding: 10px;
    caption-side: bottom;
}

table {
    border-collapse: collapse;
    border: 2px solid rgb(200, 200, 200);
    letter-spacing: 1px;
    font-family: sans-serif;
    font-size: .8rem;
}

td,
th {
    border: 1px solid rgb(190, 190, 190);
    padding: 5px 10px;
}

td {
    text-align: center;
}

    </style>
    </head>
    <body>
    <table>
    <caption>Pornhub Pages Summary</caption>
    <thead>
        <tr>
            <th>ID</th>
            <th scope="col">Progress</th>
            <th scope="col">Stucked</th>
            <th scope="col">Finished</th>
            <th scope="col">Busy</th>
        </tr>
    </thead>
    <tbody>
        ${rows}
    </tbody>
</table>
    </body>
    </html>`
}

И вот код для генерацииrowsаргумент вышеуказанной функции

      async function getTheImgOfTheSummaryOfThePages() {
    const rows = []
    for (const [index, val] of statuesOfThePages.entries()) {
        const row = `<tr>
        <th scope="row">${index}</th>
        <th>${val.progress}</th>
        <th>${val.stucked}</th>
        <th>${val.finished}</th>
        <th>${val.pageBusy}</th>
      </tr>`

        rows.push(row)
    }

    const path = './summaryOfThePagesOfPornhub.png'
    const html = await generateHtml(rows.join('\n'))
    await util.takescrrenshotOnTheHtml(html, browser, path, 'table')
    return path
}

А вот код скриншота элемента table

      async function takescrrenshotOnTheHtml(html, browser, pathToSave, onElement) {
    const page = await newPage(browser);
    await page.setContent(html)
    const element = await page.$(onElement)
    await element.screenshot({path: pathToSave})
    await page.close()
}

Вот результат

Ну, вам просто нужно изменить заголовки таблицы и строки таблицы

Я нашел эту библиотеку - TableJs - которая решает эту проблему. Отлично работает в клиентах для настольных ПК, однако клиенты Android не отображали его должным образом.

      import warnings
from PIL import Image, ImageDraw, ImageFont

def table_to_image(my_table):
    warnings.filterwarnings('ignore', category=DeprecationWarning)
    font = ImageFont.truetype("courbd.ttf", 15)
    text_width, text_height = font.getsize_multiline(my_table.get_string())
    im = Image.new("RGB", (text_width + 15, text_height + 15), "white")
    draw = ImageDraw.Draw(im)
    draw.text((7, 7), my_table.get_string(), font=font, fill="black")
    im.show()
    im.save(my_table_image.png, 'PNG')

Formatting the text as "Monospace" works too

Я написал код для создания html-таблицы Telegram из массива строк.

Просто создайте массив со строками с данными столбцов, разделенными ";" и этот код выведет готовую таблицу Telegram.

Наслаждайтесь, разберитесь с параметрами :)

Вы должны использовать «parse_mode» = «html» при отправке сообщения в Telegram Api.

      public string BuildTelegramTable(
            List<string> table_lines,
            string tableColumnSeparator = "|", char inputArraySeparator = ';',
            int maxColumnWidth = 0, bool fixedColumnWidth = false, bool autoColumnWidth = false,
            int minimumColumnWidth = 4, int columnPadRight = 0, int columnPadLeft = 0,
            bool beginEndBorders = true)
        {
            var prereadyTable = new List<string>() { "<pre>" };
            var columnsWidth = new List<int>();
            var firstLine = table_lines[0];
            var lineVector = firstLine.Split(inputArraySeparator);

            if (fixedColumnWidth && maxColumnWidth == 0) throw new ArgumentException("For fixedColumnWidth usage must set maxColumnWidth > 0");
            else if (fixedColumnWidth && maxColumnWidth > 0)
            {
                for(var x=0;x<lineVector.Length;x++)
                    columnsWidth.Add(maxColumnWidth + columnPadRight + columnPadLeft);
            }
            else
            {
                for(var x=0;x<lineVector.Length;x++)
                {
                    var columnData = lineVector[x].Trim();
                    var columnFullLength = columnData.Length;

                    if (autoColumnWidth)
                        table_lines.ForEach(line => columnFullLength = line.Split(inputArraySeparator)[x].Length > columnFullLength ? line.Split(inputArraySeparator)[x].Length : columnFullLength);
                    
                    columnFullLength = columnFullLength < minimumColumnWidth ? minimumColumnWidth : columnFullLength;

                    var columnWidth = columnFullLength + columnPadRight + columnPadLeft;

                    if (maxColumnWidth > 0 && columnWidth > maxColumnWidth)
                        columnWidth = maxColumnWidth;

                    columnsWidth.Add(columnWidth);
                }
            }

            foreach(var line in table_lines)
            {
                lineVector = line.Split(inputArraySeparator);

                var fullLine = new string[lineVector.Length+(beginEndBorders ? 2 : 0)];
                if (beginEndBorders) fullLine[0] = "";

                for(var x=0;x<lineVector.Length;x++)
                {
                    var clearedData = lineVector[x].Trim();
                    var dataLength = clearedData.Length;
                    var columnWidth = columnsWidth[x];
                    var columnSizeWithoutTrimSize = columnWidth - columnPadRight - columnPadLeft;
                    var dataCharsToRead = columnSizeWithoutTrimSize > dataLength ? dataLength : columnSizeWithoutTrimSize;
                    var columnData = clearedData.Substring(0,dataCharsToRead);
                    columnData = columnData.PadRight(columnData.Length + columnPadRight);
                    columnData = columnData.PadLeft(columnData.Length + columnPadLeft);

                    var column = columnData.PadRight(columnWidth);

                    fullLine[x+(beginEndBorders ? 1 : 0)] = column;
                }

                if (beginEndBorders) fullLine[fullLine.Length - 1] = "";

                prereadyTable.Add(string.Join(tableColumnSeparator,fullLine));
            }

            prereadyTable.Add("</pre>");

            return string.Join("\r\n",prereadyTable);
        }
Другие вопросы по тегам