Compare commits

..

15 Commits

Author SHA1 Message Date
Sijmen Schoon
a4ff6e81c8
Merge pull request #43 from vurpo/master
Telegram message formatting changes
2017-11-04 15:50:02 +01:00
Max Sandholm
cd1d66ffee Revert .gitignore to correct version 2017-11-02 15:36:17 +02:00
Max Sandholm
2b186ad31c Merge remote-tracking branch 'upstream/master' 2017-10-25 13:23:51 +03:00
Max Sandholm
9e003f8ff9 Remove "(Telegram)" from mentions 2017-09-21 14:42:12 +03:00
Max Sandholm
e98b7312f6 Correctly use the re.sub function 2017-09-21 14:39:50 +03:00
Max Sandholm
3a21a819b9 Merge branch 'master' of github.com:vurpo/telematrix 2017-09-21 13:36:49 +02:00
Max Sandholm
828f92e37b Fix escaping error 2017-09-21 14:36:37 +03:00
Max Sandholm
2ee824f4ca Merge branch 'master' of github.com:vurpo/telematrix 2017-09-21 13:31:33 +02:00
Max Sandholm
8e422d683b Merge branch 'master' of github.com:vurpo/telematrix 2017-09-21 13:30:23 +02:00
Max Sandholm
d537cfb1b3 Fix quoting formatting and change Matrix->Telegram username formatting 2017-09-21 13:29:26 +02:00
Max Sandholm
09945d75cc Replace Matrix mentions with Telegram mentions (ping) 2017-09-21 13:50:17 +03:00
Max Sandholm
b0aeb11e8a Merge branch 'master' of https://github.com/SijmenSchoon/telematrix 2017-09-21 11:13:44 +03:00
Max Sandholm
fea8d89493 Fix aliases-related breakage 2017-04-08 13:32:19 +03:00
Max Sandholm
15e84f6861 Handle users without profile pictures correctly 2017-04-04 00:07:07 +03:00
Max Sandholm
fc65d5f0f5 Telegram profile pictures and display names are updated
The bridge updates the displayname and/or the avatar of the bridged Matrix
user when the Telegram user changes them.

This is done by checking the name and profile pic of the sender when a message
is received from Telegram, and comparing to the database to see if they have
changed. If they have, it will update the database and send the updates to the
Matrix homeserver.
2017-04-03 22:12:03 +03:00
4 changed files with 38 additions and 69 deletions

1
.gitignore vendored
View File

@ -152,5 +152,4 @@ Temporary Items
# Config
config.json
asconfig.yaml
database.db

View File

@ -42,8 +42,6 @@ First, copy config.json.example to config.json. Then fill in the fields:
* `hosts.bare`: Just the (sub)domain of the server.
* `user_id_format`: A Python `str.format`-style string to format user IDs as
* `db_url`: A SQLAlchemy URL for the database. See the [SQLAlchemy docs](http://docs.sqlalchemy.org/en/latest/core/engines.html).
* `bot_owners`: A list of matrix users the bot won't use a `<username>` prefix for. Can be left blank to print a prefix for all matrix users. Useful if you would like the bridge to replace Telegram for yourself, but also want to allow others to use the Matrix room.
* `print_url_with_image`: Set to `false` to disable sending the Matrix url of an image to Telegram.
**Synapse configuration**

View File

@ -12,16 +12,8 @@
"bare": "DOMAIN.TLD"
},
"bot_owners": [
"@youruser:DOMAIN.TLD",
"@youruser:matrix.org",
"@youruser:example.com"
],
"user_id_format": "@telegram_{}:DOMAIN.TLD",
"db_url": "sqlite:///database.db",
"print_url_with_image": true,
"as_port": 5000
}

View File

@ -12,6 +12,7 @@ from datetime import datetime
from time import time
from urllib.parse import unquote, quote, urlparse, parse_qs
from io import BytesIO
import re
from PIL import Image
from aiohttp import web, ClientSession
@ -38,11 +39,6 @@ try:
MATRIX_HOST_EXT = CONFIG['hosts']['external']
MATRIX_HOST_BARE = CONFIG['hosts']['bare']
try:
MATRIX_BOT_OWNERS = CONFIG['bot_owners']
except KeyError:
MATRIX_BOT_OWNERS = {}
MATRIX_PREFIX = MATRIX_HOST + '_matrix/client/r0/'
MATRIX_MEDIA_PREFIX = MATRIX_HOST + '_matrix/media/r0/'
@ -50,8 +46,6 @@ try:
DATABASE_URL = CONFIG['db_url']
AS_PORT = CONFIG['as_port'] if 'as_port' in CONFIG else 5000
PRINT_URL_WITH_IMAGE = CONFIG['print_url_with_image'] if 'print_url_with_image' in CONFIG else True
except (OSError, IOError) as exception:
print('Error opening config file:')
print(exception)
@ -89,26 +83,26 @@ def sanitize_html(string):
soup = BeautifulSoup(string, 'html.parser')
for tag in soup.find_all(True):
if tag.name == 'blockquote':
tag.string = ('\n' + tag.text).replace('\n', '\n> ').rstrip('\n>')
tag.string = ('\n' + tag.text).replace('\n', '\n> ')[3:-3]
if tag.name not in VALID_TAGS:
tag.hidden = True
return soup.renderContents().decode('utf-8')
def format_matrix_msg(form, username, content):
def format_matrix_msg(form, content):
"""
Formats a matrix message for sending to Telegram
:param form: The format string of the message, where the first parameter
is the username and the second one the message.
:param username: The username of the user.
:param content: The content to be sent.
:return: The formatted string.
"""
if 'format' in content and content['format'] == 'org.matrix.custom.html':
sanitized = sanitize_html(content['formatted_body'])
return html.escape(form).format(username, sanitized), 'HTML'
sanitized = re.sub("<a href=\\\"https://matrix.to/#/@telegram_([0-9]+):{}\\\">(.+?) \(Telegram\)</a>".format(MATRIX_HOST_BARE), "<a href=\"tg://user?id=\\1\">\\2</a>", content['formatted_body'])
sanitized = sanitize_html(sanitized)
return html.escape(form).format(sanitized), 'HTML'
else:
return form.format(username, content['body']), None
return form.format(html.escape(content['body'])), None
async def download_matrix_file(url, filename):
@ -190,7 +184,7 @@ async def matrix_transaction(request):
for alias in aliases:
print(alias)
if alias.split('_')[0] != '#telegram' \
or not alias.endswith(MATRIX_HOST_BARE):
or alias.split(':')[-1] != MATRIX_HOST_BARE:
continue
tg_id = alias.split('_')[1].split(':')[0]
@ -212,9 +206,6 @@ async def matrix_transaction(request):
if event['type'] == 'm.room.message':
user_id = event['user_id']
if user_id in MATRIX_BOT_OWNERS:
displayname = ''
else:
if matrix_is_telegram(user_id):
continue
@ -239,17 +230,14 @@ async def matrix_transaction(request):
continue
if content['msgtype'] == 'm.text':
prefix = '' if displayname == '' else '<' + displayname + '> '
msg, mode = format_matrix_msg('{}{}', prefix, content)
response = await group.send_text(msg, parse_mode=mode)
msg, mode = format_matrix_msg('{}', content)
response = await group.send_text("<b>{}:</b> {}".format(displayname, msg), parse_mode='HTML')
elif content['msgtype'] == 'm.notice':
prefix = '' if displayname == '' else '[' + displayname + '] '
msg, mode = format_matrix_msg('{}{}', prefix, content)
response = await group.send_text(msg, parse_mode=mode)
msg, mode = format_matrix_msg('{}', content)
response = await group.send_text("[{}] {}".format(displayname, msg), parse_mode=mode)
elif content['msgtype'] == 'm.emote':
prefix = '' if displayname == '' else '* ' + displayname + ' '
msg, mode = format_matrix_msg('{}{}', prefix, content)
response = await group.send_text(msg, parse_mode=mode)
msg, mode = format_matrix_msg('{}', content)
response = await group.send_text("* {} {}".format(displayname, msg), parse_mode=mode)
elif content['msgtype'] == 'm.image':
try:
url = urlparse(content['url'])
@ -262,18 +250,13 @@ async def matrix_transaction(request):
# Download the file
await download_matrix_file(url, content['body'])
with open('/tmp/{}'.format(content['body']), 'rb') as img_file:
url_str = ''
if PRINT_URL_WITH_IMAGE:
# Create the URL and shorten it
url_str = MATRIX_HOST_EXT + \
'_matrix/media/r0/download/{}{}' \
.format(url.netloc, quote(url.path))
url_str = await shorten_url(url_str)
url_str = ' (' + url_str + ')'
prefix = '' if displayname == '' else '<' + displayname + '> '
caption = '{}{}{}'.format(prefix,
content['body'], url_str)
caption = '{} sent an image'.format(displayname)
response = await group.send_photo(img_file, caption=caption)
except:
pass
@ -466,10 +449,7 @@ async def register_join_matrix(chat, room_id, user_id):
await matrix_put('client', 'profile/{}/displayname'.format(user_id),
user_id, {'displayname': name})
j = await matrix_post('client', 'join/{}'.format(room_id), user_id, {})
if 'errcode' in j and j['errcode'] == 'M_FORBIDDEN':
print("Error with <{}> joining room <{}>. This is likely because guests are not allowed to join the room."
.format(user_id, room_id))
await matrix_post('client', 'join/{}'.format(room_id), user_id, {})
async def update_matrix_displayname_avatar(tg_user):
name = tg_user['first_name']