From 935fada1c5ec4e00c14ed3dac0a61dd9d3dd31c2 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Tue, 15 Nov 2016 00:52:00 +0100 Subject: [PATCH] Use a database for links, allowing for automatic configuration Fixes #6 --- app_service.py | 131 +++++++++++++++++++++++++++++++++++++------- config.json.example | 6 +- database.py | 63 +++++++++++++++++++++ requirements.txt | 1 + 4 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 database.py diff --git a/app_service.py b/app_service.py index 8041045..28b94c3 100644 --- a/app_service.py +++ b/app_service.py @@ -16,6 +16,8 @@ from aiohttp import web, ClientSession from aiotg import Bot from bs4 import BeautifulSoup +import database as db + # Read the configuration file try: with open('config.json', 'r') as config_file: @@ -28,6 +30,7 @@ try: MATRIX_HOST = CONFIG['hosts']['internal'] MATRIX_HOST_EXT = CONFIG['hosts']['external'] + MATRIX_HOST_BARE = CONFIG['hosts']['bare'] MATRIX_PREFIX = MATRIX_HOST + '_matrix/client/r0/' MATRIX_MEDIA_PREFIX = MATRIX_HOST + '_matrix/media/r0/' @@ -36,6 +39,8 @@ try: TELEGRAM_CHATS = CONFIG['chats'] MATRIX_ROOMS = {v: k for k, v in TELEGRAM_CHATS.items()} + + DATABASE_URL = CONFIG['db_url'] except (OSError, IOError) as exception: print('Error opening config file:') print(exception) @@ -126,6 +131,12 @@ async def shorten_url(url): else: return url +def matrix_is_telegram(user_id): + username = user_id.split(':')[0][1:] + return username.startswith('telegram_') + +def get_username(user_id): + return user_id.split(':')[0][1:] async def matrix_transaction(request): """ @@ -136,24 +147,65 @@ async def matrix_transaction(request): body = await request.json() events = body['events'] for event in events: - if event['room_id'] not in MATRIX_ROOMS: - print('{} not in matrix_rooms!'.format(event['room_id'])) - elif event['type'] == 'm.room.message': - group = TG_BOT.group(MATRIX_ROOMS[event['room_id']]) + print(event) - username = event['user_id'].split(':')[0][1:] - if username.startswith('telegram_'): - return create_response(200, {}) + if event['type'] == 'm.room.aliases': + aliases = event['content']['aliases'] + links = db.session.query(db.ChatLink)\ + .filter_by(matrix_room=event['room_id']).all() + for link in links: + db.session.delete(link) + + for alias in aliases: + print(alias) + if alias.split('_')[0] != '#telegram' \ + or alias.split(':')[-1] != MATRIX_HOST_BARE: + continue + + tg_id = alias.split('_')[1].split(':')[0] + link = db.ChatLink(event['room_id'], tg_id, True) + db.session.add(link) + + db.session.commit() + continue + + link = db.session.query(db.ChatLink)\ + .filter_by(matrix_room=event['room_id']).first() + if not link: + print('{} isn\'t linked!'.format(event['room_id'])) + continue + group = TG_BOT.group(link.tg_room) + + if event['type'] == 'm.room.message': + user_id = event['user_id'] + if matrix_is_telegram(user_id): + continue + + sender = db.session.query(db.MatrixUser)\ + .filter_by(matrix_id=user_id).first() + + if not sender: + response = await matrix_get('client', 'profile/{}/displayname' + .format(user_id), None) + try: + displayname = response['displayname'] + except KeyError: + displayname = get_username(user_id) + sender = db.MatrixUser(user_id, displayname) + db.session.add(sender) + else: + displayname = sender.name or get_username(user_id) content = event['content'] + if content['msgtype'] == 'm.text': - msg, mode = format_matrix_msg('<{}> {}', username, content) + msg, mode = format_matrix_msg('<{}> {}', displayname, content) await group.send_text(msg, parse_mode=mode) elif content['msgtype'] == 'm.notice': - msg, mode = format_matrix_msg('[{}] {}', username, content) + msg, mode = format_matrix_msg('[{}] {}', displayname, content) await group.send_text(msg, parse_mode=mode) elif content['msgtype'] == 'm.emote': - msg, mode = format_matrix_msg('* {} {}', username, content) + msg, mode = format_matrix_msg('* {} {}', displayname, content) await group.send_text(msg, parse_mode=mode) elif content['msgtype'] == 'm.image': url = urlparse(content['url']) @@ -164,13 +216,45 @@ async def matrix_transaction(request): .format(url.netloc, quote(url.path)) url_str = await shorten_url(url_str) - caption = '<{}> {} ({})'.format(username, content['body'], - url_str) + caption = '<{}> {} ({})'.format(displayname, + content['body'], url_str) await group.send_photo(img_file, caption=caption) else: print('Unsupported message type {}'.format(content['msgtype'])) print(json.dumps(content, indent=4)) + elif event['type'] == 'm.room.member': + if matrix_is_telegram(event['state_key']): + continue + user_id = event['state_key'] + content = event['content'] + + sender = db.session.query(db.MatrixUser)\ + .filter_by(matrix_id=user_id).first() + if sender: + displayname = sender.name + else: + displayname = get_username(user_id) + + if content['membership'] == 'join': + displayname = content['displayname'] or get_username(user_id) + if not sender: + sender = db.MatrixUser(user_id, displayname) + else: + sender.name = displayname + db.session.add(sender) + + msg = '> {} has joined the room'.format(displayname) + await group.send_text(msg) + elif content['membership'] == 'leave': + msg = '< {} has left the room'.format(displayname) + await group.send_text(msg) + elif content['membership'] == 'ban': + msg = '