diff --git a/src/models/event.ts b/src/models/event.ts index 246390629..ba16939cc 100644 --- a/src/models/event.ts +++ b/src/models/event.ts @@ -26,6 +26,7 @@ import { logger } from '../logger'; import { VerificationRequest } from "../crypto/verification/request/VerificationRequest"; import { EventType, RelationType } from "../@types/event"; import { Crypto } from "../crypto"; +import { deepSortedObjectEntries } from "../utils"; /** * Enum for event statuses. @@ -1176,6 +1177,45 @@ export class MatrixEvent extends EventEmitter { return this._isCancelled; } + /** + * Get a copy/snapshot of this event. The returned copy will be loosely linked + * back to this instance, though will have "frozen" event information. Other + * properties of this MatrixEvent instance will be copied verbatim, which can + * mean they are in reference to this instance despite being on the copy too. + * The reference the snapshot uses does not change, however members aside from + * the underlying event will not be deeply cloned, thus may be mutated internally. + * For example, the sender profile will be copied over at snapshot time, and + * the sender profile internally may mutate without notice to the consumer. + * + * This is meant to be used to snapshot the event details themselves, not the + * features (such as sender) surrounding the event. + * @returns {MatrixEvent} A snapshot of this event. + */ + toSnapshot(): MatrixEvent { + const ev = new MatrixEvent(JSON.parse(JSON.stringify(this.event))); + for (const [p, v] of Object.entries(this)) { + if (p !== "event") { // exclude the thing we just cloned + ev[p] = v; + } + } + return ev; + } + + /** + * Determines if this event is equivalent to the given event. This only checks + * the event object itself, not the other properties of the event. Intended for + * use with toSnapshot() to identify events changing. + * @param {MatrixEvent} otherEvent The other event to check against. + * @returns {boolean} True if the events are the same, false otherwise. + */ + isEquivalentTo(otherEvent: MatrixEvent): boolean { + if (!otherEvent) return false; + if (otherEvent === this) return true; + const myProps = deepSortedObjectEntries(this.event); + const theirProps = deepSortedObjectEntries(otherEvent.event); + return JSON.stringify(myProps) === JSON.stringify(theirProps); + } + /** * Summarise the event as JSON for debugging. If encrypted, include both the * decrypted and encrypted view of the event. This is named `toJSON` for use