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,16 @@
import _defineProperty from "@babel/runtime/helpers/defineProperty";
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.EventTimelineSet = exports.DuplicateStrategy = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _eventTimeline = require("./event-timeline");
var _logger = require("../logger");
var _room = require("./room");
var _typedEventEmitter = require("./typed-event-emitter");
var _relationsContainer = require("./relations-container");
/*
Copyright 2016 - 2021 The Matrix.org Foundation C.I.C.
@@ -15,28 +27,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { EventTimeline } from "./event-timeline.js";
import { logger } from "../logger.js";
import { RoomEvent } from "./room.js";
import { TypedEventEmitter } from "./typed-event-emitter.js";
import { RelationsContainer } from "./relations-container.js";
const DEBUG = true;
/* istanbul ignore next */
let debuglog;
if (DEBUG) {
// using bind means that we get to keep useful line numbers in the console
debuglog = logger.log.bind(logger);
debuglog = _logger.logger.log.bind(_logger.logger);
} else {
/* istanbul ignore next */
debuglog = function () {};
}
export let DuplicateStrategy = /*#__PURE__*/function (DuplicateStrategy) {
let DuplicateStrategy = /*#__PURE__*/function (DuplicateStrategy) {
DuplicateStrategy["Ignore"] = "ignore";
DuplicateStrategy["Replace"] = "replace";
return DuplicateStrategy;
}({});
export class EventTimelineSet extends TypedEventEmitter {
exports.DuplicateStrategy = DuplicateStrategy;
class EventTimelineSet extends _typedEventEmitter.TypedEventEmitter {
/**
* Construct a set of EventTimeline objects, typically on behalf of a given
* room. A room may have multiple EventTimelineSets for different levels
@@ -64,30 +72,31 @@ export class EventTimelineSet extends TypedEventEmitter {
* @param client - the Matrix client which owns this EventTimelineSet,
* can be omitted if room is specified.
* @param thread - the thread to which this timeline set relates.
* @param threadListType - the type of thread list represented, if any
* @param isThreadTimeline - Whether this timeline set relates to a thread list timeline
* (e.g., All threads or My threads)
*/
constructor(room, opts = {}, client, thread, threadListType = null) {
var _this$room$relations, _this$room, _room$client;
super();
_defineProperty(this, "relations", void 0);
_defineProperty(this, "timelineSupport", void 0);
_defineProperty(this, "displayPendingEvents", void 0);
_defineProperty(this, "liveTimeline", void 0);
_defineProperty(this, "timelines", void 0);
_defineProperty(this, "_eventIdToTimeline", new Map());
_defineProperty(this, "filter", void 0);
this.room = room;
this.thread = thread;
this.threadListType = threadListType;
(0, _defineProperty2.default)(this, "relations", void 0);
(0, _defineProperty2.default)(this, "timelineSupport", void 0);
(0, _defineProperty2.default)(this, "displayPendingEvents", void 0);
(0, _defineProperty2.default)(this, "liveTimeline", void 0);
(0, _defineProperty2.default)(this, "timelines", void 0);
(0, _defineProperty2.default)(this, "_eventIdToTimeline", new Map());
(0, _defineProperty2.default)(this, "filter", void 0);
this.timelineSupport = Boolean(opts.timelineSupport);
this.liveTimeline = new EventTimeline(this);
this.liveTimeline = new _eventTimeline.EventTimeline(this);
this.displayPendingEvents = opts.pendingEvents !== false;
// just a list - *not* ordered.
this.timelines = [this.liveTimeline];
this._eventIdToTimeline = new Map();
this.filter = opts.filter;
this.relations = this.room?.relations ?? new RelationsContainer(room?.client ?? client);
this.relations = (_this$room$relations = (_this$room = this.room) === null || _this$room === void 0 ? void 0 : _this$room.relations) !== null && _this$room$relations !== void 0 ? _this$room$relations : new _relationsContainer.RelationsContainer((_room$client = room === null || room === void 0 ? void 0 : room.client) !== null && _room$client !== void 0 ? _room$client : client);
}
/**
@@ -195,7 +204,7 @@ export class EventTimelineSet extends TypedEventEmitter {
// if timeline support is disabled, forget about the old timelines
const resetAllTimelines = !this.timelineSupport || !forwardPaginationToken;
const oldTimeline = this.liveTimeline;
const newTimeline = resetAllTimelines ? oldTimeline.forkLive(EventTimeline.FORWARDS) : oldTimeline.fork(EventTimeline.FORWARDS);
const newTimeline = resetAllTimelines ? oldTimeline.forkLive(_eventTimeline.EventTimeline.FORWARDS) : oldTimeline.fork(_eventTimeline.EventTimeline.FORWARDS);
if (resetAllTimelines) {
this.timelines = [newTimeline];
this._eventIdToTimeline = new Map();
@@ -205,17 +214,17 @@ export class EventTimelineSet extends TypedEventEmitter {
if (forwardPaginationToken) {
// Now set the forward pagination token on the old live timeline
// so it can be forward-paginated.
oldTimeline.setPaginationToken(forwardPaginationToken, EventTimeline.FORWARDS);
oldTimeline.setPaginationToken(forwardPaginationToken, _eventTimeline.EventTimeline.FORWARDS);
}
// make sure we set the pagination token before firing timelineReset,
// otherwise clients which start back-paginating will fail, and then get
// stuck without realising that they *can* back-paginate.
newTimeline.setPaginationToken(backPaginationToken ?? null, EventTimeline.BACKWARDS);
newTimeline.setPaginationToken(backPaginationToken !== null && backPaginationToken !== void 0 ? backPaginationToken : null, _eventTimeline.EventTimeline.BACKWARDS);
// Now we can swap the live timeline to the new one.
this.liveTimeline = newTimeline;
this.emit(RoomEvent.TimelineReset, this.room, this, resetAllTimelines);
this.emit(_room.RoomEvent.TimelineReset, this.room, this, resetAllTimelines);
}
/**
@@ -258,7 +267,7 @@ export class EventTimelineSet extends TypedEventEmitter {
if (!this.timelineSupport) {
throw new Error("timeline support is disabled. Set the 'timelineSupport'" + " parameter to true when creating MatrixClient to enable" + " it.");
}
const timeline = new EventTimeline(this);
const timeline = new _eventTimeline.EventTimeline(this);
this.timelines.push(timeline);
return timeline;
}
@@ -283,7 +292,7 @@ export class EventTimelineSet extends TypedEventEmitter {
* Fires {@link RoomEvent.Timeline}
*
*/
addEventsToTimeline(events, toStartOfTimeline, addToState, timeline, paginationToken) {
addEventsToTimeline(events, toStartOfTimeline, timeline, paginationToken) {
if (!timeline) {
throw new Error("'timeline' not specified for EventTimelineSet.addEventsToTimeline");
}
@@ -296,8 +305,8 @@ export class EventTimelineSet extends TypedEventEmitter {
return;
}
}
const direction = toStartOfTimeline ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS;
const inverseDirection = toStartOfTimeline ? EventTimeline.FORWARDS : EventTimeline.BACKWARDS;
const direction = toStartOfTimeline ? _eventTimeline.EventTimeline.BACKWARDS : _eventTimeline.EventTimeline.FORWARDS;
const inverseDirection = toStartOfTimeline ? _eventTimeline.EventTimeline.FORWARDS : _eventTimeline.EventTimeline.BACKWARDS;
// Adding events to timelines can be quite complicated. The following
// illustrates some of the corner-cases.
@@ -376,8 +385,7 @@ export class EventTimelineSet extends TypedEventEmitter {
if (!existingTimeline) {
// we don't know about this event yet. Just add it to the timeline.
this.addEventToTimeline(event, timeline, {
toStartOfTimeline,
addToState
toStartOfTimeline
});
lastEventWasNew = true;
didUpdate = true;
@@ -400,33 +408,34 @@ export class EventTimelineSet extends TypedEventEmitter {
// that would happen, so I'm going to ignore it for now.
//
if (existingTimeline == neighbour) {
debuglog("Event " + eventId + " in neighbouring timeline - switching to " + existingTimeline);
debuglog("Event " + eventId + " in neighbouring timeline - " + "switching to " + existingTimeline);
} else {
debuglog("Event " + eventId + " already in a different timeline " + existingTimeline);
debuglog("Event " + eventId + " already in a different " + "timeline " + existingTimeline);
}
timeline = existingTimeline;
continue;
}
// time to join the timelines.
logger.info("Already have timeline for " + eventId + " - joining timeline " + timeline + " to " + existingTimeline);
_logger.logger.info("Already have timeline for " + eventId + " - joining timeline " + timeline + " to " + existingTimeline);
// Variables to keep the line length limited below.
const existingIsLive = existingTimeline === this.liveTimeline;
const timelineIsLive = timeline === this.liveTimeline;
const backwardsIsLive = direction === EventTimeline.BACKWARDS && existingIsLive;
const forwardsIsLive = direction === EventTimeline.FORWARDS && timelineIsLive;
const backwardsIsLive = direction === _eventTimeline.EventTimeline.BACKWARDS && existingIsLive;
const forwardsIsLive = direction === _eventTimeline.EventTimeline.FORWARDS && timelineIsLive;
if (backwardsIsLive || forwardsIsLive) {
// The live timeline should never be spliced into a non-live position.
// We use independent logging to better discover the problem at a glance.
if (backwardsIsLive) {
logger.warn("Refusing to set a preceding existingTimeLine on our " + "timeline as the existingTimeLine is live (" + existingTimeline + ")");
_logger.logger.warn("Refusing to set a preceding existingTimeLine on our " + "timeline as the existingTimeLine is live (" + existingTimeline + ")");
}
if (forwardsIsLive) {
logger.warn("Refusing to set our preceding timeline on a existingTimeLine " + "as our timeline is live (" + timeline + ")");
_logger.logger.warn("Refusing to set our preceding timeline on a existingTimeLine " + "as our timeline is live (" + timeline + ")");
}
continue; // abort splicing - try next event
}
timeline.setNeighbouringTimeline(existingTimeline, direction);
existingTimeline.setNeighbouringTimeline(timeline, inverseDirection);
timeline = existingTimeline;
@@ -437,15 +446,15 @@ export class EventTimelineSet extends TypedEventEmitter {
// new information, we update the pagination token for whatever
// timeline we ended up on.
if (lastEventWasNew || !didUpdate) {
if (direction === EventTimeline.FORWARDS && timeline === this.liveTimeline) {
logger.warn({
if (direction === _eventTimeline.EventTimeline.FORWARDS && timeline === this.liveTimeline) {
_logger.logger.warn({
lastEventWasNew,
didUpdate
}); // for debugging
logger.warn(`Refusing to set forwards pagination token of live timeline ${timeline} to ${paginationToken}`);
_logger.logger.warn(`Refusing to set forwards pagination token of live timeline ` + `${timeline} to ${paginationToken}`);
return;
}
timeline.setPaginationToken(paginationToken ?? null, direction);
timeline.setPaginationToken(paginationToken !== null && paginationToken !== void 0 ? paginationToken : null, direction);
}
}
@@ -455,13 +464,26 @@ export class EventTimelineSet extends TypedEventEmitter {
* @param event - Event to be added
* @param options - addLiveEvent options
*/
addLiveEvent(event, {
duplicateStrategy,
fromCache,
roomState,
timelineWasEmpty,
addToState
}) {
/**
* @deprecated In favor of the overload with `IAddLiveEventOptions`
*/
addLiveEvent(event, duplicateStrategyOrOpts, fromCache = false, roomState) {
let duplicateStrategy = duplicateStrategyOrOpts || DuplicateStrategy.Ignore;
let timelineWasEmpty;
if (typeof duplicateStrategyOrOpts === "object") {
({
duplicateStrategy = DuplicateStrategy.Ignore,
fromCache = false,
roomState,
timelineWasEmpty
} = duplicateStrategyOrOpts);
} else if (duplicateStrategyOrOpts !== undefined) {
// Deprecation warning
// FIXME: Remove after 2023-06-01 (technical debt)
_logger.logger.warn("Overload deprecated: " + "`EventTimelineSet.addLiveEvent(event, duplicateStrategy?, fromCache?, roomState?)` " + "is deprecated in favor of the overload with " + "`EventTimelineSet.addLiveEvent(event, IAddLiveEventOptions)`");
}
if (this.filter) {
const events = this.filter.filterRoomTimeline([event]);
if (!events.length) {
@@ -477,9 +499,9 @@ export class EventTimelineSet extends TypedEventEmitter {
if (tlEvents[j].getId() === event.getId()) {
// still need to set the right metadata on this event
if (!roomState) {
roomState = timeline.getState(EventTimeline.FORWARDS);
roomState = timeline.getState(_eventTimeline.EventTimeline.FORWARDS);
}
EventTimeline.setEventMetadata(event, roomState, false);
_eventTimeline.EventTimeline.setEventMetadata(event, roomState, false);
tlEvents[j] = event;
// XXX: we need to fire an event when this happens.
@@ -495,8 +517,7 @@ export class EventTimelineSet extends TypedEventEmitter {
toStartOfTimeline: false,
fromCache,
roomState,
timelineWasEmpty,
addToState
timelineWasEmpty
});
}
@@ -506,23 +527,35 @@ export class EventTimelineSet extends TypedEventEmitter {
*
* Will fire "Room.timeline" for each event added.
*
* @param event - the event to add
* @param timeline - the timeline onto which to add it
* @param options - addEventToTimeline options
*
* @remarks
* Fires {@link RoomEvent.Timeline}
*/
addEventToTimeline(event, timeline, {
toStartOfTimeline,
fromCache = false,
roomState,
timelineWasEmpty,
addToState
}) {
/**
* @deprecated In favor of the overload with `IAddEventToTimelineOptions`
*/
addEventToTimeline(event, timeline, toStartOfTimelineOrOpts, fromCache = false, roomState) {
let toStartOfTimeline = !!toStartOfTimelineOrOpts;
let timelineWasEmpty;
if (typeof toStartOfTimelineOrOpts === "object") {
({
toStartOfTimeline,
fromCache = false,
roomState,
timelineWasEmpty
} = toStartOfTimelineOrOpts);
} else if (toStartOfTimelineOrOpts !== undefined) {
// Deprecation warning
// FIXME: Remove after 2023-06-01 (technical debt)
_logger.logger.warn("Overload deprecated: " + "`EventTimelineSet.addEventToTimeline(event, timeline, toStartOfTimeline, fromCache?, roomState?)` " + "is deprecated in favor of the overload with " + "`EventTimelineSet.addEventToTimeline(event, timeline, IAddEventToTimelineOptions)`");
}
if (timeline.getTimelineSet() !== this) {
var _this$thread;
throw new Error(`EventTimelineSet.addEventToTimeline: Timeline=${timeline.toString()} does not belong " +
"in timelineSet(threadId=${this.thread?.id})`);
"in timelineSet(threadId=${(_this$thread = this.thread) === null || _this$thread === void 0 ? void 0 : _this$thread.id})`);
}
const eventId = event.getId();
this.relations.aggregateParentEvent(event);
@@ -534,25 +567,25 @@ export class EventTimelineSet extends TypedEventEmitter {
// We can only run this check for timelines with a `room` because `canContain`
// requires it
if (this.room && !this.canContain(event)) {
var _this$thread2;
let eventDebugString = `event=${eventId}`;
if (event.threadRootId) {
eventDebugString += `(belongs to thread=${event.threadRootId})`;
}
logger.warn(`EventTimelineSet.addEventToTimeline: Ignoring ${eventDebugString} that does not belong ` + `in timeline=${timeline.toString()} timelineSet(threadId=${this.thread?.id})`);
_logger.logger.warn(`EventTimelineSet.addEventToTimeline: Ignoring ${eventDebugString} that does not belong ` + `in timeline=${timeline.toString()} timelineSet(threadId=${(_this$thread2 = this.thread) === null || _this$thread2 === void 0 ? void 0 : _this$thread2.id})`);
return;
}
timeline.addEvent(event, {
toStartOfTimeline,
roomState,
timelineWasEmpty,
addToState
timelineWasEmpty
});
this._eventIdToTimeline.set(eventId, timeline);
const data = {
timeline: timeline,
liveEvent: !toStartOfTimeline && timeline == this.liveTimeline && !fromCache
};
this.emit(RoomEvent.Timeline, event, this.room, Boolean(toStartOfTimeline), false, data);
this.emit(_room.RoomEvent.Timeline, event, this.room, Boolean(toStartOfTimeline), false, data);
}
/**
@@ -570,13 +603,16 @@ export class EventTimelineSet extends TypedEventEmitter {
*
* @internal
*
* @param options - addEventToTimeline options
*
* @remarks
* Fires {@link RoomEvent.Timeline}
*/
insertEventIntoTimeline(event, timeline, roomState, addToState) {
insertEventIntoTimeline(event, timeline, roomState) {
if (timeline.getTimelineSet() !== this) {
var _this$thread3;
throw new Error(`EventTimelineSet.insertEventIntoTimeline: Timeline=${timeline.toString()} does not belong " +
"in timelineSet(threadId=${this.thread?.id})`);
"in timelineSet(threadId=${(_this$thread3 = this.thread) === null || _this$thread3 === void 0 ? void 0 : _this$thread3.id})`);
}
const eventId = event.getId();
this.relations.aggregateParentEvent(event);
@@ -588,11 +624,12 @@ export class EventTimelineSet extends TypedEventEmitter {
// We can only run this check for timelines with a `room` because `canContain`
// requires it
if (this.room && !this.canContain(event)) {
var _this$thread4;
let eventDebugString = `event=${eventId}`;
if (event.threadRootId) {
eventDebugString += `(belongs to thread=${event.threadRootId})`;
}
logger.warn(`EventTimelineSet.insertEventIntoTimeline: Ignoring ${eventDebugString} that does not belong ` + `in timeline=${timeline.toString()} timelineSet(threadId=${this.thread?.id})`);
_logger.logger.warn(`EventTimelineSet.insertEventIntoTimeline: Ignoring ${eventDebugString} that does not belong ` + `in timeline=${timeline.toString()} timelineSet(threadId=${(_this$thread4 = this.thread) === null || _this$thread4 === void 0 ? void 0 : _this$thread4.id})`);
return;
}
@@ -604,8 +641,7 @@ export class EventTimelineSet extends TypedEventEmitter {
toStartOfTimeline: false,
fromCache: false,
timelineWasEmpty: false,
roomState,
addToState
roomState
});
return;
}
@@ -626,16 +662,13 @@ export class EventTimelineSet extends TypedEventEmitter {
// If we got to the end of the loop, insertIndex points at the end of
// the list.
timeline.insertEvent(event, insertIndex, roomState, addToState);
timeline.insertEvent(event, insertIndex, roomState);
this._eventIdToTimeline.set(eventId, timeline);
const data = {
timeline: timeline,
// The purpose of this method is inserting events in the middle of the
// timeline, so the events are, by definition, not live (whether or not
// we're adding them to the live timeline).
liveEvent: false
liveEvent: timeline == this.liveTimeline
};
this.emit(RoomEvent.Timeline, event, this.room, false, false, data);
this.emit(_room.RoomEvent.Timeline, event, this.room, false, false, data);
}
/**
@@ -657,8 +690,7 @@ export class EventTimelineSet extends TypedEventEmitter {
this._eventIdToTimeline.set(newEventId, existingTimeline);
} else if (!this.filter || this.filter.filterRoomTimeline([localEvent]).length) {
this.addEventToTimeline(localEvent, this.liveTimeline, {
toStartOfTimeline: false,
addToState: false
toStartOfTimeline: false
});
}
}
@@ -682,7 +714,7 @@ export class EventTimelineSet extends TypedEventEmitter {
const data = {
timeline: timeline
};
this.emit(RoomEvent.Timeline, removed, this.room, undefined, true, data);
this.emit(_room.RoomEvent.Timeline, removed, this.room, undefined, true, data);
}
return removed;
}
@@ -692,10 +724,11 @@ export class EventTimelineSet extends TypedEventEmitter {
*
* @param eventId1 - The id of the first event
* @param eventId2 - The id of the second event
* @returns -1 if eventId1 precedes eventId2, and +1 eventId1 succeeds
* eventId2. 0 if they are the same event; null if we can't tell (either
* because we don't know about one of the events, or because they are in
* separate timelines which don't join up).
* @returns a number less than zero if eventId1 precedes eventId2, and
* greater than zero if eventId1 succeeds eventId2. zero if they are the
* same event; null if we can't tell (either because we don't know about one
* of the events, or because they are in separate timelines which don't join
* up).
*/
compareEventOrdering(eventId1, eventId2) {
if (eventId1 == eventId2) {
@@ -724,16 +757,7 @@ export class EventTimelineSet extends TypedEventEmitter {
idx2 = idx;
}
}
const difference = idx1 - idx2;
// Return the sign of difference.
if (difference < 0) {
return -1;
} else if (difference > 0) {
return 1;
} else {
return 0;
}
return idx1 - idx2;
}
// the events are in different timelines. Iterate through the
@@ -746,7 +770,7 @@ export class EventTimelineSet extends TypedEventEmitter {
// timeline1 is before timeline2
return -1;
}
tl = tl.getNeighbouringTimeline(EventTimeline.FORWARDS);
tl = tl.getNeighbouringTimeline(_eventTimeline.EventTimeline.FORWARDS);
}
// now try backwards from timeline1
@@ -756,7 +780,7 @@ export class EventTimelineSet extends TypedEventEmitter {
// timeline2 is before timeline1
return 1;
}
tl = tl.getNeighbouringTimeline(EventTimeline.BACKWARDS);
tl = tl.getNeighbouringTimeline(_eventTimeline.EventTimeline.BACKWARDS);
}
// the timelines are not contiguous.
@@ -787,9 +811,11 @@ export class EventTimelineSet extends TypedEventEmitter {
return this.thread.id === threadId;
}
if (!shouldLiveInRoom && !shouldLiveInThread) {
logger.warn(`EventTimelineSet:canContain event encountered which cannot be added to any timeline roomId=${this.room?.roomId} eventId=${event.getId()} threadId=${event.threadRootId}`);
var _this$room2;
_logger.logger.warn(`EventTimelineSet:canContain event encountered which cannot be added to any timeline roomId=${(_this$room2 = this.room) === null || _this$room2 === void 0 ? void 0 : _this$room2.roomId} eventId=${event.getId()} threadId=${event.threadRootId}`);
}
return shouldLiveInRoom;
}
}
exports.EventTimelineSet = EventTimelineSet;
//# sourceMappingURL=event-timeline-set.js.map