async def aiotg_sticker(chat, sticker): link = db.session.query(db.ChatLink).filter_by(tg_room=chat.id).first() if not link: print('Unknown telegram chat {}: {}'.format(chat, chat.id)) return await update_matrix_displayname_avatar(chat.sender) room_id = link.matrix_room user_id = USER_ID_FORMAT.format(chat.sender['id']) txn_id = quote('{}{}'.format(chat.message['message_id'], chat.id)) file_id = sticker['file_id'] uri, length = await upload_tgfile_to_matrix(file_id, user_id, 'image/png', 'PNG') info = { 'mimetype': 'image/png', 'size': length, 'h': sticker['height'], 'w': sticker['width'] } body = 'Sticker_{}.png'.format(int(time() * 1000)) if uri: j = await send_matrix_message(room_id, user_id, txn_id, body=body, url=uri, info=info, msgtype='m.image') if 'errcode' in j and j['errcode'] == 'M_FORBIDDEN': await register_join_matrix(chat, room_id, user_id) await send_matrix_message(room_id, user_id, txn_id + 'join', body=body, url=uri, info=info, msgtype='m.image') if 'caption' in chat.message: await send_matrix_message(room_id, user_id, txn_id + 'caption', body=chat.message['caption'], msgtype='m.text') if 'event_id' in j: name = chat.sender['first_name'] if 'last_name' in chat.sender: name += " " + chat.sender['last_name'] name += " (Telegram)" message = db.Message(chat.message['chat']['id'], chat.message['message_id'], room_id, j['event_id'], name) db.session.add(message) db.session.commit()
async def send_file_to_matrix(chat, room_id, user_id, txn_id, body, uri, info, msgtype): j = await send_matrix_message(room_id, user_id, txn_id, body=body, url=uri, info=info, msgtype=msgtype) if 'errcode' in j and j['errcode'] == 'M_FORBIDDEN': await register_join_matrix(chat, room_id, user_id) await send_matrix_message(room_id, user_id, txn_id + 'join', body=body, url=uri, info=info, msgtype=msgtype) if 'caption' in chat.message: await send_matrix_message(room_id, user_id, txn_id + 'caption', body=chat.message['caption'], msgtype='m.text') if 'event_id' in j: name = chat.sender['first_name'] if 'last_name' in chat.sender: name += " " + chat.sender['last_name'] name += " (Telegram)" message = db.Message(chat.message['chat']['id'], chat.message['message_id'], room_id, j['event_id'], name) db.session.add(message) db.session.commit()
async def aiotg_message(chat, match): link = db.session.query(db.ChatLink).filter_by(tg_room=chat.id).first() if link: room_id = link.matrix_room else: print('Unknown telegram chat {}: {}'.format(chat, chat.id)) return await update_matrix_displayname_avatar(chat.sender); user_id = USER_ID_FORMAT.format(chat.sender['id']) txn_id = quote('{}:{}'.format(chat.message['message_id'], chat.id)) message = match.group(0) if 'forward_from' in chat.message: fw_from = chat.message['forward_from'] if 'last_name' in fw_from: msg_from = '{} {} (Telegram)'.format(fw_from['first_name'], fw_from['last_name']) else: msg_from = '{} (Telegram)'.format(fw_from['first_name']) quoted_msg = '\n'.join(['>{}'.format(x) for x in message.split('\n')]) quoted_msg = 'Forwarded from {}:\n{}' \ .format(msg_from, quoted_msg) quoted_html = '<blockquote>{}</blockquote>' \ .format(html.escape(message).replace('\n', '<br />')) quoted_html = '<i>Forwarded from {}:</i>\n{}' \ .format(html.escape(msg_from), quoted_html) j = await send_matrix_message(room_id, user_id, txn_id, body=quoted_msg, formatted_body=quoted_html, format='org.matrix.custom.html', msgtype='m.text') elif 'reply_to_message' in chat.message: re_msg = chat.message['reply_to_message'] if not 'text' in re_msg and not 'photo' in re_msg and not 'sticker' in re_msg: return if 'last_name' in re_msg['from']: msg_from = '{} {} (Telegram)'.format(re_msg['from']['first_name'], re_msg['from']['last_name']) else: msg_from = '{} (Telegram)'.format(re_msg['from']['first_name']) date = datetime.fromtimestamp(re_msg['date']) \ .strftime('%Y-%m-%d %H:%M:%S') reply_mx_id = db.session.query(db.Message)\ .filter_by(tg_group_id=chat.message['chat']['id'], tg_message_id=chat.message['reply_to_message']['message_id']).first() html_message = html.escape(message).replace('\n', '<br />') if 'text' in re_msg: quoted_msg = '\n'.join(['>{}'.format(x) for x in re_msg['text'].split('\n')]) quoted_html = '<blockquote>{}</blockquote>' \ .format(html.escape(re_msg['text']) .replace('\n', '<br />')) else: quoted_msg = '' quoted_html = '' if reply_mx_id: quoted_msg = 'Reply to {}:\n{}\n\n{}' \ .format(reply_mx_id.displayname, quoted_msg, message) quoted_html = '<i><a href="https://matrix.to/#/{}/{}">Reply to {}</a>:</i><br />{}<p>{}</p>' \ .format(html.escape(room_id), html.escape(reply_mx_id.matrix_event_id), html.escape(reply_mx_id.displayname), quoted_html, html_message) else: quoted_msg = 'Reply to {}:\n{}\n\n{}' \ .format(msg_from, quoted_msg, message) quoted_html = '<i>Reply to {}:</i><br />{}<p>{}</p>' \ .format(html.escape(msg_from), quoted_html, html_message) j = await send_matrix_message(room_id, user_id, txn_id, body=quoted_msg, formatted_body=quoted_html, format='org.matrix.custom.html', msgtype='m.text') else: j = await send_matrix_message(room_id, user_id, txn_id, body=message, msgtype='m.text') if 'errcode' in j and j['errcode'] == 'M_FORBIDDEN': await register_join_matrix(chat, room_id, user_id) await asyncio.sleep(0.5) j = await send_matrix_message(room_id, user_id, txn_id + 'join', body=message, msgtype='m.text') elif 'event_id' in j: name = chat.sender['first_name'] if 'last_name' in chat.sender: name += " " + chat.sender['last_name'] name += " (Telegram)" message = db.Message( chat.message['chat']['id'], chat.message['message_id'], room_id, j['event_id'], name) db.session.add(message) db.session.commit()
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'] == '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 = '{} sent an image'.format(displayname) response = 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: 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, {})