5

I'm trying to create a simple Telegram Bot using the python-telegram-bot library, but i can't align a dictionary with the default "{0:<20} {1}".format(key, value) idea.

Let me give u an example:

Mapy = {
    "one": "1",
    "two": "2",
    "three": "3",
    "four": "4",
    "five": "5",
    "six": "6",
    "seven": "7",
    "eight": "8"
}

tmpstring = ""

for key, value in Mapy.items():
    tmpstring = tmpstring + "{0:<20} {1}".format(key, value) + "\n"

print(tmpstring)
context.bot.send_message(chat_id=update.message.chat_id, text=tmpstring)

the printed finish looks like this:

one                  1
two                  2
three                3
four                 4
five                 5
six                  6
seven                7
eight                8

as expected nicely aligned, but the message in Telegram looks like this:

enter image description here

So my question is: How can i align the chat message so it looks like the printed output?

Lyux
  • 453
  • 1
  • 10
  • 22

2 Answers2

19

Use Markdowns (V2) 'pre-formatted fixed-width code block' to preserve the alignment. [Docs]

Wrap the wonderfully aligned table in a code-block using 3 back-ticks (```)

```
one          1
two          2
three        3
```

Send your message with the parse_mode option set to: MarkDown (V2)

0stone0
  • 34,288
  • 4
  • 39
  • 64
  • 1
    perfect, thanks, wrapping the String in `"```" ` and using `parse_mode="Markdown"` in the `send_message` fixed my problem. – Lyux May 08 '19 at 17:19
  • @Lyux Perfect! Keep in mind that the end users screen resolution decides if the table will show normal. I used to send some 3 column tables via Telegram. Smaller phones required landscape mode to see the table. I had te most trouble with iPhones users who could not see them, telegram wrapped the message, even in landscape!! – 0stone0 May 08 '19 at 20:08
  • 1
    When wrapping into ``` you can't add links into the text, like [one]('https://link.com/') because it will show up like a piece of code? – Oleg O May 06 '21 at 10:26
1

You can also use PrettyTable to build the layout instead of using spaces inside your code. The nice thing about this is you never have to worry about the spacing if you add more items to your response data that have variable widths.

This is also helpful when pulling in text from a data source such as an API, database, list, etc. (even taking it a step farther, if you are storing your users in a database, they could set their locale, and then you can convert it before sending: i.e 9,000.00 vs 9.000,00 etc.

Static Text Example:

    from prettytable import PrettyTable

    table = PrettyTable()
    table.field_names = ['Item', 'Price']
    table.add_row(['ham', '$3.99')
    table.add_row(['egg', '$2.99')
    table.add_row(['spam', 'Free!')
    
    response = '```\n{}```'.format(table.get_string())
    update.message.reply_text(response, parse_mode='Markdown')

Output:

+------+------------------+
| Item |      Price       |
+------+------------------+
| ham  |      $3.99       |
| egg  |      $2.99       |
| spam | Free Today Only! |
+------+------------------+

List Example:

    items = [
        ['ham', '$3.99'],
        ['egg', '$2.99'],
        ['spam', 'Free Today Only!']
    ]

    table = PrettyTable()
    table.field_names = ['Item', 'Price']
    for item in items:
        table.add_row(item)
    response = '```\n{}```'.format(table.get_string())
    update.message.reply_text(response, parse_mode='Markdown')

The table alignment can be set to r, l, c (Right, Left, or Center)

table.align = "r"

More info: https://pypi.org/project/prettytable/

Repository: https://github.com/jazzband/prettytable

JRB
  • 11
  • 2