Read inbound media, and fetch its bytes - #18
Merged
Merged
Conversation
The Matrix adapter's only event source was mx_extract_text_events(), which filters to text msgtypes. An image sent into a room was not merely unreadable to a consumer, it was invisible: nothing in the poll's output said a picture had ever been sent, so an agent asked about one answered that there was no image attached. chat_poll() now runs mx_extract_media_events() over the same sync and maps each media event onto its own chat_message carrying one chat_attachment -- the shape chat_send() already produces outbound, where each file goes as a separate event. Media rides the existing position ordering, so a picture sent before a comment does not arrive after it, and a throwing extractor costs the poll its media rather than the room's conversation. An inbound attachment names where its content lives, not what it is: the mxc URL needs this client's credentials, so a consumer cannot fetch it on its own. chat_download() is the verb that turns one into a file on disk, capability-gated on chat_capabilities()$attachments and throwing by default rather than quietly leaving the caller pointing at an empty path. The loopback adapter implements it as a copy, so a consumer writes one code path and tests it against the reference. Encrypted attachments are refused rather than fetched. The bytes behind the URL are ciphertext and this adapter has no media decryption path, so downloading would write a file that is not the picture, with nothing to say so -- the same bargain chat_send() makes refusing to upload into an encrypted room. The capability stays TRUE on an e2ee client, because the events are still reported; it is the fetch that cannot happen. The mx.client floor moves to 0.2.0.6, where mx_extract_media_events() arrived. It is probed rather than assumed, so an older build degrades to no media instead of failing every poll, and CI enforces the floor so the tests that meet the real extractor actually run. That last part matters more than it looks. The first version of matrix_media_records() passed an undefined self_id, and all thirteen seamed assertions passed: R hands the argument to the seam as a promise, and a seam double that ignores it never forces it. The real-extractor test in test_matrix_mxclient.R is what went red. The argument is forced up front now, and the seamed test reads it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Matrix adapter's only event source was
mx_extract_text_events(), which filters to text msgtypes. An image sent into a room was not merely unreadable to a consumer, it was invisible: nothing in the poll's output said a picture had ever been sent.What changed
chat_poll()runsmx_extract_media_events()over the same sync and maps each media event onto its ownchat_messagecarrying onechat_attachment— the shapechat_send()already produces outbound, where each file goes as a separate event. Media rides the existing position ordering, so a picture sent before a comment does not arrive after it. A throwing extractor costs the poll its media rather than the room's conversation.chat_download(client, attachment, dest = NULL)is new. An inbound attachment names where its content lives, not what it is: the mxc URL needs the client's credentials, so a consumer cannot fetch it on its own. Capability-gated onchat_capabilities()$attachments, throwing by default rather than quietly leaving the caller pointing at an empty path. The destination keeps the attachment's extension, so a consumer handing the file to something that sniffs by extension does not have to rename it.The loopback adapter implements
chat_download()as a copy of the path it recorded, so a consumer writes one code path and tests it against the reference.Encrypted media
Refused rather than fetched. The bytes behind the URL are ciphertext and this adapter has no media decryption path, so downloading would write a file that is not the picture with nothing to say so — the same bargain
chat_send()makes refusing to upload into an encrypted room. The capability stays TRUE on an e2ee client, because the events are still reported; it is the fetch that cannot happen.Floor
mx.client (>= 0.2.0.6), wheremx_extract_media_events()arrived. Probed rather than assumed, so an older build degrades to no media instead of failing every poll, and CI's existing floor check makes the real-extractor tests actually run.One note on the tests
The first version of
matrix_media_records()passed an undefinedself_id, and all thirteen seamed assertions passed: R hands the argument to the seam as a promise, and a seam double that ignores it never forces it. The real-extractor test intest_matrix_mxclient.Ris what went red. The argument is forced up front now, and the seamed test reads it.1072 tests pass locally with mx.api/mx.client/mx.crypto installed.