| Title: | Stateful Matrix Client Helpers |
|---|---|
| Description: | Stateful helpers for building 'Matrix' (<https://matrix.org>) chat clients in R. Builds on the low-level 'mx.api' Client-Server API bindings, adding local configuration persistence, room resolution, sync cursor handling, sync-event extraction, invite acceptance, a conservative Markdown-to-HTML converter for formatted messages, and 'Olm'/'Megolm' end-to-end encryption orchestration over the optional 'mx.crypto' package. |
| Authors: | Troy Hernandez [aut, cre] (ORCID: <https://orcid.org/0009-0005-4248-604X>), cornball.ai [cph] |
| Maintainer: | Troy Hernandez <[email protected]> |
| License: | Apache License (>= 2) |
| Version: | 0.1.1 |
| Built: | 2026-06-20 08:50:05 UTC |
| Source: | https://github.com/cornball-ai/mx.client |
Stateful helpers for building 'Matrix' (<https://matrix.org>) chat clients in R. Builds on the low-level 'mx.api' Client-Server API bindings, adding local configuration persistence, room resolution, sync cursor handling, sync-event extraction, invite acceptance, a conservative Markdown-to-HTML converter for formatted messages, and 'Olm'/'Megolm' end-to-end encryption orchestration over the optional 'mx.crypto' package.
Index of help topics:
mx_accept_invites Accept pending Matrix room invites
mx_client_config_path Path to a Matrix client config file
mx_client_configure Configure and save a Matrix client
mx_client_from_config Wrap a list as an mx.client config
mx_client_legacy_config_path
Legacy Matrix config path for an application
mx_client_load Load a Matrix client config
mx_client_relogin Re-login with stored credentials and refresh
the saved token
mx_client_save Save a Matrix client config
mx_client_session Build an mx.api session from a client config
mx_crypto_account Load or create this client's Olm account
mx_crypto_account_save
Persist an Olm account to the store
mx_crypto_claim_otks Claim a one-time key for each device
mx_crypto_decrypt_event
Decrypt an m.room.encrypted event (Megolm)
mx_crypto_device_keys Build a signed device_keys object for upload
mx_crypto_encrypt_event
Encrypt event content for a room (Megolm)
mx_crypto_encrypt_for_devices
Encrypt an event for an encrypted room's
devices
mx_crypto_handle_to_device
Decrypt an inbound Olm to-device payload
mx_crypto_inbound_session
Build an inbound Megolm session from a shared
room key
mx_crypto_known_devices
List the devices (and identity keys) of some
users
mx_crypto_process_sync
Process a sync response: store room keys,
decrypt room events
mx_crypto_publish_keys
Publish this device's identity and one-time
keys
mx_crypto_room_key_payload
Encrypt a Megolm room key to one device as a
to-device payload
mx_crypto_sessions_load
Load a session set from the crypto store
mx_crypto_sessions_new
Create an empty E2EE session set
mx_crypto_sessions_save
Persist a session set to the crypto store
mx_crypto_store_dir Directory holding this client's encryption
state
mx_extract_invites Extract pending invite room ids from a sync
response
mx_extract_reaction_verdict
Extract a reaction approval verdict from sync
events
mx_extract_text_events
Extract text message events from a sync
response
mx_markdown_to_html Convert a conservative markdown subset to
Matrix custom HTML
mx_pill_mentions Turn textual @mentions into matrix.to pills
mx_resolve_room Resolve a room id, name, or default room
mx_room_encrypted Is a room end-to-end encrypted?
mx_room_lookup_by_name
Look up a joined room by display name
mx_send_encrypted Send an end-to-end encrypted message to a room
mx_send_media Send a media file to a Matrix room
mx_send_text Send plain text to a Matrix room
mx_sync_update Sync once and update the stored cursor
mx_with_relogin Run a client operation, re-logging in once on
an expired token
mx.client-package Stateful Matrix Client Helpers
Troy Hernandez <[email protected]>
Troy Hernandez [aut, cre] (ORCID: <https://orcid.org/0009-0005-4248-604X>), cornball.ai [cph]
Accept pending Matrix room invites
mx_accept_invites(client, invites)mx_accept_invites(client, invites)
client |
Matrix client config. |
invites |
Character vector of room ids. |
Character vector of joined room ids.
## Not run: # Needs a live homeserver session. client <- mx_client_load("myapp") res <- mx_sync_update(client) mx_accept_invites(res$client, mx_extract_invites(res$sync)) ## End(Not run)## Not run: # Needs a live homeserver session. client <- mx_client_load("myapp") res <- mx_sync_update(client) mx_accept_invites(res$client, mx_extract_invites(res$sync)) ## End(Not run)
Resolves the config path for an application that uses mx.client. The
default environment variable is derived from app; for example,
app = "corteza" honors CORTEZA_MATRIX_CONFIG.
mx_client_config_path(app = "mx.client", env_var = NULL)mx_client_config_path(app = "mx.client", env_var = NULL)
app |
Character. Application namespace for |
env_var |
Character or NULL. Override environment variable name. |
Character path.
mx_client_config_path("myapp")mx_client_config_path("myapp")
Logs in with mx.api, joins or records the target room, and writes a reusable local config. Extra fields are merged into the saved config so applications can persist their own defaults without reimplementing login.
mx_client_configure(server, user, password, room, app = "mx.client", path = NULL, device_id = NULL, extra = list())mx_client_configure(server, user, password, room, app = "mx.client", path = NULL, device_id = NULL, extra = list())
server |
Character. Homeserver base URL. |
user |
Character. Matrix user localpart or full MXID. |
password |
Character. Account password. |
room |
Character. Room ID or alias to join. |
app |
Character. Application namespace. |
path |
Character or NULL. Explicit destination path. |
device_id |
Character or NULL. Existing device id to reuse. |
extra |
Named list. Additional fields to save. |
Saved "mx_client_config", invisibly.
## Not run: # Needs a live homeserver and account credentials. mx_client_configure("https://matrix.example.org", "bot", "secret", room = "#general:example.org", app = "myapp") ## End(Not run)## Not run: # Needs a live homeserver and account credentials. mx_client_configure("https://matrix.example.org", "bot", "secret", room = "#general:example.org", app = "myapp") ## End(Not run)
Wrap a list as an mx.client config
mx_client_from_config(cfg, path = NULL, app = NULL)mx_client_from_config(cfg, path = NULL, app = NULL)
cfg |
Named list. |
path |
Character or NULL. Source/sink path for saves. |
app |
Character or NULL. Application namespace. |
An object of class "mx_client_config".
cfg <- mx_client_from_config(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID")) class(cfg)cfg <- mx_client_from_config(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID")) class(cfg)
Currently only app = "corteza" has a historical path:
~/.corteza/matrix.json.
mx_client_legacy_config_path(app = "mx.client")mx_client_legacy_config_path(app = "mx.client")
app |
Character. Application namespace. |
Character path or NULL.
mx_client_legacy_config_path("corteza")mx_client_legacy_config_path("corteza")
Reads a JSON config. If path or the derived environment variable
is explicit, that path is authoritative. Otherwise legacy_path
is used as a compatibility fallback when present.
mx_client_load(app = "mx.client", path = NULL, legacy_path = mx_client_legacy_config_path(app), env_var = NULL)mx_client_load(app = "mx.client", path = NULL, legacy_path = mx_client_legacy_config_path(app), env_var = NULL)
app |
Character. Application namespace. |
path |
Character or NULL. Explicit config path. |
legacy_path |
Character or NULL. Backward-compatible fallback path. |
env_var |
Character or NULL. Override environment variable name. |
An "mx_client_config" object.
path <- file.path(tempdir(), "matrix.json") cfg <- mx_client_from_config(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID")) mx_client_save(cfg, path = path) mx_client_load(path = path)$user_id unlink(path)path <- file.path(tempdir(), "matrix.json") cfg <- mx_client_from_config(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID")) mx_client_save(cfg, path = path) mx_client_load(path = path)$user_id unlink(path)
Uses the password persisted in the client config to obtain a fresh
access token for the same device (reusing
client$device_id, so an E2EE device identity survives the
refresh), then saves the updated config. Typical use is recovering
from an invalidated token; see mx_with_relogin for the
catch-and-retry wrapper.
mx_client_relogin(client, save = TRUE)mx_client_relogin(client, save = TRUE)
client |
Matrix client config with |
save |
Logical. Persist the refreshed config (default TRUE). |
The refreshed "mx_client_config".
## Not run: # Needs a live homeserver and a stored password. client <- mx_client_relogin(mx_client_load("myapp")) ## End(Not run)## Not run: # Needs a live homeserver and a stored password. client <- mx_client_relogin(mx_client_load("myapp")) ## End(Not run)
Writes JSON with mode 0600.
mx_client_save(client, app = NULL, path = NULL)mx_client_save(client, app = NULL, path = NULL)
client |
Named list or |
app |
Character or NULL. Application namespace. |
path |
Character or NULL. Destination path. |
The saved config, invisibly.
path <- file.path(tempdir(), "matrix.json") mx_client_save(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID"), path = path) unlink(path)path <- file.path(tempdir(), "matrix.json") mx_client_save(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID"), path = path) unlink(path)
Build an mx.api session from a client config
mx_client_session(client)mx_client_session(client)
client |
Named list or |
An "mx_session" from mx.api.
s <- mx_client_session(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID")) class(s)s <- mx_client_session(list(server = "https://matrix.example.org", token = "syt_example", user_id = "@bot:example.org", device_id = "DEVICEID")) class(s)
Unpickles account.pickle from the store, or mints a fresh
account and persists it. The account holds the device's long-lived
Curve25519/Ed25519 identity keys.
mx_crypto_account(store_dir)mx_crypto_account(store_dir)
store_dir |
Character. Crypto store directory. |
An mx.crypto account handle.
if (requireNamespace("mx.crypto", quietly = TRUE)) { store <- mx_crypto_store_dir("myapp", path = tempfile()) acct <- mx_crypto_account(store) unlink(store, recursive = TRUE) }if (requireNamespace("mx.crypto", quietly = TRUE)) { store <- mx_crypto_store_dir("myapp", path = tempfile()) acct <- mx_crypto_account(store) unlink(store, recursive = TRUE) }
Persist an Olm account to the store
mx_crypto_account_save(account, store_dir)mx_crypto_account_save(account, store_dir)
account |
An mx.crypto account handle. |
store_dir |
Character. Crypto store directory. |
The pickle path, invisibly.
if (requireNamespace("mx.crypto", quietly = TRUE)) { store <- mx_crypto_store_dir("myapp", path = tempfile()) acct <- mx_crypto_account(store) mx_crypto_account_save(acct, store) unlink(store, recursive = TRUE) }if (requireNamespace("mx.crypto", quietly = TRUE)) { store <- mx_crypto_store_dir("myapp", path = tempfile()) acct <- mx_crypto_account(store) mx_crypto_account_save(acct, store) unlink(store, recursive = TRUE) }
Calls /keys/claim and attaches the claimed key to each device as
$otk, ready for mx_crypto_encrypt_for_devices().
mx_crypto_claim_otks(client, devices)mx_crypto_claim_otks(client, devices)
client |
Matrix client config. |
devices |
List of devices from |
The devices with an otk field added where one was
claimed.
## Not run: devs <- mx_crypto_claim_otks(client, mx_crypto_known_devices(client, uid)) ## End(Not run)## Not run: devs <- mx_crypto_claim_otks(client, mx_crypto_known_devices(client, uid)) ## End(Not run)
Decrypt an m.room.encrypted event (Megolm)
mx_crypto_decrypt_event(inbound_session, encrypted)mx_crypto_decrypt_event(inbound_session, encrypted)
inbound_session |
An inbound Megolm session for the event's
|
encrypted |
The |
The decrypted event payload (a parsed list).
## Not run: ev <- mx_crypto_decrypt_event(inb, encrypted_content) ev$content$body ## End(Not run)## Not run: ev <- mx_crypto_decrypt_event(inb, encrypted_content) ev$content$body ## End(Not run)
Produces the device_keys structure /keys/upload expects:
the device's public identity keys plus an Ed25519 signature over their
canonical JSON. Hand the result to mx.api::mx_keys_upload().
mx_crypto_device_keys(account, user_id, device_id)mx_crypto_device_keys(account, user_id, device_id)
account |
An mx.crypto account handle. |
user_id |
Character. Full Matrix user id. |
device_id |
Character. This device's id. |
A named list ready to upload.
if (requireNamespace("mx.crypto", quietly = TRUE)) { store <- mx_crypto_store_dir("myapp", path = tempfile()) acct <- mx_crypto_account(store) dk <- mx_crypto_device_keys(acct, "@bot:example.org", "DEVICEID") unlink(store, recursive = TRUE) } ## Not run: # Uploading needs a live homeserver session: mx.api::mx_keys_upload(session, device_keys = dk) ## End(Not run)if (requireNamespace("mx.crypto", quietly = TRUE)) { store <- mx_crypto_store_dir("myapp", path = tempfile()) acct <- mx_crypto_account(store) dk <- mx_crypto_device_keys(acct, "@bot:example.org", "DEVICEID") unlink(store, recursive = TRUE) } ## Not run: # Uploading needs a live homeserver session: mx.api::mx_keys_upload(session, device_keys = dk) ## End(Not run)
Returns the m.room.encrypted content to send as the event body.
mx_crypto_encrypt_event(megolm_out, content, room_id, sender_curve25519, device_id)mx_crypto_encrypt_event(megolm_out, content, room_id, sender_curve25519, device_id)
megolm_out |
An outbound Megolm session. |
content |
Named list. The plaintext event content (e.g. an
|
room_id |
Character. Room id. |
sender_curve25519 |
Character. This device's Curve25519 key. |
device_id |
Character. This device's id. |
A named list: m.room.encrypted content.
## Not run: enc <- mx_crypto_encrypt_event(megolm_out, list(msgtype = "m.text", body = "hi"), "!room:ex", my_curve, "DEV") ## End(Not run)## Not run: enc <- mx_crypto_encrypt_event(megolm_out, list(msgtype = "m.text", body = "hi"), "!room:ex", my_curve, "DEV") ## End(Not run)
Ensures an outbound Megolm session for the room, shares its key with
any recipient device that has not received it yet (establishing an Olm
session, claiming a one-time key when needed), and encrypts the event.
Returns the to-device payloads and the m.room.encrypted event;
the caller sends them with mx.api::mx_send_to_device() and
mx.api::mx_send().
mx_crypto_encrypt_for_devices(account, sessions, room_id, content, sender_curve25519, device_id, recipients = list())mx_crypto_encrypt_for_devices(account, sessions, room_id, content, sender_curve25519, device_id, recipients = list())
account |
An mx.crypto account handle. |
sessions |
A session set. |
room_id |
Character room id. |
content |
Named list. Plaintext event content. |
sender_curve25519 |
Character. This device's Curve25519 key. |
device_id |
Character. This device's id. |
recipients |
List of recipient devices, each a list with
|
List with to_device (per-device payloads), event
(the m.room.encrypted content), and the updated sessions.
if (requireNamespace("mx.crypto", quietly = TRUE)) { acct <- mx.crypto::mxc_account_new() out <- mx_crypto_encrypt_for_devices( acct, mx_crypto_sessions_new(), "!r:ex", list(msgtype = "m.text", body = "hi"), mx.crypto::mxc_account_identity_keys(acct)$curve25519, "DEV", recipients = list()) names(out) }if (requireNamespace("mx.crypto", quietly = TRUE)) { acct <- mx.crypto::mxc_account_new() out <- mx_crypto_encrypt_for_devices( acct, mx_crypto_sessions_new(), "!r:ex", list(msgtype = "m.text", body = "hi"), mx.crypto::mxc_account_identity_keys(acct)$curve25519, "DEV", recipients = list()) names(out) }
Accepts an m.room.encrypted to-device content addressed to this
device and returns the decrypted event. When it is an m.room_key,
the caller builds an inbound Megolm session from
content$session_key with mx_crypto_inbound_session().
mx_crypto_handle_to_device(account, my_curve25519, content)mx_crypto_handle_to_device(account, my_curve25519, content)
account |
An mx.crypto account handle. |
my_curve25519 |
Character. This device's Curve25519 key. |
content |
The to-device |
The decrypted event (a parsed list), or NULL if not for us.
## Not run: ev <- mx_crypto_handle_to_device(acct, my_curve, td_content) if (identical(ev$type, "m.room_key")) { inb <- mx_crypto_inbound_session(ev$content$session_key) } ## End(Not run)## Not run: ev <- mx_crypto_handle_to_device(acct, my_curve, td_content) if (identical(ev$type, "m.room_key")) { inb <- mx_crypto_inbound_session(ev$content$session_key) } ## End(Not run)
Build an inbound Megolm session from a shared room key
mx_crypto_inbound_session(session_key)mx_crypto_inbound_session(session_key)
session_key |
Character. The |
An inbound Megolm session.
## Not run: inb <- mx_crypto_inbound_session(ev$content$session_key) ## End(Not run)## Not run: inb <- mx_crypto_inbound_session(ev$content$session_key) ## End(Not run)
Queries /keys/query and flattens the result to a list of devices.
mx_crypto_known_devices(client, user_ids)mx_crypto_known_devices(client, user_ids)
client |
Matrix client config. |
user_ids |
Character vector of Matrix user ids. |
List of devices, each list(user_id, device_id,
curve25519, ed25519).
## Not run: mx_crypto_known_devices(client, "@bob:example.org") ## End(Not run)## Not run: mx_crypto_known_devices(client, "@bob:example.org") ## End(Not run)
Handles inbound to-device m.room.encrypted (Olm) messages,
storing any m.room_key as an inbound Megolm session, then
decrypts m.room.encrypted timeline events whose session is
known. Returns normalized text events in the same shape as
mx_extract_text_events(), plus the updated session set.
mx_crypto_process_sync(account, sessions, sync_resp, self_curve25519, self_id = NULL)mx_crypto_process_sync(account, sessions, sync_resp, self_curve25519, self_id = NULL)
account |
An mx.crypto account handle. |
sessions |
A session set. |
sync_resp |
Parsed |
self_curve25519 |
Character. This device's Curve25519 key. |
self_id |
Character or NULL. This user's Matrix id, for
|
List with events (decrypted, normalized) and the updated
sessions.
if (requireNamespace("mx.crypto", quietly = TRUE)) { acct <- mx.crypto::mxc_account_new() res <- mx_crypto_process_sync(acct, mx_crypto_sessions_new(), list(to_device = list(events = list()), rooms = list(join = list())), mx.crypto::mxc_account_identity_keys(acct)$curve25519) length(res$events) }if (requireNamespace("mx.crypto", quietly = TRUE)) { acct <- mx.crypto::mxc_account_new() res <- mx_crypto_process_sync(acct, mx_crypto_sessions_new(), list(to_device = list(events = list()), rooms = list(join = list())), mx.crypto::mxc_account_identity_keys(acct)$curve25519) length(res$events) }
Builds and signs the device keys and a batch of one-time keys, uploads
them with mx.api::mx_keys_upload(), marks them published, and
persists the account. Call once after login and again to replenish
one-time keys.
mx_crypto_publish_keys(client, account, store_dir, n_otks = 50L)mx_crypto_publish_keys(client, account, store_dir, n_otks = 50L)
client |
Matrix client config (needs |
account |
An mx.crypto account handle. |
store_dir |
Character. Crypto store directory. |
n_otks |
Integer. Number of one-time keys to publish. |
The /keys/upload response, invisibly.
## Not run: acct <- mx_crypto_account(mx_crypto_store_dir("corteza")) mx_crypto_publish_keys(mx_client_load(app = "corteza"), acct, mx_crypto_store_dir("corteza")) ## End(Not run)## Not run: acct <- mx_crypto_account(mx_crypto_store_dir("corteza")) mx_crypto_publish_keys(mx_client_load(app = "corteza"), acct, mx_crypto_store_dir("corteza")) ## End(Not run)
Wraps the outbound Megolm session's key in an m.room_key event,
Olm-encrypts it to the recipient device, and returns the
m.room.encrypted to-device content to hand to
mx.api::mx_send_to_device().
mx_crypto_room_key_payload(olm_session, sender_curve25519, recipient_curve25519, room_id, megolm_out)mx_crypto_room_key_payload(olm_session, sender_curve25519, recipient_curve25519, room_id, megolm_out)
olm_session |
An outbound Olm session
( |
sender_curve25519 |
Character. This device's Curve25519 key. |
recipient_curve25519 |
Character. Target device's Curve25519 key. |
room_id |
Character. Room the key is for. |
megolm_out |
An outbound Megolm session. |
A named list: the to-device m.room.encrypted content.
## Not run: content <- mx_crypto_room_key_payload(olm, my_curve, their_curve, "!room:ex", megolm_out) ## End(Not run)## Not run: content <- mx_crypto_room_key_payload(olm, my_curve, their_curve, "!room:ex", megolm_out) ## End(Not run)
Load a session set from the crypto store
mx_crypto_sessions_load(store_dir)mx_crypto_sessions_load(store_dir)
store_dir |
Character. Crypto store directory. |
A session set (empty if nothing is stored yet).
if (requireNamespace("mx.crypto", quietly = TRUE)) { s <- mx_crypto_sessions_load(file.path(tempfile(), "crypto")) }if (requireNamespace("mx.crypto", quietly = TRUE)) { s <- mx_crypto_sessions_load(file.path(tempfile(), "crypto")) }
Create an empty E2EE session set
mx_crypto_sessions_new()mx_crypto_sessions_new()
A session set: named lists olm, olm_in,
megolm_out, megolm_in.
s <- mx_crypto_sessions_new() names(s)s <- mx_crypto_sessions_new() names(s)
Pickles every live session (encrypted at rest with the store key) into
sessions.json. Reload with mx_crypto_sessions_load().
mx_crypto_sessions_save(sessions, store_dir)mx_crypto_sessions_save(sessions, store_dir)
sessions |
A session set. |
store_dir |
Character. Crypto store directory. |
The path written, invisibly.
if (requireNamespace("mx.crypto", quietly = TRUE)) { dir <- file.path(tempfile(), "crypto") mx_crypto_sessions_save(mx_crypto_sessions_new(), dir) }if (requireNamespace("mx.crypto", quietly = TRUE)) { dir <- file.path(tempfile(), "crypto") mx_crypto_sessions_save(mx_crypto_sessions_new(), dir) }
The crypto store keeps the pickled Olm account, the 32-byte key that
encrypts those pickles at rest, and (later) per-peer Olm and per-room
Megolm sessions. It lives beside the JSON config under
tools::R_user_dir().
mx_crypto_store_dir(app = "mx.client", path = NULL)mx_crypto_store_dir(app = "mx.client", path = NULL)
app |
Character. Application namespace. |
path |
Character or NULL. Explicit store directory. |
Character directory path.
mx_crypto_store_dir("myapp", path = tempfile())mx_crypto_store_dir("myapp", path = tempfile())
Extract pending invite room ids from a sync response
mx_extract_invites(sync_resp)mx_extract_invites(sync_resp)
sync_resp |
Parsed |
Character vector of invited room ids.
sync_resp <- list(rooms = list(invite = list("!inv:example.org" = list()))) mx_extract_invites(sync_resp)sync_resp <- list(rooms = list(invite = list("!inv:example.org" = list()))) mx_extract_invites(sync_resp)
Scans a room timeline for a reaction on target_event_id from
someone other than self_id. Returns TRUE for approval keys,
FALSE for denial keys, or NULL when no verdict is present.
mx_extract_reaction_verdict(sync_resp, room_id, self_id, target_event_id, approve_keys = NULL, deny_keys = NULL)mx_extract_reaction_verdict(sync_resp, room_id, self_id, target_event_id, approve_keys = NULL, deny_keys = NULL)
sync_resp |
Parsed |
room_id |
Character room id. |
self_id |
Current user's Matrix id. |
target_event_id |
Event id being reacted to. |
approve_keys |
Character vector of reaction keys read as approval.
|
deny_keys |
Character vector of reaction keys read as denial.
|
TRUE, FALSE, or NULL.
sync_resp <- list(rooms = list(join = list("!room:example.org" = list( timeline = list(events = list(list(type = "m.reaction", sender = "@alice:example.org", content = list("m.relates_to" = list(rel_type = "m.annotation", event_id = "$msg", key = "yes"))))))))) mx_extract_reaction_verdict(sync_resp, "!room:example.org", self_id = "@bot:example.org", target_event_id = "$msg")sync_resp <- list(rooms = list(join = list("!room:example.org" = list( timeline = list(events = list(list(type = "m.reaction", sender = "@alice:example.org", content = list("m.relates_to" = list(rel_type = "m.annotation", event_id = "$msg", key = "yes"))))))))) mx_extract_reaction_verdict(sync_resp, "!room:example.org", self_id = "@bot:example.org", target_event_id = "$msg")
Walks joined-room timeline events and returns normalized text-message
records. Self events are retained and tagged with is_self.
mx_extract_text_events(sync_resp, self_id, msgtypes = "m.text")mx_extract_text_events(sync_resp, self_id, msgtypes = "m.text")
sync_resp |
Parsed |
self_id |
Current user's Matrix id. |
msgtypes |
Character vector of message types to include. |
List of normalized event records.
sync_resp <- list(rooms = list(join = list("!room:example.org" = list( timeline = list(events = list(list(type = "m.room.message", event_id = "$1", sender = "@alice:example.org", content = list(msgtype = "m.text", body = "hello")))))))) mx_extract_text_events(sync_resp, self_id = "@bot:example.org")sync_resp <- list(rooms = list(join = list("!room:example.org" = list( timeline = list(events = list(list(type = "m.room.message", event_id = "$1", sender = "@alice:example.org", content = list(msgtype = "m.text", body = "hello")))))))) mx_extract_text_events(sync_resp, self_id = "@bot:example.org")
Supports headings, bullets, numbered lists, fenced code blocks, inline code, bold, and simple underscore emphasis.
mx_markdown_to_html(text)mx_markdown_to_html(text)
text |
Character markdown body. |
Character HTML suitable for m.room.message formatted_body.
mx_markdown_to_html("# Status\n- built\n- checked\n\nShip `0.1.0` **soon**")mx_markdown_to_html("# Status\n- built\n- checked\n\nShip `0.1.0` **soon**")
Replaces each occurrence of @localpart (or the full
@localpart:server id) in already-rendered HTML with a
matrix.to anchor, which Matrix clients render as a mention pill.
A user id with no textual occurrence is left to m.mentions alone,
which still notifies.
mx_pill_mentions(html, user_ids)mx_pill_mentions(html, user_ids)
html |
Character HTML (e.g. from |
user_ids |
Character vector of full Matrix user ids. |
Character HTML with mention pills.
mx_pill_mentions("<p>ping @jorge</p>", "@jorge:example.org")mx_pill_mentions("<p>ping @jorge</p>", "@jorge:example.org")
Resolution order:
literal room IDs beginning with !, a supplied room_cache
name-to-id map, joined-room display-name lookup, then the config's
room_id fallback.
mx_resolve_room(client, room = NULL, room_cache = NULL, fallback = TRUE, details = FALSE, quiet = FALSE)mx_resolve_room(client, room = NULL, room_cache = NULL, fallback = TRUE, details = FALSE, quiet = FALSE)
client |
Matrix client config. |
room |
Character or NULL. |
room_cache |
Named list or character vector mapping names to ids. |
fallback |
Logical. Use |
details |
Logical. Return source metadata instead of just the id. |
quiet |
Logical. Suppress fallback message. |
Character room id, or a list when details = TRUE.
client <- list(room_id = "!default:example.org") # Literal ids and cache hits resolve without a server round-trip: mx_resolve_room(client, "!abc:example.org") mx_resolve_room(client, "general", room_cache = list(general = "!gen:example.org")) mx_resolve_room(client) # NULL room falls back to the config defaultclient <- list(room_id = "!default:example.org") # Literal ids and cache hits resolve without a server round-trip: mx_resolve_room(client, "!abc:example.org") mx_resolve_room(client, "general", room_cache = list(general = "!gen:example.org")) mx_resolve_room(client) # NULL room falls back to the config default
Resolves the room (by name, id, or the config default) and reads its
m.room.encryption state. Needs mx.api >= 0.3.0.
mx_room_encrypted(client, room = NULL, room_cache = NULL)mx_room_encrypted(client, room = NULL, room_cache = NULL)
client |
Matrix client config. |
room |
Character room id/name or NULL for the default room. |
room_cache |
Optional room name-to-id cache. |
TRUE when the room advertises an encryption algorithm, FALSE otherwise.
## Not run: if (mx_room_encrypted(client, "secret plans")) { # use mx_send_encrypted() instead of mx_send_text() } ## End(Not run)## Not run: if (mx_room_encrypted(client, "secret plans")) { # use mx_send_encrypted() instead of mx_send_text() } ## End(Not run)
Look up a joined room by display name
mx_room_lookup_by_name(client, name)mx_room_lookup_by_name(client, name)
client |
Matrix client config. |
name |
Character room name. |
Room id, or NULL when no joined room has that name.
## Not run: # Needs a live homeserver session. mx_room_lookup_by_name(mx_client_load("myapp"), "general") ## End(Not run)## Not run: # Needs a live homeserver session. mx_room_lookup_by_name(mx_client_load("myapp"), "general") ## End(Not run)
Discovers the room members' devices (unless recipients is given),
claims one-time keys for any without an Olm session, shares the room key
over to-device, encrypts the content with Megolm, sends the
m.room.encrypted event, and persists the updated sessions.
mx_send_encrypted(client, account, sessions, room_id, content, store_dir, recipients = NULL, member_ids = NULL)mx_send_encrypted(client, account, sessions, room_id, content, store_dir, recipients = NULL, member_ids = NULL)
client |
Matrix client config. |
account |
An mx.crypto account handle. |
sessions |
A session set (see |
room_id |
Character room id. |
content |
Named list. Plaintext event content. |
store_dir |
Character. Crypto store directory. |
recipients |
List of recipient devices, or NULL to discover them
from |
member_ids |
Character vector of room member user ids (used when
|
List with event_id and the updated sessions.
## Not run: res <- mx_send_encrypted(client, acct, sessions, "!r:ex", list(msgtype = "m.text", body = "secret"), store, member_ids = "@bob:example.org") ## End(Not run)## Not run: res <- mx_send_encrypted(client, acct, sessions, "!r:ex", list(msgtype = "m.text", body = "secret"), store, member_ids = "@bob:example.org") ## End(Not run)
Client-layer wrapper over mx.api::mx_send_media(): resolves the
room by name (or falls back to the config's default room), builds the
session from the client config, and uploads + posts in one call. The
msgtype is derived from the file's MIME type unless given.
mx_send_media(client, path, room = NULL, body = basename(path), msgtype = NULL, content_type = NULL, info = list(), room_cache = NULL, dry_run = FALSE)mx_send_media(client, path, room = NULL, body = basename(path), msgtype = NULL, content_type = NULL, info = list(), room_cache = NULL, dry_run = FALSE)
client |
Matrix client config. |
path |
Character. Path to the file to upload. |
room |
Character room id/name or NULL for the default room. |
body |
Character. Message body / filename shown by clients. |
msgtype |
Character or NULL. NULL derives it from the MIME type. |
content_type |
Character or NULL. MIME type override for files whose extension guesses wrong (tempfiles, odd extensions); NULL guesses from the extension. |
info |
List. Extra fields merged into the media |
room_cache |
Optional room name-to-id cache. |
dry_run |
Logical. Print instead of uploading/sending. |
If you attach mx.api and mx.client together, namespace-qualify – the
two packages export an mx_send_media each (session-first there,
client-first here).
Event id, or NULL on dry-run.
client <- list(room_id = "!default:example.org") png <- file.path(tempdir(), "plot.png") file.create(png) mx_send_media(client, png, dry_run = TRUE) unlink(png)client <- list(room_id = "!default:example.org") png <- file.path(tempdir(), "plot.png") file.create(png) mx_send_media(client, png, dry_run = TRUE) unlink(png)
Send plain text to a Matrix room
mx_send_text(client, text, room = NULL, msgtype = "m.text", room_cache = NULL, dry_run = FALSE, markdown = FALSE, mentions = NULL)mx_send_text(client, text, room = NULL, msgtype = "m.text", room_cache = NULL, dry_run = FALSE, markdown = FALSE, mentions = NULL)
client |
Matrix client config. |
text |
Character message body. |
room |
Character room id/name or NULL for the default room. |
msgtype |
Character Matrix message type. |
room_cache |
Optional room name-to-id cache. |
dry_run |
Logical. Print instead of sending. |
markdown |
Logical. If TRUE, include Matrix custom HTML derived from a conservative markdown subset. |
mentions |
Character vector of Matrix user ids to mention
(e.g. |
Event id, or NULL on dry-run.
client <- list(room_id = "!default:example.org") mx_send_text(client, "release is out", dry_run = TRUE) ## Not run: # A real send needs a live homeserver session: client <- mx_client_load("myapp") mx_send_text(client, "release is out", markdown = TRUE, mentions = "@jorge:example.org") ## End(Not run)client <- list(room_id = "!default:example.org") mx_send_text(client, "release is out", dry_run = TRUE) ## Not run: # A real send needs a live homeserver session: client <- mx_client_load("myapp") mx_send_text(client, "release is out", markdown = TRUE, mentions = "@jorge:example.org") ## End(Not run)
Calls mx.api::mx_sync() using client$sync_token, stores
the returned next_batch in a returned client object, and
optionally saves it back to disk.
mx_sync_update(client, timeout = 0L, filter = NULL, save = TRUE, path = NULL, app = NULL)mx_sync_update(client, timeout = 0L, filter = NULL, save = TRUE, path = NULL, app = NULL)
client |
Matrix client config. |
timeout |
Integer long-poll timeout in milliseconds. |
filter |
Character or NULL. Matrix sync filter. |
save |
Logical. Persist the updated client config. |
path |
Character or NULL. Save destination. |
app |
Character or NULL. Application namespace for default saves. |
List with sync, client, and first_run.
## Not run: # Needs a live homeserver session. client <- mx_client_load("myapp") res <- mx_sync_update(client, timeout = 30000L) events <- mx_extract_text_events(res$sync, client$user_id) ## End(Not run)## Not run: # Needs a live homeserver session. client <- mx_client_load("myapp") res <- mx_sync_update(client, timeout = 30000L) events <- mx_extract_text_events(res$sync, client$user_id) ## End(Not run)
Calls fn(client); if it fails with the server's invalid-token
error (M_UNKNOWN_TOKEN, signalled as a classed condition by
mx.api >= 0.3.0), re-logs in via mx_client_relogin and
retries once with the refreshed client. Any other error propagates.
mx_with_relogin(client, fn, save = TRUE)mx_with_relogin(client, fn, save = TRUE)
client |
Matrix client config with |
fn |
Function taking a client config. |
save |
Logical. Persist the refreshed config on relogin. |
fn's return value.
## Not run: mx_with_relogin(client, function(cl) { mx_send_text(cl, "still here after a token rotation") }) ## End(Not run)## Not run: mx_with_relogin(client, function(cl) { mx_send_text(cl, "still here after a token rotation") }) ## End(Not run)