Redact message events according to spec and ruma types. Remove content
using events redact() method and insert the redacting event into the
event being redacted.
High-level summary of changes:
- Rewrite the disambiguation algorithm to simplify it.
- Fixes to state tracking, e.g. use `state_key` instead of `user_id` when
determining which member an event is acting on.
- Changes to `RoomMember`:
* Make `RoomMember` "dumber" and don't let it mutate itself. This came about
primarily because `update_profile` cannot live on `RoomMember` because it
needs some information from `Room`. The other few mutating methods then
looked odd so it seemed best to move them to `Room` so that the room takes
care of updating its members.
* Each `RoomMember` now contains all information to calculate its set of
names:
+ `.name()` (short/ergonomic but potentially ambiguous),
+ `.unique_name()` (unique but may be contain MXID when not necessary),
+ `.disambiguated_name()` (shortest possible while being unique).
- Add some logging using the `tracing` crate.
- Improvements to `EventBuilder`:
* Add a docstring.
* Make it clear itself when building a sync response so the same builder can
be reused for later sync responses.
- A few tests.
This makes more sense as all the required information is now available
on `RoomMember`. We also don't have to handle the case of the missing
member since now you have to actually get a `RoomMember` before you can
ask for their name.
- use `state_key` instead of `user_id` to determine which member is
affected by the event
- assign state directly from the event in `add_member` instead of using
`membership_change`
- expand/fix docstrings
- add some logging
The new algorithm is simpler. Instead of tracking a list of
disambiguated display names in `Room`, we instead track the display name
ambiguity status in `RoomMember`. This allows a client to generate the
correct name for a member using solely the information available in
`RoomMember`.
The disambiguation algorithm itself now only calculates the set of members
whose ambiguity status had changed instead of producing disambiguated
display names for everyone affected. This is called on each room entry
(join or invite), room entry and profile change, and the updates are
propagated to the affected `RoomMember`s.
Ruma can't currently handle an event with the wrong event content type.
When replacing the MessageEventStub's content it automatically
serializes as "m.room.redaction".
The MessageQueue holds MessageEventStub<AnyMessageEventContent> so when
a redaction event is encountered the redacted event's content can be
replaced. The Unsigned field redacted_because is also populated with the
redaction event itself with the addition of a room_id Stub -> full
event.
The `update_profile` method cannot live in `RoomMember` since that
operation needs information which only exists in `Room` (for instance,
it needs other members in order to perform display name disambiguation).
Leaving other mutating methods on `RoomMember` (like `update_power` and
`update_presence`) then seemed illogical so they were all moved into
`Room`.
In addition, a small refactoring was done to remove
`did_update_presence` and `update_presence` since their existence
doesn't make much sense anymore and it saves us from repeating work.
Their function is now done in `receive_presence_event`.
Also, several docstrings were corrected and reworded.
The state store creates directory structure but the crypto store does
not.
This can lead to confusing errors where we require a directory to be
created by the library user but it gets created by the library.
The previous test only tested using the `EventEmitter`, which missed the
fact that the client was receiving unhoisted events. The test now also
tests the client state to detect this.
Also refactor and document why this hoisting is needed.
This change makes the user_presence test fail because the hoisting
exposes an error encoded into the test's expected result.
Previously, the test expected 2 members in the room at the end. This is
incorrect since one of the members in the test data leaves the room.
However, since the prev_content of state events was previously not
hoisted to the top level, the `membership_change` method would not
notice it and thus not realize the member had left the room. The test
was corrected to expect only a single member in the room.
Another test change was made due to a limitation of EventBuilder: due to
the fact that it makes the test data go through a de/ser cycle, it
cannot easily hoist prev_content to the top level. Because of this, the
tests were change to put prev_content into the top level from the
outset.
After discussing with poljar, we concluded we don't actually need to
tracking membership state, since we won't be tracking users that
left (banned, kicked, disinvited).
The only thing we need to keep track of is the difference between joined
and invited users which will be dealt with in a separate commit.