Fix markdown's reparse function (#11)

This commit is contained in:
udf 2018-06-11 13:26:12 +02:00 committed by Lonami
parent 2e82c440d0
commit 238ff05f20
1 changed files with 28 additions and 15 deletions

View File

@ -57,7 +57,7 @@ PARSED_ENTITIES = (
MessageEntityBold, MessageEntityItalic, MessageEntityCode, MessageEntityBold, MessageEntityItalic, MessageEntityCode,
MessageEntityPre, MessageEntityTextUrl MessageEntityPre, MessageEntityTextUrl
) )
# a matcher is a tuple of (regex pattern, parse function) # A matcher is a tuple of (regex pattern, parse function)
# where the parse function takes the match and returns (text, entity) # where the parse function takes the match and returns (text, entity)
MATCHERS = [ MATCHERS = [
(DEFAULT_URL_RE, parse_url_match), (DEFAULT_URL_RE, parse_url_match),
@ -70,13 +70,23 @@ MATCHERS = [
] ]
def parse(message): def parse(message, old_entities=None):
entities = [] entities = []
old_entities = sorted(old_entities or [], key=lambda e: e.offset)
i = 0 i = 0
after = 0
message = _add_surrogate(message) message = _add_surrogate(message)
while i < len(message): while i < len(message):
# find the first pattern that matches for after, e in enumerate(old_entities[after:], start=after):
# If the next entity is strictly to our right, we're done here
if i < e.offset:
break
# Skip already existing entities if we're at one
if i == e.offset:
i += e.length
# Find the first pattern that matches
for pattern, parser in MATCHERS: for pattern, parser in MATCHERS:
match = pattern.match(message, pos=i) match = pattern.match(message, pos=i)
if match: if match:
@ -86,34 +96,37 @@ def parse(message):
continue continue
text, entity = parser(match) text, entity = parser(match)
# replace whole match with text from parser
# Shift old entities after our current position (so they stay in place)
shift = len(text) - len(match[0])
if shift:
for e in old_entities[after:]:
e.offset += shift
# Replace whole match with text from parser
message = ''.join(( message = ''.join((
message[:match.start()], message[:match.start()],
text, text,
message[match.end():] message[match.end():]
)) ))
# append entity if we got one # Append entity if we got one
if entity: if entity:
entities.append(entity) entities.append(entity)
# skip past the match # Skip past the match
i += len(text) i += len(text)
return _del_surrogate(message), entities return _del_surrogate(message), entities + old_entities
@borg.on(events.MessageEdited(outgoing=True)) @borg.on(events.MessageEdited(outgoing=True))
@borg.on(events.NewMessage(outgoing=True)) @borg.on(events.NewMessage(outgoing=True))
async def reparse(event): async def reparse(event):
message, msg_entities = await borg._parse_message_text(event.text, parse) old_entities = event.message.entities or []
# filter out entities that we don't generate parser = partial(parse, old_entities=old_entities)
old_entities = [] message, msg_entities = await borg._parse_message_text(event.raw_text, parser)
for entity in event.message.entities or []: if len(old_entities) >= len(msg_entities) and event.raw_text == message:
if isinstance(entity, PARSED_ENTITIES):
old_entities.append(entity)
if len(old_entities) == len(msg_entities) and event.raw_text == message:
return return
await borg(EditMessageRequest( await borg(EditMessageRequest(