matrix-nio
matrix-nio copied to clipboard
Message sent after creating encrypted private chat is encrypted, but the keys are not sent with it
The following code invites the user to an encrypted private chat and sends a message, but the client (Element/Riot Desktop) can't decrypt it and shows the warning ** Unable to decrypt: The sender's device has not sent us the keys for this message. **
My code is based on https://github.com/anoadragon453/nio-template
#!/usr/bin/env python3
import logging
import asyncio
import sys
import traceback
from time import sleep
import nio
from aiohttp import (
ServerDisconnectedError,
ClientConnectionError
)
from callbacks import Callbacks
from config import Config
from storage import Storage
logger = logging.getLogger(__name__)
async def main():
# Read config file
# A different config file path can be specified as the first command line argument
if len(sys.argv) > 1:
config_filepath = sys.argv[1]
else:
config_filepath = "config.yaml"
config = Config(config_filepath)
# Configure the database
store = Storage(config.database_filepath)
# Configuration options for the AsyncClient
client_config = nio.AsyncClientConfig(
max_limit_exceeded=0,
max_timeouts=0,
store_sync_tokens=True,
encryption_enabled=True,
)
# Initialize the matrix client
client = nio.AsyncClient(
config.homeserver_url,
config.user_id,
device_id=config.device_id,
store_path=config.store_filepath,
config=client_config,
)
# Set up event callbacks
callbacks = Callbacks(client, store, config)
client.add_event_callback(callbacks.message, (nio.RoomMessageText,))
client.add_event_callback(callbacks.invite, (nio.InviteMemberEvent,))
# My Code
async def background():
try:
await asyncio.sleep(5)
logger.info("creating private chat...")
invite = "@example:matrix.org" # CHANGEME
res = await client.get_profile(invite)
logger.info(res.displayname)
response = await client.room_create(
invite=[invite],
is_direct=True,
visibility=nio.RoomVisibility.private,
initial_state= [nio.EnableEncryptionBuilder().as_dict()],
)
logger.info(response.room_id)
room_id = response.room_id
await client.room_send(
room_id=room_id,
content={
"msgtype": "m.text",
"body": "Hello, this message is encrypted!"
},
message_type="m.room.message",
ignore_unverified_devices=True,
)
except:
logger.info("Error")
logger.info(sys.exc_info()[0])
# Keep trying to reconnect on failure (with some time in-between)
while True:
try:
# Try to login with the configured username/password
try:
login_response = await client.login(
password=config.user_password,
device_name=config.device_name,
)
# Check if login failed
if type(login_response) == nio.LoginError:
logger.error(f"Failed to login: %s",
login_response.message)
return False
except nio.LocalProtocolError as e:
# There's an edge case here where the user hasn't installed the correct C
# dependencies. In that case, a LocalProtocolError is raised on login.
logger.fatal(
"Failed to login. Have you installed the correct dependencies? "
"https://github.com/poljar/matrix-nio#installation "
"Error: %s", e
)
return False
# Login succeeded!
# Sync encryption keys with the server
# Required for participating in encrypted rooms
if client.should_upload_keys:
await client.keys_upload()
logger.info(f"Logged in as {config.user_id}")
bg_task = asyncio.run_coroutine_threadsafe(
background(), asyncio.get_event_loop())
logger.info("sync_forever")
await client.sync_forever(timeout=30000, full_state=True)
except (ClientConnectionError, ServerDisconnectedError):
logger.warning(
"Unable to connect to homeserver, retrying in 15s...")
# Sleep so we don't bombard the server with login requests
sleep(15)
finally:
# Make sure to close the client connection on disconnect
await client.close()
asyncio.get_event_loop().run_until_complete(main())