summaryrefslogtreecommitdiffstats
path: root/telepot/text.py
blob: d4b3cb753e46b960df142b11c5ab3fe35c466609 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def _apply_entities(text, entities, escape_map, format_map):
    def inside_entities(i):
        return any(map(lambda e:
                           e['offset'] <= i < e['offset']+e['length'],
                       entities))

    # Split string into char sequence and escape in-place to
    # preserve index positions.
    seq = list(map(lambda c,i:
                       escape_map[c]     # escape special characters
                           if c in escape_map and not inside_entities(i)
                       else c,
                   list(text),           # split string to char sequence
                   range(0,len(text))))  # along with each char's index

    # Ensure smaller offsets come first
    sorted_entities = sorted(entities, key=lambda e: e['offset'])
    offset = 0
    result = ''

    for e in sorted_entities:
        f,n,t = e['offset'], e['length'], e['type']

        result += ''.join(seq[offset:f])

        if t in format_map:
            # apply format
            result += format_map[t](''.join(seq[f:f+n]), e)
        else:
            result += ''.join(seq[f:f+n])

        offset = f + n

    result += ''.join(seq[offset:])
    return result


def apply_entities_as_markdown(text, entities):
    """
    Format text as Markdown. Also take care of escaping special characters.
    Returned value can be passed to :meth:`.Bot.sendMessage` with appropriate
    ``parse_mode``.

    :param text:
        plain text

    :param entities:
        a list of `MessageEntity <https://core.telegram.org/bots/api#messageentity>`_ objects
    """
    escapes = {'*': '\\*',
               '_': '\\_',
               '[': '\\[',
               '`': '\\`',}

    formatters = {'bold':         lambda s,e: '*'+s+'*',
                  'italic':       lambda s,e: '_'+s+'_',
                  'text_link':    lambda s,e: '['+s+']('+e['url']+')',
                  'text_mention': lambda s,e: '['+s+'](tg://user?id='+str(e['user']['id'])+')',
                  'code':         lambda s,e: '`'+s+'`',
                  'pre':          lambda s,e: '```text\n'+s+'```'}

    return _apply_entities(text, entities, escapes, formatters)


def apply_entities_as_html(text, entities):
    """
    Format text as HTML. Also take care of escaping special characters.
    Returned value can be passed to :meth:`.Bot.sendMessage` with appropriate
    ``parse_mode``.

    :param text:
        plain text

    :param entities:
        a list of `MessageEntity <https://core.telegram.org/bots/api#messageentity>`_ objects
    """
    escapes = {'<': '&lt;',
               '>': '&gt;',
               '&': '&amp;',}

    formatters = {'bold':         lambda s,e: '<b>'+s+'</b>',
                  'italic':       lambda s,e: '<i>'+s+'</i>',
                  'text_link':    lambda s,e: '<a href="'+e['url']+'">'+s+'</a>',
                  'text_mention': lambda s,e: '<a href="tg://user?id='+str(e['user']['id'])+'">'+s+'</a>',
                  'code':         lambda s,e: '<code>'+s+'</code>',
                  'pre':          lambda s,e: '<pre>'+s+'</pre>'}

    return _apply_entities(text, entities, escapes, formatters)