matrix-bot-sdk

repository·main·Indexed 42 days ago

https://github.com/turt2live/matrix-bot-sdk

A TypeScript/JavaScript SDK for creating Matrix bots and appservices. It provides high-level abstractions for interacting with the Matrix protocol, including support for standard bots using a sync loop and high-capability Appservices for bridges, featuring built-in webserver support and namespace management via Intents.

Tokens
18.6K
Snippets
53
Records
77
Agent score
54%

What's inside matrix-bot-sdk

  1. Overview of matrix-bot-sdk

    main

    The matrix-bot-sdk is a TypeScript/JavaScript SDK designed for building Matrix bots. It provides the necessary abstractions to interact with the Matrix protocol via a homeserver.

    For help and support, users can visit the Matrix room #matrix-bot-sdk:t2bot.io.

  2. Use Intents to manage appservice namespaces

    main

    Intents are the mechanism used to interact with the namespaces (users/aliases) declared in the appservice registration.

    • Bridge Bot Intent: Use appservice.botIntent for actions that don't require impersonating a specific user, such as querying room state or inviting users. The underlying client is available via appservice.botClient.
    • User/Alias Intents: For users or aliases defined by a specific suffix (e.g., from a third-party platform), use appservice.getIntentForSuffix("suffix").

    Common Intent operations:

    • intent.ensureRegistered(): Ensures the user/alias is registered in the Matrix ecosystem (safe to call multiple times).
    • intent.underlyingClient: Provides access to the Client instance for that specific intent to perform actions like setDisplayName().
    // Get an intent for a specific suffix
    const intent = appservice.getIntentForSuffix("your_suffix");
    
    // Ensure the user is registered
    await intent.ensureRegistered();
    
    // Use the underlying client to perform actions
    await intent.underlyingClient.setDisplayName("Name");
    
    // Access the bridge bot client directly
    const botClient = appservice.botClient;
  3. Use appservice.botClient for API calls

    main

    When running as an Appservice, you can access a MatrixClient instance via appservice.botClient to perform actions like sending messages or creating rooms.

    CRITICAL WARNINGS:

    • The botClient instance will not emit events because it is not syncing.
    • Do NOT call botClient.start(). Calling start() on the client instance in an appservice context can cause data loss or duplication.
  4. Handle room upgrades and data migration

    main

    To perform data relocation or migration during a room upgrade, you should listen for the room.upgraded event.

    Important: Do not attempt to migrate data during the room.archived phase. You should wait for room.upgraded because that is the point where referential integrity between the old room and the new replacement room is guaranteed. Prior to this event, the advertised replacement room may not be valid.

  5. Matrix version compatibility and support

    main

    The SDK is designed to work with homeservers that support at least one of the last two versions of the Matrix specification at the time of the SDK's release.

    Important Considerations:

    • Compatibility Risk: If you connect the SDK to a homeserver that is 3 or more Matrix versions out of date, functionality may break.
    • Maintenance: It is recommended to update the matrix-bot-sdk frequently (ideally as soon as new Matrix spec releases are available) to ensure compatibility with modern homeservers.
    • Error Handling: Currently, the SDK does not explicitly throw an error if it detects an incompatible server version, though this behavior may change in future releases.
  6. Automatically join upgraded rooms with AutojoinUpgradedRoomsMixin

    main

    When a Matrix room is upgraded, it undergoes two phases: room.archived (the old room is flagged as replaced) and room.upgraded (the bot/bridge is aware of the new room).

    To ensure your bot or appservice automatically attempts to join the new replacement room, attach the AutojoinUpgradedRoomsMixin to your client or appservice. This works similarly to the AutojoinRoomsMixin.

  7. Create a Quickstart Bot

    main

    To create a basic bot, follow these steps:

    1. Initialize a SimpleFsStorageProvider to persist state (e.g., to a JSON file).
    2. Instantiate a MatrixClient with the homeserverUrl, accessToken, and your storage provider.
    3. Use AutojoinRoomsMixin.setupOnClient(client) to allow the bot to automatically join rooms it is invited to.
    4. Register event listeners using client.on(eventName, handler).
    5. Call client.start() to begin the sync loop.

    In the handler, always validate the event type (e.g., checking if msgtype is m.text) and ensure the sender is not the bot itself to avoid infinite loops.

    import { 
        MatrixClient,
        SimpleFsStorageProvider,
        AutojoinRoomsMixin,
    } from "matrix-bot-sdk";
    
    const homeserverUrl = "https://example.org";
    const accessToken = "ACQUIRED_FROM_ABOVE";
    const storage = new SimpleFsStorageProvider("hello-bot.json");
    
    const client = new MatrixClient(homeserverUrl, accessToken, storage);
    AutojoinRoomsMixin.setupOnClient(client);
    
    // Register command handler
    client.on("room.message", handleCommand);
    
    // Start the bot
    client.start().then(() => console.log("Bot started!"));
    
    async function handleCommand(roomId: string, event: any) {
        if (event['content']?.['msgtype'] !== 'm.text') return;
        if (event['sender'] === await client.getUserId()) return;
        
        const body = event['content']['body'];
        if (!body?.startsWith("!hello")) return;
        
        await client.replyNotice(roomId, event, "Hello world!");
    }
  8. Access Matrix bot SDK documentation and templates

    main

    The SDK provides several resources for different bot implementation types:

  9. Convert a bot to an Appservice

    main

    When a bot outgrows the performance of a /sync loop, you can convert it to a Matrix Appservice. This changes how the application receives events (via push from the homeserver instead of polling) and may require migrating datastores.

    To perform this conversion, you must:

    1. Create an Appservice registration file.
    2. Install the registration on your homeserver.
    3. Update your code to use the IAppserviceRegistration and IAppserviceOptions interfaces.
    4. Attach event listeners to the appservice instance instead of a standard MatrixClient.
    5. Start the service using appservice.begin().
  10. Enable encryption in matrix-bot-sdk

    main

    Matrix supports end-to-end encryption (E2EE), but it is not enabled by default in the matrix-bot-sdk. To support encrypted rooms, you must deliberately enable encryption in your code.

    For both bots and appservices, you must provide an implementation of ICryptoStorageProvider to handle the storage of cryptographic keys. Currently, you must use RustSdkCryptoStorageProvider or a derivative of it to enable encryption functionality.

  11. Manually control encryption for Intents

    main

    If you do not want encryption enabled globally via intentOptions.encryption: true, you can control it per Intent.

    1. Set intentOptions.encryption = false in your IAppserviceOptions.
    2. Call await intent.enableEncryption() when encryption is required.

    Calling enableEncryption() multiple times is safe.

    // In IAppserviceOptions
    const options: IAppserviceOptions = {
       // ...
       intentOptions: {
          encryption: false,
       },
    };
    
    // Later, when needed:
    await intent.enableEncryption();
  12. Configure encryption for Appservices

    main

    To enable encryption in an Appservice, you must provide both a standard IStorageProvider and a RustSdkAppserviceCryptoStorageProvider. The standard storage handles general appservice data, while the crypto storage handles encryption keys.

    Important: Always back up both the storage file (e.g., appservice.json) and the directory used for cryptoStorage to prevent data loss.

    In the IAppserviceOptions, you can enable encryption globally for all appservice users (including the sender_localpart user) by setting intentOptions.encryption to true.

    const storage = new SimpleFsStorageProvider("./path/to/appservice.json");
    const cryptoStorage = new RustSdkAppserviceCryptoStorageProvider("./path/to/directory");
    
    const options: IAppserviceOptions = {
       storage: storage,
       cryptoStorage: cryptoStorage,
       intentOptions: {
          // Enable encryption on all appservice users, including the `sender_localpart` user
          encryption: true,
       },
    };
    
    const appservice = new Appservice(options);