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,14 @@
import _defineProperty from "@babel/runtime/helpers/defineProperty";
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MediaHandlerEvent = exports.MediaHandler = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _typedEventEmitter = require("../models/typed-event-emitter");
var _groupCall = require("../webrtc/groupCall");
var _logger = require("../logger");
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 New Vector Ltd
@@ -17,26 +27,23 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { TypedEventEmitter } from "../models/typed-event-emitter.js";
import { GroupCallType, GroupCallState } from "../webrtc/groupCall.js";
import { logger } from "../logger.js";
export let MediaHandlerEvent = /*#__PURE__*/function (MediaHandlerEvent) {
let MediaHandlerEvent = /*#__PURE__*/function (MediaHandlerEvent) {
MediaHandlerEvent["LocalStreamsChanged"] = "local_streams_changed";
return MediaHandlerEvent;
}({});
export class MediaHandler extends TypedEventEmitter {
exports.MediaHandlerEvent = MediaHandlerEvent;
class MediaHandler extends _typedEventEmitter.TypedEventEmitter {
constructor(client) {
super();
_defineProperty(this, "audioInput", void 0);
_defineProperty(this, "audioSettings", void 0);
_defineProperty(this, "videoInput", void 0);
_defineProperty(this, "localUserMediaStream", void 0);
_defineProperty(this, "userMediaStreams", []);
_defineProperty(this, "screensharingStreams", []);
// Promise chain to serialise calls to getMediaStream
_defineProperty(this, "getMediaStreamPromise", void 0);
this.client = client;
(0, _defineProperty2.default)(this, "audioInput", void 0);
(0, _defineProperty2.default)(this, "audioSettings", void 0);
(0, _defineProperty2.default)(this, "videoInput", void 0);
(0, _defineProperty2.default)(this, "localUserMediaStream", void 0);
(0, _defineProperty2.default)(this, "userMediaStreams", []);
(0, _defineProperty2.default)(this, "screensharingStreams", []);
// Promise chain to serialise calls to getMediaStream
(0, _defineProperty2.default)(this, "getMediaStreamPromise", void 0);
}
restoreMediaSettings(audioInput, videoInput) {
this.audioInput = audioInput;
@@ -49,7 +56,7 @@ export class MediaHandler extends TypedEventEmitter {
* undefined treated as unset
*/
async setAudioInput(deviceId) {
logger.info(`MediaHandler setAudioInput() running (deviceId=${deviceId})`);
_logger.logger.info(`MediaHandler setAudioInput() running (deviceId=${deviceId})`);
if (this.audioInput === deviceId) return;
this.audioInput = deviceId;
await this.updateLocalUsermediaStreams();
@@ -60,7 +67,7 @@ export class MediaHandler extends TypedEventEmitter {
* @param opts - audio options to set
*/
async setAudioSettings(opts) {
logger.info(`MediaHandler setAudioSettings() running (opts=${JSON.stringify(opts)})`);
_logger.logger.info(`MediaHandler setAudioSettings() running (opts=${JSON.stringify(opts)})`);
this.audioSettings = Object.assign({}, opts);
await this.updateLocalUsermediaStreams();
}
@@ -71,7 +78,7 @@ export class MediaHandler extends TypedEventEmitter {
* undefined treated as unset
*/
async setVideoInput(deviceId) {
logger.info(`MediaHandler setVideoInput() running (deviceId=${deviceId})`);
_logger.logger.info(`MediaHandler setVideoInput() running (deviceId=${deviceId})`);
if (this.videoInput === deviceId) return;
this.videoInput = deviceId;
await this.updateLocalUsermediaStreams();
@@ -84,7 +91,7 @@ export class MediaHandler extends TypedEventEmitter {
* undefined treated as unset
*/
async setMediaInputs(audioInput, videoInput) {
logger.log(`MediaHandler setMediaInputs() running (audioInput: ${audioInput} videoInput: ${videoInput})`);
_logger.logger.log(`MediaHandler setMediaInputs() running (audioInput: ${audioInput} videoInput: ${videoInput})`);
this.audioInput = audioInput;
this.videoInput = videoInput;
await this.updateLocalUsermediaStreams();
@@ -103,7 +110,7 @@ export class MediaHandler extends TypedEventEmitter {
});
}
for (const stream of this.userMediaStreams) {
logger.log(`MediaHandler updateLocalUsermediaStreams() stopping all tracks (streamId=${stream.id})`);
_logger.logger.log(`MediaHandler updateLocalUsermediaStreams() stopping all tracks (streamId=${stream.id})`);
for (const track of stream.getTracks()) {
track.stop();
}
@@ -118,7 +125,7 @@ export class MediaHandler extends TypedEventEmitter {
audio,
video
} = callMediaStreamParams.get(call.callId);
logger.log(`MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (callId=${call.callId})`);
_logger.logger.log(`MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (callId=${call.callId})`);
const stream = await this.getUserMediaStream(audio, video);
if (call.callHasEnded()) {
continue;
@@ -129,9 +136,9 @@ export class MediaHandler extends TypedEventEmitter {
if (!groupCall.localCallFeed) {
continue;
}
logger.log(`MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (groupCallId=${groupCall.groupCallId})`);
const stream = await this.getUserMediaStream(true, groupCall.type === GroupCallType.Video);
if (groupCall.state === GroupCallState.Ended) {
_logger.logger.log(`MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (groupCallId=${groupCall.groupCallId})`);
const stream = await this.getUserMediaStream(true, groupCall.type === _groupCall.GroupCallType.Video);
if (groupCall.state === _groupCall.GroupCallState.Ended) {
continue;
}
await groupCall.updateLocalUsermediaStream(stream);
@@ -143,7 +150,7 @@ export class MediaHandler extends TypedEventEmitter {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === "audioinput").length > 0;
} catch (err) {
logger.log(`MediaHandler hasAudioDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);
_logger.logger.log(`MediaHandler hasAudioDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);
return false;
}
}
@@ -152,7 +159,7 @@ export class MediaHandler extends TypedEventEmitter {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === "videoinput").length > 0;
} catch (err) {
logger.log(`MediaHandler hasVideoDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);
_logger.logger.log(`MediaHandler hasVideoDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);
return false;
}
}
@@ -180,6 +187,7 @@ export class MediaHandler extends TypedEventEmitter {
let stream;
let canReuseStream = true;
if (this.localUserMediaStream) {
var _this$localUserMediaS, _this$localUserMediaS2;
// This figures out if we can reuse the current localUsermediaStream
// based on whether or not the "mute state" (presence of tracks of a
// given kind) matches what is being requested
@@ -193,28 +201,19 @@ export class MediaHandler extends TypedEventEmitter {
// This code checks that the device ID is the same as the localUserMediaStream stream, but we update
// the localUserMediaStream whenever the device ID changes (apart from when restoring) so it's not
// clear why this would ever be different, unless there's a race.
if (shouldRequestAudio && this.localUserMediaStream.getAudioTracks()[0]?.getSettings()?.deviceId !== this.audioInput) {
if (shouldRequestAudio && ((_this$localUserMediaS = this.localUserMediaStream.getAudioTracks()[0]) === null || _this$localUserMediaS === void 0 || (_this$localUserMediaS = _this$localUserMediaS.getSettings()) === null || _this$localUserMediaS === void 0 ? void 0 : _this$localUserMediaS.deviceId) !== this.audioInput) {
canReuseStream = false;
}
if (shouldRequestVideo && this.localUserMediaStream.getVideoTracks()[0]?.getSettings()?.deviceId !== this.videoInput) {
if (shouldRequestVideo && ((_this$localUserMediaS2 = this.localUserMediaStream.getVideoTracks()[0]) === null || _this$localUserMediaS2 === void 0 || (_this$localUserMediaS2 = _this$localUserMediaS2.getSettings()) === null || _this$localUserMediaS2 === void 0 ? void 0 : _this$localUserMediaS2.deviceId) !== this.videoInput) {
canReuseStream = false;
}
} else {
canReuseStream = false;
}
if (!canReuseStream) {
let constraints;
try {
// Not specifying exact for deviceId means switching devices does not always work,
// try with exact and fallback to ideal if it fails
constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo, true);
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (e) {
logger.warn(`MediaHandler getUserMediaStreamInternal() error (e=${e}), retrying without exact deviceId`);
constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo, false);
stream = await navigator.mediaDevices.getUserMedia(constraints);
}
logger.log(`MediaHandler getUserMediaStreamInternal() calling getUserMediaStream (streamId=${stream.id}, shouldRequestAudio=${shouldRequestAudio}, shouldRequestVideo=${shouldRequestVideo}, constraints=${JSON.stringify(constraints)})`);
const constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo);
stream = await navigator.mediaDevices.getUserMedia(constraints);
_logger.logger.log(`MediaHandler getUserMediaStreamInternal() calling getUserMediaStream (streamId=${stream.id}, shouldRequestAudio=${shouldRequestAudio}, shouldRequestVideo=${shouldRequestVideo}, constraints=${JSON.stringify(constraints)})`);
for (const track of stream.getTracks()) {
const settings = track.getSettings();
if (track.kind === "audio") {
@@ -227,8 +226,9 @@ export class MediaHandler extends TypedEventEmitter {
this.localUserMediaStream = stream;
}
} else {
var _this$localUserMediaS3;
stream = this.localUserMediaStream.clone();
logger.log(`MediaHandler getUserMediaStreamInternal() cloning (oldStreamId=${this.localUserMediaStream?.id} newStreamId=${stream.id} shouldRequestAudio=${shouldRequestAudio} shouldRequestVideo=${shouldRequestVideo})`);
_logger.logger.log(`MediaHandler getUserMediaStreamInternal() cloning (oldStreamId=${(_this$localUserMediaS3 = this.localUserMediaStream) === null || _this$localUserMediaS3 === void 0 ? void 0 : _this$localUserMediaS3.id} newStreamId=${stream.id} shouldRequestAudio=${shouldRequestAudio} shouldRequestVideo=${shouldRequestVideo})`);
if (!shouldRequestAudio) {
for (const track of stream.getAudioTracks()) {
stream.removeTrack(track);
@@ -251,13 +251,13 @@ export class MediaHandler extends TypedEventEmitter {
* Stops all tracks on the provided usermedia stream
*/
stopUserMediaStream(mediaStream) {
logger.log(`MediaHandler stopUserMediaStream() stopping (streamId=${mediaStream.id})`);
_logger.logger.log(`MediaHandler stopUserMediaStream() stopping (streamId=${mediaStream.id})`);
for (const track of mediaStream.getTracks()) {
track.stop();
}
const index = this.userMediaStreams.indexOf(mediaStream);
if (index !== -1) {
logger.debug(`MediaHandler stopUserMediaStream() splicing usermedia stream out stream array (streamId=${mediaStream.id})`, mediaStream.id);
_logger.logger.debug(`MediaHandler stopUserMediaStream() splicing usermedia stream out stream array (streamId=${mediaStream.id})`, mediaStream.id);
this.userMediaStreams.splice(index, 1);
}
this.emit(MediaHandlerEvent.LocalStreamsChanged);
@@ -270,7 +270,8 @@ export class MediaHandler extends TypedEventEmitter {
// cached stream too in order to stop all its tracks (in case they are different)
// and un-cache it.
for (const track of mediaStream.getTracks()) {
if (this.localUserMediaStream?.getTrackById(track.id)) {
var _this$localUserMediaS4;
if ((_this$localUserMediaS4 = this.localUserMediaStream) !== null && _this$localUserMediaS4 !== void 0 && _this$localUserMediaS4.getTrackById(track.id)) {
this.stopUserMediaStream(this.localUserMediaStream);
break;
}
@@ -279,7 +280,7 @@ export class MediaHandler extends TypedEventEmitter {
}
/**
* @param opts - screensharing stream options
* @param desktopCapturerSourceId - sourceId for Electron DesktopCapturer
* @param reusable - is allowed to be reused by the MediaHandler
* @returns based on passed parameters
*/
@@ -289,16 +290,16 @@ export class MediaHandler extends TypedEventEmitter {
const screenshareConstraints = this.getScreenshareContraints(opts);
if (opts.desktopCapturerSourceId) {
// We are using Electron
logger.debug(`MediaHandler getScreensharingStream() calling getUserMedia() (opts=${JSON.stringify(opts)})`);
_logger.logger.debug(`MediaHandler getScreensharingStream() calling getUserMedia() (opts=${JSON.stringify(opts)})`);
stream = await navigator.mediaDevices.getUserMedia(screenshareConstraints);
} else {
// We are not using Electron
logger.debug(`MediaHandler getScreensharingStream() calling getDisplayMedia() (opts=${JSON.stringify(opts)})`);
_logger.logger.debug(`MediaHandler getScreensharingStream() calling getDisplayMedia() (opts=${JSON.stringify(opts)})`);
stream = await navigator.mediaDevices.getDisplayMedia(screenshareConstraints);
}
} else {
const matchingStream = this.screensharingStreams[this.screensharingStreams.length - 1];
logger.log(`MediaHandler getScreensharingStream() cloning (streamId=${matchingStream.id})`);
_logger.logger.log(`MediaHandler getScreensharingStream() cloning (streamId=${matchingStream.id})`);
stream = matchingStream.clone();
}
if (reusable) {
@@ -312,13 +313,13 @@ export class MediaHandler extends TypedEventEmitter {
* Stops all tracks on the provided screensharing stream
*/
stopScreensharingStream(mediaStream) {
logger.debug(`MediaHandler stopScreensharingStream() stopping stream (streamId=${mediaStream.id})`);
_logger.logger.debug(`MediaHandler stopScreensharingStream() stopping stream (streamId=${mediaStream.id})`);
for (const track of mediaStream.getTracks()) {
track.stop();
}
const index = this.screensharingStreams.indexOf(mediaStream);
if (index !== -1) {
logger.debug(`MediaHandler stopScreensharingStream() splicing stream out (streamId=${mediaStream.id})`);
_logger.logger.debug(`MediaHandler stopScreensharingStream() splicing stream out (streamId=${mediaStream.id})`);
this.screensharingStreams.splice(index, 1);
}
this.emit(MediaHandlerEvent.LocalStreamsChanged);
@@ -329,7 +330,7 @@ export class MediaHandler extends TypedEventEmitter {
*/
stopAllStreams() {
for (const stream of this.userMediaStreams) {
logger.log(`MediaHandler stopAllStreams() stopping (streamId=${stream.id})`);
_logger.logger.log(`MediaHandler stopAllStreams() stopping (streamId=${stream.id})`);
for (const track of stream.getTracks()) {
track.stop();
}
@@ -344,51 +345,43 @@ export class MediaHandler extends TypedEventEmitter {
this.localUserMediaStream = undefined;
this.emit(MediaHandlerEvent.LocalStreamsChanged);
}
getUserMediaContraints(audio, video, exactDeviceId) {
getUserMediaContraints(audio, video) {
const isWebkit = !!navigator.webkitGetUserMedia;
const deviceIdKey = exactDeviceId ? "exact" : "ideal";
const audioConstraints = {};
if (this.audioInput) {
audioConstraints.deviceId = {
[deviceIdKey]: this.audioInput
};
}
if (this.audioSettings) {
audioConstraints.autoGainControl = {
ideal: this.audioSettings.autoGainControl
};
audioConstraints.echoCancellation = {
ideal: this.audioSettings.echoCancellation
};
audioConstraints.noiseSuppression = {
ideal: this.audioSettings.noiseSuppression
};
}
const videoConstraints = {
/* We want 640x360. Chrome will give it only if we ask exactly,
FF refuses entirely if we ask exactly, so have to ask for ideal
instead
XXX: Is this still true?
*/
width: isWebkit ? {
exact: 640
} : {
ideal: 640
},
height: isWebkit ? {
exact: 360
} : {
ideal: 360
}
};
if (this.videoInput) {
videoConstraints.deviceId = {
[deviceIdKey]: this.videoInput
};
}
return {
audio: audio ? audioConstraints : false,
video: video ? videoConstraints : false
audio: audio ? {
deviceId: this.audioInput ? {
ideal: this.audioInput
} : undefined,
autoGainControl: this.audioSettings ? {
ideal: this.audioSettings.autoGainControl
} : undefined,
echoCancellation: this.audioSettings ? {
ideal: this.audioSettings.echoCancellation
} : undefined,
noiseSuppression: this.audioSettings ? {
ideal: this.audioSettings.noiseSuppression
} : undefined
} : false,
video: video ? {
deviceId: this.videoInput ? {
ideal: this.videoInput
} : undefined,
/* We want 640x360. Chrome will give it only if we ask exactly,
FF refuses entirely if we ask exactly, so have to ask for ideal
instead
XXX: Is this still true?
*/
width: isWebkit ? {
exact: 640
} : {
ideal: 640
},
height: isWebkit ? {
exact: 360
} : {
ideal: 360
}
} : false
};
}
getScreenshareContraints(opts) {
@@ -398,7 +391,7 @@ export class MediaHandler extends TypedEventEmitter {
} = opts;
if (desktopCapturerSourceId) {
return {
audio: audio ?? false,
audio: audio !== null && audio !== void 0 ? audio : false,
video: {
mandatory: {
chromeMediaSource: "desktop",
@@ -408,10 +401,11 @@ export class MediaHandler extends TypedEventEmitter {
};
} else {
return {
audio: audio ?? false,
audio: audio !== null && audio !== void 0 ? audio : false,
video: true
};
}
}
}
exports.MediaHandler = MediaHandler;
//# sourceMappingURL=mediaHandler.js.map