async def matrix_transaction(request): """ Handle a transaction sent by the homeserver. :param request: The request containing the transaction. :return: The response to send. """ body = await request.json() events = body['events'] for event in events: if 'age' in event and event['age'] > 600000: print('discarded event of age', event['age']) continue try: print('{}: <{}> {}'.format(event['room_id'], event['user_id'], event['type'])) except KeyError: pass 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) try: 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 'msgtype' not in content: continue if content['msgtype'] == 'm.text': 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('[{}] {}', displayname, content) await group.send_text(msg, parse_mode=mode) elif content['msgtype'] == 'm.emote': msg, mode = format_matrix_msg('* {} {}', displayname, content) await group.send_text(msg, parse_mode=mode) elif content['msgtype'] == 'm.image': try: url = urlparse(content['url']) # Append the correct extension if it's missing or wrong ext = mime_extensions[content['info']['mimetype']] if not content['body'].endswith(ext): content['body'] += '.' + ext # Download the file await download_matrix_file(url, content['body']) with open('/tmp/{}'.format(content['body']), 'rb') as img_file: # 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) caption = '<{}> {} ({})'.format( displayname, content['body'], url_str) await group.send_photo(img_file, caption=caption) except: pass 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': oldname = sender.name if sender else get_username(user_id) try: displayname = content['displayname'] or get_username( user_id) except KeyError: displayname = get_username(user_id) if not sender: sender = db.MatrixUser(user_id, displayname) else: sender.name = displayname db.session.add(sender) msg = None if 'unsigned' in event and 'prev_content' in event[ 'unsigned']: prev = event['unsigned']['prev_content'] if prev['membership'] == 'join': if 'displayname' in prev and prev['displayname']: oldname = prev['displayname'] msg = '> {} changed their display name to {}'\ .format(oldname, displayname) else: msg = '> {} has joined the room'.format(displayname) if msg: 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 = '<! {} was banned from the room'.format(displayname) await group.send_text(msg) except RuntimeError as e: print('Got a runtime error:', e) print('Group:', group) db.session.commit() return create_response(200, {})
async def matrix_transaction(request): """ Handle a transaction sent by the homeserver. :param request: The request containing the transaction. :return: The response to send. """ body = await request.json() events = body['events'] for event in events: if 'age' in event and event['age'] > 600000: print('discarded event of age', event['age']) continue try: print('{}: <{}> {}'.format(event['room_id'], event['user_id'], event['type'])) except KeyError: pass if event['type'] == 'm.room.aliases' and event[ 'state_key'] == MATRIX_HOST_BARE: 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) try: response = None 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 'msgtype' not in content: continue if content['msgtype'] == 'm.text': msg, mode = format_matrix_msg('{}', content) response = await group.send_text("<b>{}:</b> {}".format( displayname, msg), parse_mode='HTML') elif content['msgtype'] == 'm.notice': msg, mode = format_matrix_msg('{}', content) response = await group.send_text("[{}] {}".format( displayname, msg), parse_mode=mode) elif content['msgtype'] == 'm.emote': msg, mode = format_matrix_msg('{}', content) response = await group.send_text("* {} {}".format( displayname, msg), parse_mode=mode) elif content['msgtype'] in [ 'm.image', 'm.audio', 'm.video', 'm.file' ]: try: url = urlparse(content['url']) # Append the correct extension if it's missing or wrong try: exts = MT.types_map_inv[1][content['info'] ['mimetype']] if not content['body'].endswith(tuple(exts)): content['body'] += '.' + exts[0] except KeyError: pass # Download the file await download_matrix_file(url, content['body']) with open('/tmp/{}'.format(content['body']), 'rb') as file: # 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) if content['msgtype'] == 'm.image': if content['info']['mimetype'] == 'image/gif': # Send gif as a video, so telegram can display it animated caption = '{} sent a gif'.format( displayname) await group.send_chat_action('upload_video' ) response = await group.send_video( file, caption=caption) else: caption = '{} sent an image'.format( displayname) await group.send_chat_action('upload_photo' ) response = await group.send_photo( file, caption=caption) elif content['msgtype'] == 'm.video': caption = '{} sent a video'.format(displayname) await group.send_chat_action('upload_video') response = await group.send_video( file, caption=caption) elif content['msgtype'] == 'm.audio': caption = '{} sent an audio file'.format( displayname) await group.send_chat_action('upload_audio') response = await group.send_audio( file, caption=caption) elif content['msgtype'] == 'm.file': caption = '{} sent a file'.format(displayname) await group.send_chat_action('upload_document') response = await group.send_document( file, caption=caption) except: pass else: print('Unsupported message type {}'.format( content['msgtype'])) print(json.dumps(content, indent=4)) elif event['type'] == 'm.sticker': 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'] try: url = urlparse(content['url']) await download_matrix_file(url, content['body']) png_image = Image.open('/tmp/{}'.format(content['body'])) png_image.save('/tmp/{}.webp'.format(content['body']), 'WEBP') with open('/tmp/{}.webp'.format(content['body']), 'rb') as file: response = await group.send_document(file) except: pass elif event['type'] == 'm.room.member': if HIDE_MEMBERSHIP_CHANGES: # Hide everything, could be improved to be # more specific continue 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': oldname = sender.name if sender else get_username(user_id) try: displayname = content['displayname'] or get_username( user_id) except KeyError: displayname = get_username(user_id) if not sender: sender = db.MatrixUser(user_id, displayname) else: sender.name = displayname db.session.add(sender) msg = None if 'unsigned' in event and 'prev_content' in event[ 'unsigned']: prev = event['unsigned']['prev_content'] if prev['membership'] == 'join': if 'displayname' in prev and prev['displayname']: oldname = prev['displayname'] msg = '> {} changed their display name to {}'\ .format(oldname, displayname) else: msg = '> {} has joined the room'.format(displayname) if msg: response = await group.send_text(msg) elif content['membership'] == 'leave': msg = '< {} has left the room'.format(displayname) response = await group.send_text(msg) elif content['membership'] == 'ban': msg = '<! {} was banned from the room'.format(displayname) response = await group.send_text(msg) if response: message = db.Message(response['result']['chat']['id'], response['result']['message_id'], event['room_id'], event['event_id'], displayname) db.session.add(message) except RuntimeError as e: print('Got a runtime error:', e) print('Group:', group) db.session.commit() return create_response(200, {})