Bridge plaintext mentions of Telegram puppets into Telegram mentions

This commit is contained in:
Tulir Asokan
2018-03-08 18:39:27 +02:00
parent 150321a4d7
commit 61d9d6890a
6 changed files with 76 additions and 8 deletions
+2
View File
@@ -35,6 +35,7 @@ from .user import init as init_user, User
from .bot import init as init_bot
from .portal import init as init_portal
from .puppet import init as init_puppet
from .formatter import init as init_formatter
from .public import PublicBridgeWebsite
from .context import Context
@@ -99,6 +100,7 @@ with appserv.run(config["appservice.hostname"], config["appservice.port"]) as st
init_abstract_user(context)
context.bot = init_bot(context)
context.mx = MatrixHandler(context)
init_formatter(context)
init_portal(context)
init_puppet(context)
startup_actions = init_user(context) + [start, context.mx.init_as_bot()]
+8 -2
View File
@@ -1,2 +1,8 @@
from .from_matrix import matrix_reply_to_telegram, matrix_to_telegram, matrix_text_to_telegram
from .from_telegram import telegram_reply_to_matrix, telegram_to_matrix
from .from_matrix import (matrix_reply_to_telegram, matrix_to_telegram, matrix_text_to_telegram,
init_mx)
from .from_telegram import (telegram_reply_to_matrix, telegram_to_matrix, init_tg)
def init(context):
init_mx(context)
init_tg(context)
+45 -1
View File
@@ -219,11 +219,46 @@ class MatrixParser(HTMLParser):
command_regex = re.compile("(\s|^)!([A-Za-z0-9@]+)")
plain_mention_regex = None
def matrix_text_to_telegram(text):
text = command_regex.sub(r"\1/\2", text)
return text
entities, pmr_replacer = plain_mention_to_text()
text = plain_mention_regex.sub(pmr_replacer, text)
return text, entities
def plain_mention_to_text():
entities = []
def replacer(match):
puppet = pu.Puppet.find_by_displayname(match.group(2))
if puppet:
offset = match.start()
length = match.end() - offset
if puppet.username:
entity = MessageEntityMention(offset, length)
text = f"@{puppet.username}"
else:
entity = InputMessageEntityMentionName(offset, length,
user_id=InputUser(puppet.tgid, 0))
text = puppet.displayname
entities.append(entity)
return text
return "".join(match.groups())
return entities, replacer
def plain_mention_to_html(match):
puppet = pu.Puppet.find_by_displayname(match.group(2))
if puppet:
return (f"{match.group(1)}"
f"<a href='https://matrix.to/#/{puppet.mxid}'>"
f"{puppet.displayname}"
"</a>")
return "".join(match.groups())
def matrix_to_telegram(html):
@@ -231,6 +266,7 @@ def matrix_to_telegram(html):
parser = MatrixParser()
html = html.replace("\n", "")
html = command_regex.sub(r"\1<command>\2</command>", html)
html = plain_mention_regex.sub(plain_mention_to_html, html)
parser.feed(add_surrogates(html))
return remove_surrogates(parser.text.strip()), parser.entities
except Exception:
@@ -258,3 +294,11 @@ def matrix_reply_to_telegram(content, tg_space, room_id=None):
except KeyError:
pass
return None
def init_mx(context):
global plain_mention_regex
config = context.config
dn_template = config.get("bridge.displayname_template", "{displayname} (Telegram)")
dn_template = re.escape(dn_template).replace(re.escape("{displayname}"), "[^>]+")
plain_mention_regex = re.compile(f"(\s|^)({dn_template})")
@@ -254,3 +254,7 @@ def _parse_url(html, entity_text, url):
url = "http://" + url
html.append(f"<a href='{url}'>{entity_text}</a>")
return False
def init_tg(context):
pass
+2 -5
View File
@@ -594,12 +594,9 @@ class Portal:
for entity in entities:
if isinstance(entity, InputMessageEntityMentionName):
entity.user_id = await client.get_input_entity(entity.user_id.user_id)
return await client.send_message(self.peer, message, entities=entities,
reply_to=reply_to)
else:
message = formatter.matrix_text_to_telegram(message["body"])
return await client.send_message(self.peer, message, reply_to=reply_to)
message, entities = formatter.matrix_text_to_telegram(message["body"])
return await client.send_message(self.peer, message, reply_to=reply_to)
async def _handle_matrix_file(self, client, message, reply_to):
file = await self.main_intent.download_file(message["url"])
+15
View File
@@ -191,6 +191,21 @@ class Puppet:
return None
@classmethod
def find_by_displayname(cls, displayname):
if not displayname:
return None
for _, puppet in cls.cache.items():
if puppet.displayname and puppet.displayname == displayname:
return puppet
puppet = DBPuppet.query.filter(DBPuppet.displayname == displayname).one_or_none()
if puppet:
return cls.from_db(puppet)
return None
def init(context):
global config