feat: complete Ancestor quote bot with production-ready Docker support

This commit is contained in:
unfunny
2026-09-13 14:14:38 -04:00
parent f2016da05a
commit fe7351a7dc
1145 changed files with 30890 additions and 97684 deletions

View File

@@ -1,4 +1,22 @@
import _defineProperty from "@babel/runtime/helpers/defineProperty";
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SlidingSyncSdk = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _room = require("./models/room");
var _logger = require("./logger");
var _utils = require("./utils");
var _eventTimeline = require("./models/event-timeline");
var _client = require("./client");
var _sync = require("./sync");
var _httpApi = require("./http-api");
var _slidingSync = require("./sliding-sync");
var _event = require("./@types/event");
var _roomState = require("./models/room-state");
var _roomMember = require("./models/room-member");
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
@@ -15,19 +33,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { NotificationCountType, Room, RoomEvent } from "./models/room.js";
import { logger } from "./logger.js";
import { promiseMapSeries } from "./utils.js";
import { EventTimeline } from "./models/event-timeline.js";
import { ClientEvent } from "./client.js";
import { SyncState, _createAndReEmitRoom, defaultClientOpts, defaultSyncApiOpts, processToDeviceMessages } from "./sync.js";
import { MatrixError } from "./http-api/index.js";
import { ExtensionState, SlidingSyncEvent, SlidingSyncState } from "./sliding-sync.js";
import { EventType } from "./@types/event.js";
import { RoomStateEvent } from "./models/room-state.js";
import { RoomMemberEvent } from "./models/room-member.js";
import { KnownMembership } from "./@types/membership.js";
// Number of consecutive failed syncs that will lead to a syncState of ERROR as opposed
// to RECONNECTING. This is needed to inform the client of server issues when the
// keepAlive is successful but the server /sync fails.
@@ -40,23 +45,17 @@ class ExtensionE2EE {
return "e2ee";
}
when() {
return ExtensionState.PreProcess;
return _slidingSync.ExtensionState.PreProcess;
}
async onRequest(isInitial) {
if (isInitial) {
// In SSS, the `?pos=` contains the stream position for device list updates.
// If we do not have a `?pos=` (e.g because we forgot it, or because the server
// invalidated our connection) then we MUST invlaidate all device lists because
// the server will not tell us the delta. This will then cause UTDs as we will fail
// to encrypt for new devices. This is an expensive call, so we should
// really really remember `?pos=` wherever possible.
logger.log("ExtensionE2EE: invalidating all device lists due to missing 'pos'");
await this.crypto.markAllTrackedUsersAsDirty();
onRequest(isInitial) {
if (!isInitial) {
return undefined;
}
return {
enabled: true // this is sticky so only send it on the initial request
};
}
async onResponse(data) {
// Handle device list updates
if (data.device_lists) {
@@ -70,36 +69,64 @@ class ExtensionE2EE {
}
class ExtensionToDevice {
constructor(client, cryptoCallbacks) {
_defineProperty(this, "nextBatch", null);
this.client = client;
this.cryptoCallbacks = cryptoCallbacks;
(0, _defineProperty2.default)(this, "nextBatch", null);
}
name() {
return "to_device";
}
when() {
return ExtensionState.PreProcess;
return _slidingSync.ExtensionState.PreProcess;
}
async onRequest(isInitial) {
return {
since: this.nextBatch !== null ? this.nextBatch : undefined,
limit: 100,
enabled: true
onRequest(isInitial) {
const extReq = {
since: this.nextBatch !== null ? this.nextBatch : undefined
};
if (isInitial) {
extReq["limit"] = 100;
extReq["enabled"] = true;
}
return extReq;
}
async onResponse(data) {
const events = data["events"] || [];
let receivedToDeviceMessages;
if (this.cryptoCallbacks) {
receivedToDeviceMessages = await this.cryptoCallbacks.preprocessToDeviceMessages(events);
} else {
// Crypto is not enabled, so we just return the events.
receivedToDeviceMessages = events.map(rawEvent => ({
message: rawEvent,
encryptionInfo: null
}));
const cancelledKeyVerificationTxns = [];
let events = data["events"] || [];
if (events.length > 0 && this.cryptoCallbacks) {
events = await this.cryptoCallbacks.preprocessToDeviceMessages(events);
}
processToDeviceMessages(receivedToDeviceMessages, this.client);
events.map(this.client.getEventMapper()).map(toDeviceEvent => {
// map is a cheap inline forEach
// We want to flag m.key.verification.start events as cancelled
// if there's an accompanying m.key.verification.cancel event, so
// we pull out the transaction IDs from the cancellation events
// so we can flag the verification events as cancelled in the loop
// below.
if (toDeviceEvent.getType() === "m.key.verification.cancel") {
const txnId = toDeviceEvent.getContent()["transaction_id"];
if (txnId) {
cancelledKeyVerificationTxns.push(txnId);
}
}
// as mentioned above, .map is a cheap inline forEach, so return
// the unmodified event.
return toDeviceEvent;
}).forEach(toDeviceEvent => {
const content = toDeviceEvent.getContent();
if (toDeviceEvent.getType() == "m.room.message" && content.msgtype == "m.bad.encrypted") {
// the mapper already logged a warning.
_logger.logger.log("Ignoring undecryptable to-device event from " + toDeviceEvent.getSender());
return;
}
if (toDeviceEvent.getType() === "m.key.verification.start" || toDeviceEvent.getType() === "m.key.verification.request") {
const txnId = content["transaction_id"];
if (cancelledKeyVerificationTxns.includes(txnId)) {
toDeviceEvent.flagCancelled();
}
}
this.client.emit(_client.ClientEvent.ToDeviceEvent, toDeviceEvent);
});
this.nextBatch = data.next_batch;
}
}
@@ -111,29 +138,30 @@ class ExtensionAccountData {
return "account_data";
}
when() {
return ExtensionState.PostProcess;
return _slidingSync.ExtensionState.PostProcess;
}
async onRequest(isInitial) {
onRequest(isInitial) {
if (!isInitial) {
return undefined;
}
return {
enabled: true
};
}
async onResponse(data) {
onResponse(data) {
if (data.global && data.global.length > 0) {
this.processGlobalAccountData(data.global);
}
// oxlint-disable-next-line guard-for-in
for (const roomId in data.rooms) {
const accountDataEvents = mapEvents(this.client, roomId, data.rooms[roomId]);
const room = this.client.getRoom(roomId);
if (!room) {
logger.warn("got account data for room but room doesn't exist on client:", roomId);
_logger.logger.warn("got account data for room but room doesn't exist on client:", roomId);
continue;
}
room.addAccountData(accountDataEvents);
accountDataEvents.forEach(e => {
this.client.emit(ClientEvent.Event, e);
this.client.emit(_client.ClientEvent.Event, e);
});
}
}
@@ -149,12 +177,12 @@ class ExtensionAccountData {
// honour push rules that were previously cached. Base rules
// will be updated when we receive push rules via getPushRules
// (see sync) before syncing over the network.
if (accountDataEvent.getType() === EventType.PushRules) {
if (accountDataEvent.getType() === _event.EventType.PushRules) {
const rules = accountDataEvent.getContent();
this.client.setPushRules(rules);
}
const prevEvent = prevEventsMap[accountDataEvent.getType()];
this.client.emit(ClientEvent.AccountData, accountDataEvent, prevEvent);
this.client.emit(_client.ClientEvent.AccountData, accountDataEvent, prevEvent);
return accountDataEvent;
});
}
@@ -167,19 +195,21 @@ class ExtensionTyping {
return "typing";
}
when() {
return ExtensionState.PostProcess;
return _slidingSync.ExtensionState.PostProcess;
}
async onRequest(isInitial) {
onRequest(isInitial) {
if (!isInitial) {
return undefined; // don't send a JSON object for subsequent requests, we don't need to.
}
return {
enabled: true
};
}
async onResponse(data) {
if (!data?.rooms) {
onResponse(data) {
if (!(data !== null && data !== void 0 && data.rooms)) {
return;
}
// oxlint-disable-next-line guard-for-in
for (const roomId in data.rooms) {
processEphemeralEvents(this.client, roomId, [data.rooms[roomId]]);
}
@@ -193,101 +223,54 @@ class ExtensionReceipts {
return "receipts";
}
when() {
return ExtensionState.PostProcess;
return _slidingSync.ExtensionState.PostProcess;
}
async onRequest(isInitial) {
return {
enabled: true
};
onRequest(isInitial) {
if (isInitial) {
return {
enabled: true
};
}
return undefined; // don't send a JSON object for subsequent requests, we don't need to.
}
async onResponse(data) {
if (!data?.rooms) {
onResponse(data) {
if (!(data !== null && data !== void 0 && data.rooms)) {
return;
}
// oxlint-disable-next-line guard-for-in
for (const roomId in data.rooms) {
processEphemeralEvents(this.client, roomId, [data.rooms[roomId]]);
}
}
}
/**
* Delivers sticky events (MSC4354) over sliding sync.
* https://github.com/matrix-org/matrix-spec-proposals/pull/4480
*
* Sticky events expire after a duration instead of living in the timeline forever, and the server
* re-sends the unexpired ones (e.g. on join) so late joiners still see them.
*
* The server sends them for every room matched by a list or subscription, even rooms currently
* outside the list window. Sticky events already in a room's timeline are excluded here, so
* `processRoomData` picks those up separately.
*/
class ExtensionStickyEvents {
constructor(client) {
_defineProperty(this, "nextBatch", void 0);
this.client = client;
}
name() {
// Keeps MSC4354's number, as the extension was originally specified there.
return "org.matrix.msc4354.sticky_events";
}
when() {
// Sticky events are stored on a Room, so the room has to exist first.
return ExtensionState.PostProcess;
}
async onRequest(isInitial) {
return {
enabled: true,
limit: 100,
// Undefined until the first response, which asks for all unexpired sticky events.
since: this.nextBatch
};
}
async onResponse(data) {
for (const [roomId, roomData] of Object.entries(data?.rooms ?? {})) {
const room = this.client.getRoom(roomId);
if (!room) {
// Dropping is safe: unexpired sticky events are re-sent once we know the room.
logger.debug(`Ignoring sticky events for unknown room ${roomId}`);
continue;
}
room._unstable_addStickyEvents(mapEvents(this.client, roomId, roomData.events ?? []));
}
// next_batch is only returned when there were changes, and must be echoed back as `since`.
if (data?.next_batch) {
this.nextBatch = data.next_batch;
}
}
}
/**
* A copy of SyncApi such that it can be used as a drop-in replacement for sync v2. For the actual
* sliding sync API, see sliding-sync.ts or the class SlidingSync.
*/
export class SlidingSyncSdk {
class SlidingSyncSdk {
// accumulator of sync events in the current sync response
constructor(slidingSync, client, opts, syncOpts) {
_defineProperty(this, "opts", void 0);
_defineProperty(this, "syncOpts", void 0);
_defineProperty(this, "syncState", null);
_defineProperty(this, "syncStateData", void 0);
_defineProperty(this, "lastPos", null);
_defineProperty(this, "failCount", 0);
_defineProperty(this, "notifEvents", []);
this.slidingSync = slidingSync;
this.client = client;
this.opts = defaultClientOpts(opts);
this.syncOpts = defaultSyncApiOpts(syncOpts);
(0, _defineProperty2.default)(this, "opts", void 0);
(0, _defineProperty2.default)(this, "syncOpts", void 0);
(0, _defineProperty2.default)(this, "syncState", null);
(0, _defineProperty2.default)(this, "syncStateData", void 0);
(0, _defineProperty2.default)(this, "lastPos", null);
(0, _defineProperty2.default)(this, "failCount", 0);
(0, _defineProperty2.default)(this, "notifEvents", []);
this.opts = (0, _sync.defaultClientOpts)(opts);
this.syncOpts = (0, _sync.defaultSyncApiOpts)(syncOpts);
if (client.getNotifTimelineSet()) {
client.reEmitter.reEmit(client.getNotifTimelineSet(), [RoomEvent.Timeline, RoomEvent.TimelineReset]);
client.reEmitter.reEmit(client.getNotifTimelineSet(), [_room.RoomEvent.Timeline, _room.RoomEvent.TimelineReset]);
}
this.slidingSync.on(SlidingSyncEvent.Lifecycle, this.onLifecycle.bind(this));
this.slidingSync.on(SlidingSyncEvent.RoomData, this.onRoomData.bind(this));
const extensions = [new ExtensionToDevice(this.client, this.syncOpts.cryptoCallbacks), new ExtensionAccountData(this.client), new ExtensionTyping(this.client), new ExtensionReceipts(this.client), new ExtensionStickyEvents(this.client)];
if (this.syncOpts.cryptoCallbacks) {
extensions.push(new ExtensionE2EE(this.syncOpts.cryptoCallbacks));
this.slidingSync.on(_slidingSync.SlidingSyncEvent.Lifecycle, this.onLifecycle.bind(this));
this.slidingSync.on(_slidingSync.SlidingSyncEvent.RoomData, this.onRoomData.bind(this));
const extensions = [new ExtensionToDevice(this.client, this.syncOpts.cryptoCallbacks), new ExtensionAccountData(this.client), new ExtensionTyping(this.client), new ExtensionReceipts(this.client)];
if (this.syncOpts.crypto) {
extensions.push(new ExtensionE2EE(this.syncOpts.crypto));
}
extensions.forEach(ext => {
this.slidingSync.registerExtension(ext);
@@ -297,26 +280,26 @@ export class SlidingSyncSdk {
let room = this.client.store.getRoom(roomId);
if (!room) {
if (!roomData.initial) {
this.syncOpts.logger.debug("initial flag not set but no stored room exists for room ", roomId, roomData);
_logger.logger.debug("initial flag not set but no stored room exists for room ", roomId, roomData);
return;
}
room = _createAndReEmitRoom(this.client, roomId, this.opts);
room = (0, _sync._createAndReEmitRoom)(this.client, roomId, this.opts);
}
await this.processRoomData(this.client, room, roomData);
}
onLifecycle(state, resp, err) {
if (err) {
this.syncOpts.logger.debug("onLifecycle", state, err);
_logger.logger.debug("onLifecycle", state, err);
}
switch (state) {
case SlidingSyncState.Complete:
case _slidingSync.SlidingSyncState.Complete:
this.purgeNotifications();
if (!resp) {
break;
}
// Element won't stop showing the initial loading spinner unless we fire SyncState.Prepared
if (!this.lastPos) {
this.updateSyncState(SyncState.Prepared, {
this.updateSyncState(_sync.SyncState.Prepared, {
oldSyncToken: undefined,
nextSyncToken: resp.pos,
catchingUp: false,
@@ -325,7 +308,7 @@ export class SlidingSyncSdk {
}
// Conversely, Element won't show the room list unless there is at least 1x SyncState.Syncing
// so hence for the very first sync we will fire prepared then immediately syncing.
this.updateSyncState(SyncState.Syncing, {
this.updateSyncState(_sync.SyncState.Syncing, {
oldSyncToken: this.lastPos,
nextSyncToken: resp.pos,
catchingUp: false,
@@ -333,18 +316,17 @@ export class SlidingSyncSdk {
});
this.lastPos = resp.pos;
break;
case SlidingSyncState.RequestFinished:
case _slidingSync.SlidingSyncState.RequestFinished:
if (err) {
this.failCount += 1;
this.updateSyncState(this.failCount > FAILED_SYNC_ERROR_THRESHOLD ? SyncState.Error : SyncState.Reconnecting, {
error: new MatrixError(err)
this.updateSyncState(this.failCount > FAILED_SYNC_ERROR_THRESHOLD ? _sync.SyncState.Error : _sync.SyncState.Reconnecting, {
error: new _httpApi.MatrixError(err)
});
if (this.shouldAbortSync(new MatrixError(err))) {
if (this.shouldAbortSync(new _httpApi.MatrixError(err))) {
return; // shouldAbortSync actually stops syncing too so we don't need to do anything.
}
} else {
this.failCount = 0;
this.syncOpts.logger.debug(`SlidingSyncState.RequestFinished with ${Object.keys(resp?.rooms || []).length} rooms`);
}
break;
}
@@ -365,7 +347,7 @@ export class SlidingSyncSdk {
* @returns A promise which resolves once the room has been added to the
* store.
*/
async peek(roomId) {
async peek(_roomId) {
return null; // TODO
}
@@ -401,7 +383,8 @@ export class SlidingSyncSdk {
* this object.
*/
getSyncStateData() {
return this.syncStateData ?? null;
var _this$syncStateData;
return (_this$syncStateData = this.syncStateData) !== null && _this$syncStateData !== void 0 ? _this$syncStateData : null;
}
// Helper functions which set up JS SDK structs are below and are identical to the sync v2 counterparts
@@ -411,12 +394,12 @@ export class SlidingSyncSdk {
const {
timelineSupport
} = this.client;
const room = new Room(roomId, this.client, this.client.getUserId(), {
const room = new _room.Room(roomId, this.client, this.client.getUserId(), {
lazyLoadMembers: this.opts.lazyLoadMembers,
pendingEventOrdering: this.opts.pendingEventOrdering,
timelineSupport
});
this.client.reEmitter.reEmit(room, [RoomEvent.Name, RoomEvent.Redaction, RoomEvent.RedactionCancelled, RoomEvent.Receipt, RoomEvent.Tags, RoomEvent.LocalEchoUpdated, RoomEvent.AccountData, RoomEvent.MyMembership, RoomEvent.Timeline, RoomEvent.TimelineReset]);
this.client.reEmitter.reEmit(room, [_room.RoomEvent.Name, _room.RoomEvent.Redaction, _room.RoomEvent.RedactionCancelled, _room.RoomEvent.Receipt, _room.RoomEvent.Tags, _room.RoomEvent.LocalEchoUpdated, _room.RoomEvent.AccountData, _room.RoomEvent.MyMembership, _room.RoomEvent.Timeline, _room.RoomEvent.TimelineReset]);
this.registerStateListeners(room);
return room;
}
@@ -425,10 +408,11 @@ export class SlidingSyncSdk {
// we need to also re-emit room state and room member events, so hook it up
// to the client now. We need to add a listener for RoomState.members in
// order to hook them correctly.
this.client.reEmitter.reEmit(room.currentState, [RoomStateEvent.Events, RoomStateEvent.Members, RoomStateEvent.NewMember, RoomStateEvent.Update]);
room.currentState.on(RoomStateEvent.NewMember, (event, state, member) => {
member.user = this.client.getUser(member.userId) ?? undefined;
this.client.reEmitter.reEmit(member, [RoomMemberEvent.Name, RoomMemberEvent.Typing, RoomMemberEvent.PowerLevel, RoomMemberEvent.Membership]);
this.client.reEmitter.reEmit(room.currentState, [_roomState.RoomStateEvent.Events, _roomState.RoomStateEvent.Members, _roomState.RoomStateEvent.NewMember, _roomState.RoomStateEvent.Update]);
room.currentState.on(_roomState.RoomStateEvent.NewMember, (event, state, member) => {
var _this$client$getUser;
member.user = (_this$client$getUser = this.client.getUser(member.userId)) !== null && _this$client$getUser !== void 0 ? _this$client$getUser : undefined;
this.client.reEmitter.reEmit(member, [_roomMember.RoomMemberEvent.Name, _roomMember.RoomMemberEvent.Typing, _roomMember.RoomMemberEvent.PowerLevel, _roomMember.RoomMemberEvent.Membership]);
});
}
@@ -443,9 +427,9 @@ export class SlidingSyncSdk {
shouldAbortSync(error) {
if (error.errcode === "M_UNKNOWN_TOKEN") {
// The logout already happened, we just need to stop.
this.syncOpts.logger.warn("Token no longer valid - assuming logout");
_logger.logger.warn("Token no longer valid - assuming logout");
this.stop();
this.updateSyncState(SyncState.Error, {
this.updateSyncState(_sync.SyncState.Error, {
error
});
return true;
@@ -464,7 +448,7 @@ export class SlidingSyncSdk {
// TODO: handle threaded / beacon events
if (roomData.limited || roomData.initial) {
if (roomData.initial) {
// we should not know about any of these timeline entries if this is a genuinely new room.
// If we do, then we've effectively done scrollback (e.g requesting timeline_limit: 1 for
// this room, then timeline_limit: 50).
@@ -489,6 +473,7 @@ export class SlidingSyncSdk {
seenKnownEvent = true;
continue; // don't include this event, it's a dupe
}
if (seenKnownEvent) {
// old -> new
oldEvents.push(recvEvent);
@@ -500,26 +485,23 @@ export class SlidingSyncSdk {
timelineEvents = newEvents;
if (oldEvents.length > 0) {
// old events are scrollback, insert them now
room.addEventsToTimeline(oldEvents, true, false, room.getLiveTimeline(), roomData.prev_batch);
room.addEventsToTimeline(oldEvents, true, room.getLiveTimeline(), roomData.prev_batch);
}
}
const encrypted = room.hasEncryptionStateEvent();
const encrypted = this.client.isRoomEncrypted(room.roomId);
// we do this first so it's correct when any of the events fire
if (roomData.notification_count != null) {
room.setUnreadNotificationCount(NotificationCountType.Total, roomData.notification_count);
room.setUnreadNotificationCount(_room.NotificationCountType.Total, roomData.notification_count);
}
if (roomData.highlight_count != null) {
// We track unread notifications ourselves in encrypted rooms, so don't
// bother setting it here. We trust our calculations better than the
// server's for this case, and therefore will assume that our non-zero
// count is accurate.
if (!encrypted || encrypted && room.getUnreadNotificationCount(NotificationCountType.Highlight) <= 0) {
room.setUnreadNotificationCount(NotificationCountType.Highlight, roomData.highlight_count);
if (!encrypted || encrypted && room.getUnreadNotificationCount(_room.NotificationCountType.Highlight) <= 0) {
room.setUnreadNotificationCount(_room.NotificationCountType.Highlight, roomData.highlight_count);
}
}
if (roomData.bump_stamp) {
room.setBumpStamp(roomData.bump_stamp);
}
if (Number.isInteger(roomData.invited_count)) {
room.currentState.setInvitedMemberCount(roomData.invited_count);
}
@@ -532,17 +514,19 @@ export class SlidingSyncSdk {
if (roomData.initial) {
room.recalculate();
this.client.store.storeRoom(room);
this.client.emit(ClientEvent.Room, room);
this.client.emit(_client.ClientEvent.Room, room);
}
inviteStateEvents.forEach(e => {
this.client.emit(ClientEvent.Event, e);
this.client.emit(_client.ClientEvent.Event, e);
});
room.updateMyMembership("invite");
return;
}
if (roomData.limited) {
if (roomData.initial) {
var _roomData$prev_batch;
// set the back-pagination token. Do this *before* adding any
// events so that clients can start back-paginating.
room.getLiveTimeline().setPaginationToken(roomData.prev_batch ?? null, EventTimeline.BACKWARDS);
room.getLiveTimeline().setPaginationToken((_roomData$prev_batch = roomData.prev_batch) !== null && _roomData$prev_batch !== void 0 ? _roomData$prev_batch : null, _eventTimeline.EventTimeline.BACKWARDS);
}
/* TODO
@@ -563,7 +547,7 @@ export class SlidingSyncSdk {
for (let i = timelineEvents.length - 1; i >= 0; i--) {
const eventId = timelineEvents[i].getId();
if (room.getTimelineForEvent(eventId)) {
this.syncOpts.logger.debug("Already have event " + eventId + " in limited " +
logger.debug("Already have event " + eventId + " in limited " +
"sync - not resetting");
limited = false;
// we might still be missing some of the events before i;
@@ -599,31 +583,26 @@ export class SlidingSyncSdk {
// local fields must be set before any async calls because call site assumes
// synchronous execution prior to emitting SlidingSyncState.Complete
room.updateMyMembership(KnownMembership.Join);
room.setMSC4186SummaryData(roomData.heroes, roomData.joined_count, roomData.invited_count);
// The MSC4480 extension excludes sticky events already present in the timeline, so we have
// to pick those up here. See ExtensionStickyEvents for the rest.
room._unstable_addStickyEvents(timelineEvents.filter(e => e.unstableStickyInfo !== undefined));
room.updateMyMembership("join");
room.recalculate();
if (roomData.initial) {
client.store.storeRoom(room);
client.emit(ClientEvent.Room, room);
client.emit(_client.ClientEvent.Room, room);
}
// check if any timeline events should bing and add them to the notifEvents array:
// we'll purge this once we've fully processed the sync response
this.addNotifications(timelineEvents);
const processRoomEvent = async e => {
client.emit(ClientEvent.Event, e);
if (e.isState() && e.getType() == EventType.RoomEncryption && this.syncOpts.cryptoCallbacks) {
client.emit(_client.ClientEvent.Event, e);
if (e.isState() && e.getType() == _event.EventType.RoomEncryption && this.syncOpts.cryptoCallbacks) {
await this.syncOpts.cryptoCallbacks.onCryptoEvent(room, e);
}
};
await promiseMapSeries(stateEvents, processRoomEvent);
await promiseMapSeries(timelineEvents, processRoomEvent);
await (0, _utils.promiseMapSeries)(stateEvents, processRoomEvent);
await (0, _utils.promiseMapSeries)(timelineEvents, processRoomEvent);
ephemeralEvents.forEach(function (e) {
client.emit(ClientEvent.Event, e);
client.emit(_client.ClientEvent.Event, e);
});
// Decrypt only the last message in all rooms to make sure we can generate a preview
@@ -635,13 +614,17 @@ export class SlidingSyncSdk {
/**
* Injects events into a room's model.
* @param stateEventList - A list of state events. This is the state
* at the *END* of the timeline list if it is supplied.
* at the *START* of the timeline list if it is supplied.
* @param timelineEventList - A list of timeline events. Lower index
* is earlier in time. Higher index is later.
* @param numLive - the number of events in timelineEventList which just happened,
* supplied from the server.
*/
async injectRoomEvents(room, stateEventList, timelineEventList = [], numLive = 0) {
async injectRoomEvents(room, stateEventList, timelineEventList, numLive) {
timelineEventList = timelineEventList || [];
stateEventList = stateEventList || [];
numLive = numLive || 0;
// If there are no events in the timeline yet, initialise it with
// the given state events
const liveTimeline = room.getLiveTimeline();
@@ -692,17 +675,16 @@ export class SlidingSyncSdk {
timelineEventList = timelineEventList.slice(0, -1 * liveTimelineEvents.length);
}
// Execute the timeline events.
// execute the timeline events. This will continue to diverge the current state
// if the timeline has any state events in it.
// This also needs to be done before running push rules on the events as they need
// to be decorated with sender etc.
await room.addLiveEvents(timelineEventList, {
fromCache: true,
addToState: false
fromCache: true
});
if (liveTimelineEvents.length > 0) {
await room.addLiveEvents(liveTimelineEvents, {
fromCache: false,
addToState: false
fromCache: false
});
}
room.recalculate();
@@ -717,7 +699,7 @@ export class SlidingSyncSdk {
const client = this.client;
// For each invited room member we want to give them a displayname/avatar url
// if they have one (the m.room.member invites don't contain this).
room.getMembersWithMembership(KnownMembership.Invite).forEach(function (member) {
room.getMembersWithMembership("invite").forEach(function (member) {
if (member.requestedProfileInfo) return;
member.requestedProfileInfo = true;
// try to get a cached copy first.
@@ -736,7 +718,7 @@ export class SlidingSyncSdk {
// the code paths remain the same between invite/join display name stuff
// which is a worthy trade-off for some minor pollution.
const inviteEvent = member.events.member;
if (inviteEvent.getContent().membership !== KnownMembership.Invite) {
if (inviteEvent.getContent().membership !== "invite") {
// between resolving and now they have since joined, so don't clobber
return;
}
@@ -757,19 +739,19 @@ export class SlidingSyncSdk {
* Main entry point. Blocks until stop() is called.
*/
async sync() {
this.syncOpts.logger.debug("Sliding sync init loop");
_logger.logger.debug("Sliding sync init loop");
// 1) We need to get push rules so we can check if events should bing as we get
// them from /sync.
while (!this.client.isGuest()) {
try {
this.syncOpts.logger.debug("Getting push rules...");
_logger.logger.debug("Getting push rules...");
const result = await this.client.getPushRules();
this.syncOpts.logger.debug("Got push rules");
_logger.logger.debug("Got push rules");
this.client.pushRules = result;
break;
} catch (err) {
this.syncOpts.logger.error("Getting push rules failed", err);
_logger.logger.error("Getting push rules failed", err);
if (this.shouldAbortSync(err)) {
return;
}
@@ -784,7 +766,7 @@ export class SlidingSyncSdk {
* Stops the sync object from syncing.
*/
stop() {
this.syncOpts.logger.debug("SyncApi.stop");
_logger.logger.debug("SyncApi.stop");
this.slidingSync.stop();
}
@@ -797,7 +779,7 @@ export class SlidingSyncSdk {
const old = this.syncState;
this.syncState = newState;
this.syncStateData = data;
this.client.emit(ClientEvent.Sync, this.syncState, old, data);
this.client.emit(_client.ClientEvent.Sync, this.syncState, old, data);
}
/**
@@ -833,13 +815,13 @@ export class SlidingSyncSdk {
return a.getTs() - b.getTs();
});
this.notifEvents.forEach(event => {
this.client.getNotifTimelineSet()?.addLiveEvent(event, {
addToState: false
});
var _this$client$getNotif;
(_this$client$getNotif = this.client.getNotifTimelineSet()) === null || _this$client$getNotif === void 0 ? void 0 : _this$client$getNotif.addLiveEvent(event);
});
this.notifEvents = [];
}
}
exports.SlidingSyncSdk = SlidingSyncSdk;
function ensureNameEvent(client, roomId, roomData) {
// make sure m.room.name is in required_state if there is a name, replacing anything previously
// there if need be. This ensures clients transparently 'calculate' the right room name. Native
@@ -848,7 +830,7 @@ function ensureNameEvent(client, roomId, roomData) {
return roomData;
}
for (const stateEvent of roomData.required_state) {
if (stateEvent.type === EventType.RoomName && stateEvent.state_key === "") {
if (stateEvent.type === _event.EventType.RoomName && stateEvent.state_key === "") {
stateEvent.content = {
name: roomData.name
};
@@ -858,7 +840,7 @@ function ensureNameEvent(client, roomId, roomData) {
roomData.required_state.push({
event_id: "$fake-sliding-sync-name-event-" + roomId,
state_key: "",
type: EventType.RoomName,
type: _event.EventType.RoomName,
content: {
name: roomData.name
},
@@ -882,12 +864,12 @@ function processEphemeralEvents(client, roomId, ephEvents) {
const ephemeralEvents = mapEvents(client, roomId, ephEvents);
const room = client.getRoom(roomId);
if (!room) {
logger.warn("got ephemeral events for room but room doesn't exist on client:", roomId);
_logger.logger.warn("got ephemeral events for room but room doesn't exist on client:", roomId);
return;
}
room.addEphemeralEvents(ephemeralEvents);
ephemeralEvents.forEach(e => {
client.emit(ClientEvent.Event, e);
client.emit(_client.ClientEvent.Event, e);
});
}
//# sourceMappingURL=sliding-sync-sdk.js.map