Пример #1
0
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()
Пример #2
0
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()
Пример #3
0
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()
Пример #4
0
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, {})