UNPKG

@skyway-sdk/sfu-bot

Version:

The official Next Generation JavaScript SDK for SkyWay

248 lines 11.1 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SfuBotMember = void 0; const common_1 = require("@skyway-sdk/common"); const core_1 = require("@skyway-sdk/core"); const connection_1 = require("./connection"); const const_1 = require("./const"); const errors_1 = require("./errors"); const log = new common_1.Logger('packages/sfu-bot/src/member.ts'); class SfuBotMember extends core_1.MemberImpl { /**@internal */ constructor(args) { super(args); this.side = 'remote'; this.subtype = SfuBotMember.subtype; this.type = 'bot'; this._connections = {}; /** @description [japanese] forwardingを開始した時に発火するイベント */ this.onForwardingStarted = new common_1.Event(); /** @description [japanese] forwardingを終了した時に発火するイベント */ this.onForwardingStopped = new common_1.Event(); /** @description [japanese] forwardingの数が変化した時に発火するイベント */ this.onForwardingListChanged = new common_1.Event(); this._startForwardQueue = new common_1.PromiseQueue(); this._forwardings = {}; /** * @description [japanese] Forwardingを停止する */ this.stopForwarding = (target) => new Promise((r, f) => __awaiter(this, void 0, void 0, function* () { const timestamp = log.info('[start] stopForwarding', yield (0, core_1.createLogPayload)({ operationName: 'SfuBotMember.stopForwarding', channel: this.channel, })); if (this.state !== 'joined') { f((0, core_1.createError)({ operationName: 'SfuBotMember.stopForwarding', context: this._context, info: errors_1.errors.sfuBotNotInChannel, path: log.prefix, channel: this.channel, payload: { status: this.state }, })); return; } const forwardingId = typeof target === 'string' ? target : target.id; const forwarding = this._forwardings[forwardingId]; if (!forwarding) { f((0, core_1.createError)({ operationName: 'SfuBotMember.stopForwarding', context: this._context, info: errors_1.errors.forwardingNotFound, path: log.prefix, channel: this.channel, payload: { forwardingId, _forwardings: Object.keys(this._forwardings), }, })); return; } delete this._forwardings[forwarding.id]; const { promise, fulfilled } = this._api.stopForwarding({ botId: this.id, forwardingId, }); let failed = false; promise.catch((e) => { failed = true; f(e); }); this.onForwardingStopped .watch((e) => e.forwarding.id === forwardingId, this._context.config.rtcApi.timeout) .then(() => __awaiter(this, void 0, void 0, function* () { log.elapsed(timestamp, '[end] stopForwarding', yield (0, core_1.createLogPayload)({ operationName: 'SfuBotMember.stopForwarding', channel: this.channel, })); r(); })) .catch((error) => { if (!failed) f((0, core_1.createError)({ operationName: 'SfuBotMember.stopForwarding', context: this._context, info: Object.assign(Object.assign({}, errors_1.errors.timeout), { detail: 'onForwardingStopped' }), path: log.prefix, channel: this.channel, payload: { fulfilled }, error, })); }); })); this._api = args.api; this._context = args.context; this._transportRepository = args.transportRepository; this.options = args.options; this.onLeft.once(() => { log.debug('SfuBotMember left: ', { id: this.id }); Object.values(this._connections).forEach((c) => { c.close({ reason: 'sfu bot left' }); }); this._connections = {}; }); } get forwardings() { return Object.values(this._forwardings); } /**@private */ _getConnection(localPersonId) { return this._connections[localPersonId]; } /**@private */ _getOrCreateConnection(localPerson) { var _a; const connection = (_a = this._getConnection(localPerson.id)) !== null && _a !== void 0 ? _a : this._createConnection(this.channel, localPerson, this); return connection; } /**@private */ _createConnection(channel, localPerson, endpointBot) { const connection = new connection_1.SFUConnection(endpointBot._api, channel, localPerson, endpointBot, this._transportRepository, this._context); connection.onClose.once(() => { delete this._connections[localPerson.id]; }); this._connections[localPerson.id] = connection; return connection; } /** * @description [japanese] StreamのPublicationをForwardingする * @throws {SkyWayError} * @example * const forwarding = await bot.startForwarding(publication, { maxSubscribers: 99 }); */ startForwarding(publication, configure = {}) { return __awaiter(this, void 0, void 0, function* () { const timestamp = log.info('[start] startForwarding', yield (0, core_1.createLogPayload)({ operationName: 'SfuBotMember.startForwarding', channel: this.channel, })); const res = yield this._startForwardQueue.push(() => this._startForwarding(publication, configure)); log.elapsed(timestamp, '[end] startForwarding', yield (0, core_1.createLogPayload)({ operationName: 'SfuBotMember.startForwarding', channel: this.channel, })); return res; }); } _startForwarding(relayed, configure) { return __awaiter(this, void 0, void 0, function* () { if (configure.maxSubscribers == undefined) { configure.maxSubscribers = const_1.defaultMaxSubscribers; } if (this.state !== 'joined') { throw (0, core_1.createError)({ operationName: 'SfuBotMember._startForwarding', context: this._context, channel: this.channel, info: errors_1.errors.sfuBotNotInChannel, path: log.prefix, payload: { status: this.state }, }); } if (!this.channel._getPublication(relayed.id)) { throw (0, core_1.createError)({ operationName: 'SfuBotMember._startForwarding', context: this._context, channel: this.channel, info: core_1.errors.publicationNotExist, path: log.prefix, }); } const localPerson = this.channel.localPerson; if (!localPerson) { throw (0, core_1.createError)({ operationName: 'SfuBotMember._startForwarding', context: this._context, channel: this.channel, info: core_1.errors.localPersonNotJoinedChannel, path: log.prefix, }); } if (localPerson.id !== relayed.publisher.id) { throw (0, core_1.createError)({ operationName: 'SfuBotMember._startForwarding', context: this._context, info: errors_1.errors.remotePublisherId, path: log.prefix, channel: this.channel, }); } const ts = log.debug('[start] SfuBotMember startForwarding', { publication: relayed.toJSON(), configure, }); const connection = this._getOrCreateConnection(localPerson); const sender = connection.addSender(relayed); const forwarding = yield sender .startForwarding(configure) .catch((error) => { throw (0, core_1.createError)({ operationName: 'SfuBotMember._startForwarding', context: this._context, info: Object.assign(Object.assign({}, errors_1.errors.internal), { detail: '[failed] SfuBotMember startForwarding' }), path: log.prefix, channel: this.channel, error, payload: { publication: relayed.toJSON() }, }); }); this._forwardings[forwarding.id] = forwarding; this.listenStopForwardEvent(forwarding); this.onForwardingStarted.emit({ forwarding }); this.onForwardingListChanged.emit(); log.elapsed(ts, '[end] SfuBotMember startForwarding', { forwarding: forwarding.toJSON(), }); return forwarding; }); } listenStopForwardEvent(forwarding) { const { removeListener } = this.channel.onStreamUnpublished.add((e) => { if (e.publication.id === forwarding.id) { removeListener(); forwarding._stop(); const origin = forwarding.originPublication; const connection = this._getConnection(origin.publisher.id); if (connection) { connection.removeSender(origin.id); } this.onForwardingStopped.emit({ forwarding }); this.onForwardingListChanged.emit(); } }); } /**@private */ _dispose() { } } exports.SfuBotMember = SfuBotMember; SfuBotMember.subtype = 'sfu'; //# sourceMappingURL=member.js.map