450 lines
13 KiB
JavaScript
450 lines
13 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||
|
|
||
|
var _events = require('events');
|
||
|
|
||
|
var _dropStream = require('drop-stream');
|
||
|
|
||
|
var _dropStream2 = _interopRequireDefault(_dropStream);
|
||
|
|
||
|
var _removeValue = require('remove-value');
|
||
|
|
||
|
var _removeValue2 = _interopRequireDefault(_removeValue);
|
||
|
|
||
|
var _rtimer = require('rtimer');
|
||
|
|
||
|
var _rtimer2 = _interopRequireDefault(_rtimer);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||
|
|
||
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||
|
|
||
|
var User = function (_EventEmitter) {
|
||
|
_inherits(User, _EventEmitter);
|
||
|
|
||
|
function User(client, id) {
|
||
|
_classCallCheck(this, User);
|
||
|
|
||
|
var _this = _possibleConstructorReturn(this, (User.__proto__ || Object.getPrototypeOf(User)).call(this));
|
||
|
|
||
|
_this._client = client;
|
||
|
_this._id = id;
|
||
|
_this._haveRequestedTexture = false;
|
||
|
_this._haveRequestedComment = false;
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
_createClass(User, [{
|
||
|
key: '_update',
|
||
|
value: function _update(msg) {
|
||
|
var changes = {};
|
||
|
if (msg.name != null) {
|
||
|
changes.username = this._username = msg.name;
|
||
|
}
|
||
|
if (msg.user_id != null) {
|
||
|
changes.uniqueId = this._uniqueId = msg.user_id;
|
||
|
}
|
||
|
if (msg.mute != null) {
|
||
|
changes.mute = this._mute = msg.mute;
|
||
|
}
|
||
|
if (msg.deaf != null) {
|
||
|
changes.deaf = this._deaf = msg.deaf;
|
||
|
}
|
||
|
if (msg.suppress != null) {
|
||
|
changes.suppress = this._suppress = msg.suppress;
|
||
|
}
|
||
|
if (msg.self_mute != null) {
|
||
|
changes.selfMute = this._selfMute = msg.self_mute;
|
||
|
}
|
||
|
if (msg.self_deaf != null) {
|
||
|
changes.selfDeaf = this._selfDeaf = msg.self_deaf;
|
||
|
}
|
||
|
if (msg.texture != null) {
|
||
|
changes.texture = this._texture = msg.texture;
|
||
|
}
|
||
|
if (msg.texture_hash != null) {
|
||
|
changes.textureHash = this._textureHash = msg.texture_hash;
|
||
|
this._haveRequestedTexture = false; // invalidate previous request
|
||
|
}
|
||
|
if (msg.comment != null) {
|
||
|
changes.comment = this._comment = msg.comment;
|
||
|
}
|
||
|
if (msg.comment_hash != null) {
|
||
|
changes.commentHash = this._commentHash = msg.comment_hash;
|
||
|
this._haveRequestedComment = false; // invalidate previous request
|
||
|
}
|
||
|
if (msg.priority_speaker != null) {
|
||
|
changes.prioritySpeaker = this._prioritySpeaker = msg.priority_speaker;
|
||
|
}
|
||
|
if (msg.recording != null) {
|
||
|
changes.recording = this._recording = msg.recording;
|
||
|
}
|
||
|
if (msg.hash != null) {
|
||
|
changes.certHash = this._certHash = msg.hash;
|
||
|
}
|
||
|
if (msg.channel_id != null) {
|
||
|
if (this.channel) {
|
||
|
(0, _removeValue2.default)(this.channel.users, this);
|
||
|
}
|
||
|
this._channelId = msg.channel_id;
|
||
|
if (this.channel) {
|
||
|
this.channel.users.push(this);
|
||
|
}
|
||
|
changes.channel = this.channel;
|
||
|
}
|
||
|
this.emit('update', this._client._userById[msg.actor], changes);
|
||
|
}
|
||
|
}, {
|
||
|
key: '_remove',
|
||
|
value: function _remove(actor, reason, ban) {
|
||
|
if (this.channel) {
|
||
|
(0, _removeValue2.default)(this.channel.users, this);
|
||
|
}
|
||
|
this.emit('remove', actor, reason, ban);
|
||
|
}
|
||
|
}, {
|
||
|
key: '_getOrCreateVoiceStream',
|
||
|
value: function _getOrCreateVoiceStream() {
|
||
|
var _this2 = this;
|
||
|
|
||
|
if (!this._voice) {
|
||
|
// New transmission
|
||
|
if (!this._client._codecs) {
|
||
|
// No codecs available, cannot decode
|
||
|
this._voice = _dropStream2.default.obj();
|
||
|
} else {
|
||
|
this._voice = this._client._codecs.createDecoderStream(this);
|
||
|
}
|
||
|
this._voice.once('close', function () {
|
||
|
_this2._voice = null;
|
||
|
});
|
||
|
this._voiceTimeout = new _rtimer2.default(function () {
|
||
|
_this2._voice.end();
|
||
|
_this2._voice = null;
|
||
|
}, this._client._options.userVoiceTimeout || 200).set();
|
||
|
this.emit('voice', this._voice);
|
||
|
}
|
||
|
return this._voice;
|
||
|
}
|
||
|
}, {
|
||
|
key: '_getDuration',
|
||
|
value: function _getDuration(codec, frames) {
|
||
|
var _this3 = this;
|
||
|
|
||
|
if (this._client._codecs) {
|
||
|
var duration = 0;
|
||
|
frames.forEach(function (frame) {
|
||
|
duration += _this3._client._codecs.getDuration(codec, frame);
|
||
|
});
|
||
|
return duration;
|
||
|
} else {
|
||
|
return frames.length * 10;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method filters and inserts empty frames as needed to accout
|
||
|
* for packet loss and then writes to the {@link #_voice} stream.
|
||
|
* If this is a new transmission it emits the 'voice' event and if
|
||
|
* the transmission has ended it closes the stream.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: '_onVoice',
|
||
|
value: function _onVoice(seqNum, codec, target, frames, position, end) {
|
||
|
var _this4 = this;
|
||
|
|
||
|
if (frames.length > 0) {
|
||
|
var duration = this._getDuration(codec, frames);
|
||
|
if (this._voice != null) {
|
||
|
// This is not the first packet in this transmission
|
||
|
|
||
|
// So drop it if it's late
|
||
|
if (this._lastVoiceSeqId > seqNum) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// And make up for lost packets
|
||
|
if (this._lastVoiceSeqId < seqNum - duration / 10) {
|
||
|
var lost = seqNum - this._lastVoiceSeqId - 1;
|
||
|
// Cap at 10 lost frames, the audio will sound broken at that point anyway
|
||
|
if (lost > 10) {
|
||
|
lost = 10;
|
||
|
}
|
||
|
for (var i = 0; i < lost; i++) {
|
||
|
this._getOrCreateVoiceStream().write({
|
||
|
target: target,
|
||
|
codec: codec,
|
||
|
frame: null,
|
||
|
position: position
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
frames.forEach(function (frame) {
|
||
|
_this4._getOrCreateVoiceStream().write({
|
||
|
target: target,
|
||
|
codec: codec,
|
||
|
frame: frame,
|
||
|
position: position
|
||
|
});
|
||
|
});
|
||
|
this._voiceTimeout.set();
|
||
|
this._lastVoiceSeqId = seqNum + duration / 10 - 1;
|
||
|
}
|
||
|
if (end && this._voice) {
|
||
|
this._voiceTimeout.clear();
|
||
|
this._voiceTimeout = null;
|
||
|
this._voice.end();
|
||
|
this._voice = null;
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setMute',
|
||
|
value: function setMute(mute) {
|
||
|
var message = {
|
||
|
name: 'UserState',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
mute: mute
|
||
|
}
|
||
|
};
|
||
|
if (!mute) message.payload.deaf = false;
|
||
|
this._client._send(message);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setDeaf',
|
||
|
value: function setDeaf(deaf) {
|
||
|
var message = {
|
||
|
name: 'UserState',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
deaf: deaf
|
||
|
}
|
||
|
};
|
||
|
if (deaf) message.payload.mute = true;
|
||
|
this._client._send(message);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'clearComment',
|
||
|
value: function clearComment() {
|
||
|
this._client._send({
|
||
|
name: 'UserState',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
comment: ''
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'clearTexture',
|
||
|
value: function clearTexture() {
|
||
|
this._client._send({
|
||
|
name: 'UserState',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
texture: ''
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'requestComment',
|
||
|
value: function requestComment() {
|
||
|
if (this._haveRequestedComment) return;
|
||
|
this._client._send({
|
||
|
name: 'RequestBlob',
|
||
|
payload: {
|
||
|
session_comment: this._id
|
||
|
}
|
||
|
});
|
||
|
this._haveRequestedComment = true;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'requestTexture',
|
||
|
value: function requestTexture() {
|
||
|
if (this._haveRequestedTexture) return;
|
||
|
this._client._send({
|
||
|
name: 'RequestBlob',
|
||
|
payload: {
|
||
|
session_texture: this._id
|
||
|
}
|
||
|
});
|
||
|
this._haveRequestedTexture = true;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'register',
|
||
|
value: function register() {
|
||
|
this._client._send({
|
||
|
name: 'UserState',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
user_id: 0
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'sendMessage',
|
||
|
value: function sendMessage(message) {
|
||
|
this._client._send({
|
||
|
name: 'TextMessage',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
message: message
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setChannel',
|
||
|
value: function setChannel(channel) {
|
||
|
this._client._send({
|
||
|
name: 'UserState',
|
||
|
payload: {
|
||
|
session: this._id,
|
||
|
channel_id: channel._id
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'id',
|
||
|
get: function get() {
|
||
|
return this._id;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'username',
|
||
|
get: function get() {
|
||
|
return this._username;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set username.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'uniqueId',
|
||
|
get: function get() {
|
||
|
return this._uniqueId;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set uniqueId. Maybe try #register()?');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'mute',
|
||
|
get: function get() {
|
||
|
return this._mute;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set mute. Use #setMute(mute) instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'deaf',
|
||
|
get: function get() {
|
||
|
return this._deaf;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set deaf. Use #setDeaf(deaf) instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'selfMute',
|
||
|
get: function get() {
|
||
|
return this._selfMute;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set selfMute. Use Client#setSelfMute(mute) instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'selfDeaf',
|
||
|
get: function get() {
|
||
|
return this._selfDeaf;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set selfDeaf. Use Client#setSelfDeaf(deaf) instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'suppress',
|
||
|
get: function get() {
|
||
|
return this._suppress;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set suppress.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'texture',
|
||
|
get: function get() {
|
||
|
return this._texture;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set texture. Use Client#setSelfTexture(texture) or #clearTexture() instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'textureHash',
|
||
|
get: function get() {
|
||
|
return this._textureHash;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set textureHash.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'comment',
|
||
|
get: function get() {
|
||
|
return this._comment;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set comment. Use Client#setSelfTexture(texture) or #clearComment() instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'commentHash',
|
||
|
get: function get() {
|
||
|
return this._commentHash;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set commentHash.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'prioritySpeaker',
|
||
|
get: function get() {
|
||
|
return this._prioritySpeaker;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set prioritySpeaker. Use #setPrioritySpeaker(prioSpeaker) instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'recording',
|
||
|
get: function get() {
|
||
|
return this._recording;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set recording. Use Client#setSelfRecording(recording) instead.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'certHash',
|
||
|
get: function get() {
|
||
|
return this._certHash;
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set certHash.');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'channel',
|
||
|
get: function get() {
|
||
|
if (this._channelId != null) {
|
||
|
return this._client._channelById[this._channelId];
|
||
|
} else {
|
||
|
return null;
|
||
|
}
|
||
|
},
|
||
|
set: function set(to) {
|
||
|
throw new Error('Cannot set channel. Use #setChannel(channel) instead.');
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return User;
|
||
|
}(_events.EventEmitter);
|
||
|
|
||
|
exports.default = User;
|